- Code viewer: the outline opens with a swipe from the left edge and closes with a swipe left, with one pane or two. - Side-by-side .h/.cpp: a draggable handle resizes the panes (20% to 80%). - Directory listing reads Git tree objects instead of the contents endpoint, which looked up the last commit of every entry. - A listing that needs more than one request shows percent and count. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
98 lines
4.6 KiB
Markdown
98 lines
4.6 KiB
Markdown
# TASK-056: Reading gestures, a resizable pair, and fast directory listing
|
|
|
|
Status: implemented; required checks pass; installed on the product owner's Z Fold7, awaiting their confirmation
|
|
Owner: Claude
|
|
Reviewer: human product owner
|
|
|
|
## Outcome
|
|
|
|
Second round of requests from the human product owner after using the app on their Galaxy Z Fold7
|
|
(SM-F966N), 2026-09-28.
|
|
|
|
## Scope
|
|
|
|
- Included:
|
|
1. Code viewer: swiping right from the far left edge brings the outline tree in; swiping left
|
|
puts it away. This also works while a `.h` and a `.cpp` are shown side by side.
|
|
2. Side-by-side pair: a handle between the two panes is dragged to resize them. Dragging left
|
|
gives the `.cpp` (right) more room, dragging right gives the `.h` (left) more room. Neither
|
|
pane can be made narrower than 20% of the width.
|
|
3. Directory listing is read from Git's tree object (`/repos/{owner}/{repo}/git/trees/{sha}`)
|
|
instead of the contents endpoint. The contents endpoint looks up the last commit of every
|
|
entry, so its cost grows with the number of files.
|
|
4. A directory listing that takes more than one request shows a progress bar with the percentage
|
|
and the count ("40% · 200 / 500개").
|
|
- Excluded:
|
|
- A percentage while a single file loads. A file arrives as one response; there is nothing to
|
|
measure it against until it has arrived. The indeterminate indicator stays.
|
|
- A percentage for a directory that fits in one request (up to 100 entries): it goes from
|
|
nothing to complete in one step, so there is no intermediate value to show.
|
|
|
|
## Writable paths
|
|
|
|
- `app/src/main/java/com/ubisam/ubgitea/data/repositories/GiteaRepositoryBrowserApi.kt`
|
|
- `app/src/main/java/com/ubisam/ubgitea/feature/codebrowser/`
|
|
- `app/src/main/res/values/strings_codebrowser.xml`
|
|
- `app/src/test/java/com/ubisam/ubgitea/`
|
|
- `tasks/`, `docs/`
|
|
|
|
## Acceptance criteria
|
|
|
|
- [x] The outline opens from the left edge and closes with a swipe left, with one pane or two.
|
|
- [x] The split is draggable, clamped, and survives rotation (`rememberSaveable`).
|
|
- [x] The root of a ref is listed from the tree of that ref's commit; a directory reached by
|
|
walking down is listed from its own tree.
|
|
- [x] A ref containing `/` works: it is passed as a query parameter, never as a path segment.
|
|
- [x] When the ref moves, directory ids remembered for the old commit are dropped.
|
|
- [x] A directory whose tree id is not known (opened directly, not by walking down), or a ref the
|
|
commit lookup cannot resolve, is still listed through the contents endpoint.
|
|
- [x] Symbolic links (mode `120000`) and submodules (`commit`) keep their types.
|
|
- [x] Unit tests cover each of the above for the listing, and the split's clamp.
|
|
|
|
## How the listing works
|
|
|
|
A tree is addressed by its id, and a directory's id is only known from the listing of its parent.
|
|
|
|
1. Root: `GET commits?sha={ref}&limit=1&stat=false&files=false&verification=false` gives the
|
|
commit; `GET git/trees/{commit}` gives the root's entries.
|
|
2. Each listing remembers the id of every directory in it, keyed by repository, ref and path.
|
|
3. A subdirectory is listed with `GET git/trees/{remembered id}`.
|
|
4. Every listing of the root compares the commit with the one remembered. If it changed, all ids
|
|
remembered for that ref are dropped.
|
|
|
|
The remembered ids live in memory only, for the life of the process.
|
|
|
|
## Security and privacy
|
|
|
|
No additional concerns. The same authenticated transport and the same host are used; no new data
|
|
is stored, and nothing is logged.
|
|
|
|
## Required checks
|
|
|
|
```text
|
|
./gradlew compileDebugKotlin compileDebugUnitTestKotlin testDebugUnitTest assembleDebug lintDebug
|
|
```
|
|
|
|
## Evidence
|
|
|
|
- Required checks pass: 427 unit tests, 0 failures; lint 0 errors.
|
|
- Measured from a PC against the company Gitea 1.23.5, on a public repository, a directory of 30
|
|
entries: contents endpoint about 0.33 s, tree endpoint 0.04 to 0.06 s, commit lookup 0.05 s.
|
|
These are request times from a PC, not timings taken inside the app.
|
|
- Installed on the SM-F966N over wireless `adb`.
|
|
- Not verified by the implementer on the device: the gestures, the handle, the listing speed as
|
|
felt in the app, and the progress bar. No directory with more than 100 entries was opened, so
|
|
the progress bar has only been exercised by reasoning and by the paging unit test.
|
|
|
|
## Known limitations
|
|
|
|
- Opening a subdirectory costs one request; opening the root costs two (commit, then tree).
|
|
- A subdirectory opened after the ref moved, without the root being listed again, shows the tree
|
|
of the commit it was remembered from until the root is next listed.
|
|
- The tree endpoint gives no last-commit information per entry. The listing never showed any, so
|
|
nothing visible is lost.
|
|
|
|
## Review findings
|
|
|
|
None yet.
|