Skip to content

feat(files): remember the Move and Copy target folder on the device - #277

Merged
altaywtf merged 3 commits into
mainfrom
feat/remember-target-folder
Oct 1, 2026
Merged

altaywtf merged 3 commits into
mainfrom
feat/remember-target-folder

Conversation

@altaywtf

@altaywtf altaywtf commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Change

The mobile Move and Make a copy picker gains web's "Remember target folder" toggle, off by default, so the next picker opens at the last chosen folder.

Toggle on, Move here Next Move opens there
Move picker with the toggle on Move picker reopened at the remembered folder
  • Stored per account on the device and cleared on sign-out or session expiry; an unreadable folder opens the picker at root.
  • A remembered folder nested deeper inside the item being moved isn't caught before the request goes out.
  • Risk: if the clear fails, the same account sees its old folder after signing in again.

Closes #276

Validation

  • ./gradlew verify and the debug assembles in CI
  • MobileMoveTargetProofTest on putio-phone, synthetic (screenshots)

Written by an agent (Claude Code, Opus 5.5)

Web's folder picker has a "Remember target folder" toggle for Move and Make
a copy, kept in web's own /config. Android always opened at root.

The mobile picker now shows the toggle, off by default. On, Move here or Copy
here records the chosen folder's path, and the next picker opens there; Back
reads each ancestor as it reaches it. A remembered folder that can't be read
reopens at root, one moved since keeps only root above it, and a move never
opens inside the item it moves.

Both values live in private SharedPreferences per signed-in account, and the
auth controller's local-session cleanup clears them on sign-out or an expired
session. TV has no Move picker.

Closes #276
…older

MobileMoveTargetProofTest drives the production Files route, controller and on-device store over a faked repository. FilesMoveRecoveryUiProofTest follows complete() now returning a transition.
Copilot AI balanced review requested due to automatic review settings October 1, 2026 07:02
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@altaywtf

altaywtf commented Oct 1, 2026

Copy link
Copy Markdown
Member Author

MobileMoveTargetProofTest ran on putio-phone (API 37) at 29f658b: OK (1 test). This is synthetic proof. The production Files route, controller, picker and on-device SharedPreferences store run over a faked repository, with no API calls.

  • 1: Move opens at root with the toggle off.
  • 2–3: with the toggle on, Move here into "Sample folder / Archive été 東京", and the next Move opens there.
  • 4: Back reads "Sample folder".
  • 5: Make a copy opens at the same folder.
  • 6: after the sign-out cleanup, the picker is at root with the toggle off.
  • 7: a remembered folder that can't be read opens at root.

Not covered: a real sign-out on the device (the emulator app has no live sign-in). The unit tests cover the cleanup call.

Written by an agent (Claude Code, Opus 5.5).

01-move-default-root

02-remember-on-chosen-folder

03-move-reopens-at-remembered

04-back-reads-parent

05-copy-reopens-at-remembered

06-after-sign-out-root

07-missing-folder-root

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🔵 Needs a closer look

It makes intricate, interdependent changes to the core move/copy picker state machine, per-account persistence, and auth session cleanup that warrant final human review despite the thorough test coverage.

Review effort: Balanced
Findings: None

What changed in this PR

This PR ports put.io web's "Remember target folder" toggle to the mobile Move and Make-a-copy folder picker (closing #276). When enabled, the picker reopens at the folder last chosen, lazily reading each ancestor as the user walks Back toward root, with graceful fallbacks when the remembered folder was deleted, moved, or renamed. The setting is persisted per signed-in account in private SharedPreferences and cleared on sign-out or session expiry. TV is unaffected (it has no Move picker).

Changes:

  • New FilesMoveTargetMemory domain model plus a FilesMoveTargetStore interface, with the move-destination state machine extended to open at a remembered path (opensRememberedTarget, completeRememberedTarget, lazy loadUnreadFolder, controller startPath).
  • Mobile UI toggle in MobileFilesMoveDestination, wiring in MobileFilesRoute/MobileNavigation, and on-device persistence via MobileMoveTargetStore.
  • Per-account cleanup hooked into MobileAuthController/MobileOAuthRuntime, plus extensive unit/UI/synthetic-proof tests and behavior.md/harness.md documentation.
