Skip to content

Add in-game screenshots#1627

Open
VinceBT wants to merge 1 commit into
utkarshdalal:masterfrom
VinceBT:feature/screenshots
Open

Add in-game screenshots#1627
VinceBT wants to merge 1 commit into
utkarshdalal:masterfrom
VinceBT:feature/screenshots

Conversation

@VinceBT

@VinceBT VinceBT commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Description

Adds in-app screenshots. While a game is running you can capture the current frame (bind a controller button for it, or trigger it from the quick menu). Capture goes through PixelCopy on the game surface, so overlays and the capture toast don't end up in the shot.

Each game gets a gallery to browse its shots, plus a fullscreen viewer with pinch zoom, pan, and full controller navigation (bumpers to flip between shots, sticks/buttons to zoom and pan). From the viewer you can open the shot in an external gallery app, save it to Downloads, share it, or delete it. The game detail page shows a small preview strip that links into the gallery.

Where they're stored is configurable in Settings: keep them in app storage, or point it at a folder you pick. Strings are localized across the existing locales.

Recording

Will add a short clip (capture → gallery → viewer/share) shortly — wanted to get the PR up first.

Type of Change

  • Bug fix
  • Performance / stability improvement
  • Compatibility improvements
  • Other (requires prior approval)

Flagging honestly: this is a new feature, so it's outside the default scope. Happy to take it to Discord first or drop it if it's not something you want in core.

Checklist

  • If I have access to #code-changes, I have discussed this change there and it has been green-lighted. If I do not have access, I have still provided clear context in this PR. If I skip both, I accept that this change may face delays in review, may not be reviewed at all, or may be closed.
  • This change aligns with the current project scope (core functionality, stability, or performance). If not, it has been explicitly approved beforehand.
  • I have attached a recording of the change.
  • I have read and agree to the contribution guidelines in CONTRIBUTING.md.

Summary by cubic

Adds in‑game screenshot capture with a per‑game gallery and a full‑screen viewer. Capture uses PixelCopy; you can choose storage, bind a controller shortcut, tap the “saved” toast to open the viewer, and open the gallery as an in‑game overlay without losing input.

  • New Features

    • Capture from the quick menu or a bindable controller combo (default: L1+R1+L3+R3); supports non‑standard buttons; new Screenshots quick‑menu tab; toast overlay opens the viewer.
    • Per‑game gallery and viewer with pinch‑zoom toward the finger centroid, pan, and full controller nav; overlays fade when zoomed; header includes bulk delete; focus ring + initial focus; deep‑link via PluviaScreen.ScreenshotGallery (optional index to jump to a shot); returns to the game when closed.
    • Share, open, export to Downloads, or delete; preview strip and quick action in the game detail/options pane; Settings > Screenshots lets you choose internal vs external storage and bind the combo; storage via ScreenshotManager + ScreenshotStore (unit‑tested).
  • Bug Fixes

    • Storage/export: sanitize appId; case‑insensitive PNG handling; atomic filename claims; prune share cache; handle bitmap OOM and always recycle; on Android Q+ delete failed MediaStore rows; on pre‑Q request WRITE_EXTERNAL_STORAGE and resume export.
    • Input/focus: track combo keys by deviceId; refresh binding on new presses; clear held keys (incl. SHOW_KEYBOARD) when menus/overlays open or on pause; preserve library selection when returning from sub‑screens; deep‑linked opens navigate correctly.
    • Viewer/UI: fix pinch‑zoom pan and clamp to viewport; only ellipsize the InfoCard label when the chevron is shown; rebind renderer view on screen changes to keep input/rendering stable.

Written for commit cdaa1fb. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added a Screenshots feature across settings and game menus, including internal/external storage selection, folder picking, and controller shortcut binding.
    • Added quick access to capture, view previews, and open a dedicated gallery/viewer with open, share, export to Downloads, and delete (single + bulk).
    • Added toast notifications for successful captures and enhanced screenshot viewing with zoom/pan and controller support.
  • Bug Fixes
    • Improved focus, selection, and back-navigation behavior across library and tabs; preserved library selection when returning from sub-screens.
    • Prevented controller “screenshot combo” getting stuck by resetting held keys when menus are open.

