Skip to content

feat: steam achievements viewer (updated #1511) - #1695

Open
VinceBT wants to merge 10 commits into
utkarshdalal:masterfrom
VinceBT:feat/steam-achievements
Open

feat: steam achievements viewer (updated #1511)#1695
VinceBT wants to merge 10 commits into
utkarshdalal:masterfrom
VinceBT:feat/steam-achievements

Conversation

@VinceBT

@VinceBT VinceBT commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Description

This is @phobos665's Steam achievements viewer from #1511, brought up to current master with some refinements on top. Most of the credit here belongs to @phobos665 — the viewer, the data plumbing and the schema handling are all theirs; I rebased the work onto current master and polished the UI and localization.

Quoting the original PR (#1511):

View Steam Achievements in the Game Details Page (LibraryAppScreen).

Also shows a little gold star for those who get 100% of achievements.

Also, this has been made so that it's generic enough to support both Epic & GOG achievements later.

On top of that, this PR:

  • Localizes achievement names/descriptions to the app's language, falling back to English per-string when a game doesn't ship that language.
  • Restyles the game-page block to match the screenshots card — in-card "Achievements ›" title with a chevron, and the whole card is clickable / controller-focusable.
  • Adds a "+N" tile for achievements beyond what fits, with a centered x / y count.
  • Makes the "all achievements" view fullscreen with the same open/close animation as the screenshot gallery, each achievement in its own card instead of divider rows.
  • Shows a progress bar with the x / y count for stat-linked achievements (e.g. 45 / 100), read from the game's stats.
  • Collapses still-locked secret achievements into a single summary row with masked icons, matching Steam; tapping it prompts to reveal them for the current session only (not remembered), and keeps focus on the first revealed row.
  • Opens a detail dialog (icon, name, description, unlock date / progress / locked) when an achievement is tapped, and makes each row in the list controller-focusable.
  • Adds the achievement strings across all locales.

Implementation note: this replaces the local InfoCard in LibraryAppScreen with the shared ui/component/InfoCard component (a superset that adds onClick/content), so a few neighbouring cards move to it as well. Progress bars need the achievement progress fields added in JavaSteam, so javasteam is bumped to 1.8.0.1-23-SNAPSHOT.

Recording

screen_recording_compressed.mp4

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 a Steam achievements viewer to Game Details with a compact card and a fullscreen list, including progress bars, hidden-achievement reveal, and a detail dialog. Text is localized with English fallbacks and icons load from the Steam CDN.

  • New Features

    • Achievements card for Steam titles: icon strip with grayed/secret-masked locked icons, “+N” overflow, x/y unlocked count, and a gold star at 100%.
    • Fullscreen Achievements view with gallery-style animation; rows show icon, name, description, and localized unlock time or stat progress; hidden achievements collapse behind a session-only “Reveal”; tap any row for a detail dialog.
  • Refactors

    • Added ui/data/Achievement and SteamService.fetchAchievementsForDisplay() with per-string English fallbacks and a 15s timeout; the screen retries failed fetches up to 3 times with a short delay.
    • Made SteamUtils.steamLanguageForAppLocale() locale-injectable and added unit tests (Spanish split, Chinese scripts, Korean, Portuguese); added SteamUtils.getBaseAchievementIconUrl().
    • Introduced reusable ui/component/InfoCard; grouped download flags into ui/data/DownloadDisplayDetails to avoid an ART VerifyError.
    • Localized achievement strings and plurals across locales; bumped javasteam to 1.8.0.1-24-SNAPSHOT to surface achievement progress.

Written for commit 0288ff6. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added Steam achievements to the library app screen, including an unlocked/total progress summary, completion indicator, and an achievements icon strip.
    • Added a full-screen achievements dialog with an item list (names, descriptions, and unlock date/time).
    • Introduced a reusable card component to support consistent labeled/value sections.
  • Localization
    • Added localized UI strings for the Steam achievements section (titles, totals, completion text, and unlock-at formatting) across supported languages.

@VinceBT
VinceBT requested a review from utkarshdalal as a code owner July 10, 2026 14:51
@coderabbitai

coderabbitai Bot commented Jul 10, 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

Steam achievements are fetched from Steam, mapped into localized display models, loaded for Steam library items, and shown through an overview row and animated detail dialog. Shared InfoCard rendering and localized achievement resources are also added.

Changes

Steam achievements

Layer / File(s) Summary
Achievement model and Steam locale utilities
app/src/main/java/app/gamenative/ui/data/Achievement.kt, app/src/main/java/app/gamenative/utils/SteamUtils.kt
Defines achievement display fields, unlock-time formatting, Steam icon URL construction, and locale mapping.
Steam achievement fetching
app/src/main/java/app/gamenative/service/SteamService.kt
Fetches expanded Steam achievements with timeout handling, localized and English fallback text, icon URLs, and nullable results.
Achievement state and screen wiring
app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt, app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt
Loads achievements asynchronously for Steam items, retries failures, and passes the resulting state into app screen content.
Achievement overview and detail UI
app/src/main/java/app/gamenative/ui/component/InfoCard.kt, app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt, app/src/main/res/values*/strings.xml
Adds the achievement summary row, animated detail dialog, reusable InfoCard, and localized achievement labels across supported locales.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant BaseAppScreen
  participant SteamService
  participant SteamUserStats
  participant AppScreenContent
  participant AchievementsDialog
  BaseAppScreen->>SteamService: fetchAchievementsForDisplay(appId)
  SteamService->>SteamUserStats: fetch expanded achievements
  SteamUserStats-->>SteamService: achievement data
  SteamService-->>BaseAppScreen: List<Achievement> or null
  BaseAppScreen->>AppScreenContent: pass achievements state
  AppScreenContent->>AchievementsDialog: open detailed achievement list
Loading

Possibly related PRs

  • utkarshdalal/GameNative#346: Both changes modify Ukrainian locale resources in values-uk/strings.xml, including achievement-related string definitions.
  • utkarshdalal/GameNative#831: Extends Steam achievement-related plumbing in SteamService.kt, which this change uses for achievement fetching.

Suggested reviewers: utkarshdalal

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.53% 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 describes the main change: a Steam achievements viewer.
Description check ✅ Passed The description follows the template and includes the change summary, recording, type of change, and checklist items.
✨ 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.

@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: 7

🧹 Nitpick comments (2)
app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt (2)

1250-1250: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Duplicate grayMatrix construction in AchievementsRow and AchievementsDialog.

Both composables independently build the same ColorMatrix().apply { setToSaturation(0f) }. Consider hoisting it to a single top-level private val (it's stateless) to avoid the duplication.

Also applies to: 1380-1380

🤖 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/library/LibraryAppScreen.kt` at
line 1250, Hoist the duplicated grayscale matrix into a single top-level private
ColorMatrix value, then update both AchievementsRow and AchievementsDialog to
reference it instead of constructing separate instances with remember.

1237-1506: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Add contentDescription to achievement icon images for accessibility.

Landscapist's ImageOptions supports a contentDescription field, but none of the three CoilImage calls here (row icons, "+N" stack icon, dialog list icon) set it. Screen-reader users get no label for achievement artwork.

♿ Suggested addition
 CoilImage(
     imageModel = { iconUrl ?: "" },
     imageOptions = ImageOptions(
         contentScale = ContentScale.Crop,
+        contentDescription = ach.displayName ?: ach.name,
         colorFilter = if (ach.isUnlocked) null else ColorFilter.colorMatrix(grayMatrix),
     ),
     ...
 )
🤖 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/library/LibraryAppScreen.kt`
around lines 1237 - 1506, Add accessibility labels to all three achievement
CoilImage calls in AchievementsRow and AchievementsDialog by setting
ImageOptions.contentDescription using each achievement’s display name or name,
with a suitable fallback for the stacked “+N” preview icon.
🤖 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/SteamService.kt`:
- Around line 3074-3113: Update fetchAchievementsForDisplay to rethrow
CancellationException before the generic Exception handler, preserving coroutine
cancellation. Bound the Steam operations, including getUserStats(...).await()
and achievement expansion, with an appropriate coroutine timeout such as
withTimeout, while keeping existing error logging and null fallback behavior.

In `@app/src/main/java/app/gamenative/ui/component/InfoCard.kt`:
- Around line 61-66: Remove the unnecessary rememberCoroutineScope and nested
scope.launch from LaunchedEffect(isFocused); call the suspend
bringIntoViewRequester.bringIntoView() directly when isFocused is true so it
remains tied to the effect lifecycle. Remove the now-unused coroutine scope and
launch imports if they are not used elsewhere.

In `@app/src/main/res/values-de/strings.xml`:
- Around line 1571-1577: Translate the German localization value for the
achievements_total string from “Total” to an appropriate German term, preferably
“Gesamt” or “Insgesamt,” while leaving the other achievement strings unchanged.

In `@app/src/main/res/values-ru/strings.xml`:
- Around line 1558-1563: Translate the achievements_total string in the Russian
resources from the English “Total” to its Russian equivalent, matching the
surrounding Cyrillic translations.

In `@app/src/main/res/values-uk/strings.xml`:
- Around line 1626-1631: Translate the achievements_total string in the
Ukrainian achievements resource block from "Total" to the appropriate Ukrainian
equivalent, keeping the existing string name and resource structure unchanged.

In `@app/src/main/res/values-zh-rCN/strings.xml`:
- Around line 1650-1655: Translate the `achievements_total` string in the Steam
achievements resource block from “Total” to the appropriate Simplified Chinese
text, keeping the existing string name unchanged.

In `@app/src/main/res/values-zh-rTW/strings.xml`:
- Around line 1641-1646: Translate the achievements_total string in the
achievements resource block from “Total” to the appropriate Traditional Chinese
wording, matching the existing zh-rTW translations and the corresponding zh-rCN
resource.

---

Nitpick comments:
In `@app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt`:
- Line 1250: Hoist the duplicated grayscale matrix into a single top-level
private ColorMatrix value, then update both AchievementsRow and
AchievementsDialog to reference it instead of constructing separate instances
with remember.
- Around line 1237-1506: Add accessibility labels to all three achievement
CoilImage calls in AchievementsRow and AchievementsDialog by setting
ImageOptions.contentDescription using each achievement’s display name or name,
with a suitable fallback for the stacked “+N” preview icon.
🪄 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: dc134ec6-8031-43de-91b7-5cca0bb9a71d

📥 Commits

Reviewing files that changed from the base of the PR and between b6fd912 and d605396.

📒 Files selected for processing (21)
  • app/src/main/java/app/gamenative/service/SteamService.kt
  • app/src/main/java/app/gamenative/ui/component/InfoCard.kt
  • app/src/main/java/app/gamenative/ui/data/Achievement.kt
  • app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt
  • app/src/main/java/app/gamenative/utils/SteamUtils.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

Comment thread app/src/main/java/app/gamenative/service/SteamService.kt
Comment thread app/src/main/java/app/gamenative/ui/component/InfoCard.kt
Comment thread app/src/main/res/values-de/strings.xml Outdated
Comment thread app/src/main/res/values-ru/strings.xml Outdated
Comment thread app/src/main/res/values-uk/strings.xml Outdated
Comment thread app/src/main/res/values-zh-rCN/strings.xml Outdated
Comment thread app/src/main/res/values-zh-rTW/strings.xml Outdated
@VinceBT
VinceBT force-pushed the feat/steam-achievements branch from d605396 to 3bce1dc Compare July 10, 2026 15:07

@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.

Review completed against the latest diff

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

Re-trigger cubic

Comment thread app/src/main/java/app/gamenative/service/SteamService.kt
Comment thread app/src/main/java/app/gamenative/service/SteamService.kt
Comment thread app/src/main/res/values-ko/strings.xml Outdated
@VinceBT
VinceBT force-pushed the feat/steam-achievements branch 3 times, most recently from ee695a0 to 85e961b Compare July 12, 2026 19:42

@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/service/SteamService.kt`:
- Around line 3085-3130: Update fetchAchievementsForDisplay after obtaining
userStats to inspect its result status and return null when userStats.result is
not OK. Keep the existing achievement mapping for successful responses unchanged
so only failed Steam fetches trigger the retry path.
🪄 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: 0a567253-c28e-4396-b215-2a8a0f3a0bf4

📥 Commits

Reviewing files that changed from the base of the PR and between ee695a0 and 85e961b.

📒 Files selected for processing (21)
  • app/src/main/java/app/gamenative/service/SteamService.kt
  • app/src/main/java/app/gamenative/ui/component/InfoCard.kt
  • app/src/main/java/app/gamenative/ui/data/Achievement.kt
  • app/src/main/java/app/gamenative/ui/screen/library/LibraryAppScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt
  • app/src/main/java/app/gamenative/utils/SteamUtils.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
🚧 Files skipped from review as they are similar to previous changes (16)
  • app/src/main/res/values-pl/strings.xml
  • app/src/main/res/values-ru/strings.xml
  • app/src/main/java/app/gamenative/ui/data/Achievement.kt
  • app/src/main/res/values-es/strings.xml
  • app/src/main/res/values-pt-rBR/strings.xml
  • app/src/main/res/values-zh-rTW/strings.xml
  • app/src/main/res/values-da/strings.xml
  • app/src/main/res/values-ro/strings.xml
  • app/src/main/res/values-zh-rCN/strings.xml
  • app/src/main/res/values-fr/strings.xml
  • app/src/main/res/values-ko/strings.xml
  • app/src/main/java/app/gamenative/utils/SteamUtils.kt
  • app/src/main/res/values/strings.xml
  • app/src/main/res/values-ja/strings.xml
  • app/src/main/res/values-de/strings.xml
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/BaseAppScreen.kt

Comment thread app/src/main/java/app/gamenative/service/SteamService.kt
@VinceBT
VinceBT force-pushed the feat/steam-achievements branch from 4e4e190 to b22dac2 Compare July 12, 2026 23:23

@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.

All reported issues were addressed across 19 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/res/values-ro/strings.xml Outdated
@VinceBT
VinceBT force-pushed the feat/steam-achievements branch from bcaaa66 to 99caba3 Compare July 14, 2026 13:53
VinceBT added 2 commits July 14, 2026 16:33
…ements

# Conflicts:
#	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
#	gradle/libs.versions.toml
@joshuatam

Copy link
Copy Markdown
Contributor

@VinceBT, please use this JavaSteam version: 1.8.0.1-24-SNAPSHOT

@phobos665 phobos665 mentioned this pull request Jul 17, 2026
8 tasks
@phobos665

Copy link
Copy Markdown
Contributor

@utkarshdalal I think we should get this in now that 1.1.1 is out. This is a massively requested feature and helps with user retention for GN.

We can then eventually expand it for GOG & Epic as well once there's room to do shim work for those.

@phobos665

Copy link
Copy Markdown
Contributor

@VinceBT Please fix the conflicts and we should be able to get this in :)

# Conflicts:
#	app/src/main/java/app/gamenative/service/SteamService.kt
#	app/src/main/res/values/strings.xml
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.

3 participants