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>
84 lines
3.6 KiB
Bash
Executable File
84 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Rebuilds androidApp/src/main/res/font/nerd_icons.ttf.
|
|
#
|
|
# The app draws a handful of icons -- a cog, a refresh arrow, send, stop --
|
|
# as text in a Nerd Fonts glyph rather than as vector assets or as ordinary
|
|
# Unicode. Unicode has no character for most of these, and the ones it does
|
|
# have are not reliably in an Android system font, so they land as tofu
|
|
# boxes on somebody's phone. Shipping the subset removes the hope: the
|
|
# glyph is in the APK.
|
|
#
|
|
# The whole symbols font is 3 MB for the handful below, so what is
|
|
# committed is a subset. Add a codepoint to GLYPHS below and to NerdIcons.kt
|
|
# (the two lists have to agree -- a codepoint in the Kotlin but not here is
|
|
# a glyph that silently doesn't exist), then run this and commit the result.
|
|
#
|
|
# Needs python3 and network access; fontTools is fetched into a temporary
|
|
# venv, so nothing has to be installed on the machine.
|
|
#
|
|
# Copied from dev-updater's script of the same name rather than shared
|
|
# through wg-app-link, for the reason Theme.kt gives about the palette: the
|
|
# link is the tunnel, the pinned CA and enrollment, and an icon set is a
|
|
# preference rather than part of that contract.
|
|
set -euo pipefail
|
|
|
|
# Codepoint, then the Nerd Fonts glyph name it came from. Material Design
|
|
# Icons bar one, so they read as one family -- and the first two are
|
|
# deliberately the same two dev-updater uses, since a cog and a refresh
|
|
# arrow mean the same thing in both apps. The exception is noted on its
|
|
# own line, as dev-updater's script does with its two.
|
|
GLYPHS=(
|
|
U+F0493 # md-cog
|
|
U+F0450 # md-refresh
|
|
U+F048A # md-send
|
|
U+F04DB # md-stop
|
|
U+F03E4 # md-pause
|
|
U+F040A # md-play
|
|
U+F1163 # md-send_clock
|
|
U+F0156 # md-close
|
|
U+F004D # md-arrow_left
|
|
U+F009A # md-bell
|
|
U+F04C5 # md-speedometer
|
|
U+F024B # md-folder -- dev-updater's too; a folder means the same in both
|
|
U+F0415 # md-plus -- likewise
|
|
U+F03EB # md-pencil
|
|
U+F0193 # md-content_save
|
|
U+F0224 # md-file_outline
|
|
U+F201 # fa-line_chart -- Font Awesome's, asked for by name
|
|
)
|
|
|
|
url=https://github.com/ryanoasis/nerd-fonts/releases/latest/download/NerdFontsSymbolsOnly.zip
|
|
out="$(cd "$(dirname "$0")" && pwd)/androidApp/src/main/res/font/nerd_icons.ttf"
|
|
work="$(mktemp -d)"
|
|
trap 'rm -rf "$work"' EXIT
|
|
|
|
echo "Fetching $url"
|
|
curl -fsSL -o "$work/nf.zip" "$url"
|
|
python3 -c 'import sys,zipfile; zipfile.ZipFile(sys.argv[1]).extractall(sys.argv[2])' "$work/nf.zip" "$work"
|
|
|
|
python3 -m venv "$work/venv"
|
|
"$work/venv/bin/pip" -q install fonttools
|
|
|
|
unicodes="$(IFS=,; echo "${GLYPHS[*]}")"
|
|
mkdir -p "$(dirname "$out")"
|
|
# The Mono face rather than the proportional one, which this used until
|
|
# 2026-08-30. Every glyph in it is one em wide and one em tall, so two
|
|
# icons drawn at the same size are the same size -- which is what makes two
|
|
# icon buttons beside each other match without either of them being told a
|
|
# width. In the proportional face the advances run from 0.46 em (play) to
|
|
# 0.92 em (line chart), so the composer's Send button came out visibly wider
|
|
# than the Stop button next to it, and any fix at the call site would have
|
|
# been one measurement hardcoded per pair.
|
|
#
|
|
# The trade is the one the old comment named: an icon inline beside text is
|
|
# padded out to a cell. That is worth it, and it is also why GLYPH_SIZE in
|
|
# NerdIcons.kt came down when this changed -- a glyph that fills its em
|
|
# draws bigger at the same point size than one that does not.
|
|
"$work/venv/bin/pyftsubset" "$work/SymbolsNerdFontMono-Regular.ttf" \
|
|
--unicodes="$unicodes" \
|
|
--layout-features= \
|
|
--drop-tables+=DSIG \
|
|
--output-file="$out"
|
|
|
|
echo "Wrote $out ($(stat -c %s "$out") bytes) with ${#GLYPHS[@]} glyphs"
|