@VinceBT VinceBT requested a review from utkarshdalal as a code owner June 26, 2026 20:37
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds screenshot capture, gallery viewing, controller binding, library and settings entry points, and localized strings across the app.

Changes

Screenshots feature rollout

Layer / File(s) Summary
Storage model
app/src/main/java/app/gamenative/PrefManager.kt, app/src/main/java/app/gamenative/utils/ScreenshotStore.kt, app/src/main/res/xml/file_provider_paths.xml, app/src/test/java/app/gamenative/utils/ScreenshotStoreTest.kt
PrefManager adds screenshot storage settings, ScreenshotStore adds filesystem helpers, FileProvider exposes screenshots/, and store behavior is covered by tests.
Capture and notifications
app/src/main/java/app/gamenative/utils/ScreenshotManager.kt, app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt, app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt, app/src/main/java/app/gamenative/ui/util/ScreenshotNotificationManager.kt, app/src/main/java/app/gamenative/ui/component/ScreenshotToastOverlay.kt, app/src/main/java/app/gamenative/ui/PluviaMain.kt
ScreenshotManager captures, deletes, exports, and opens screenshots; PhysicalControllerHandler and XServerScreen trigger capture; and the toast overlay renders saved screenshots in the main UI stack.
Gallery route and viewer
app/src/main/java/app/gamenative/ui/screen/PluviaScreen.kt, app/src/main/java/app/gamenative/ui/PluviaMain.kt, app/src/main/java/app/gamenative/ui/screen/screenshots/*, app/src/main/java/app/gamenative/ui/component/GamepadInputView.kt
PluviaScreen and PluviaMain register the screenshot gallery destination, and the gallery/viewer screens handle paging, deletion, and image interaction.
Shared UI and quick menu
app/src/main/java/app/gamenative/ui/component/AccentActionRow.kt, app/src/main/java/app/gamenative/ui/component/FocusRing.kt, app/src/main/java/app/gamenative/ui/component/InfoCard.kt, app/src/main/java/app/gamenative/ui/component/RememberScreenshots.kt, app/src/main/java/app/gamenative/ui/component/ScreenshotsPreviewStrip.kt, app/src/main/java/app/gamenative/ui/component/ScreenshotsQuickMenuTab.kt, app/src/main/java/app/gamenative/ui/component/QuickMenu.kt, app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt
Shared focus-aware components are added, the quick menu gains a screenshots tab, and the screen effects reset row uses the new accent action row.
Library and settings wiring
app/src/main/java/app/gamenative/ui/enums/AppOptionMenuType.kt, app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt, app/src/main/java/app/gamenative/ui/screen/library/components/GameOptionsPanel.kt, app/src/main/java/app/gamenative/ui/screen/library/components/LibraryDetailPane.kt, app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt, app/src/main/java/app/gamenative/ui/screen/library/LibraryScreen.kt, app/src/main/java/app/gamenative/ui/screen/downloads/DownloadsScreen.kt, app/src/main/java/app/gamenative/ui/screen/HomeScreen.kt, app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupScreenshots.kt, app/src/main/java/app/gamenative/ui/screen/settings/SettingsScreen.kt, app/src/main/java/app/gamenative/ui/component/dialog/ScreenshotControllerBindDialog.kt
Library menus and detail screens add a screenshots option, the selected app is persisted, downloads pass navigation through, the settings screen adds a screenshots section for storage selection and controller binding, and the bind dialog reads and writes the saved combo.
Localized strings
app/src/main/res/values/strings.xml, app/src/main/res/values-*/strings.xml
New screenshot labels and messages are added for the base app strings and translated resource files.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • utkarshdalal/GameNative#342: Both PRs modify app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt, with the main PR extending it to support the screenshot key-combo trigger and held-key reset logic.
  • utkarshdalal/GameNative#422: Both PRs touch the Android Romanian translations (app/src/main/res/values-ro/strings.xml).
  • utkarshdalal/GameNative#667: Main PR’s screenshots feature extends the QuickMenu and related library UI wiring introduced in PR #667.
  • utkarshdalal/GameNative#697: Both PRs touch PluviaMain.kt to change the app’s transient notification UI layer.

