Skip to content

feat: show Steam cloud save status#1383

Open
kiequoo wants to merge 4 commits into
utkarshdalal:masterfrom
kiequoo:feat/steam-cloud-save-status
Open

feat: show Steam cloud save status#1383
kiequoo wants to merge 4 commits into
utkarshdalal:masterfrom
kiequoo:feat/steam-cloud-save-status

Conversation

@kiequoo
Copy link
Copy Markdown
Contributor

@kiequoo kiequoo commented May 6, 2026

Description

Adds the cloud save status UI and sync controls for Steam games.

This comes from the broader cloud saves status indicator work originally developed on feat/cloud-saves-game-info. This PR intentionally narrows the scope to Steam only for now, so the Steam status UI and service behavior can be reviewed independently.

What this PR includes:

  • Adds CloudSaveStatus state used by the library UI.
  • Tracks active Steam cloud operations in SteamService.
  • Refactors Steam Auto-Cloud helpers so status snapshots and sync phase updates can be reported cleanly.
  • Shows Steam cloud save status on the app screen.
  • Adds a force-sync action for Steam cloud saves.
  • Emits Android events when Steam cloud save status changes or is invalidated.

The commits are best reviewed separately: the first refactors Steam Auto-Cloud helpers, the second adds the Steam cloud save status UI/service wiring, and the third preserves returning to the app info screen after closing a game.

What this PR intentionally does not include:

  • Cloud save status UI for other stores.
  • Cross-platform conflict dialog work.

Those can follow separately after this Steam-only version is reviewed.

Screenshots

Screenshot_20260506-192547
Screenshot_20260506-192522
Screenshot_20260506-192505

Type of Change

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

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 Steam-only cloud save status and controls to the game info screen with live updates, conflict handling, and a force-sync action. Refactors Auto-Cloud to expose a reusable sync snapshot and emit status events.

  • New Features

    • Shows Steam cloud status on the app screen: checking, downloading/uploading, pending download/upload, pending operations, up to date, conflict, offline, failed.
    • Live updates via AndroidEvent.CloudStatusChanged; resolves status on load using service logic; conflict dialog shows local/remote timestamps and upgrade text when available.
    • Force sync for Steam saves (auto/local/remote) via SteamService.launchForceSync().
    • UI gated by SteamApp.supportsCloudSaves and hidden for local-saves-only containers; keeps you on the game info screen after closing a game.
  • Refactors

    • Extracts path mapping, local scanning, diffing, and remote-change decisions from SteamAutoCloud.syncUserFiles() into helpers and fetchSyncSnapshot, reused by SteamService.resolveCloudSaveStatus().
    • Adds CloudSaveStatus model and display strings; SteamApp.supportsCloudSaves to gate UI; new AndroidEvent.CloudStatusChanged.
    • Adds SteamService helpers for status resolution, active phase markers (start/finish), in-progress status queries, and a launchForceSync() entry point.

Written for commit 461d370. Summary will update on new commits.

Summary by CodeRabbit

  • New Features
    • Per-game cloud-save detection and detailed statuses surfaced (checking, downloading, uploading, up-to-date, pending, failed, conflict, offline) with localized labels.
    • Real-time sync phase reporting in library and game screens, manual "Force Sync" action, and conflict-resolution dialog showing timestamps/version.
  • Bug Fixes
    • Library selection now persists correctly across process recreation.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

Adds end-to-end cloud-save support: CloudSaveStatus type and strings, CloudPathResolver and phase callbacks in SteamAutoCloud, SteamService per-app status tracking and public APIs, UI components/wiring (status/action/conflict), and small data/schema and selection-state updates.

Changes

Cloud Save Synchronization

