fix(themes): correct themes loading on v307.5+

This commit is contained in:
cocobo1 2025-11-24 12:52:30 +02:00
parent 85af53e537
commit ee81cf5be5
7 changed files with 5 additions and 155 deletions

View file

@ -5,7 +5,6 @@
"name": "Kettu",
"dependencies": {
"@gullerya/object-observer": "^6.1.4",
"@shopify/react-native-skia": "^1.12.4",
"@tanstack/react-query": "^5.83.0",
"@types/chroma-js": "~2.4.5",
"@types/lodash": "~4.17.20",
@ -473,8 +472,6 @@
"@semantic-release/release-notes-generator": ["@semantic-release/release-notes-generator@14.0.3", "", { "dependencies": { "conventional-changelog-angular": "^8.0.0", "conventional-changelog-writer": "^8.0.0", "conventional-commits-filter": "^5.0.0", "conventional-commits-parser": "^6.0.0", "debug": "^4.0.0", "get-stream": "^7.0.0", "import-from-esm": "^2.0.0", "into-stream": "^7.0.0", "lodash-es": "^4.17.21", "read-package-up": "^11.0.0" }, "peerDependencies": { "semantic-release": ">=20.1.0" } }, "sha512-XxAZRPWGwO5JwJtS83bRdoIhCiYIx8Vhr+u231pQAsdFIAbm19rSVJLdnBN+Avvk7CKvNQE/nJ4y7uqKH6WTiw=="],
"@shopify/react-native-skia": ["@shopify/react-native-skia@1.12.4", "", { "dependencies": { "canvaskit-wasm": "0.40.0", "react-reconciler": "0.27.0" }, "peerDependencies": { "react": ">=18.0 <19.0.0", "react-native": ">=0.64 <0.78.0", "react-native-reanimated": ">=2.0.0" }, "optionalPeers": ["react-native", "react-native-reanimated"], "bin": { "setup-skia-web": "scripts/setup-canvaskit.js" } }, "sha512-8QDIBKSU7XB3Lc1kAv4jSFddTQK8AE+1AEoJnQLNllsiex1gufLQ8kN7rs9zii+iboSY8tYKT7ocV+5cE2Exdw=="],
"@sinclair/typebox": ["@sinclair/typebox@0.27.8", "", {}, "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA=="],
"@sindresorhus/is": ["@sindresorhus/is@4.6.0", "", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="],
@ -569,8 +566,6 @@
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
"@webgpu/types": ["@webgpu/types@0.1.21", "", {}, "sha512-pUrWq3V5PiSGFLeLxoGqReTZmiiXwY3jRkIG5sLLKjyqNxrwm/04b4nw7LSmGWJcKk59XOM/YRTUwOzo4MMlow=="],
"JSONStream": ["JSONStream@1.3.5", "", { "dependencies": { "jsonparse": "^1.2.0", "through": ">=2.2.7 <3" }, "bin": { "JSONStream": "./bin.js" } }, "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ=="],
"abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="],
@ -685,8 +680,6 @@
"caniuse-lite": ["caniuse-lite@1.0.30001727", "", {}, "sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q=="],
"canvaskit-wasm": ["canvaskit-wasm@0.40.0", "", { "dependencies": { "@webgpu/types": "0.1.21" } }, "sha512-Od2o+ZmoEw9PBdN/yCGvzfu0WVqlufBPEWNG452wY7E9aT8RBE+ChpZF526doOlg7zumO4iCS+RAeht4P0Gbpw=="],
"chalk": ["chalk@5.4.1", "", {}, "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w=="],
"char-regex": ["char-regex@1.0.2", "", {}, "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw=="],
@ -1413,8 +1406,6 @@
"react-native-reanimated": ["react-native-reanimated@3.19.0", "", { "dependencies": { "@babel/plugin-transform-arrow-functions": "^7.0.0-0", "@babel/plugin-transform-class-properties": "^7.0.0-0", "@babel/plugin-transform-classes": "^7.0.0-0", "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", "@babel/plugin-transform-optional-chaining": "^7.0.0-0", "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", "@babel/plugin-transform-template-literals": "^7.0.0-0", "@babel/plugin-transform-unicode-regex": "^7.0.0-0", "@babel/preset-typescript": "^7.16.7", "convert-source-map": "^2.0.0", "invariant": "^2.2.4", "react-native-is-edge-to-edge": "1.1.7" }, "peerDependencies": { "@babel/core": "^7.0.0-0", "react": "*", "react-native": "*" } }, "sha512-FNfqLuPuVHsW9KcsZtnJqIPlMQvuySnSFJXgSt9fVDPqptbSUkiAF6MthUwd4Mxt05hCRcbV+T65CENgVS5iCg=="],
"react-reconciler": ["react-reconciler@0.27.0", "", { "dependencies": { "loose-envify": "^1.1.0", "scheduler": "^0.21.0" }, "peerDependencies": { "react": "^18.0.0" } }, "sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA=="],
"react-refresh": ["react-refresh@0.14.2", "", {}, "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA=="],
"read-package-up": ["read-package-up@11.0.0", "", { "dependencies": { "find-up-simple": "^1.0.0", "read-pkg": "^9.0.0", "type-fest": "^4.6.0" } }, "sha512-MbgfoNPANMdb4oRBNg5eqLbB2t2r+o5Ua1pNt8BqGp4I0FJZhuVSOj3PaBPni4azWuSzEdNn2evevzVmEk1ohQ=="],
@ -2219,8 +2210,6 @@
"react-native/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"react-reconciler/scheduler": ["scheduler@0.21.0", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ=="],
"read-pkg/parse-json": ["parse-json@8.3.0", "", { "dependencies": { "@babel/code-frame": "^7.26.2", "index-to-position": "^1.1.0", "type-fest": "^4.39.1" } }, "sha512-ybiGyvspI+fAoRQbIPRddCcSTV9/LsJbf0e/S85VLowVGzRmokfneg2kwVW/KU5rOXrPSbF1qAKPMgNTqqROQQ=="],
"read-pkg/unicorn-magic": ["unicorn-magic@0.1.0", "", {}, "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ=="],

