Skip to content

feat: automatic frontend sync for installed/uninstalled games#1454

Open
vitormf wants to merge 4 commits into
utkarshdalal:masterfrom
vitormf:feat/frontend-sync
Open

feat: automatic frontend sync for installed/uninstalled games#1454
vitormf wants to merge 4 commits into
utkarshdalal:masterfrom
vitormf:feat/frontend-sync

Conversation

@vitormf
Copy link
Copy Markdown

@vitormf vitormf commented May 18, 2026

Description

Expands the existing functionality that allowed exporting installed games to other frontends (such as ES-DE) by making it automatic. This is an optional feature, off by default, that can be enabled in the app settings. Once configured, the app listens to install and uninstall events and keeps the configured directories in sync automatically. A full resync can also be triggered on demand from the settings.

When the user configures a directory per store, the app writes a small marker file for each installed game into that directory. The file is named <Game Title>.<ext> (e.g. Half-Life 2.steam) and contains the app ID as its content. ES-DE and similar launchers can watch these directories to discover installed titles without needing direct access to the app's internal database.

What's included:

  • FrontendSyncManager — singleton that reacts to install/uninstall events and exposes resyncAll() / changeDirectory() with reactive StateFlow for UI
  • FrontendSyncDialog — per-source directory picker (Steam, Epic, GOG, Amazon, Custom) with OK/Cancel buffering; a confirmation prompt offers to delete old export files when changing or clearing a directory
  • Settings row shows a Resync All icon button (animated spinner while running, cancellable by tap) only when at least one directory is configured
  • PrefManager: getFrontendSyncDir / setFrontendSyncDir per GameSource
  • SteamAppDao: getInstalledGames() JOIN query against app_info — avoids the previous per-app filesystem marker checks that made full sync slow on large libraries
  • 9 unit tests covering extensionFor and deleteAllFilesWithExtension
  • Translated strings for all 13 supported locales

Recording

Screen_Recording_20260518_120309_GameNative.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 CodeRabbit

  • New Features

    • Frontend Sync: per-source export directories (Steam/Epic/GOG/Amazon/Custom), app startup sync, manual "Resync all" with progress indicator, and a Settings dialog to configure/clear export directories.
  • Improvements

    • Library install/uninstall events now include source info so UI and library status updates are more accurate.
  • Localization

    • Added Frontend Sync UI strings in multiple languages.
  • Tests

    • Added tests for file operations and source→extension mappings.

Review Change Stack

Automatically writes a small marker file per installed game into
user-configured directories, one directory per store (Steam, Epic,
GOG, Amazon, custom). ES-DE and other frontends can watch those
directories to discover installed titles without needing direct
access to the app's internal state.

- New FrontendSyncManager singleton: reacts to install/uninstall
  events and exposes resyncAll() + changeDirectory() with reactive
  StateFlow for UI
- FrontendSyncDialog: per-source directory picker with OK/Cancel
  buffering; confirmation prompt offers to delete old export files
  when changing or clearing a directory
- Settings row shows a Resync All icon button (animated spinner while
  running, cancellable by tap) only when at least one directory is
  configured
- PrefManager: getFrontendSyncDir / setFrontendSyncDir per GameSource
- SteamAppDao: getInstalledGames() JOIN query avoids per-app
  filesystem marker checks that made full sync slow
- 9 unit tests covering extensionFor and deleteAllFilesWithExtension
- Translated strings for all 13 supported locales
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cedf8afd-7398-4b05-a168-aea553767bd6

📥 Commits

Reviewing files that changed from the base of the PR and between 2e5a2e1 and f05fe2f.

📒 Files selected for processing (7)
  • app/src/main/java/app/gamenative/PrefManager.kt
  • app/src/main/java/app/gamenative/db/dao/AmazonGameDao.kt
  • app/src/main/java/app/gamenative/db/dao/EpicGameDao.kt
  • app/src/main/java/app/gamenative/db/dao/SteamAppDao.kt
  • app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt
  • app/src/main/java/app/gamenative/ui/screen/settings/FrontendSyncDialog.kt
  • app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt
🚧 Files skipped from review as they are similar to previous changes (6)
  • app/src/main/java/app/gamenative/db/dao/AmazonGameDao.kt
  • app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt
  • app/src/main/java/app/gamenative/ui/screen/settings/FrontendSyncDialog.kt
  • app/src/main/java/app/gamenative/PrefManager.kt
  • app/src/main/java/app/gamenative/db/dao/EpicGameDao.kt
  • app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt

📝 Walkthrough

Walkthrough

Adds a per-source frontend export sync: event payloads include GameSource, new DAO queries and prefs, a FrontendSyncManager singleton, settings UI and dialog, localized strings, and unit tests.

Changes

Frontend Sync Feature

Layer / File(s) Summary
Event contract, database, and preference storage
app/src/main/java/app/gamenative/events/AndroidEvent.kt, app/src/main/java/app/gamenative/PrefManager.kt, app/src/main/java/app/gamenative/db/dao/{SteamAppDao, EpicGameDao, AmazonGameDao}.kt
LibraryInstallStatusChanged event now includes source: GameSource. New getInstalledGames() DAO queries added. PrefManager stores per-source frontend sync directories and exposes getFrontendSyncDir()/setFrontendSyncDir().
FrontendSyncManager core implementation
app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt
Singleton manages initialization, registers install-status listener, resolves configured directories, writes/deletes per-game export files, supports resyncAll(), changeDirectory(), and provides isSyncing/anyConfigured state flows and file-cleanup helpers.
Application initialization
app/src/main/java/app/gamenative/PluviaApp.kt
Imports FrontendSyncManager and calls init(this) in onCreate() to start the manager at app startup.
Service & UI event emission updates
app/src/main/java/app/gamenative/service/*, app/src/main/java/app/gamenative/ui/*, app/src/main/java/app/gamenative/utils/ContainerStorageManager.kt
All places emitting AndroidEvent.LibraryInstallStatusChanged now pass the corresponding GameSource argument (STEAM, AMAZON, EPIC, GOG) across download completion, uninstall, cancellation, cleanup, and container operations.
Settings UI and configuration dialog
app/src/main/java/app/gamenative/ui/screen/settings/FrontendSyncDialog.kt, app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt
New FrontendSyncDialog composable lists sources with directory pickers and clear-confirmation flows; SettingsGroupInterface adds a resync button and links the dialog into settings.
Tests and localization
app/src/test/java/app/gamenative/sync/FrontendSyncManagerTest.kt, app/src/main/res/values*/strings.xml
Unit tests validate extensionFor() and deleteAllFilesWithExtension() behaviors. Added localized strings for the frontend sync UI across multiple locales (da,de,es,fr,it,ko,pl,pt-BR,ro,ru,uk,zh-CN,zh-TW and default).

Sequence Diagram(s)

sequenceDiagram
  participant EventBus
  participant FrontendSyncManager
  participant DAOs
  participant PrefManager
  participant FileSystem
  participant SettingsUI

  Note over FrontendSyncManager: Initialization
  FrontendSyncManager->>PrefManager: load configured dirs
  FrontendSyncManager->>DAOs: fetch installed games per source
  FrontendSyncManager->>FileSystem: write export files

  Note over FrontendSyncManager: Event-driven sync
  EventBus->>FrontendSyncManager: LibraryInstallStatusChanged(appId, source)
  FrontendSyncManager->>DAOs: lookup game name / installed state
  FrontendSyncManager->>FileSystem: write/delete game export file

  Note over SettingsUI: Manual resync
  SettingsUI->>FrontendSyncManager: resyncAll()
  FrontendSyncManager->>DAOs: fetch installed per source
  FrontendSyncManager->>FileSystem: recreate export files
  FrontendSyncManager->>SettingsUI: show completion snackbar
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • utkarshdalal

Poem

🐰 I hop through folders, nibble names so neat,

I leave a tiny note for every game you keep.
Sources marked and filenames tidy too,
I sync each list and blink — hooray for you! 🎮✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.79% 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 describes the main feature addition: automatic frontend sync for installed/uninstalled games, matching the core changeset.
Description check ✅ Passed The description provides comprehensive context including feature overview, component breakdown, recording, and checklist items. However, it does not fully match the template structure with clearly marked template sections.
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.

