Skip to content

feat: Community Settings Sharing - #564

Open
maxjivi05 wants to merge 17 commits into
WinNative-Emu:mainfrom
maxjivi05:community-configs
Open

feat: Community Settings Sharing#564
maxjivi05 wants to merge 17 commits into
WinNative-Emu:mainfrom
maxjivi05:community-configs

Conversation

@maxjivi05

Copy link
Copy Markdown
Contributor

No description provided.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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 👍 / 👎.

@Xnick417x

Copy link
Copy Markdown
Collaborator

Needs proper ui. See Workshop and Achievements in latest pr. Background should be (WsBg)
Needs to ensure proper PANE_NAV (aka controller navigation)
Needs to ensure all strings are translated to all locales

@Xnick417x
Xnick417x marked this pull request as draft July 1, 2026 04:02
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.
@maxjivi05
maxjivi05 marked this pull request as ready for review August 2, 2026 18:38

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 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() }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge 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.
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