Skip to content

Update SteamApp container language handling#507

Merged
utkarshdalal merged 4 commits intoutkarshdalal:masterfrom
joshuatam:feat/steam-language-handling
Feb 18, 2026
Merged

Update SteamApp container language handling#507
utkarshdalal merged 4 commits intoutkarshdalal:masterfrom
joshuatam:feat/steam-language-handling

Conversation

@joshuatam
Copy link
Contributor

@joshuatam joshuatam commented Feb 10, 2026

Ensures Steam app downloads use the container's language setting, allowing users to download games in their preferred language.

When user changed the language of the container, automatic download the required data for the new language.

Also remove duplicated lines in ContainerUtils


Summary by cubic

Steam downloads and app manifests now use each container’s language. Changing a container’s language triggers a download of the correct language files and updates the manifest.

  • New Features

    • Select depots using the target container’s language for main app and DLC during download/update/verify.
    • Write the container language to appmanifest (UserConfig and MountedConfig).
    • Auto re-download language data when the container language changes in SteamAppScreen.
  • Refactors

    • Removed duplicate marker cleanup in ContainerUtils.

Written for commit 1f9f27d. Summary will update on new commits.

Summary by CodeRabbit

  • New Features

    • Downloads now respect the container language preference and can re-download assets when container language differs.
  • Bug Fixes

    • App manifest language synchronized with container language.
    • Removed duplicate language-change handling to avoid redundant actions.
  • UI Improvements

    • Uninstall dialog text color updated for improved theme consistency.
    • Improved last-played time handling for library items.

Copy link
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.

1 issue found across 4 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


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

<violation number="1" location="app/src/main/java/app/gamenative/service/SteamService.kt:1005">
P2: `getContainerById` can return null, but `container.language` is dereferenced without a null check, which can crash downloads when the container doesn't exist.</violation>
</file>

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 10, 2026

📝 Walkthrough

Walkthrough

Threads container language through SteamService depot selection and download flows, syncs installed app manifest language in SteamUtils, triggers re-download when container language changes from the UI, and removes a duplicate language-change handler in ContainerUtils.

Changes

Cohort / File(s) Summary
SteamService: language-aware download flow
app/src/main/java/app/gamenative/service/SteamService.kt
Added containerLanguage parameter to getMainAppDepots and downloadApp; new overload getDownloadableDepots(appId, preferredLanguage) and delegation from the no-arg overload; uses ContainerManager/pref fallback for language and passes language through depot filtering and download orchestration; logging updated.
UI: trigger re-download on container language change
app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt
Loads container via getContainer(context, appId) in saveContainerConfig, compares container.language to saved config, and calls SteamService.downloadApp when mismatched; imports and File usage adjusted.
Steam manifest language sync
app/src/main/java/app/gamenative/utils/SteamUtils.kt
When appmanifest_<appId>.acf exists, updates/creates language entries under UserConfig and MountedConfig to match container language and saves the manifest; logs the update.
ContainerUtils cleanup
app/src/main/java/app/gamenative/utils/ContainerUtils.kt
Removed a duplicated language-change handling block that cleared STEAM_DLL_REPLACED and STEAM_COLDCLIENT_USED markers.

Sequence Diagram

sequenceDiagram
    autonumber
    actor User
    participant SteamAppScreen as "SteamAppScreen\n(UI)"
    participant ContainerManager as "ContainerManager"
    participant SteamService as "SteamService"
    participant PrefManager as "PrefManager"
    participant SteamUtils as "SteamUtils"

    User->>SteamAppScreen: change container language/config
    SteamAppScreen->>ContainerManager: getContainer(context, appId)
    ContainerManager-->>SteamAppScreen: container { language }
    SteamAppScreen->>SteamAppScreen: compare container.language vs saved config
    alt languages differ
        SteamAppScreen->>SteamService: downloadApp(appId, containerLanguage)
        SteamService->>ContainerManager: (verify/get) container language
        SteamService->>PrefManager: read fallback containerLanguage
        SteamService->>SteamService: getDownloadableDepots(appId, containerLanguage)
        SteamService->>SteamUtils: sync manifest language(appId, containerLanguage)
        SteamUtils-->>SteamService: manifest updated
        SteamService-->>SteamAppScreen: start download / return DownloadInfo
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • PR #123: Also introduces and propagates container language support across prefs, containers, and SteamService flows.
  • PR #206: Modifies SteamService depot-selection with architecture-based filtering; intersects with the new language-based depot filtering.
  • PR #159: Earlier changes to language-aware depot selection in SteamService; overlaps the same functions and filters.

Poem

🐰 I hopped through manifests, snug and spry,
Swapped languages where depots lie,
Containers whispered which files to keep,
Downloads stirred from their multilingual sleep,
A joyous thump — the rabbit's cry.

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 25.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Update SteamApp container language handling' clearly and concisely describes the main change: implementing container language awareness across Steam app download and manifest handling.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into master

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

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@joshuatam joshuatam force-pushed the feat/steam-language-handling branch from 41a6290 to 0d2cbf0 Compare February 12, 2026 14:09
Copy link
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