@vitormf vitormf marked this pull request as ready for review May 18, 2026 11:16
@vitormf vitormf requested a review from utkarshdalal as a code owner May 18, 2026 11:16
@vitormf vitormf changed the title feat: add ES-DE frontend sync feat: automatic frontend sync for installed/uninstalled games May 18, 2026
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: 8

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/screen/library/appscreen/EpicAppScreen.kt (1)

800-806: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Avoid double-emitting install-status for the same Epic delete action.

EpicService.deleteGame(...) already emits LibraryInstallStatusChanged; emitting it again here causes duplicate event handling for one user action.

Proposed fix
                             withContext(Dispatchers.Main) {
                                 BaseAppScreen.hideInstallDialog(appId)
                                 app.gamenative.PluviaApp.events.emit(app.gamenative.events.AndroidEvent.DownloadStatusChanged(gameId, false))
-                                app.gamenative.PluviaApp.events.emit(app.gamenative.events.AndroidEvent.LibraryInstallStatusChanged(gameId, app.gamenative.data.GameSource.EPIC))
                             }
🤖 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/appscreen/EpicAppScreen.kt`
around lines 800 - 806, The delete path is emitting LibraryInstallStatusChanged
twice: EpicService.deleteGame(...) already emits LibraryInstallStatusChanged, so
remove the redundant
app.gamenative.PluviaApp.events.emit(...AndroidEvent.LibraryInstallStatusChanged(...))
call after DownloadService.invalidateCache(); keep
DownloadService.invalidateCache(), the DownloadStatusChanged emit, and
BaseAppScreen.hideInstallDialog(appId) to preserve cache invalidation, UI
cleanup, and download-status notification.
🤖 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/sync/FrontendSyncManager.kt`:
- Around line 148-149: The code constructs marker filenames directly from game
titles (e.g., File(dir, "$gameName${extensionFor(source)}")), which allows
characters like '/' '\' or traversal patterns; add a sanitize helper (e.g.,
sanitizeFileName(name): strip/replace path separators and control chars, remove
leading/trailing dots/slashes, collapse ".." sequences, enforce a safe max
length and fall back to a safe default) and use it wherever filenames are built
(the File(...) call and the related usages around the other marker creation at
lines corresponding to extensionFor(source) and the other occurrence); ensure
you call sanitizeFileName(gameName) before composing
"$sanitized${extensionFor(source)}" so writes cannot escape dir or create
invalid filenames.
- Around line 162-189: The resyncAllInstalledGames logic in
syncAllInstalledGames currently only writes files for installed games and never
removes stale marker files, leaving deleted/uninstalled games present; update
syncAllInstalledGames (inside the function using targetDir, extensionFor and
games) to first enumerate existing marker files in targetDir with the correct
extension, compute the set of expected filenames from games.map {
"$name${extensionFor(source)}" }, delete any existing files not in that expected
set (handling IO exceptions with Timber.e), then proceed to write the current
installed entries as before so the directory is fully authoritative after a
resync.
- Around line 120-135: In changeDirectory capture the current
PrefManager.getFrontendSyncDir(source) into a local variable (e.g., oldPath)
before mutating configuredDirs and before launching the coroutine, then use that
captured oldPath inside the coroutine when calling
deleteAllFilesWithExtension(oldPath, extensionFor(source)) and when deciding
deletion, and still call PrefManager.setFrontendSyncDir(source, newPath) inside
the coroutine; this prevents stale or incorrect deletion when changeDirectory is
called rapidly.
- Around line 109-112: The iteration over configuredDirs in resyncAll (the
forEach calling ensureActive() and syncAllInstalledGames) is not safe against
concurrent mutations by changeDirectory(); wrap both iteration sites (lines
around the forEach and the similar block at 122-127) with a single consistent
lock (e.g., synchronize on a private mutex object or use
synchronized(configuredDirs)) so that changeDirectory() also acquires the same
lock before mutating configuredDirs; ensure syncAllInstalledGames and
ensureActive remain called while holding that lock to prevent concurrent
modification or missed entries.

