feat(tv): row actions on Files: VLC, watched toggle, trash or delete - #171
Conversation
Long-press Center or the Menu key on a Files row opens the oracle's actions dialog: Open in VLC hands the original stream URL to org.videolan.vlc, Mark as watched or unwatched writes the account's position through the new FilesWatchedRepository (only when the account keeps positions), and Move to trash or Delete permanently follows the confirmed Trash setting, confirms first, and runs the shared delete operation whose phases and verdict show above the rows. Every dialog returns focus to its row.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Live proof on the API 36 TV emulator,
Mark as unwatched read back 0 through |
There was a problem hiding this comment.
🟢 Approval recommended
The implementation matches the stated TV Files row-actions behavior and adds focused tests; only a minor unused-string cleanup was noted.
Pull request overview
Adds TV “row actions” parity to the Files screen by introducing a long-press/Menu-key action dialog and wiring it into the TV session, including VLC handoff, watched/unwatched toggling, and trash/delete flows consistent with the shared Files browser operation model.
Changes:
- Introduces
TvFilesActionsDialog/ delete confirmation dialog and row key handling (Menu + long-press) on TV Files rows. - Adds watched-position and original-stream-url dependencies to the TV session (
FilesWatchedRepository,FilesStreamUrls) and connects them from the TV app runtime. - Expands TV test coverage for menu actions, watched toggling behavior, and delete-status UI.
File summaries
| File | Description |
|---|---|
| README.md | Updates TV feature overview to mention Files row actions and delete status reporting. |
| docs/harness.md | Documents a concrete proof script/flow for the new TV Files actions oracle state. |
| app/src/tv/res/values/strings.xml | Adds strings for the TV Files actions UI and delete status/notice copy. |
| app/src/tv/kotlin/io/putdotio/android/tv/TvSessionViewModel.kt | Adds session APIs and state for watched toggling failures and original stream URL access. |
| app/src/tv/kotlin/io/putdotio/android/tv/files/TvFilesScreen.kt | Implements actions dialog state, focus return behavior, delete-status banner, and row Menu-key handling. |
| app/src/tv/kotlin/io/putdotio/android/tv/files/TvFilesActions.kt | Adds the TV actions model, dialogs, and VLC intent launcher. |
| app/src/tv/kotlin/io/putdotio/android/PutioApp.kt | Wires new repos into dependencies and connects Files screen callbacks for VLC + watched toggling + notices. |
| app/src/testTv/kotlin/io/putdotio/android/tv/TvSessionViewModelTest.kt | Adds tests for watched write behavior, failure reporting, and stream URL availability. |
| app/src/testTv/kotlin/io/putdotio/android/tv/files/TvFilesScreenTest.kt | Adds UI tests for Menu-key actions, delete confirmation, action availability rules, and delete-status UI. |
| app/src/main/kotlin/io/putdotio/android/files/FilesWatchedRepository.kt | Adds SDK-backed repository for watched position writes and stream URL provider types. |
Review details
- Files reviewed: 10/10 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fe265b100a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…ized watched writes The chosen trash mode is kept while the confirmation is up and a setting that changes underneath withdraws it; a failed delete reports only through its own status line; a media file without a position keeps its duration so it can be marked watched; a newer watched write supersedes an unfinished one.
There was a problem hiding this comment.
🔵 Needs a closer look
The VLC launch intent currently always uses FLAG_ACTIVITY_NEW_TASK, which can break expected back-stack behavior when launching from an Activity context.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
app/src/tv/kotlin/io/putdotio/android/tv/files/TvFilesActions.kt:116
launchVlcalways setsFLAG_ACTIVITY_NEW_TASK, which changes task/back-stack behavior when launching from an Activity context (e.g., Back from VLC may go Home instead of returning to the app). It’s safer to add this flag only when the providedContextisn’t anActivity(still avoiding the "Calling startActivity from outside of an Activity" crash for app-context calls).
- Files reviewed: 12/12 changed files
- Comments generated: 0 new
- Review effort level: Lite
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bdf60ad84b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
🟡 Changes recommended
There’s a race/cancellation correctness issue in TvSession.setWatched where an older cancelled job can still report results unless guarded, which can lead to stale UI/failure state.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
app/src/tv/kotlin/io/putdotio/android/tv/files/TvFilesActions.kt:10
- Unused import: FocusRequester isn’t referenced in this file (the dialog focus requester is provided as a lambda parameter), so this import is dead code and should be removed to keep the file clean.
- Files reviewed: 12/12 changed files
- Comments generated: 1
- Review effort level: Lite
There was a problem hiding this comment.
🔵 Needs a closer look
Deletion actions are enabled in some non-idle folder states despite the PR description stating they should be offered only when the folder is idle.
Review details
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
app/src/tv/kotlin/io/putdotio/android/tv/files/TvFilesScreen.kt:289
- The PR description says trash/delete should be offered only when the folder is idle, but the menu currently enables deletion whenever
canStartOperationis true (which includes some failed-operation states like failed refresh/sort). If the intent is to match the stated behavior, gate deletion actions onFilesFolderOperation.Idleinstead.
app/src/tv/kotlin/io/putdotio/android/tv/files/TvFilesScreen.kt:679 onActionsis documented as null when the row offers nothing beyond opening, but in the Files list every row is currently wired with a non-nullonActions(so even rows with no available actions can open a Cancel-only dialog). Either pass null for rows with no actions, or adjust this KDoc so it matches the actual contract (null disables the actions affordance).
- Files reviewed: 12/12 changed files
- Comments generated: 0 new
- Review effort level: Lite
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 492cabc7dc
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…confirmation closes when the folder gets busy
There was a problem hiding this comment.
🔵 Needs a closer look
There are a couple of correctness/quality issues to address (notably an unused import that can break strict builds, and a misleading KDoc contract that doesn’t match current call sites).
Review details
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
app/src/tv/kotlin/io/putdotio/android/tv/files/TvFilesActions.kt:10
- Unused import
FocusRequesterin this file; it isn’t referenced and can trigger unused-import checks in static analysis. Remove it to keep the file warning-free.
app/src/tv/kotlin/io/putdotio/android/tv/files/TvFilesScreen.kt:682 - The KDoc for
onActionssays it is null when the row offers nothing beyond opening, but the list always passes a non-null lambda (onActions = { onActions(item) }), even when the actions list is empty. Update the comment so it matches the actual contract (null disables actions; non-null opens the actions menu).
- Files reviewed: 12/12 changed files
- Comments generated: 0 new
- Review effort level: Lite
Part of #33 (Files long-press action menu, oracle
files-actionsstate). Needs putdotio/putio-sdk-kotlin#52 (merged as 2c61413).Problem
TV Files rows could only be opened. The oracle's Android baseline offers a long-press menu per row: VLC handoff with the original stream URL, Mark watched / unwatched, and Trash or Delete per the account's Trash setting. None of it existed on TV.
Solution
Long-press Center or the Menu key on a row opens
TvFilesActionsDialog(app/src/tv/.../tv/files/TvFilesActions.kt), a centred dialog titled with the file name, one full-width button per action, Cancel last, first action focused:/files/{id}/streamURL from the newFilesStreamUrlsgoes toorg.videolan.vlcasACTION_VIEWdata only. A dialog explains when VLC is not installed or no session token is set.use_start_fromis on; marking watched also needs a known duration):TvSession.setWatchedwrites the duration or clears the position through the newFilesWatchedRepository, then dispatchesPlaybackPositionReportedso the row updates. Failures show as a dismissible dialog; a 401 rejects the session.trash_enabledis known and the folder is idle): confirms with Cancel focused, then dispatches the sharedFilesBrowserEvent.Delete. The pane shows the operation's phases above the rows, Check status or Retry when it fails, and the fresh listing's verdict once settled.Dialog state is saveable per session and folder, closes when the row leaves the listing, and every close returns focus to the row.
Proof
./gradlew verify :buildSrc:test :app:assembleTvProductionDebug :app:assembleMobileProductionDebuggreen;TvFilesScreenTest(+3),TvSessionViewModelTest(+2).Live on the API 36 TV emulator with
devs-auto: Menu opened the actions on a video row; Mark as watched wrote the 10 s duration (files.getStartFrom→ 10) and the row read “100% watched”; Mark as unwatched read back 0; Open in VLC showed the not-installed dialog (no VLC on the emulator, so the handoff itself is unproven); Move to trash on a fixture text file confirmed, ran, reported “no longer in Files”, andtrash.listshows it. Captures follow in a comment.