Suggested reviewers

  • phobos665
  • morganwalkup
  • utkarshdalal

Poem

Hop hop, I tucked each snapshot in a row,
Then watched the little toast say “saved!” so bright.
My paws tapped combos, quick as morning dew,
Through menus and galleries I bounded right.
🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding in-game screenshots.
Description check ✅ Passed The description follows the template and covers the change, type, and checklist, but the recording is still only promised, not attached.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

8 issues found across 46 files

Note: This PR contains a large number of files. cubic only reviews up to 40 files per PR, so some files may not have been reviewed. cubic prioritizes the most important files to review.
On a pro plan you can use ultrareview for larger PRs.

Re-trigger cubic

Comment thread app/src/main/java/app/gamenative/utils/ScreenshotStore.kt Outdated
Comment thread app/src/main/java/app/gamenative/ui/component/RememberScreenshots.kt Outdated
Comment thread app/src/main/res/values-es/strings.xml Outdated
Comment thread app/src/main/res/values-ro/strings.xml Outdated
Comment thread app/src/main/res/values-it/strings.xml Outdated
Comment thread app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/java/app/gamenative/ui/component/QuickMenu.kt (1)

716-733: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

No initial focus when the Screenshots tab is the active tab.

QuickMenuTab.SCREENSHOTS isn't handled here, so it falls into else -> controllerItemFocusRequester.requestFocus(). That requester is only attached in the controller content branch (Line 694), which isn't composed while ScreenshotsQuickMenuTab is shown. The call throws IllegalStateException (FocusRequester not initialized), is swallowed by the catch, retried 3×, then gives up — leaving the screenshots tab with no initial focus for D-pad/controller navigation. Since selectedTab is persisted via PrefManager.quickMenuLastTab, reopening the menu on this tab reproduces it.