In `@app/src/main/java/app/gamenative/ui/screen/settings/FrontendSyncDialog.kt`:
- Around line 128-137: The folder and clear IconButton controls in
FrontendSyncDialog currently set contentDescription = null which makes them
inaccessible; update the IconButton usages that call picker.launchPicker() and
the clear button (which sets pendingPath = "" and showConfirm = true) to provide
meaningful contentDescription strings (ideally from string resources, e.g.,
"select directory" and "clear selection" or their localized equivalents) so
TalkBack/Accessibility services can announce the buttons; ensure descriptions
are non-null, localized via stringResource, and remain null only for purely
decorative icons elsewhere.

In
`@app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt`:
- Around line 102-107: The IconButton currently replaces its icon with a bare
CircularProgressIndicator when isSyncing, removing the spoken label; preserve
accessibility by supplying a contentDescription or semantics label for the
control even while loading. Update the IconButton/CircularProgressIndicator
rendering in SettingsGroupInterface (the IconButton onClick = {
FrontendSyncManager.resyncAll() } and the isSyncing branch) to include an
explicit contentDescription or Modifier.semantics {
contentDescription("Resyncing" or "Resync now") } on the spinner or on the
IconButton so screen readers still announce the purpose while the spinner is
shown.

In `@app/src/main/res/values-fr/strings.xml`:
- Line 1486: The French string resource frontend_sync_clear_confirm_title
contains a stray backslash before the apostrophe ("d\’export") causing a visible
backslash in the UI; remove the backslash so the value reads "Supprimer les
anciens fichiers d’export ?" (i.e., update the string value for
frontend_sync_clear_confirm_title to the correct French text without the
backslash).

In `@app/src/main/res/values-zh-rTW/strings.xml`:
- Line 1549: The string resource frontend_sync_source_custom currently uses
"自定義遊戲" which is inconsistent with the file's regional phrasing; update the
value for the resource named frontend_sync_source_custom to use "自訂遊戲" to match
other keys like custom_games_title and maintain consistent Traditional Chinese
(zh-rTW) terminology across the file.

---

Outside diff comments:
In
`@app/src/main/java/app/gamenative/ui/screen/library/appscreen/EpicAppScreen.kt`:
- Around line 800-806: The delete path is emitting LibraryInstallStatusChanged
twice: EpicService.deleteGame(...) already emits LibraryInstallStatusChanged, so
remove the redundant
app.gamenative.PluviaApp.events.emit(...AndroidEvent.LibraryInstallStatusChanged(...))
call after DownloadService.invalidateCache(); keep
DownloadService.invalidateCache(), the DownloadStatusChanged emit, and
BaseAppScreen.hideInstallDialog(appId) to preserve cache invalidation, UI
cleanup, and download-status notification.
🪄 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: d80db9c7-aa26-48f5-bf51-24a4198042a4

📥 Commits

Reviewing files that changed from the base of the PR and between 089e177 and 6ce8eb3.

📒 Files selected for processing (35)
  • app/src/main/java/app/gamenative/PluviaApp.kt
  • app/src/main/java/app/gamenative/PrefManager.kt
  • app/src/main/java/app/gamenative/db/dao/AmazonGameDao.kt
  • app/src/main/java/app/gamenative/db/dao/EpicGameDao.kt
  • app/src/main/java/app/gamenative/db/dao/SteamAppDao.kt
  • app/src/main/java/app/gamenative/events/AndroidEvent.kt
  • app/src/main/java/app/gamenative/service/SteamService.kt
  • app/src/main/java/app/gamenative/service/amazon/AmazonService.kt
  • app/src/main/java/app/gamenative/service/epic/EpicDownloadManager.kt
  • app/src/main/java/app/gamenative/service/epic/EpicService.kt
  • app/src/main/java/app/gamenative/service/gog/GOGDownloadManager.kt
  • app/src/main/java/app/gamenative/service/gog/GOGManager.kt
  • app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt
  • app/src/main/java/app/gamenative/ui/model/DownloadsViewModel.kt
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/AmazonAppScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/EpicAppScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/library/appscreen/SteamAppScreen.kt
  • app/src/main/java/app/gamenative/ui/screen/settings/FrontendSyncDialog.kt
  • app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt
  • app/src/main/java/app/gamenative/utils/ContainerStorageManager.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
  • app/src/test/java/app/gamenative/sync/FrontendSyncManagerTest.kt