Layer / File(s) Summary
Data Shape / Resources
app/src/main/java/app/gamenative/data/SteamApp.kt, app/src/main/java/app/gamenative/ui/data/CloudSaveStatus.kt, app/src/main/java/app/gamenative/ui/data/GameDisplayInfo.kt, app/src/main/res/values/strings.xml
Adds SteamApp.supportsCloudSaves; new CloudSaveStatus enum + display mapping; GameDisplayInfo gains nullable cloud fields; adds multiple cloud_saves_* string resources and localized entries.
Events
app/src/main/java/app/gamenative/events/AndroidEvent.kt
Adds AndroidEvent.CloudStatusChanged(appId, status) and imports CloudSaveStatus.
Core Cloud Logic / Refactor
app/src/main/java/app/gamenative/service/SteamAutoCloud.kt
Introduces CloudPathResolver, centralizes prefix→path mapping and user-file conversion, updates local discovery and remote-change decision to use resolver, passes resolver functions into download/upload helpers, and adds onPhaseStarted callback to syncUserFiles.
Service-level Tracking & APIs
app/src/main/java/app/gamenative/service/SteamService.kt
Adds cloudSyncStatuses map, CloudSaveStatusResolution, isSyncInProgress/getActiveCloudSyncStatus, markCloudSyncStarted/markCloudSyncFinished, resolveCloudSaveStatus, buildPrefixToPath, and launchForceSync; integrates onPhaseStarted into flows and ensures final cleanup signaling.
UI Wiring & Components
app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt
Adds CloudSaveStatusRow, CloudSaveActionButton, CloudSaveConflictDialog, extends AppScreenContent with onForceCloudSync, and conditionally shows cloud status/actions in the action bar.
App Screen Classes
.../appscreen/BaseAppScreen.kt, .../appscreen/SteamAppScreen.kt
BaseAppScreen adds overridable getForceCloudSync hook; SteamAppScreen subscribes to cloud events, maintains sync UI state, fills GameDisplayInfo cloud fields, and implements getForceCloudSync to call SteamService.launchForceSync.
Library Screen UX state
app/src/main/java/app/gamenative/ui/screen/library/LibraryScreen.kt
Persist selectedAppId via rememberSaveable, derive currentSelectedLibraryItem, add BackHandler/LaunchedEffect to synchronize selection state and update handlers.

Sequence Diagram

sequenceDiagram
    participant UI as LibraryAppScreen
    participant Event as AndroidEventBus
    participant Service as SteamService
    participant Cloud as SteamAutoCloud
    participant Storage as SteamCloudStorage

    UI->>Service: onForceCloudSync(appId, SaveLocation)
    Service->>Service: markCloudSyncStarted(appId, UPLOADING/DOWNLOADING)
    Service->>Event: emit CloudStatusChanged(appId, status)
    Event->>UI: Update cloud status UI
    Service->>Cloud: syncUserFiles(appInfo, onPhaseStarted)
    Cloud->>Cloud: CloudPathResolver resolves prefixes/paths
    Cloud->>Storage: Upload/download file deltas
    Storage-->>Cloud: Return remote changes / acks
    Cloud->>Service: onPhaseStarted(isUploading=false/true)
    Service->>Service: markCloudSyncStarted(appId, DOWNLOADING/UPLOADING)
    Cloud-->>Service: Return SyncResult
    Service->>Service: markCloudSyncFinished(appId, result)
    Service->>Event: emit CloudStatusChanged(appId, UP_TO_DATE/CONFLICT/FAILED)
    Service->>Service: releaseSync (remove cloudSyncStatuses entry)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • utkarshdalal
  • phobos665

"🐰 I hopped through paths and fixed the map,
Status lights blink true as I tap,
Uploads and downloads snug in my lap,
Conflicts eased with one gentle tap,
Hooray — cloud saves on the app!"

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.52% 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
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding Steam cloud save status display to the UI.
Description check ✅ Passed The PR description is comprehensive, covering scope, features, refactors, exclusions, and includes screenshots. All required checklist items are marked as complete.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

@kiequoo
Copy link
Copy Markdown
Contributor Author

kiequoo commented May 6, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@kiequoo
Copy link
Copy Markdown
Contributor Author

kiequoo commented May 6, 2026

@coderabbitai review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

1 similar comment
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