View file

@ -38,7 +38,6 @@
},
"dependencies": {
"@gullerya/object-observer": "^6.1.4",
"@shopify/react-native-skia": "^1.12.4",
"@tanstack/react-query": "^5.83.0",
"@types/chroma-js": "~2.4.5",
"@types/lodash": "~4.17.20",

View file

@ -1,4 +1,4 @@
// import patchErrorBoundary from "@core/debug/patches/patchErrorBoundary";
import patchErrorBoundary from "@core/debug/patches/patchErrorBoundary";
import initFixes from "@core/fixes";
import { initFetchI18nStrings } from "@core/i18n";
import initSettings from "@core/ui/settings";
@ -13,7 +13,6 @@ import { injectFluxInterceptor } from "@lib/api/flux";
import { patchJsx } from "@lib/api/react/jsx";
import { logger } from "@lib/utils/logger";
import { patchSettings } from "@ui/settings";
import { getDebugInfo } from "@lib/api/debug";
import * as lib from "./lib";
@ -31,7 +30,7 @@ export default async () => {
initFetchI18nStrings(),
initSettings(),
initFixes(),
// patchErrorBoundary(),
patchErrorBoundary(),
updatePlugins(),
updateFonts(),
initPlugins(),

View file

@ -1,5 +1,3 @@
import fixStatusBar from "./statusbar";
import fixKeyboard from "./keyboard";
import patchChatBackground from "./patches/background";
import patchDefinitionAndResolver from "./patches/resolver";
import patchStorage from "./patches/storage";
@ -8,16 +6,13 @@ import { updateBunnyColor } from "./updater";
/** @internal */
export default function initColors(manifest: ColorManifest | null) {
if (manifest) updateBunnyColor(manifest, { update: false });
const patches = [
patchStorage(),
patchDefinitionAndResolver(),
patchChatBackground()
];
fixStatusBar();
fixKeyboard();
if (manifest) updateBunnyColor(manifest, { update: false });
return () => patches.forEach(p => p());
}
}

View file

@ -1,64 +0,0 @@
import { TextInput, Platform, NativeModules } from "react-native";
import { findByStoreNameLazy } from "@metro/wrappers";
import { _colorRef } from "./updater";
const ThemeStore = findByStoreNameLazy("ThemeStore");
function getKeyboardAppearance() {
// Check for custom theme
const custom = _colorRef.current;
if (custom) {
// Bunny theme (spec 3)
if (custom.spec === 3 && custom.reference) {
return custom.reference === "light" ? "light" : "dark";
}
// Vendetta theme (spec 2)
if (custom.spec === 2 && custom.reference) {
return custom.reference === "light" ? "light" : "dark";
}
}
// Fallback to Discord theme string
const theme = ThemeStore?.theme;
if (typeof theme === "string") {
const lowerTheme = theme.toLowerCase();
return (lowerTheme.includes("dark") || lowerTheme.includes("midnight"))
? "dark"
: "light";
}
return "dark";
}
export default function fixKeyboard() {
if (Platform.OS !== "ios") return;
const UIManager = NativeModules.UIManager;
const origUpdateView = UIManager?.updateView;
const origCreateView = UIManager?.createView;
if (origUpdateView) {
UIManager.updateView = function(viewTag: number, viewName: string, props: any) {
if (props && typeof props === 'object') {
if (viewName.toLowerCase().includes('text') || viewName.toLowerCase().includes('input')) {
props.keyboardAppearance = getKeyboardAppearance();
}
}
return origUpdateView.call(this, viewTag, viewName, props);
};
}
if (origCreateView) {
UIManager.createView = function(reactTag: number, viewName: string, rootTag: number, props: any) {
if (props && typeof props === 'object') {
if (viewName.toLowerCase().includes('text') || viewName.toLowerCase().includes('input')) {
props.keyboardAppearance = getKeyboardAppearance();
}
}
return origCreateView.call(this, reactTag, viewName, rootTag, props);
};
}
return ThemeStore?.addChangeListener?.(() => {});
}

View file

@ -24,18 +24,6 @@ const SEMANTIC_FALLBACK_MAP: Record<string, string> = {
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<string, string> = {
"PRIMARY_230": origRawColor.PLUM_19 || "#000000"
};
return DARK_MODE_RAW_FALLBACK[key];
}
export default function patchDefinitionAndResolver() {
const callback = ([theme]: any[]) => theme === _colorRef.key ? [_colorRef.current!.reference] : void 0;
@ -47,9 +35,6 @@ export default function patchDefinitionAndResolver() {
const ret = _colorRef.current?.raw[key];
if (ret) return ret;
const fallback = getRawFallback(key);
if (fallback) return fallback;
return origRawColor[key];
}
});
@ -83,11 +68,6 @@ export default function patchDefinitionAndResolver() {
return colorDef.opacity === 1 ? rawValue : chroma(rawValue).alpha(colorDef.opacity).hex();
}
const fallbackValue = getRawFallback(colorDef.raw);
if (fallbackValue) {
return colorDef.opacity === 0 ? fallbackValue : chroma(fallbackValue).alpha(colorDef.opacity).hex();
}
// Fallback to default
return orig(...args);
}),

