Skip to content

Fix recently played library sort#1509

Open
xXJSONDeruloXx wants to merge 3 commits into
utkarshdalal:masterfrom
xXJSONDeruloXx:fix/recently-played-library-sort
Open

Fix recently played library sort#1509
xXJSONDeruloXx wants to merge 3 commits into
utkarshdalal:masterfrom
xXJSONDeruloXx:fix/recently-played-library-sort

Conversation

@xXJSONDeruloXx

@xXJSONDeruloXx xXJSONDeruloXx commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Description

Fixes incorrect Recently Played sorting in the Library view. Previously, non-installed games in that sort mode fell back to alphabetical ordering because Steam account last-played data was not persisted and refreshed for library ordering.

Recording

recently-played-library

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

Fixes Recently Played sorting in the Library by persisting Steam play stats and using true last-played times across stores. Sorting now favors installed games, then most recently played, and keeps stats intact during PICS updates.

  • Bug Fixes
    • DB v22: add play stats fields to steam_app (auto-migration).
    • Owned-games sync: upsert and batch persist stats; insert missing apps with stats; reload when stats change.
    • PICS upserts now carry forward play stats to avoid resets.
    • Normalize timestamps; Steam install mtime fallback; apply to GOG/Epic/Amazon.
    • Recently Played comparator: installed first, then last-played (desc), then name.
    • Background refresh of Steam play stats when Recently Played is active.
    • Tests for normalization, fallback, and comparator.

Written for commit 2206d63. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added improved Recently Played sorting using per-entry last-played timestamps with install-time fallback.
    • Persist Steam play stats per owned app (last played + playtime minutes) and refresh them in the background when using the Recently Played sort.
    • Added support for initializing/migrating the database to store the new play-stat fields.
  • Bug Fixes

    • Prevented play stats from being cleared during Steam metadata refreshes.
  • Tests

    • Added unit tests for play-stat normalization, fallback logic, and Recently Played sorting.

@coderabbitai

coderabbitai Bot commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1aed10c8-9c02-4853-a9c7-bc448e313340

📥 Commits

Reviewing files that changed from the base of the PR and between 263060b and 2206d63.

📒 Files selected for processing (1)
  • app/src/main/java/app/gamenative/service/SteamService.kt
🚧 Files skipped from review as they are similar to previous changes (1)
  • app/src/main/java/app/gamenative/service/SteamService.kt

📝 Walkthrough

Walkthrough

Adds persistent per-app Steam play stats (last-played and play-time minutes) with a DB migration to v22, DAO support to read/update stats and trigger library reloads, service-side collection/persistence, sorting utilities and ViewModel wiring for "Recently Played", plus unit tests for the sorting utilities.

Changes

Steam Play Stats Tracking and Recently Played Sorting

Layer / File(s) Summary
Database schema v21→v22 migration and SteamApp entity
app/schemas/app.gamenative.db.PluviaDatabase/22.json, app/src/main/java/app/gamenative/data/SteamApp.kt, app/src/main/java/app/gamenative/db/PluviaDatabase.kt
Schema version incremented to 22 with full entity definitions and auto-migration support. SteamApp entity adds lastPlayed and playTimeMinutes fields with database column mappings and defaults.
DAO layer: play-stats DTO and query/update methods
app/src/main/java/app/gamenative/db/dao/SteamAppDao.kt
Introduces SteamAppPlayStatsUpdate DTO and adds findAccountPlayStats() and updateAccountPlayStats() methods. Replaces owned-app library observation from count-only to version-based (row count + sum of last_played), and updates getAllOwnedApps to use the new version flow.
Service layer: play-stats collection and persistence
app/src/main/java/app/gamenative/service/SteamService.kt
refreshOwnedGamesFromServer() derives per-app play stats from Steam's owned-games list, updates existing apps when stats differ, and inserts new apps with play stats. PICS refresh now preserves existing play stats from the database; adds MAX_SQL_BIND_VARIABLES constant.
Sorting utilities for recently-played order
app/src/main/java/app/gamenative/ui/model/LibrarySortUtils.kt
Introduces normalizeLastPlayedMillis() for consistent timestamp normalization, steamLastPlayedOrInstallFallback() for Steam/install fallback, and recentlyPlayedComparator() for multi-key sorting (installed-first, then lastPlayed descending, then name).
ViewModel: recently-played sort integration and refresh coordination
app/src/main/java/app/gamenative/ui/model/LibraryViewModel.kt
LibraryEntry model extended with lastPlayed. Adds background steamPlayStatsRefreshJob and refreshSteamPlayStatsForRecentlyPlayedSort() helper triggered on init, Steam data change, and sort-option change. All entry builders (Steam, Custom, GOG, Epic, Amazon) populate lastPlayed. Recently-played sort uses LibrarySortUtils.recentlyPlayedComparator().
Unit tests for sorting utilities
app/src/test/java/app/gamenative/ui/model/LibrarySortUtilsTest.kt
Tests validate installed-first ordering, name fallback tie-breaker, timestamp normalization, and steam/install fallback logic.

