The file explorer on the phone
The other half of EXPLORER.md: a folder button on the session header opens the machine's filesystem, starting where the session works. It draws **over** the session in the same `Box`, so the session under it stays composed -- its event stream keeps flowing, its draft and scroll position stay where they were, and coming back from a file costs nothing. Back steps one level inside it (editor, viewer, directory, parent) and only closes from where it opened; the platform gesture, the button and the swipe all go through the one function, so they cannot mean different things. The viewer is a `LazyColumn` of lines rather than one `Text`, because text layout is linear in the text and a twenty-thousand-line file in a single `Text` measures all of it to draw a screenful. Lines do not wrap and share one horizontal scroll, so a logical line is a visual line and the gutter cannot come to number the wrong text; the gutter's width is measured from the digit count of the line count in the style it is drawn in. The editor is a `BasicTextField` with a `VisualTransformation` carrying the scanner's spans, which is the one Compose API that colours a field's own text rather than replacing the field. `fileLanguage` reads the same table `fenceLanguage` does, so a language added for fences is a language added for files. A file that changed on the machine while it was open here refuses to be overwritten and asks, with what each of the three answers costs. That is the ordinary case, not the exotic one: an agent editing the file somebody is reading is what this whole feature is for. The speedometer moves off the header into the session settings dialog, where the session's other about-the-session controls are, and the folder takes a place between the usage chart and the cog -- widest scope to narrowest, cog at the end, as Iris asked. Both benchmark scripts move onto `ui-trace`'s new tap-by-label action in the same change, so the render report is never unavailable and never pressed at a coordinate that has stopped meaning anything; `app/bench-lib.sh` is what they share, and `grep -n "tap [0-9]" app/*.sh` is the check. Exercised on the emulator against the sandbox's new fixture tree, with a screenshot or a ui-trace for each: the listing (dotfiles, directories first, a symlink to a directory sorted with them, a name with a tab in it), a highlighted file, binary, too big, a permission error, editing and saving, the 409 and its Overwrite, back with unsaved edits, creating a name that exists, creating one that does not and landing in the editor, an empty directory, and `..` above the directory the session opened in. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4a9c547293
commit
db55ed4a8f
22 files changed
+1647
-161
No files matched your search
+16
-48
@@ -7,10 +7,11 @@ existing syntax highlighting, line numbers, no wrapping; edit a file behind
|
||||
a pencil icon; create files through a modal like the ones the app already
|
||||
has; work over ssh; open at the session's working directory.
|
||||
|
||||
This is the plan. Like PLAN.md it records each decision with the reason and
|
||||
what was rejected, so that when one changes it is changed here rather than
|
||||
re-argued. Once built, the operational notes (how to test it, what bit)
|
||||
move to AGENTS.md and this file keeps only the design.
|
||||
Built on 2026-09-03. This is the design, decision by decision with the
|
||||
reason and what was rejected, so that when one changes it is changed here
|
||||
rather than re-argued. The operational half -- how to run it, what to press,
|
||||
what to produce on purpose -- is in AGENTS.md, where the rest of this
|
||||
project's working notes are.
|
||||
|
||||
## What it is, in one paragraph
|
||||
|
||||
@@ -258,12 +259,18 @@ rerun and its output committed (it needs network):
|
||||
codepoint dev-updater uses, and it must not drift from it, as the cog
|
||||
and the refresh arrow already must not.
|
||||
- `md-plus` U+F0415 -- create. Also dev-updater's.
|
||||
- `md-pencil` -- edit.
|
||||
- `md-content_save` -- save.
|
||||
- `md-file_outline` -- file rows.
|
||||
- `md-pencil` U+F03EB -- edit.
|
||||
- `md-content_save` U+F0193 -- save.
|
||||
- `md-file_outline` U+F0224 -- file rows.
|
||||
|
||||
The last three are verified against the Nerd Fonts cheat sheet when they
|
||||
are added, not copied from memory.
|
||||
All five were looked up in Nerd Fonts' own `glyphnames.json` rather than
|
||||
copied from memory, which is the check that a codepoint means the glyph its
|
||||
comment names.
|
||||
|
||||
**Where the folder button sits**: between the usage chart and the cog, so
|
||||
the header reads widest scope to narrowest and the cog stays at the end
|
||||
where every other screen in this app keeps it. Asked for in that order by
|
||||
Iris on 2026-09-03.
|
||||
|
||||
### 13. The render report moves, and the benches move with it
|
||||
|
||||
@@ -386,32 +393,6 @@ pure functions with tests.
|
||||
`~/repos/emulator-tools`, `ui-trace`'s tap-by-label action; then the
|
||||
two bench scripts onto it, with no coordinate tap left in `app/*.sh`.
|
||||
|
||||
## Testing
|
||||
|
||||
- **Server**: `./run-tests.sh`, `cargo clippy --all-targets`, `cargo fmt`.
|
||||
- **Local transport, by hand**: `./ui-sandbox.sh api
|
||||
"/setups/<id>/dir?path=~"` against the sandbox, whose `$HOME` is a
|
||||
throwaway tree it is fine to write into. The sandbox gets a small
|
||||
fixture directory with the states worth seeing: an empty directory, a
|
||||
file with a tab in its name, a binary file, one over `FILE_LIMIT`, an
|
||||
unreadable one (`chmod 000`), a symlink to a directory, and a source
|
||||
file in each of a few languages.
|
||||
- **Remote transport**: the ssh-to-this-VM recipe in AGENTS.md ("How to
|
||||
test SSH here"). The point of the exercise is the quoting and the
|
||||
stdin path: write a file whose name has a `'` in it, and read it back.
|
||||
- **Phone**: `ui-trace`, not screenshots, for the things this feature is
|
||||
made of -- that the gutter's number and its line share a baseline at
|
||||
the first and the last row, that a long line's row is wider than the
|
||||
viewport and does not grow the row height, that the editor's gutter
|
||||
stays put while the text scrolls sideways. Screenshots for colour and
|
||||
contrast on `rawSurface`.
|
||||
- **States to produce on purpose**, since the default state is the one
|
||||
everybody looks at: a directory that fails to list (permission),
|
||||
an unreachable machine (a setup pointing at a dead address), `binary`,
|
||||
`tooBig`, the 409 conflict (edit the file with `sed -i` on the machine
|
||||
between opening and saving), creating a name that exists, back with
|
||||
unsaved edits, and the keyboard up over the editor.
|
||||
|
||||
## Numbers to measure, before deciding
|
||||
|
||||
- Scan time for a 1 MiB source file on the emulator, and on the phone
|
||||
@@ -425,19 +406,6 @@ pure functions with tests.
|
||||
If not, edit mode gets a lower cap than the viewer, stated in the
|
||||
editor rather than discovered by a stuck keyboard.
|
||||
|
||||
## Order of work
|
||||
|
||||
Each step leaves the app working and is one commit.
|
||||
|
||||
1. Server: `files.rs` with `list` and `read`, routes, tests. Half a day.
|
||||
2. App: icons, `Api.kt`, `FilesScreen` listing, `FileViewer`, the root
|
||||
and session wiring, the render-report move with the benches. A day.
|
||||
3. Server: `write`, `create_file`, `create_dir`, the stdin helper and
|
||||
`ship_attachment` onto it. Half a day.
|
||||
4. App: `FileEditor`, the create dialog, the conflict dialog. Half a day.
|
||||
5. Measurements above, the sandbox fixture, PLAN.md and AGENTS.md. Half a
|
||||
day.
|
||||
|
||||
## Later, deliberately not now
|
||||
|
||||
- Delete, rename and move. Destructive controls belong here eventually,
|
||||
|
||||
Reference in new issue
Block a user