kiequoo added 3 commits May 8, 2026 15:54
Extract the Steam Auto Cloud path mapping, local save scanning, file diffing, and remote-change decision code out of syncUserFiles().

Keep syncUserFiles() on the same launch-time decision path from master: it still uses the cached local change list, the effective local change number, the cache rehydration shortcut for byte-identical local and remote files, and the same preferred-save conflict handling.

This commit is intentionally behavior-preserving so the cloud save status indicator can call the same logic in the following commit instead of duplicating or approximating it.
Switches selectedAppId from remember to rememberSaveable so it survives
navigation to XServerScreen. Adds currentSelectedLibraryItem to
re-hydrate the detail pane from the app list on return, so the user
lands back on the game info screen rather than the library list.
@kiequoo kiequoo marked this pull request as ready for review May 8, 2026 13:57
@kiequoo kiequoo requested a review from utkarshdalal as a code owner May 8, 2026 13:57
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

⚠️ Outside diff range comments (2)
app/src/main/java/app/gamenative/service/SteamAutoCloud.kt (1)

183-218: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Keep embedded %GameInstall% files in the %GameInstall% prefix bucket.

getFullFilePath() already compensates for Steam returning prefix="" plus filename="%GameInstall%...", but getFilePrefix() still returns "" for that case. hasHashConflicts() keys localUserFiles by getFilePrefix(), so these entries never match the %GameInstall% bucket and post-download validation can incorrectly report success.

Suggested fix
 fun getFilePrefix(file: AppFileInfo, fileList: AppFileChangeList): String {
+    val gameInstallPrefix = "%${PathType.GameInstall.name}%"
+    if (file.filename.startsWith(gameInstallPrefix)) {
+        return gameInstallPrefix
+    }
+
     return if (file.pathPrefixIndex < fileList.pathPrefixes.size) {
         Paths.get(fileList.pathPrefixes[file.pathPrefixIndex]).pathString
     } else {
         ""
     }
 }