Consider adding a dedicated focus requester wired into ScreenshotsQuickMenuTab and a branch here, e.g.:

                     when (selectedTab) {
                         QuickMenuTab.HUD -> hudItemFocusRequester.requestFocus()
                         QuickMenuTab.LSFG -> lsfgItemFocusRequester.requestFocus()
                         QuickMenuTab.EFFECTS -> effectsItemFocusRequester.requestFocus()
                         QuickMenuTab.TOOLS -> toolsItemFocusRequester.requestFocus()
+                        QuickMenuTab.SCREENSHOTS -> screenshotsItemFocusRequester.requestFocus()
                         else -> controllerItemFocusRequester.requestFocus()
                     }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@app/src/main/java/app/gamenative/ui/component/QuickMenu.kt` around lines 716
- 733, The initial focus logic in LaunchedEffect(isVisible) does not handle
QuickMenuTab.SCREENSHOTS, so it incorrectly falls back to
controllerItemFocusRequester and fails when ScreenshotsQuickMenuTab is composed.
Add a dedicated focus requester for the screenshots tab, attach it to the
ScreenshotsQuickMenuTab branch, and extend the selectedTab when block to request
that focus explicitly instead of using the controller fallback.
🧹 Nitpick comments (1)
app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt (1)

84-91: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

pressedKeyCodes can leak stale held-keys across focus changes.

If an ACTION_UP is never delivered (e.g., the window loses focus while a combo button is held), that keycode stays in pressedKeyCodes, which can cause the combo to fire spuriously or fail to re-arm later. Consider clearing pressedKeyCodes (and resetting screenshotComboFired) in cleanup() and/or setProfile() so the combo state can't wedge.

Also applies to: 98-106

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt`
around lines 84 - 91, The cleanup path in PhysicalControllerHandler is leaving
combo key state behind, which can wedge later input handling. Update cleanup()
and/or setProfile() so pressedKeyCodes is cleared and screenshotComboFired is
reset whenever focus/profile changes, alongside the existing
releaseActiveAxes(), mouseMoveTimer, and clearScrollRepeats() resets. Make sure
the combo state is fully re-armed after loss of focus so stale held keys cannot
survive across sessions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/src/main/java/app/gamenative/utils/ScreenshotManager.kt`:
- Around line 142-157: The Q+ branch in ScreenshotManager’s MediaStore save flow
leaves a pending Downloads row behind if resolver.openOutputStream or
item.file.inputStream().copyTo fails after resolver.insert succeeds. Update the
logic around the insert/update block in ScreenshotManager to clean up the
inserted uri on failure by catching exceptions or using a finally path that
deletes the row when the copy does not complete, while still preserving the
existing IS_PENDING=0 update on success.
- Around line 158-172: The pre-Q Downloads export path in ScreenshotManager is
writing directly via FileOutputStream without first ensuring storage permission
is granted, so add a permission request/check before entering this branch for
API 26–28. Update the export flow around the Downloads handling in
ScreenshotManager so it requests WRITE_EXTERNAL_STORAGE before creating the
destination file, and only proceeds with the copy once permission is approved.
Keep the existing de-duplication and file creation logic intact after the
permission gate.

---

Outside diff comments:
In `@app/src/main/java/app/gamenative/ui/component/QuickMenu.kt`:
- Around line 716-733: The initial focus logic in LaunchedEffect(isVisible) does
not handle QuickMenuTab.SCREENSHOTS, so it incorrectly falls back to
controllerItemFocusRequester and fails when ScreenshotsQuickMenuTab is composed.
Add a dedicated focus requester for the screenshots tab, attach it to the
ScreenshotsQuickMenuTab branch, and extend the selectedTab when block to request
that focus explicitly instead of using the controller fallback.

---

Nitpick comments:
In
`@app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt`:
- Around line 84-91: The cleanup path in PhysicalControllerHandler is leaving
combo key state behind, which can wedge later input handling. Update cleanup()
and/or setProfile() so pressedKeyCodes is cleared and screenshotComboFired is
reset whenever focus/profile changes, alongside the existing
releaseActiveAxes(), mouseMoveTimer, and clearScrollRepeats() resets. Make sure
the combo state is fully re-armed after loss of focus so stale held keys cannot
survive across sessions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 10a0443a-9cdd-42c3-a3b9-d6473cafd469

📥 Commits

Reviewing files that changed from the base of the PR and between 82fc5b2 and 90f5dfb.

📒 Files selected for processing (46)
  • app/src/main/java/app/gamenative/PrefManager.kt
  • app/src/main/java/app/gamenative/ui/PluviaMain.kt
  • app/src/main/java/app/gamenative/ui/component/AccentActionRow.kt
  • app/src/main/java/app/gamenative/ui/component/FocusRing.kt
  • app/src/main/java/app/gamenative/ui/component/GamepadInputView.kt
  • app/src/main/java/app/gamenative/ui/component/InfoCard.kt
  • app/src/main/java/app/gamenative/ui/component/QuickMenu.kt
  • app/src/main/java/app/gamenative/ui/component/RememberScreenshots.kt
  • app/src/main/java/app/gamenative/ui/component/ScreenEffectsPanel.kt
  • app/src/main/java/app/gamenative/ui/component/ScreenshotToastOverlay.kt
  • app/src/main/java/app/gamenative/ui/component/ScreenshotsPreviewStrip.kt
  • app/src/main/java/app/gamenative/ui/component/ScreenshotsQuickMenuTab.kt
  • app/src/main/java/app/gamenative/ui/component/dialog/ScreenshotControllerBindDialog.kt
  • app/src/main/java/app/gamenative/ui/enums/AppOptionMenuType.kt
  • app/src/main/java/app/gamenative/ui/screen/PluviaScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/LibraryScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/components/GameOptionsPanel.kt
  • app/src/main/java/app/gamenative/ui/screen/library/components/LibraryDetailPane.kt
  • app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotGalleryScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotViewer.kt
  • app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupScreenshots.kt
  • app/src/main/java/app/gamenative/ui/screen/settings/SettingsScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/java/app/gamenative/ui/util/ScreenshotNotificationManager.kt
  • app/src/main/java/app/gamenative/utils/ScreenshotManager.kt
  • app/src/main/java/app/gamenative/utils/ScreenshotStore.kt
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-ja/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values/strings.xml
  • app/src/main/res/xml/file_provider_paths.xml
  • app/src/test/java/app/gamenative/utils/ScreenshotStoreTest.kt

Comment thread app/src/main/java/app/gamenative/utils/ScreenshotManager.kt Outdated
Comment thread app/src/main/java/app/gamenative/utils/ScreenshotManager.kt
VinceBT added a commit to VinceBT/GameNative that referenced this pull request Jun 26, 2026
P1:
- Sanitize appId in ScreenshotStore.gameDir to prevent path traversal
- Guard rememberScreenshots listing against I/O/SecurityException crashes
- Make LibraryDetailPane.onNavigateRoute required and wire it through the
  Downloads screen so screenshot taps work there

P2:
- Scope screenshot combo key tracking by deviceId so keys from different
  controllers can't falsely combine; refresh the combo on each fresh press
  so a mid-session rebind takes effect
- Convert screenshots_deleted_all to a <plurals> resource across all locales
  (one/few/other as the language requires) and use getQuantityString

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

2 issues found across 23 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread app/src/main/res/values-pl/strings.xml
Comment thread app/src/main/res/values-uk/strings.xml
VinceBT added a commit to VinceBT/GameNative that referenced this pull request Jun 26, 2026
…ed_all

Provide the full Slavic one/few/many/other plural forms instead of an
other-only fallback, so deletion counts are grammatically correct
(cubic review on PR utkarshdalal#1627).

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt`:
- Around line 99-108: Reset the keyboard latch in
PhysicalControllerHandler.resetPressedKeys() as well as the screenshot state.
This helper already clears pressedKeyCodesByDevice and screenshotComboFired when
input forwarding stops, so also clear showKeyboardPressed here to avoid leaving
the SHOW_KEYBOARD binding latched true after focus changes; use the existing
resetPressedKeys() method and the showKeyboardPressed field to locate the
change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: eec1bfe2-d7a9-4217-92a5-8c900d213b86

