Remember what is in the trash, and add a screen to restore from it

The staged-delete work left a hole. The undo handle lived in BrowserUiState, so a delete from an earlier session was unreachable even though the files were sitting on the volume; and because nothing on disk recorded which folder an item came from, not even the user could put one back by hand with confidence. Adding a Trash screen alone would not have fixed it: the recovery data did not survive the process. So the origin is now written at delete time.

data/ gains its first persistence: a SQLite index (staged path, original path, name, type, size, timestamp). SQLite rather than Room because an annotation processor is a large addition to this build for one table and three queries, and behind a TrashIndex port so domain/Trash keeps no Context while the tests drive it with a map and the real one is still tested against real SQLite. New Trash entry in the overflow menu lists batches and restores a whole one.

The index is an index, not the truth: the staged files are the truth, and the two can disagree if a user empties the folder by hand or pulls a card. Reconciled both ways - restorableFrom drops entries whose file has gone, purgeExpired forgets entries whose folder has gone and sweeps folders no entry mentions - and rows are written after the move, so a crash leaves an unindexed folder (harmless, swept) rather than an entry that could never restore. Verified on hardware: delete, force-stop, relaunch, restore.

Also corrects the docs where they claimed input swipe x y x y 900 is delivered as a plain tap on MIUI. It does open the selection bar - it was driven that way - but it has also landed as a tap, so it is flaky rather than impossible.
This commit is contained in:
2026-10-15 10:25:37 +02:00
parent d1bc61e717
commit 667a85f80c
16 changed files with 758 additions and 22 deletions
+6
View File
@@ -64,6 +64,12 @@
<string name="incoming_save_action">Save here</string>
<string name="incoming_pick_hint">Navigate to a file and tap it to hand it back</string>
<string name="incoming_cancel">Cancel</string>
<!-- ===== Trash ===== -->
<string name="trash_title">Trash</string>
<string name="trash_empty">Nothing in the trash</string>
<string name="trash_restore">Restore</string>
<string name="browser_action_trash">Trash</string>
<string name="browser_action_more">More options</string>
<string name="browser_action_refresh">Refresh</string>
<string name="browser_action_cancel">Cancel</string>