🤖 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/service/SteamAutoCloud.kt` around lines 183
- 218, getFilePrefix currently returns "" when Steam put the embedded
"%GameInstall%" in file.filename, causing hasHashConflicts (which keys by
getFilePrefix) to miss those files; change getFilePrefix(file, fileList) to
detect when file.filename startsWith the gameInstallPrefix
("%${PathType.GameInstall.name}%") and return that prefix in that case,
otherwise keep the existing logic (checking file.pathPrefixIndex against
fileList.pathPrefixes and returning that prefix or ""). This ensures entries
keyed by getFilePrefix match the same "%GameInstall%" bucket that
getFullFilePath handles.
app/src/main/java/app/gamenative/service/SteamService.kt (1)

2587-2630: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Emit a terminal cloud status when close-time sync fails.

This path only calls markCloudSyncFinished() when syncUserFiles() returns a non-null result. If all retries fail or the sync exits early, releaseSync() clears the in-progress state without ever emitting FAILED, so the UI can drop from CHECKING/UPLOADING back to idle with no error.

Suggested fix
+                    var syncResult = SyncResult.UnknownFail
                     val maxAttempts = 3
                     for (attempt in 1..maxAttempts) {
                         try {
                             PrefManager.clientId?.let { clientId ->
                                 instance?.let { steamInstance ->
@@
-                                            postSyncInfo?.let { info ->
-                                                markCloudSyncFinished(appId, info.syncResult)
-                                            }
+                                            postSyncInfo?.let { info ->
+                                                syncResult = info.syncResult
+                                            }
                                             steamCloud.signalAppExitSyncDone(
                                                 appId = appId,
                                                 clientId = clientId,
                                                 uploadsCompleted = postSyncInfo?.uploadsCompleted == true,
                                                 uploadsRequired = postSyncInfo?.uploadsRequired == false,
@@
                 } finally {
+                    markCloudSyncFinished(appId, syncResult)
                     releaseSync(appId)
                 }
🤖 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/service/SteamService.kt` around lines 2587 -
2630, The close-time sync loop can exit without ever calling
markCloudSyncFinished(appId, ...) if syncUserFiles() returns null or all retries
throw AsyncJobFailedException, leaving releaseSync(appId) to clear progress
without emitting a FAILED status; update the logic in the retry loop around
SteamAutoCloud.syncUserFiles(...) so that any terminal failure path (null
postSyncInfo after all attempts or catch where attempt == maxAttempts) calls
markCloudSyncFinished(appId, SyncResult.FAILED) (or the equivalent FAILED
enum/state your code uses) before breaking/propagating, and ensure the
AsyncJobFailedException catch block and the post-loop path both set FAILED when
appropriate so the UI receives the terminal status prior to releaseSync(appId).
🤖 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/service/SteamAutoCloud.kt`:
- Around line 221-239: In fileChangeListToUserFiles, resolve the root by using
the indexed prefix from appFileListChange.pathPrefixes (using
it.pathPrefixIndex) instead of indexing into the flattened pathTypePairs; call
PathType.from on the actual prefix string at
appFileListChange.pathPrefixes[it.pathPrefixIndex] and if the index is out of
range fall back to PathType.DEFAULT (not PathType.GameInstall); keep the path
value aligned by reading appFileListChange.pathPrefixes[it.pathPrefixIndex] when
in-range and using "" on fallback; references: function
fileChangeListToUserFiles, variable appFileListChange, property pathPrefixes,
index pathPrefixIndex, helper getPathTypePairs, and enum PathType.

In `@app/src/main/java/app/gamenative/service/SteamService.kt`:
- Around line 441-449: The helper markCloudSyncFinished is collapsing all
non-success/non-conflict SyncResult values into CloudSaveStatus.FAILED; update
its when expression to handle SyncResult.PendingOperations separately (the value
produced by beginLaunchApp()/signalAppLaunchIntent()) and map it to the
appropriate pending CloudSaveStatus (e.g., CloudSaveStatus.PENDING_OPERATIONS)
instead of FAILED so the UI shows a recoverable pending state; keep existing
mappings for Success/UpToDate and Conflict unchanged.

In
`@app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt`:
- Around line 385-418: The LaunchedEffect watching gameId and
cloudConnectivityVersion should also include isInstalled so the cloud-status
resolution re-runs when install state changes; update the LaunchedEffect key
list (the one wrapping the block that reads hasCloudSaves, isInstalled,
SteamService.* and updates cloudSaveStatus, syncStateText, conflictUfsVersion,
conflictLocalTimestamp, conflictRemoteTimestamp) to include isInstalled (and
optionally hasCloudSaves if you want updates when that toggles) so the initial
cloud snapshot is fetched once the app becomes installed.
- Around line 364-370: The onCloudStatusChanged lambda only refreshes dialog
metadata when status == FAILED, so when status flips to CloudSaveStatus.CONFLICT
the conflict dialog can show stale/empty details; update the handler so that
when event.status == CloudSaveStatus.CONFLICT you also retrigger the
snapshot-resolution/metadata refresh (the same path used for FAILED) — e.g.,
call the same refresh routine or increment cloudConnectivityVersion (or invoke
the existing snapshot resolution method) inside the onCloudStatusChanged block
when status == CONFLICT so the dialog timestamps/UFS version are repopulated.

---

Outside diff comments:
In `@app/src/main/java/app/gamenative/service/SteamAutoCloud.kt`:
- Around line 183-218: getFilePrefix currently returns "" when Steam put the
embedded "%GameInstall%" in file.filename, causing hasHashConflicts (which keys
by getFilePrefix) to miss those files; change getFilePrefix(file, fileList) to
detect when file.filename startsWith the gameInstallPrefix
("%${PathType.GameInstall.name}%") and return that prefix in that case,
otherwise keep the existing logic (checking file.pathPrefixIndex against
fileList.pathPrefixes and returning that prefix or ""). This ensures entries
keyed by getFilePrefix match the same "%GameInstall%" bucket that
getFullFilePath handles.

In `@app/src/main/java/app/gamenative/service/SteamService.kt`:
- Around line 2587-2630: The close-time sync loop can exit without ever calling
markCloudSyncFinished(appId, ...) if syncUserFiles() returns null or all retries
throw AsyncJobFailedException, leaving releaseSync(appId) to clear progress
without emitting a FAILED status; update the logic in the retry loop around
SteamAutoCloud.syncUserFiles(...) so that any terminal failure path (null
postSyncInfo after all attempts or catch where attempt == maxAttempts) calls
markCloudSyncFinished(appId, SyncResult.FAILED) (or the equivalent FAILED
enum/state your code uses) before breaking/propagating, and ensure the
AsyncJobFailedException catch block and the post-loop path both set FAILED when
appropriate so the UI receives the terminal status prior to releaseSync(appId).
🪄 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: 94d74446-d3d9-4333-8a56-8c27bc492a6a

📥 Commits

Reviewing files that changed from the base of the PR and between 6e63d36 and a4f2bab.

📒 Files selected for processing (11)
  • app/src/main/java/app/gamenative/data/SteamApp.kt
  • app/src/main/java/app/gamenative/events/AndroidEvent.kt
  • app/src/main/java/app/gamenative/service/SteamAutoCloud.kt
  • app/src/main/java/app/gamenative/service/SteamService.kt
  • app/src/main/java/app/gamenative/ui/data/CloudSaveStatus.kt
  • app/src/main/java/app/gamenative/ui/data/GameDisplayInfo.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/appscreen/SteamAppScreen.kt
  • app/src/main/res/values/strings.xml

Comment thread app/src/main/java/app/gamenative/service/SteamAutoCloud.kt
Comment thread app/src/main/java/app/gamenative/service/SteamService.kt
Comment thread app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt Outdated
Copy link
Copy Markdown
Contributor

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

Choose a reason for hiding this comment

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

5 issues found across 11 files

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/service/SteamAutoCloud.kt">

<violation number="1" location="app/src/main/java/app/gamenative/service/SteamAutoCloud.kt:226">
P1: Resolve root/path directly from `appFileListChange.pathPrefixes[pathPrefixIndex]` rather than indexing the deduplicated `pathTypePairs`; using `pathPrefixIndex` against a `distinct()` list can misalign prefixes and produce incorrect remote file metadata.</violation>
</file>

<file name="app/src/main/java/app/gamenative/service/SteamService.kt">

<violation number="1" location="app/src/main/java/app/gamenative/service/SteamService.kt:447">
P1: Do not fall through pending sync outcomes to `FAILED`; map `SyncResult.PendingOperations` to a pending cloud status so the UI does not show a false failure state.</violation>
</file>

<file name="app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt">

<violation number="1" location="app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt:368">
P2: Trigger a cloud-status re-resolution when status becomes `CONFLICT` as well as `FAILED`; otherwise the conflict dialog can show stale or missing timestamps/UFS version.</violation>

<violation number="2" location="app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt:385">
P2: Cloud save status `LaunchedEffect` is missing reactive dependencies `hasCloudSaves` and `isInstalled` in its key set. If these values change (e.g., the user installs the game while on the screen), the effect will not rerun and cloud save status resolution is skipped, leaving the UI stale until an unrelated key-changing event occurs.</violation>

<violation number="3" location="app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt:412">
P2: Conflict timestamps are never cleared when resolution has no conflict data, so stale timestamps can persist in the UI model and conflict dialog details.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread app/src/main/java/app/gamenative/service/SteamAutoCloud.kt
Comment thread app/src/main/java/app/gamenative/service/SteamService.kt
Comment thread app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt Outdated
Comment thread app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt Outdated
Comment thread app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt Outdated
@kiequoo kiequoo force-pushed the feat/steam-cloud-save-status branch from a4f2bab to 461d370 Compare May 8, 2026 14:39
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

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/res/values/strings.xml`:
- Line 1248: The string resource named cloud_saves_pending_operations uses
singular wording ("Remote Operation Pending") but the key/state is plural;
update the value of string name="cloud_saves_pending_operations" to use plural
phrasing (e.g., "Remote Operations Pending" or "Remote operations pending") so
the text matches the plural key and UI state.
🪄 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: 0b508aff-750a-4acb-a456-b481c5eb574b

