feat: Community Settings Sharing - #564
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e4bee40978
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // WineInfo resolves bundled/main versions; only flag if clearly a | ||
| // managed profile name that isn't installed. | ||
| val resolved = runCatching { | ||
| WineInfo.fromIdentifier(context, contentsManager, wineVer) |
There was a problem hiding this comment.
Check Wine profile presence without fallback
When a config requests a Wine/Proton identifier that is not installed, this check treats it as present because WineInfo.fromIdentifier() is not an existence check: it falls back to the bundled MAIN_WINE_VERSION instead of returning null for unrecognized or missing identifiers. As a result, the missing-component dialog is skipped and the config is applied with the wrong Wine runtime for games that require a custom Wine/Proton build; please check the installed profile names directly before considering it resolved.
Useful? React with 👍 / 👎.
| val s = JSONObject() | ||
|
|
||
| fun put(key: String, value: String?) { | ||
| if (!value.isNullOrBlank()) s.put(key, value) |
There was a problem hiding this comment.
Serialize disabled shortcut-only settings
This drops settings whose disabled state is represented by an absent or blank extra, such as sgsrEnabled, fpsLimit, and refreshRate. Since ConfigApplier.apply() only writes keys that are present and never clears existing allowed extras, applying a config where those options are off to a shortcut that currently has them on leaves the old values enabled, so the applied result is not the shared config; please encode explicit disabled values or clear absent allowed keys during apply.
Useful? React with 👍 / 👎.
|
Needs proper ui. See Workshop and Achievements in latest pr. Background should be (WsBg) |
Resolve conflicts in .gitignore, app/build.gradle, GameSettings.kt and ShortcutSettingsComposeDialog.kt by keeping both sides: main's controller nav, artwork scraper and ReShade catalog alongside the community config sharing UI, preview mode and HMAC build config.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 90d58ffd96
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| .onSuccess { configs = it.configs; deviceDisplay = it.deviceDisplay; loading = false } | ||
| .onFailure { error = it.message ?: "Failed to load"; loading = false } | ||
| } | ||
| LaunchedEffect(filter) { reload() } |
There was a problem hiding this comment.
Delay list load until identity resolves
When the download dialog is opened after an app start, this initial reload can run before the asynchronous UploaderIdentity.resolveGoogle() started by CommunityController has populated cachedGoogleId, so CommunityApiClient signs the list request with the fallback device UUID. In that state the server computes ownedByMe/myVote for the wrong uploader, hiding Delete and showing stale vote state for a signed-in user's own configs, and there is no reload when the Google identity callback later completes.
Useful? React with 👍 / 👎.
| val v = version.lowercase() | ||
| return installed.any { name -> | ||
| val n = name.lowercase() | ||
| n == v || n.endsWith(v) || n.contains(v) || v.contains(n) |
There was a problem hiding this comment.
Require exact component version matches
Separate from the Wine resolver issue, this matcher treats an installed component whose name is a substring of the requested version as present; for example, with only DXVK 2.4 installed, a config requiring 2.4.1 passes because v.contains(n) is true for the bare verName added by installedNames. That skips the missing-component guard and applies a config with a runtime version the device does not actually have, so version matching should avoid the reverse substring case or compare normalized identifiers exactly.
Useful? React with 👍 / 👎.
| * If anything is missing, show the MISSING COMPONENT overlay and do nothing. | ||
| */ | ||
| private fun applyPreview() { | ||
| saveSettings() // writes edited UI state into the temp shortcut |
There was a problem hiding this comment.
Avoid regular saves while applying preview
In preview mode, this calls the normal shortcut save path before the missing-component check. If the user changes the Container dropdown in the preview and then taps Apply, saveSettings() takes its container-change branch, copies the temporary cache .desktop into the selected container's Desktop, deletes only the original temp file, and refreshes the library even if the subsequent component check fails; preview apply should serialize the edited state without those save/move side effects or hide container switching.
Useful? React with 👍 / 👎.
Add CommunitySettings as the single source of truth for which shortcut settings are portable, with per-key validators, container defaults and the runtime's own resolution order. ConfigSerializer and ConfigApplier now derive from it, so they cannot drift apart, and a Gradle check fails the build when a newly persisted shortcut setting is neither shared nor explicitly excluded. Share the seven settings that were being dropped: zinkMode, useUnixLibs, screenTouchMode and the four ReShade keys. Resolve refreshRate through the container the way the runtime does, clear portable keys a config omits so an applied config is the uploader's config rather than a merge, and check downloaded values against the same rules the server enforces. Restyle the community dialogs onto the shared palette and wire controller navigation through the config browser, report dialog, missing-component dialog and the Download/Upload header buttons. Share one OkHttpClient, cap response reads, guard an unconfigured build instead of failing at signing time, and replace the per-apply executor with the shared IO dispatcher.
Wrap the Download and Upload entry points so a setup or runtime failure names the exception instead of taking the process down. Move the Download/Upload buttons into the scrolling sidebar list so they scroll away with the sections while the game name stays pinned, and bring them back into view when the controller cursor lands on them. Resolve the hardware block once per process instead of forking getprop on the UI thread every time the browser opens.
The deployed API only accepts schemaVersion 1 and rejects any key it does not know, so an app that sends version 2 fails the whole upload. Retry once against the older contract with the keys that version accepted, and report the settings that were left behind rather than failing outright. Uploads now work against either server; once the API is updated the first attempt succeeds and nothing is dropped.
ContentDialog inherited the default cutout mode while the host activity theme uses shortEdges, so on a device with a camera cutout the dialog window was letterboxed into the safe area and its centre gravity landed off-centre. Give ContentDialog the activity's cutout mode on API 27+ via a shared base style, and size the community browser against the navigation-bar and cutout insets the way the shortcut settings dialog already does, so the panel spans the real centre without sitting under the camera.
An absent GitHub secret still exports the variable, as an empty string, so COMMUNITY_API_BASE overrode its own default with "" and disabled community sharing even when the HMAC secret was present. Treat blank as unset for both, and warn during configuration when the secret is missing so the build log says why sharing is off instead of leaving it to be discovered on device.
Build.SOC_MODEL reports "unknown" on many devices, which is not blank, so it was used verbatim as the chipset and bucketed unrelated hardware together. Reject placeholder values, widen the property fallbacks, and send the board platform alongside the SoC model instead of collapsing them, so the read path keys the same way the upload path already did - a device could previously upload a config and then fail to find it. The sign-in prompt fired whenever the cached Play Games id had not resolved yet, so it appeared and was then contradicted by a successful upload moments later. Only prompt once an interactive sign-in is actually required. Deleting a config now asks first; it removes the config for everyone.
No description provided.