📥 Commits

Reviewing files that changed from the base of the PR and between 471d6d1 and ac7f21f.

📒 Files selected for processing (9)
  • app/src/main/java/app/gamenative/ui/component/AccentActionRow.kt
  • app/src/main/java/app/gamenative/ui/component/QuickMenu.kt
  • app/src/main/java/app/gamenative/ui/component/ScreenshotsQuickMenuTab.kt
  • app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotViewer.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/PhysicalControllerHandler.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt
  • app/src/main/java/app/gamenative/utils/ScreenshotManager.kt
  • app/src/main/java/app/gamenative/utils/ScreenshotStore.kt
  • app/src/test/java/app/gamenative/utils/ScreenshotStoreTest.kt
🚧 Files skipped from review as they are similar to previous changes (7)
  • app/src/main/java/app/gamenative/ui/component/AccentActionRow.kt
  • app/src/main/java/app/gamenative/utils/ScreenshotStore.kt
  • app/src/main/java/app/gamenative/ui/component/ScreenshotsQuickMenuTab.kt
  • app/src/main/java/app/gamenative/ui/component/QuickMenu.kt
  • app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotViewer.kt
  • app/src/main/java/app/gamenative/utils/ScreenshotManager.kt
  • app/src/main/java/app/gamenative/ui/screen/xserver/XServerScreen.kt

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 9 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