Estimated Code Review Effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly Related PRs

  • utkarshdalal/GameNative#308: Both PRs touch SteamService.refreshOwnedGamesFromServer() and owned-games handling; this PR extends refresh to persist play stats.
  • utkarshdalal/GameNative#407: Both PRs modify Room database versioning/auto-migrations; this PR adds the v21→v22 migration for play-stats fields.

Suggested Reviewers

  • utkarshdalal

🐰 A rabbit hops through the code with cheer,
Saves play-time minutes and timestamps dear.
"Sort by recent!" it sings with a twitchy nose—
Preserved last-played, so the library knows. 🎮

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% 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 summarizes the main change: fixing Recently Played library sorting, which is the primary focus of the entire changeset across database schema, service logic, UI utilities, and tests.
Description check ✅ Passed The description covers all required template sections: a clear explanation of the bug fix, an attached recording demonstrating the change, Type of Change marked as bug fix, and all checklist items completed. The description aligns well with the changeset.
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

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.

@xXJSONDeruloXx xXJSONDeruloXx marked this pull request as ready for review June 3, 2026 04:24

@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 8 files

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

Re-trigger cubic

Comment thread app/src/main/java/app/gamenative/service/SteamService.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: 3

🤖 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/db/dao/SteamAppDao.kt`:
- Around line 158-159: The call site in
SteamService.refreshOwnedGamesFromServer() should chunk existingAppIds before
calling SteamAppDao.findAccountPlayStats() to avoid SQLite bind-variable limits:
split existingAppIds.toList() into batches (e.g., ~900 ids per batch, similar to
MAX_PICS_BUFFER but larger), call findAccountPlayStats(batch) for each chunk,
collect and merge all returned SteamAppPlayStatsUpdate results into a single
list used downstream; ensure the chunking logic mirrors the existing
missingAppIds batching so large libraries won’t generate “too many SQL
variables” errors.

In `@app/src/main/java/app/gamenative/service/SteamService.kt`:
- Around line 813-815: The query call to SteamAppDao.findAccountPlayStats is
passed a potentially huge existingAppIds.toList() from
refreshOwnedGamesFromServer which can exceed SQLite bind-variable limits; fix by
chunking the app ID list (e.g., using Kotlin List.chunked with a safe size like
900) and calling findAccountPlayStats for each chunk, then merge the results
into a single map (associateBy { it.id }) so currentStatsByAppId is built from
the concatenated results; update the code around existingAppIds,
findAccountPlayStats, and currentStatsByAppId to perform chunked queries and
merge the responses before proceeding.

In `@app/src/main/java/app/gamenative/ui/model/LibraryViewModel.kt`:
- Around line 526-529: The current merge strategy uses max(...) so directory
mtime can override Steam's real lastPlayed; change LibraryViewModel to treat
install-directory mtime as a fallback: call
LibrarySortUtils.normalizeLastPlayedMillis(item.lastPlayed) into a local (e.g.,
normalizedLastPlayed) and set lastPlayed to normalizedLastPlayed unless it
equals 0L, in which case (and only if isInstalled) use
steamInstalledLastPlayedMillis(item.id) else 0L; update the assignment that
currently uses max(...) to this conditional fallback logic so Steam timestamps
always take precedence.
🪄 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: 92aa9de2-ad90-4f36-bffa-4ff6e6b89f09

📥 Commits

Reviewing files that changed from the base of the PR and between b7b4198 and e019858.

📒 Files selected for processing (8)
  • app/schemas/app.gamenative.db.PluviaDatabase/22.json
  • app/src/main/java/app/gamenative/data/SteamApp.kt
  • app/src/main/java/app/gamenative/db/PluviaDatabase.kt
  • app/src/main/java/app/gamenative/db/dao/SteamAppDao.kt
  • app/src/main/java/app/gamenative/service/SteamService.kt
  • app/src/main/java/app/gamenative/ui/model/LibrarySortUtils.kt
  • app/src/main/java/app/gamenative/ui/model/LibraryViewModel.kt
  • app/src/test/java/app/gamenative/ui/model/LibrarySortUtilsTest.kt

Comment thread app/src/main/java/app/gamenative/db/dao/SteamAppDao.kt
Comment thread app/src/main/java/app/gamenative/service/SteamService.kt
Comment thread app/src/main/java/app/gamenative/ui/model/LibraryViewModel.kt Outdated
@xXJSONDeruloXx xXJSONDeruloXx force-pushed the fix/recently-played-library-sort branch from e019858 to 9f85720 Compare June 5, 2026 13:57
…ed-library-sort

# Conflicts:
#	app/src/main/java/app/gamenative/service/SteamService.kt
#	app/src/main/java/app/gamenative/ui/model/LibraryViewModel.kt
@utkarshdalal

Copy link
Copy Markdown
Owner

@xXJSONDeruloXx the tests are failing

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