From 4c151503384ab9fe09e1467b9a0d94ef02f72eb0 Mon Sep 17 00:00:00 2001 From: iris <2+iris@noreply.localhost> Date: Wed, 9 Sep 2026 22:48:52 -0400 Subject: [PATCH] Return from files to explorer --- EXPLORER.md | 10 +++---- .../kotlin/com/example/aiapp/FilesScreen.kt | 30 +++++++++++++------ 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/EXPLORER.md b/EXPLORER.md index 612079c..e082c8c 100644 --- a/EXPLORER.md +++ b/EXPLORER.md @@ -214,11 +214,11 @@ be lost. The explorer draws over the session, which deliberately has no `FilesScreen` is composed **on top of** the session in the same `Box`, and the session stays composed under it: its event stream keeps flowing, its scroll position and draft stay where they were, and returning from a file -costs nothing. Back — the button and the platform gesture — clears `files` -and returns to the session from anywhere in the explorer. Directory navigation -stays in the listing: `..` is an explicit row rather than a hidden second -meaning for Back. An editor with unsaved changes asks before closing. "Back -returns; it does not exit." +costs nothing. Back — the button and the platform gesture — returns from an +open file to its containing directory, then clears `files` and returns to the +session. Directory navigation stays in the listing: `..` is an explicit row +rather than a hidden second meaning for Back. An editor with unsaved changes +asks before returning to the directory. "Back returns; it does not exit." Rejected: a `Screen.Files` beside `Screen.Session`. Every route back from a leaf screen goes to Main today, and a session disposed and re-created on each diff --git a/app/androidApp/src/main/kotlin/com/example/aiapp/FilesScreen.kt b/app/androidApp/src/main/kotlin/com/example/aiapp/FilesScreen.kt index 3937eb5..cf74fe2 100644 --- a/app/androidApp/src/main/kotlin/com/example/aiapp/FilesScreen.kt +++ b/app/androidApp/src/main/kotlin/com/example/aiapp/FilesScreen.kt @@ -54,15 +54,16 @@ data class FilesTarget(val setup: String, val setupName: String, val start: Stri private sealed class Spot(val path: String) { class Dir(path: String) : Spot(path) - class Doc(path: String) : Spot(path) + class Doc(path: String, val directory: Dir) : Spot(path) } /** * The files on the machine a session runs on: browse them, read one, change one. * * Drawn **over** the session rather than instead of it (see [AppRoot]), so its event stream keeps - * flowing and coming back from a file costs nothing. Back always closes the explorer and returns to - * that session; directory navigation stays inside the listing, where its `..` row is explicit. + * flowing and coming back from a file costs nothing. Back from a file returns to its directory; + * back from a directory closes the explorer and returns to the session. Directory navigation stays + * inside the listing, where its `..` row is explicit. * * Every directory that has been visited is kept for as long as this is open; the refresh glyph is * how one gets asked again on purpose, and creating something refetches the directory it was @@ -88,7 +89,11 @@ fun FilesScreen(settings: ServerSettings, target: FilesTarget, onClose: () -> Un } fun back() { - if (editing && dirty) askUnsaved = true else onClose() + when { + editing && dirty -> askUnsaved = true + here is Spot.Doc -> go((here as Spot.Doc).directory) + else -> onClose() + } } suspend fun load(path: String, again: Boolean) { @@ -140,7 +145,7 @@ fun FilesScreen(settings: ServerSettings, target: FilesTarget, onClose: () -> Un ) } LaunchedEffect(spot.path) { load(spot.path, again = false) } - DirectoryBody(state, onOpen = ::go) + DirectoryBody(state, directory = spot, onOpen = ::go) } is Spot.Doc -> DocPane( @@ -161,7 +166,8 @@ fun FilesScreen(settings: ServerSettings, target: FilesTarget, onClose: () -> Un UnsavedDialog( onDiscard = { askUnsaved = false - onClose() + val spot = here + if (spot is Spot.Doc) go(spot.directory) else onClose() }, onCancel = { askUnsaved = false }, ) @@ -183,7 +189,7 @@ fun FilesScreen(settings: ServerSettings, target: FilesTarget, onClose: () -> Un load(dir.path, again = true) // A new file has nothing to look at, so it opens where it can be filled in. if (!isDirectory) { - go(Spot.Doc(path)) + go(Spot.Doc(path, dir)) editing = true } } @@ -235,7 +241,11 @@ private fun FilesHeader( * looks like a right one. */ @Composable -private fun ColumnScope.DirectoryBody(state: LoadState