VinceBT added a commit to VinceBT/GameNative that referenced this pull request Jun 27, 2026
showKeyboardPressed has the same lifetime as the screenshot combo state:
if the keyboard binding is held when a menu/editor steals focus, its
ACTION_UP is routed away and the latch stays true, so the next
SHOW_KEYBOARD press is ignored. Reset it alongside the combo state.

Addresses PR utkarshdalal#1627 review feedback.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

3 issues found across 14 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotViewer.kt">

<violation number="1" location="app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotViewer.kt:367">
P2: Duplicated hardcoded scrim color literal `Color(0x88000000)`. This same value is used on the bottom toolbar as well. Move it to a named constant in the theme (e.g., `val ScreenshotScrim = Color(0x88000000)`) and reference it from both locations to prevent drift.</violation>
</file>

<file name="app/src/main/java/app/gamenative/ui/component/InfoCard.kt">

<violation number="1" location="app/src/main/java/app/gamenative/ui/component/InfoCard.kt:92">
P2: Label Text in the header Row lacks width constraints and overflow handling, risking clipped or unstable layout with localized text.</violation>
</file>

<file name="app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotGalleryScreen.kt">

<violation number="1" location="app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotGalleryScreen.kt:137">
P2: FocusRequester.requestFocus() returns Boolean indicating success or cancellation, but the return value is ignored. didInitialFocus is set to true unconditionally and the coroutine returns immediately, so if the request is canceled (returns false) the screen will never retry and may enter with no focused element, breaking controller/D-pad navigation.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotViewer.kt Outdated
Comment thread app/src/main/java/app/gamenative/ui/component/InfoCard.kt
Comment thread app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotGalleryScreen.kt Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotGalleryScreen.kt">

<violation number="1" location="app/src/main/java/app/gamenative/ui/screen/screenshots/ScreenshotGalleryScreen.kt:137">
P2: FocusRequester.requestFocus() returns Boolean indicating success or cancellation, but the return value is ignored. didInitialFocus is set to true unconditionally and the coroutine returns immediately, so if the request is canceled (returns false) the screen will never retry and may enter with no focused element, breaking controller/D-pad navigation.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread app/src/main/java/app/gamenative/ui/component/InfoCard.kt Outdated
@VinceBT VinceBT force-pushed the feature/screenshots branch from 43e38ef to c6c1354 Compare July 2, 2026 09:03
VinceBT added a commit to VinceBT/GameNative that referenced this pull request Jul 2, 2026
P1:
- Sanitize appId in ScreenshotStore.gameDir to prevent path traversal
- Guard rememberScreenshots listing against I/O/SecurityException crashes
- Make LibraryDetailPane.onNavigateRoute required and wire it through the
  Downloads screen so screenshot taps work there

P2:
- Scope screenshot combo key tracking by deviceId so keys from different
  controllers can't falsely combine; refresh the combo on each fresh press
  so a mid-session rebind takes effect
- Convert screenshots_deleted_all to a <plurals> resource across all locales
  (one/few/other as the language requires) and use getQuantityString
VinceBT added a commit to VinceBT/GameNative that referenced this pull request Jul 2, 2026
…ed_all

Provide the full Slavic one/few/many/other plural forms instead of an
other-only fallback, so deletion counts are grammatically correct
(cubic review on PR utkarshdalal#1627).
VinceBT added a commit to VinceBT/GameNative that referenced this pull request Jul 2, 2026
showKeyboardPressed has the same lifetime as the screenshot combo state:
if the keyboard binding is held when a menu/editor steals focus, its
ACTION_UP is routed away and the latch stays true, so the next
SHOW_KEYBOARD press is ignored. Reset it alongside the combo state.

Addresses PR utkarshdalal#1627 review feedback.
@VinceBT VinceBT force-pushed the feature/screenshots branch from 0d276fa to ca87d0b Compare July 7, 2026 21:20
@VinceBT VinceBT force-pushed the feature/screenshots branch from ca87d0b to cdaa1fb Compare July 7, 2026 21:47
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.

1 participant