diff --git a/src/lib/addons/themes/colors/patches/resolver.ts b/src/lib/addons/themes/colors/patches/resolver.ts index b81d581..c21b365 100644 --- a/src/lib/addons/themes/colors/patches/resolver.ts +++ b/src/lib/addons/themes/colors/patches/resolver.ts @@ -10,98 +10,103 @@ const tokenReference = findByProps("SemanticColor"); const isThemeModule = createLazyModule(byMutableProp("isThemeDark")); const SEMANTIC_FALLBACK_MAP: Record = { - BG_BACKDROP: "BACKGROUND_FLOATING", - BG_BASE_PRIMARY: "BACKGROUND_PRIMARY", - BG_BASE_SECONDARY: "BACKGROUND_SECONDARY", - BG_BASE_TERTIARY: "BACKGROUND_SECONDARY_ALT", - BG_MOD_FAINT: "BACKGROUND_MODIFIER_ACCENT", - BG_MOD_STRONG: "BACKGROUND_MODIFIER_ACCENT", - BG_MOD_SUBTLE: "BACKGROUND_MODIFIER_ACCENT", - BG_SURFACE_OVERLAY: "BACKGROUND_FLOATING", - BG_SURFACE_OVERLAY_TMP: "BACKGROUND_FLOATING", - BG_SURFACE_RAISED: "BACKGROUND_MOBILE_PRIMARY", + "BG_BACKDROP": "BACKGROUND_FLOATING", + "BG_BASE_PRIMARY": "BACKGROUND_PRIMARY", + "BG_BASE_SECONDARY": "BACKGROUND_SECONDARY", + "BG_BASE_TERTIARY": "BACKGROUND_SECONDARY_ALT", + "BG_MOD_FAINT": "BACKGROUND_MODIFIER_ACCENT", + "BG_MOD_STRONG": "BACKGROUND_MODIFIER_ACCENT", + "BG_MOD_SUBTLE": "BACKGROUND_MODIFIER_ACCENT", + "BG_SURFACE_OVERLAY": "BACKGROUND_FLOATING", + "BG_SURFACE_OVERLAY_TMP": "BACKGROUND_FLOATING", + "BG_SURFACE_RAISED": "BACKGROUND_MOBILE_PRIMARY" }; +const origRawColor = { ...tokenReference.RawColor }; + +function getRawFallback(key: string): string | undefined { + const isDark = isThemeModule.isThemeDark?.(_colorRef.current?.reference); + + if (!isDark) return undefined; + + const DARK_MODE_RAW_FALLBACK: Record = { + "PRIMARY_230": origRawColor.PRIMARY_700 || "#000000" + }; + + return DARK_MODE_RAW_FALLBACK[key]; +} + export default function patchDefinitionAndResolver() { - const callback = ([theme]: any[]) => - theme === _colorRef.key ? [_colorRef.current!.reference] : void 0; + const callback = ([theme]: any[]) => theme === _colorRef.key ? [_colorRef.current!.reference] : void 0; - Object.keys(tokenReference.RawColor).forEach((key) => { - Object.defineProperty(tokenReference.RawColor, key, { - configurable: true, - enumerable: true, - get: () => { - const ret = _colorRef.current?.raw[key]; - return ret || _colorRef.origRaw[key]; - }, + Object.keys(tokenReference.RawColor).forEach(key => { + Object.defineProperty(tokenReference.RawColor, key, { + configurable: true, + enumerable: true, + get: () => { + const ret = _colorRef.current?.raw[key]; + if (ret) return ret; + + const fallback = getRawFallback(key); + if (fallback) return fallback; + + return origRawColor[key]; + } + }); }); - }); - const unpatches = [ - before("isThemeDark", isThemeModule, callback), - before("isThemeLight", isThemeModule, callback), - before("updateTheme", NativeThemeModule, callback), - instead( - "resolveSemanticColor", - tokenReference.default.meta ?? tokenReference.default.internal, - (args: any[], orig: any) => { - if (!_colorRef.current) return orig(...args); - if (args[0] !== _colorRef.key) return orig(...args); + const unpatches = [ + before("isThemeDark", isThemeModule, callback), + before("isThemeLight", isThemeModule, callback), + before("updateTheme", NativeThemeModule, callback), + instead("resolveSemanticColor", tokenReference.default.meta ?? tokenReference.default.internal, (args: any[], orig: any) => { + if (!_colorRef.current) return orig(...args); + if (args[0] !== _colorRef.key) return orig(...args); - args[0] = _colorRef.current.reference; + args[0] = _colorRef.current.reference; - const [name, colorDef] = extractInfo( - _colorRef.current!.reference, - args[1], - ); + const [name, colorDef] = extractInfo(_colorRef.current!.reference, args[1]); - let semanticDef = _colorRef.current.semantic[name]; - if ( - !semanticDef && - _colorRef.current.spec === 2 && - name in SEMANTIC_FALLBACK_MAP - ) { - semanticDef = _colorRef.current.semantic[SEMANTIC_FALLBACK_MAP[name]]; + let semanticDef = _colorRef.current.semantic[name]; + if (!semanticDef && _colorRef.current.spec === 2 && name in SEMANTIC_FALLBACK_MAP) { + semanticDef = _colorRef.current.semantic[SEMANTIC_FALLBACK_MAP[name]]; + } + + if (semanticDef?.value) { + if (semanticDef.opacity === 1) return semanticDef.value; + return chroma(semanticDef.value).alpha(semanticDef.opacity).hex(); + } + + const rawValue = _colorRef.current.raw[colorDef.raw]; + if (rawValue) { + // Set opacity if needed + return colorDef.opacity === 1 ? rawValue : chroma(rawValue).alpha(colorDef.opacity).hex(); + } + + const fallbackValue = getRawFallback(colorDef.raw); + if (fallbackValue) { + return colorDef.opacity === 1 ? fallbackValue : chroma(fallbackValue).alpha(colorDef.opacity).hex(); + } + + // Fallback to default + return orig(...args); + }), + () => { + Object.defineProperty(tokenReference, "RawColor", { + configurable: true, + writable: true, + value: origRawColor + }); } + ]; - if (semanticDef?.value) { - if (semanticDef.opacity === 1) return semanticDef.value; - return chroma(semanticDef.value).alpha(semanticDef.opacity).hex(); - } - - const rawValue = _colorRef.current.raw[colorDef.raw]; - if (rawValue) { - // Set opacity if needed - return colorDef.opacity === 1 - ? rawValue - : chroma(rawValue).alpha(colorDef.opacity).hex(); - } - - // Fallback to default - return orig(...args); - }, - ), - () => { - // Not the actual module but.. yeah. - Object.defineProperty(tokenReference, "RawColor", { - configurable: true, - writable: true, - value: _colorRef.origRaw, - }); - }, - ]; - - return () => unpatches.forEach((p) => p()); + return () => unpatches.forEach(p => p()); } -function extractInfo( - themeName: string, - colorObj: any, -): [name: string, colorDef: any] { - // @ts-ignore - assigning to extractInfo._sym - const propName = - colorObj[(extractInfo._sym ??= Object.getOwnPropertySymbols(colorObj)[0])]; - const colorDef = tokenReference.SemanticColor[propName]; +function extractInfo(themeName: string, colorObj: any): [name: string, colorDef: any] { + // @ts-ignore - assigning to extractInfo._sym + const propName = colorObj[extractInfo._sym ??= Object.getOwnPropertySymbols(colorObj)[0]]; + const colorDef = tokenReference.SemanticColor[propName]; - return [propName, colorDef[themeName]]; + return [propName, colorDef[themeName]]; } diff --git a/src/lib/addons/themes/colors/updater.ts b/src/lib/addons/themes/colors/updater.ts index ad57bc8..c7b265b 100644 --- a/src/lib/addons/themes/colors/updater.ts +++ b/src/lib/addons/themes/colors/updater.ts @@ -13,64 +13,47 @@ const FormDivider = findByPropsLazy("DIVIDER_COLORS"); let _inc = 1; interface InternalColorRef { - key: `bn-theme-${string}`; - current: InternalColorDefinition | null; - readonly origRaw: Record; - lastSetDiscordTheme: string; + key: `bn-theme-${string}`; + current: InternalColorDefinition | null; + readonly origRaw: Record; + lastSetDiscordTheme: string; } /** @internal */ export const _colorRef: InternalColorRef = { - current: null, - key: `bn-theme-${_inc}`, - origRaw: origRawColor, - lastSetDiscordTheme: "darker", + current: null, + key: `bn-theme-${_inc}`, + origRaw: origRawColor, + lastSetDiscordTheme: "darker" }; -export function updateBunnyColor( - colorManifest: ColorManifest | null, - { update = true, startup = true }, -) { - if (settings.safeMode?.enabled) return; +export function updateBunnyColor(colorManifest: ColorManifest | null, { update = true } ) { + if (settings.safeMode?.enabled) return; - const internalDef = colorManifest ? parseColorManifest(colorManifest) : null; - const ref = Object.assign(_colorRef, { - current: internalDef, - key: `bn-theme-${++_inc}`, - lastSetDiscordTheme: !ThemeStore.theme.startsWith("bn-theme-") - ? ThemeStore.theme - : _colorRef.lastSetDiscordTheme, - }); - - if (internalDef != null) { - tokenRef.Theme[ref.key.toUpperCase()] = ref.key; - FormDivider.DIVIDER_COLORS[ref.key] = - FormDivider.DIVIDER_COLORS[ref.current!.reference]; - - 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], - }; + const internalDef = colorManifest ? parseColorManifest(colorManifest) : null; + const ref = Object.assign(_colorRef, { + current: internalDef, + key: `bn-theme-${++_inc}`, + lastSetDiscordTheme: !ThemeStore.theme.startsWith("bn-theme-") + ? ThemeStore.theme + : _colorRef.lastSetDiscordTheme }); - } - if (update) { - AppearanceManager.setShouldSyncAppearanceSettings(false); - AppearanceManager.updateTheme( - internalDef != null ? ref.key : ref.lastSetDiscordTheme, - ); - } + if (internalDef != null) { + tokenRef.Theme[ref.key.toUpperCase()] = ref.key; + FormDivider.DIVIDER_COLORS[ref.key] = FormDivider.DIVIDER_COLORS[ref.current!.reference]; - if (startup) { - // scuffed but it works - AppearanceManager.setShouldSyncAppearanceSettings(true); - AppearanceManager.updateTheme( - internalDef != null ? ref.key : ref.lastSetDiscordTheme, - ); - } + 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 (update) { + AppearanceManager.setShouldSyncAppearanceSettings(false); + AppearanceManager.updateTheme(internalDef != null ? ref.key : ref.lastSetDiscordTheme); + } } +