fix(review): make WebGL toggle per-device and fix sticky-marker semantics (PR #140)

- saveAppSettings no longer sends webglRendererEnabled on the settings PUT:
  the key is absent from the .strict() SettingsUpdateSchema, so every save
  400'd with INVALID_INPUT, silently killing all server-side settings
  persistence. Stripped in the per-device destructure alongside
  localEchoEnabled/skin/etc.
- shouldSkipWebGL now treats a stored true like the untouched default w.r.t.
  the sticky marker: the checkbox defaults checked on desktop, so any
  unrelated save stored true and every page load then cleared the
  'codeman-webgl-disabled' marker, permanently defeating the GPU-stall
  auto-fallback. Only ?webgl=force clears the marker at init.
- The marker is instead retired on a real OFF->ON toggle flip detected at
  save time (mirrors the _prevGestureEnabled pattern in settings-ui.js).
- webglRendererEnabled added to the displayKeys per-device set in
  loadAppSettingsFromServer (renderer choice is device/GPU-specific; syncing
  would leak mobile's hidden-checkbox false onto desktop).
- Tests: stored true + sticky marker -> still skips WebGL; OFF->ON save
  clears the marker and keeps the key off the wire; default-checked save
  leaves the marker alone; ?webgl=force / ?nowebgl behavior unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Codeman maintainer
2026-07-12 12:42:36 +02:00
parent bf36eb0db4
commit 7fa52cdcd6
4 changed files with 109 additions and 12 deletions
+10 -5
View File
@@ -120,8 +120,14 @@ function evaluateWebGLLongTaskTrip(recent, entries, now, config = WEBGL_FALLBACK
* Precedence (desktop only — mobile always skips):
* 1. user toggle OFF -> skip (one-shot opt-out, sticky untouched)
* 2. ?nowebgl -> skip (one-shot opt-out, sticky untouched)
* 3. user toggle ON / ?webgl=force -> enable + clear stale sticky marker
* 4. untouched (default on) -> respect the auto-fallback sticky marker
* 3. ?webgl=force -> enable + clear stale sticky marker
* 4. toggle ON / untouched -> respect the auto-fallback sticky marker
*
* A stored `true` is treated like the untouched default here: the checkbox
* ships checked on desktop, so any unrelated settings save stores `true` —
* letting it clear the marker would permanently defeat the GPU-stall
* auto-fallback safety net. The marker is only retired by ?webgl=force or by
* a real OFF->ON toggle flip, which saveAppSettings() detects at save time.
*
* @param {{deviceType?: string, noWebglParam?: boolean, forceParam?: boolean,
* stickyDisabled?: boolean, userPrefEnabled?: (boolean|undefined)}} [input]
@@ -129,10 +135,9 @@ function evaluateWebGLLongTaskTrip(recent, entries, now, config = WEBGL_FALLBACK
*/
function shouldSkipWebGL(input = {}) {
if (input.deviceType !== 'desktop') return { skip: true, clearSticky: false };
const pref = input.userPrefEnabled; // true | false | undefined (default on)
if (pref === false) return { skip: true, clearSticky: false };
if (input.userPrefEnabled === false) return { skip: true, clearSticky: false };
if (input.noWebglParam) return { skip: true, clearSticky: false };
if (pref === true || input.forceParam) return { skip: false, clearSticky: true };
if (input.forceParam) return { skip: false, clearSticky: true };
return { skip: !!input.stickyDisabled, clearSticky: false };
}