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
@@ -29,10 +29,10 @@ import androidx.compose.ui.unit.sp
|
||||
* grounds that a system font may not have the glyph and whoever gets the empty box instead is never
|
||||
* the person who wrote it. That objection is about *relying* on a system font, and it is exactly
|
||||
* right: the answer is not to avoid glyphs but to ship them. The font here is
|
||||
* `app/build-icon-font.sh`'s output -- eleven glyphs, 2.1 KB, subset out of the 3 MB symbols font
|
||||
* and committed -- so the codepoints below are resolved by an asset in the APK and cannot come back
|
||||
* as tofu. Adding one means adding its codepoint in *both* places; a codepoint here that the script
|
||||
* did not subset is a glyph that silently isn't there.
|
||||
* `app/build-icon-font.sh`'s output -- seventeen glyphs, 2.8 KB, subset out of the 3 MB symbols
|
||||
* font and committed -- so the codepoints below are resolved by an asset in the APK and cannot come
|
||||
* back as tofu. Adding one means adding its codepoint in *both* places; a codepoint here that the
|
||||
* script did not subset is a glyph that silently isn't there.
|
||||
*
|
||||
* The subset is the font's **Mono** face, where every glyph is exactly one em wide and one em tall.
|
||||
* That is what makes two icons the same size without either of them being given a size: the
|
||||
@@ -117,6 +117,33 @@ val USAGE_GLYPH = glyph(0xF201)
|
||||
*/
|
||||
val SPEED_GLYPH = glyph(0xF04C5)
|
||||
|
||||
/**
|
||||
* `md-folder` -- the files on the machine this session runs on.
|
||||
*
|
||||
* The same codepoint dev-updater uses, and it must not drift from it, for the reason the cog and
|
||||
* the refresh arrow must not: a folder that meant something else in one of the two apps is exactly
|
||||
* the confusion sharing them prevents. Doubles as the mark on a directory row inside the explorer,
|
||||
* which is what makes the button say where it leads.
|
||||
*/
|
||||
val FOLDER_GLYPH = glyph(0xF024B)
|
||||
|
||||
/** `md-file_outline` -- one file, in a listing beside the directories. */
|
||||
val FILE_GLYPH = glyph(0xF0224)
|
||||
|
||||
/** `md-plus` -- make something here. dev-updater's codepoint as well. */
|
||||
val PLUS_GLYPH = glyph(0xF0415)
|
||||
|
||||
/** `md-pencil` -- change what this file says, rather than only reading it. */
|
||||
val EDIT_GLYPH = glyph(0xF03EB)
|
||||
|
||||
/**
|
||||
* `md-content_save` -- write the edits back to the machine.
|
||||
*
|
||||
* The floppy disk, which is what save has meant for longer than most of the people reading it have
|
||||
* been alive and is still the only mark anybody recognises for it.
|
||||
*/
|
||||
val SAVE_GLYPH = glyph(0xF0193)
|
||||
|
||||
/**
|
||||
* The size an icon draws at beside a line of text.
|
||||
*
|
||||
|
||||
Reference in new issue
Block a user