📥 Commits

Reviewing files that changed from the base of the PR and between a4f2bab and 461d370.

📒 Files selected for processing (24)
  • app/src/main/java/app/gamenative/data/SteamApp.kt
  • app/src/main/java/app/gamenative/events/AndroidEvent.kt
  • app/src/main/java/app/gamenative/service/SteamAutoCloud.kt
  • app/src/main/java/app/gamenative/service/SteamService.kt
  • app/src/main/java/app/gamenative/ui/data/CloudSaveStatus.kt
  • app/src/main/java/app/gamenative/ui/data/GameDisplayInfo.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/appscreen/SteamAppScreen.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-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
✅ Files skipped from review due to trivial changes (9)
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-it/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-uk/strings.xml
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-ko/strings.xml
🚧 Files skipped from review as they are similar to previous changes (10)
  • app/src/main/java/app/gamenative/ui/data/CloudSaveStatus.kt
  • app/src/main/java/app/gamenative/events/AndroidEvent.kt
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt
  • app/src/main/java/app/gamenative/ui/data/GameDisplayInfo.kt
  • app/src/main/java/app/gamenative/ui/screen/library/LibraryScreen.kt
  • app/src/main/java/app/gamenative/service/SteamAutoCloud.kt
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt
  • app/src/main/java/app/gamenative/data/SteamApp.kt
  • app/src/main/java/app/gamenative/service/SteamService.kt

