diff --git a/src/lib/addons/themes/colors/updater.ts b/src/lib/addons/themes/colors/updater.ts index 6a3c80f..daeadd8 100644 --- a/src/lib/addons/themes/colors/updater.ts +++ b/src/lib/addons/themes/colors/updater.ts @@ -40,19 +40,55 @@ export function updateBunnyColor(colorManifest: ColorManifest | null, { update = }); if (internalDef != null) { - tokenRef.Theme[ref.key.toUpperCase()] = ref.key; - FormDivider.DIVIDER_COLORS[ref.key] = FormDivider.DIVIDER_COLORS[ref.current!.reference]; + // Register the synthetic key BEFORE calling native, and verify it actually + // landed in every table native reads from. If any registration step fails, + // bail out to a known-good theme instead of handing native an unknown key. + try { + tokenRef.Theme[ref.key.toUpperCase()] = ref.key; - Object.keys(tokenRef.Shadow).forEach(k => tokenRef.Shadow[k][ref.key] = tokenRef.Shadow[k][ref.current!.reference]); - Object.keys(tokenRef.SemanticColor).forEach(k => { - tokenRef.SemanticColor[k][ref.key] = { - ...tokenRef.SemanticColor[k][ref.current!.reference] - }; - }); + if (!FormDivider.DIVIDER_COLORS[ref.current!.reference]) { + throw new Error(`Missing divider color reference: ${ref.current!.reference}`); + } + FormDivider.DIVIDER_COLORS[ref.key] = FormDivider.DIVIDER_COLORS[ref.current!.reference]; + + Object.keys(tokenRef.Shadow).forEach(k => { + if (!(ref.current!.reference in tokenRef.Shadow[k])) { + throw new Error(`Missing shadow reference: ${ref.current!.reference}`); + } + tokenRef.Shadow[k][ref.key] = tokenRef.Shadow[k][ref.current!.reference]; + }); + + Object.keys(tokenRef.SemanticColor).forEach(k => { + if (!(ref.current!.reference in tokenRef.SemanticColor[k])) { + throw new Error(`Missing semantic color reference: ${ref.current!.reference}`); + } + tokenRef.SemanticColor[k][ref.key] = { + ...tokenRef.SemanticColor[k][ref.current!.reference] + }; + }); + } catch (e) { + console.error("Failed to register custom theme key, falling back", e); + ref.current = null; // force fallback path below + } } if (update) { AppearanceManager.setShouldSyncAppearanceSettings(false); - AppearanceManager.updateTheme(internalDef != null ? ref.key : ref.lastSetDiscordTheme); + + const targetTheme = ref.current != null ? ref.key : ref.lastSetDiscordTheme; + + // This is the actual crash site: a raw call into native code with no + // guard. Wrap it so a native-side rejection can't take the whole + // bridge/thread down — fall back to the last known-good Discord theme. + try { + AppearanceManager.updateTheme(targetTheme); + } catch (e) { + console.error(`Native rejected theme "${targetTheme}", reverting to "${ref.lastSetDiscordTheme}"`, e); + try { + AppearanceManager.updateTheme(ref.lastSetDiscordTheme); + } catch (e2) { + console.error("Fallback theme also failed to apply", e2); + } + } } }