🤖 Fix all issues with AI agents
In
`@app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt`:
- Around line 1002-1008: saveContainerConfig calls SteamService.downloadApp
synchronously which internally uses runBlocking and can block the main thread;
wrap the download call in a background coroutine instead. Replace the direct
SteamService.downloadApp(libraryItem.gameId) invocation in saveContainerConfig
with launching a coroutine on Dispatchers.IO (e.g.,
CoroutineScope(Dispatchers.IO).launch {
SteamService.downloadApp(libraryItem.gameId) }) so the blocking runBlocking
calls inside SteamService (getAppInfoOf, getDownloadableDepots,
ContainerManager) run off the UI thread.
🧹 Nitpick comments (1)
app/src/main/java/app/gamenative/service/SteamService.kt (1)

1004-1022: Container lookup may NPE if the container was never created for this app.

ContainerManager.getContainerById("STEAM_${appId}") on Line 1005 can return null if no container exists yet (e.g., first-time install before the user ever opened the container editor). The null-check on Line 1006 handles that gracefully by falling back to PrefManager.containerLanguage, so the logic is safe. However, getContainerById instantiates a ContainerManager for every download call, including resume and verify flows. Consider caching or reusing the manager if this becomes a hot path.

Copy link
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

🤖 Fix all issues with AI agents
In
`@app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt`:
- Around line 1002-1012: The file has an extra closing brace after the
saveContainerConfig method that prematurely ends the SteamAppScreen class;
remove the stray `}` following saveContainerConfig so the class remains open and
the subsequent members (supportsContainerConfig, getExportFileExtension,
AdditionalDialogs, etc.) stay inside SteamAppScreen; verify brace balance around
the saveContainerConfig method and the SteamAppScreen class to ensure no other
unmatched braces remain.

joshuatam and others added 4 commits February 14, 2026 00:00
Ensures Steam app downloads use the container's language setting, allowing users to download games in their preferred language.

When user changed the language of the container, automatic download the required data for the new language.
…teamAppScreen.kt

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@joshuatam joshuatam force-pushed the feat/steam-language-handling branch from 0570fb1 to 1f9f27d Compare February 13, 2026 16:05
Copy link
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

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/service/SteamService.kt (1)

644-712: ⚠️ Potential issue | 🟠 Major

Normalize preferredLanguage before depot filtering to avoid missing language depots.

DepotInfo.language values are lower-case Steam codes. If preferredLanguage is blank or mixed-case, the filter can reject all language-specific depots, leading to incomplete downloads. Normalize and default once per call.

🔧 Suggested fix
-        fun getMainAppDepots(appId: Int, containerLanguage: String): Map<Int, DepotInfo> {
+        fun getMainAppDepots(appId: Int, containerLanguage: String): Map<Int, DepotInfo> {
             val appInfo = getAppInfoOf(appId) ?: return emptyMap()
             val ownedDlc = runBlocking { getOwnedAppDlc(appId) }
+            val normalizedLanguage = containerLanguage.trim().lowercase().ifBlank { "english" }

             // If the game ships any 64-bit depot, prefer those and ignore x86 ones
             val has64Bit = appInfo.depots.values.any { it.osArch == OSArch.Arch64 }

             return appInfo.depots.asSequence()
                 .filter { (depotId, depot) ->
-                    return@filter filterForDownloadableDepots(depot, has64Bit, containerLanguage, ownedDlc)
+                    return@filter filterForDownloadableDepots(depot, has64Bit, normalizedLanguage, ownedDlc)
                 }
                 .associate { it.toPair() }
         }
...
-        fun getDownloadableDepots(appId: Int, preferredLanguage: String): Map<Int, DepotInfo> {
+        fun getDownloadableDepots(appId: Int, preferredLanguage: String): Map<Int, DepotInfo> {
             val appInfo = getAppInfoOf(appId) ?: return emptyMap()
             val ownedDlc = runBlocking { getOwnedAppDlc(appId) }
+            val normalizedLanguage = preferredLanguage.trim().lowercase().ifBlank { "english" }

             // If the game ships any 64-bit depot, prefer those and ignore x86 ones
             val has64Bit = appInfo.depots.values.any { it.osArch == OSArch.Arch64 }

             val map = appInfo.depots
                 .asSequence()
                 .filter { (depotId, depot) ->
-                    return@filter filterForDownloadableDepots(depot, has64Bit, preferredLanguage, ownedDlc)
+                    return@filter filterForDownloadableDepots(depot, has64Bit, normalizedLanguage, ownedDlc)
                 }
...
                     .filter { (depotId, depot) ->
-                        return@filter filterForDownloadableDepots(depot, has64Bit, preferredLanguage, null)
+                        return@filter filterForDownloadableDepots(depot, has64Bit, normalizedLanguage, null)
                     }
🤖 Fix all issues with AI agents
In `@app/src/main/java/app/gamenative/utils/SteamUtils.kt`:
- Around line 1199-1237: The manifest language should be normalized and
defaulted before writing: read container.language into userLanguage, trim and
normalize to lowercase (e.g., userLanguage =
container.language?.trim()?.lowercase()) and if empty or null set it to
"english", then use that normalized value wherever KeyValue("language",
userLanguage) or languageKey.value = userLanguage is assigned (affecting the
existing userConfig/mountedConfig handling and the final manifestData.saveToFile
call) so the manifest always contains a valid, lowercase language string.

@utkarshdalal utkarshdalal merged commit d7e2871 into utkarshdalal:master Feb 18, 2026
2 checks passed
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