<string name="cloud_saves_up_to_date">Up to Date</string>
<string name="cloud_saves_pending_download">Pending Download</string>
<string name="cloud_saves_pending_upload">Pending Upload</string>
<string name="cloud_saves_pending_operations">Remote Operation Pending</string>
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.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use plural wording for pending operations status.

Line 1248 is singular (Remote Operation Pending) while the key/state is plural (cloud_saves_pending_operations). This can read as inconsistent in UI.

Suggested text tweak
-    <string name="cloud_saves_pending_operations">Remote Operation Pending</string>
+    <string name="cloud_saves_pending_operations">Remote Operations Pending</string>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<string name="cloud_saves_pending_operations">Remote Operation Pending</string>
<string name="cloud_saves_pending_operations">Remote Operations Pending</string>
🤖 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/res/values/strings.xml` at line 1248, The string resource named
cloud_saves_pending_operations uses singular wording ("Remote Operation
Pending") but the key/state is plural; update the value of string
name="cloud_saves_pending_operations" to use plural phrasing (e.g., "Remote
Operations Pending" or "Remote operations pending") so the text matches the
plural key and UI state.

Comment on lines -103 to -116
fun syncUserFiles(
appInfo: SteamApp,
clientId: Long,
steamInstance: SteamService,
steamCloud: SteamCloud,
preferredSave: SaveLocation = SaveLocation.None,
parentScope: CoroutineScope = CoroutineScope(Dispatchers.IO),
prefixToPath: (String) -> String,
overrideLocalChangeNumber: Long? = null,
onProgress: ((message: String, progress: Float) -> Unit)? = null,
): Deferred<PostSyncInfo?> = parentScope.async {
val postSyncInfo: PostSyncInfo?

Timber.i("Retrieving save files of ${appInfo.name}")
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Changing syncUserFiles is setting off alarm bells here. I'm not sure if you've just added new methods and this has just been moved, or if there are actual changes. Can you please update so that the diff only shows what is changed?
This is of course a very sensitive file and I'll need to check each change carefully.

Copy link
Copy Markdown
Contributor Author

@kiequoo kiequoo May 12, 2026

Choose a reason for hiding this comment

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

@utkarshdalal it's better to review each commit, then you can see more clearly that the sync logic wasn't actually changed.
It's only been refactored in such a way as to make the current sync status accessible outside the sync process

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.

2 participants