Comment thread app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt Outdated
Comment thread app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt
Comment thread app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt Outdated
Comment thread app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt
Comment thread app/src/main/java/app/gamenative/ui/screen/settings/SettingsGroupInterface.kt Outdated
Comment thread app/src/main/res/values-fr/strings.xml Outdated
Comment thread app/src/main/res/values-zh-rTW/strings.xml 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.

7 issues found across 35 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/ui/screen/settings/FrontendSyncDialog.kt">

<violation number="1" location="app/src/main/java/app/gamenative/ui/screen/settings/FrontendSyncDialog.kt:44">
P2: Buffered changes map uses `remember` while row display state uses `rememberSaveable`, causing pending edits to be lost after configuration changes while the UI still shows them.</violation>
</file>

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

Re-trigger cubic

Comment thread app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt Outdated
GameSource.CUSTOM_GAME to stringResource(R.string.frontend_sync_source_custom),
)
// Buffered changes: source → (newPath, deleteOldFiles). Applied only on OK.
val pendingChanges = remember { mutableStateMapOf<GameSource, Pair<String, Boolean>>() }
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.

P2: Buffered changes map uses remember while row display state uses rememberSaveable, causing pending edits to be lost after configuration changes while the UI still shows them.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At app/src/main/java/app/gamenative/ui/screen/settings/FrontendSyncDialog.kt, line 44:

<comment>Buffered changes map uses `remember` while row display state uses `rememberSaveable`, causing pending edits to be lost after configuration changes while the UI still shows them.</comment>

<file context>
@@ -0,0 +1,173 @@
+        GameSource.CUSTOM_GAME to stringResource(R.string.frontend_sync_source_custom),
+    )
+    // Buffered changes: source → (newPath, deleteOldFiles). Applied only on OK.
+    val pendingChanges = remember { mutableStateMapOf<GameSource, Pair<String, Boolean>>() }
+
+    AlertDialog(
</file context>

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 2e5a2e1 — changed displayPath from rememberSaveable to remember to make both consistent: vitormf@2e5a2e1e

Comment thread app/src/main/java/app/gamenative/db/dao/EpicGameDao.kt Outdated
Comment thread app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt Outdated
Comment thread app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt
Comment thread app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt
Comment thread app/src/main/java/app/gamenative/sync/FrontendSyncManager.kt
- Sanitize game titles before using as filenames (strip path separators)
- Re-throw CancellationException so job cancellation actually stops sync
- Snapshot configuredDirs before iterating in resyncAll (thread safety)
- Capture oldPath synchronously in changeDirectory before coroutine launch
- Clear stale marker files before rewriting in syncAllInstalledGames
- Add DLC/UE namespace filters to EpicGameDao.getInstalledGames()
- Fix French backslash in frontend_sync_clear_confirm_title
- Fix zh-rTW custom games translation inconsistency
@vitormf
Copy link
Copy Markdown
Author

vitormf commented May 18, 2026

Hi, I couldn't find the #code-changes channel to discuss it previously, but I think this can be useful for people who'd prefer to access the games from other frontends, such as ES-DE.

- Add contentDescription to folder/clear icon buttons in FrontendSyncDialog
- Add semantics label to resync IconButton so TalkBack works during spinner
- Align displayPath state scope with pendingChanges (both use remember)
@vitormf
Copy link
Copy Markdown
Author

vitormf commented May 18, 2026

@phobos665 given your work on #423 and your suggestion in #751 about the file-based approach, would love your thoughts on this!

Covers FrontendSyncManager, FrontendSyncDialog, SettingsGroupInterface,
the new DAO queries, and PrefManager helpers to satisfy the docstring
coverage threshold flagged in code review.
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