File Description
app/​src/​main/​kotlin/​io/​putdotio/​android/​files/​FilesMoveTargetMemory.kt New model + store interface; startPath/chosen encode the remember rules.
app/​src/​main/​kotlin/​io/​putdotio/​android/​files/​FilesMoveDestinationState.kt complete() now returns a transition; adds remembered-target dispatch and lazy ancestor loading.
app/​src/​main/​kotlin/​io/​putdotio/​android/​files/​FilesMoveDestinationStart.kt Remembered-target completion: root fallback, current-name refresh, moved-folder handling.
app/​src/​main/​kotlin/​io/​putdotio/​android/​files/​FilesMoveDestinationController.kt Accepts startPath, builds unread-ancestor stack, chains follow-up requests on completion.
app/​src/​mobile/​kotlin/​io/​putdotio/​android/​files/​MobileMoveTargetStore.kt Per-account SharedPreferences JSON store with clearAll and damaged-record fallback.
app/​src/​mobile/​kotlin/​io/​putdotio/​android/​files/​MobileFilesRoute.kt Reads/writes memory per picker, passes startPath, wires toggle callbacks.
app/​src/​mobile/​kotlin/​io/​putdotio/​android/​files/​MobileFilesMoveDestination.kt Adds the "Remember target folder" switch row with accessible toggleable semantics.
app/​src/​mobile/​kotlin/​io/​putdotio/​android/​MobileNavigation.kt Constructs the account-scoped MobileMoveTargetStore and passes it to the route.
app/​src/​mobile/​kotlin/​io/​putdotio/​android/​auth/​MobileAuthController.kt Adds clearAccountLocalState, invoked in clearLocalSession.
app/​src/​mobile/​kotlin/​io/​putdotio/​android/​auth/​MobileOAuthRuntime.kt Wires cleanup to MobileMoveTargetStore.clearAll.
app/​src/​mobile/​res/​values/​strings.xml New mobile_files_move_remember_target string.
app/​src/​test/​.../​FilesMoveTargetMemoryTest.kt, FilesMoveDestinationControllerTest.kt Unit coverage for memory rules and controller navigation/fallbacks.
app/​src/​testMobile/​.../​MobileMoveTargetStoreTest.kt, InMemoryMoveTargetStore.kt, MobileFilesMoveTest.kt, MobileFilesCopyTest.kt, MobileAuthControllerTest.kt Store, UI, and sign-out-cleanup coverage.
app/​src/​androidTestMobile/​.../​MobileMoveTargetProofTest.kt, FilesMoveRecoveryUiProofTest.kt New synthetic device proof; recovery proof updated for the new complete() return type.
docs/​behavior.md, docs/​harness.md Documents the new behavior and proof lane.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Keep a rejected session visible instead of falling back to root, take a
remembered ancestor's current name and place when Back reads it, and
reopen at root when a remembered folder now sits directly inside the
item being moved.
@altaywtf

altaywtf commented Oct 1, 2026

Copy link
Copy Markdown
Member Author

Local review (slopguard, Codex gpt-6.1-sol, high): 4 findings on the first pass, 3 fixed and 1 partly fixed in 2fc01cf. The re-review of 2fc01cf raised 2 more, both rejected.

  • Fixed: a rejected session while opening a remembered folder now shows as a session failure instead of falling back to root.
  • Fixed: Back now checks each remembered ancestor when it first reads it (current name; if it moved, only root stays above it).
  • Fixed: added coverage for Copy here recording the folder the next picker opens at.
  • Partly fixed: a remembered folder whose parent is now the item being moved opens at root. Rejected on re-review: a full ancestry check for deeper nesting. It needs breadcrumbs that the app's files repository doesn't expose, so docs/behavior.md now names the gap.
  • Rejected: root fallback when a remembered ancestor fails to read on Back. That failure keeps Retry and Back. An ancestor can't be missing while its remembered descendant still reads, and the contract's fallback covers the remembered folder itself.

Negative control: with the fixes reverted, exactly the 4 new tests fail.

Written by an agent (Claude Code, Opus 5.5).

@altaywtf
altaywtf merged commit 4d42152 into main Oct 1, 2026
1 check passed
@altaywtf
altaywtf deleted the feat/remember-target-folder branch October 1, 2026 07:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

files: remember the Move and Copy target folder

2 participants