Let a folder be starred, and put the starred ones on the home screen

The app bar of any folder now carries a star, and a starred folder appears in a Favourites section
on the home screen, above the libraries. Above, because it is the user's own list - and absent
entirely while empty, so someone opening the app for the first time still meets the libraries first,
which is the order they were given for a reason. The star in the row is the removal, which is what a
star means everywhere else: the mark that says "this is a favourite" is the thing you tap to stop it
being one. That avoids a long-press as well, and with it a destructive gesture nobody can see.

A favourite is a reference, not a copy: data/BookmarkStore keeps one path per row and nothing about
the folder's contents, so reading the whole list is one query and no filesystem work, which is what
makes it affordable on every visit to the home screen. It has its own SQLite database rather than a
table in the trash index - one table and three queries do not justify Room in a build that has no
annotation processor, and the two stores have nothing to say to each other. Two behaviours there are
decisions rather than defaults. A folder that has gone is kept and marked (Folder not found) instead
of being deleted: a card out of its slot and a folder deleted in another app are indistinguishable
from here, and silently forgetting someone's list because their SD card was out is the worse of the
two mistakes. And opening the row re-checks existence at that moment, because the flag is as old as
the screen - so the answer is a message rather than an empty listing, which would read as an empty
folder instead of a missing one.

Two smaller refusals came out of the same question. There is no star in a library or on the root
screen, because neither is a folder and there would be nothing to come back to: the distinction that
governs the new-folder button, and one the view model enforces too rather than trusting a stale
screen. And a bookmark has no undo, because Undo means "the last change to the filesystem the app
made" and a favourite is not one - the star is one tap to put back. The row's label comes from the
same place the breadcrumbs do, which is why a starred volume root reads as "Internal storage" rather
than as "0".

Sixteen tests: nine against real SQLite through Robolectric (round trip, ordering, starring twice
neither duplicating nor moving a row, and the same no-drop migration guard the trash index carries),
and seven through the view model (toggling, outliving the view model that added it, newest first,
the missing folder kept and marked, the missing folder refusing to open, and a library refusing to be
starred). 371 JVM tests, lint clean. Verified on the phone: the star appears only inside a folder and
flips from "Add to favourites" to "Remove from favourites" without leaving the screen; the home
screen lists the volume root above the libraries with its own label and its path underneath; the row
opens it with the star already filled; and the row's star takes the whole section away with a
snackbar. The documentation moved with it - CHANGELOG, ROADMAP (M15), README, COMPETITIVE_ANALYSIS
(that gap closes instead of joining the candidates), EDGE_CASE_TESTING, and the generated code map.
This commit is contained in:
2026-10-17 07:48:26 +02:00
parent ddae70a8bc
commit 0743bda29e
21 changed files with 831 additions and 32 deletions
+24
View File
@@ -232,6 +232,30 @@ Two things this session added to the tooling notes:
positions apart, which is also why the numbers quoted above come from a dump rather than from
memory.
## The favourites session (M15)
Driven on the Xiaomi phone, starring the volume root — the smallest thing that can be starred, and
the one where the label matters most, because its own name is `0`.
- **The star is offered exactly where it means something.** The app bar of the volume root shows it
as *Add to favourites* (four actions now: star, search, sort, more); the home screen and a library
show none, because neither is a folder. Tapping it flipped the description to *Remove from
favourites* without leaving the screen, which means the state came back out of SQLite rather than
out of the button.
- **The home screen puts it where it belongs.** Back at the root view, a **Favourites** section
appeared above *Libraries* with the volume's own label — *Internal storage*, not `0` — and
`/storage/emulated/0` underneath, which is the path the details sheet would show as well.
- **The row opens what it says.** Tapping it opened the volume with the star already filled.
- **The row's star is the removal.** Tapping it on the home screen took the whole section away and
said *Removed from favourites*; the libraries moved back to the top, which is the empty case a new
user sees.
- **Nothing was left behind.** No files were created for this pass and the one bookmark made was
removed through the UI, so the device is as it was found.
Deliberately not done on the device: a favourite whose folder disappears. The case is covered by two
JVM tests, and staging it would have meant deleting a folder on someone else's phone; the missing
row's wording and the message are the same strings those tests assert.
## Not verified, and why
- **Long-press multi-select via adb: it works, but not every time.** `input swipe x y x y 900`