View file

@ -1,48 +0,0 @@
import { StatusBar, TextInput, Platform } from "react-native";
import { findByStoreNameLazy } from "@metro/wrappers";
import { _colorRef } from "./updater";
const ThemeStore = findByStoreNameLazy("ThemeStore");
function getBarStyle() {
// Check for custom theme
const custom = _colorRef.current;
if (custom) {
// Bunny theme (spec 3)
if (custom.spec === 3 && custom.reference) {
return custom.reference === "light" ? "dark-content" : "light-content";
}
// Vendetta theme (spec 2)
if (custom.spec === 2 && custom.reference) {
return custom.reference === "light" ? "dark-content" : "light-content";
}
}
// Fallback to Discord theme string
const theme = ThemeStore?.theme;
if (typeof theme === "string") {
const lowerTheme = theme.toLowerCase();
return (lowerTheme.includes("dark") || lowerTheme.includes("midnight")) ? "light-content" : "dark-content";
}
return "dark-content";
}
export default function fixStatusBar() {
const origSetBarStyle = StatusBar.setBarStyle;
if (Platform.OS == "android") {
StatusBar.setBarStyle = function (_style: any, ...args: any[]) {
return origSetBarStyle.call(this, getBarStyle(), ...args);
};
}
if (Platform.OS === "ios") {
function applyStatusBar() {
const style = getBarStyle();
origSetBarStyle.call(StatusBar, style, true);
}
applyStatusBar();
setInterval(applyStatusBar, 500);
}
}