Merge pull request #8 from tralwdwd/master
Some checks failed
Build and deploy / deploy (push) Failing after 52s

fix: crash when opening settings
Merged.
This commit is contained in:
Win8.1VMUser 2026-06-03 07:04:37 +02:00 • committed by GitHub
commit b01130e837
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -14,8 +14,13 @@ const { TableRowIcon } = findByProps("TableRowIcon");
const bunny = window.bunny; const bunny = window.bunny;
const tabsNavigationRef = bunny?.metro?.findByPropsLazy("getRootNavigationRef"); const tabsNavigationRef = bunny?.metro?.findByPropsLazy("getRootNavigationRef");
const settingConstants = bunny?.metro?.findByPropsLazy("SETTING_RENDERER_CONFIG"); const settingConstants = bunny?.metro?.findByPropsLazy(
const SettingsOverviewScreen = bunny?.metro?.findByNameLazy("SettingsOverviewScreen", false); "SETTING_RENDERER_CONFIG",
);
const SettingsOverviewScreen = bunny?.metro?.findByNameLazy(
"SettingsOverviewScreen",
false,
);
const createListModule = bunny.metro.findByPropsLazy("createList"); const createListModule = bunny.metro.findByPropsLazy("createList");
function Section({ tabs }) { function Section({ tabs }) {
@ -26,15 +31,15 @@ function Section({ tabs }) {
leading: React.createElement(FormRow.Icon, { source: tabs.icon }), leading: React.createElement(FormRow.Icon, { source: tabs.icon }),
trailing: React.createElement(React.Fragment, {}, [ trailing: React.createElement(React.Fragment, {}, [
tabs.trailing ? tabs.trailing() : null, tabs.trailing ? tabs.trailing() : null,
React.createElement(FormRow.Arrow, { key: "arrow" }) React.createElement(FormRow.Arrow, { key: "arrow" }),
]), ]),
onPress: () => { onPress: () => {
const Component = tabs.page; const Component = tabs.page;
navigation.navigate("VendettaCustomPage", { navigation.navigate("VendettaCustomPage", {
title: tabs.title(), title: tabs.title(),
render: () => React.createElement(Component) render: () => React.createElement(Component),
}); });
} },
}); });
} }
@ -43,11 +48,14 @@ function patchPanelUI(tabs, patches) {
patches.push( patches.push(
after( after(
"default", "default",
bunny?.metro?.findByNameLazy("UserSettingsOverviewWrapper", false), bunny?.metro?.findByNameLazy(
"UserSettingsOverviewWrapper",
false,
),
(_, ret) => { (_, ret) => {
const UserSettingsOverview = findInReactTree( const UserSettingsOverview = findInReactTree(
ret.props.children, ret.props.children,
n => n.type?.name === "UserSettingsOverview" (n) => n.type?.name === "UserSettingsOverview",
); );
if (UserSettingsOverview) { if (UserSettingsOverview) {
@ -58,27 +66,35 @@ function patchPanelUI(tabs, patches) {
(_args, res) => { (_args, res) => {
const sections = findInReactTree( const sections = findInReactTree(
res.props.children, res.props.children,
n => n?.children?.[1]?.type === FormSection (n) =>
n?.children?.[1]?.type ===
FormSection,
)?.children; )?.children;
if (sections) { if (sections) {
const index = sections.findIndex((c) => const index = sections.findIndex((c) =>
["BILLING_SETTINGS", "PREMIUM_SETTINGS"].includes(c?.props?.label) [
"BILLING_SETTINGS",
"PREMIUM_SETTINGS",
].includes(c?.props?.label),
); );
sections.splice( sections.splice(
-~index || 4, -~index || 4,
0, 0,
React.createElement(Section, { key: tabs.key, tabs }) React.createElement(Section, {
key: tabs.key,
tabs,
}),
); );
} }
} },
) ),
); );
} }
}, },
true true,
) ),
); );
} catch (error) { } catch (error) {
logger.info("Panel UI patch failed graciously 💔", error); logger.info("Panel UI patch failed graciously 💔", error);
@ -87,7 +103,9 @@ function patchPanelUI(tabs, patches) {
function patchTabsUI(tabs, patches) { function patchTabsUI(tabs, patches) {
if (!settingConstants || !SettingsOverviewScreen || !tabsNavigationRef) { if (!settingConstants || !SettingsOverviewScreen || !tabsNavigationRef) {
console.warn("[AccountSwitcher] Missing required constants for tabs UI patch"); console.warn(
"[AccountSwitcher] Missing required constants for tabs UI patch",
);
return; return;
} }
@ -95,13 +113,19 @@ function patchTabsUI(tabs, patches) {
row[tabs.key] = { row[tabs.key] = {
type: "pressable", type: "pressable",
title: tabs.title, title: tabs.title,
useTitle: tabs.title,
icon: tabs.icon, icon: tabs.icon,
IconComponent: tabs.icon && (() => { IconComponent:
const actualIconSource = (typeof tabs.icon === 'object' && tabs.icon.uri !== undefined) tabs.icon &&
? tabs.icon.uri (() => {
: tabs.icon; const actualIconSource =
return React.createElement(TableRowIcon, { source: actualIconSource }); typeof tabs.icon === "object" && tabs.icon.uri !== undefined
}), ? tabs.icon.uri
: tabs.icon;
return React.createElement(TableRowIcon, {
source: actualIconSource,
});
}),
usePredicate: tabs.predicate, usePredicate: tabs.predicate,
useTrailing: tabs.trailing, useTrailing: tabs.trailing,
onPress: () => { onPress: () => {
@ -110,7 +134,7 @@ function patchTabsUI(tabs, patches) {
navigation.navigate("VendettaCustomPage", { navigation.navigate("VendettaCustomPage", {
title: tabs.title(), title: tabs.title(),
render: () => React.createElement(Component) render: () => React.createElement(Component),
}); });
}, },
withArrow: true, withArrow: true,
@ -125,40 +149,40 @@ function patchTabsUI(tabs, patches) {
...rendererConfigValue, ...rendererConfigValue,
...row, ...row,
}), }),
set: v => (rendererConfigValue = v), set: (v) => (rendererConfigValue = v),
}); });
const firstRender = Symbol("AccountSwitcher-pinToSettings"); const firstRender = Symbol("AccountSwitcher-pinToSettings");
try { try {
if(!createListModule) return; if (!createListModule) return;
patches.push( patches.push(
after("createList", createListModule, (args, ret) => { after("createList", createListModule, (args, ret) => {
if(!args[0][firstRender]) { if (!args[0][firstRender]) {
args[0][firstRender] = true; args[0][firstRender] = true;
const [config] = args; const [config] = args;
const sections = config.sections; const sections = config.sections;
const section = sections?.find((x) => const section = sections?.find((x) =>
["Bunny", "Kettu", "Revenge"].includes(x?.label) ["Bunny", "Kettu", "Revenge"].includes(x?.label),
); );
// If unable to find a section // If unable to find a section
if(!section) { if (!section) {
const isMainSettings = Boolean( const isMainSettings = Boolean(
sections?.find((x) => sections?.find((x) =>
x.settings.includes("ACCOUNT") x.settings.includes("ACCOUNT"),
) ),
) );
if(isMainSettings) { if (isMainSettings) {
// Add a new section to the top // Add a new section to the top
sections.unshift({ sections.unshift({
label: manifest.name, label: manifest.name,
title: manifest.name, title: manifest.name,
settings: [tabs.key] settings: [tabs.key],
}); });
} }
} }
@ -167,47 +191,47 @@ function patchTabsUI(tabs, patches) {
section.settings = [...section.settings, tabs.key]; section.settings = [...section.settings, tabs.key];
} }
} }
}) }),
) );
} catch { } catch {
patches.push( patches.push(
after("default", SettingsOverviewScreen, (args, ret) => { after("default", SettingsOverviewScreen, (args, ret) => {
if (!args[0][firstRender]) { if (!args[0][firstRender]) {
args[0][firstRender] = true; args[0][firstRender] = true;
const { sections } = findInReactTree( const { sections } = findInReactTree(
ret, ret,
i => i.props?.sections, (i) => i.props?.sections,
).props; ).props;
const section = sections?.find((x) =>
["Bunny", "Kettu", "Revenge"].includes(x?.label)
);
// If unable to find a section const section = sections?.find((x) =>
if(!section) { ["Bunny", "Kettu", "Revenge"].includes(x?.label),
);
// If unable to find a section
if (!section) {
const isMainSettings = Boolean( const isMainSettings = Boolean(
sections?.find((x) => sections?.find((x) =>
x.settings.includes("ACCOUNT") x.settings.includes("ACCOUNT"),
) ),
) );
if(isMainSettings) { if (isMainSettings) {
// Add a new section to the top // Add a new section to the top
sections.unshift({ sections.unshift({
label: manifest.name, label: manifest.name,
title: manifest.name, title: manifest.name,
settings: [tabs.key] settings: [tabs.key],
}); });
} }
} }
if (section?.settings) { if (section?.settings) {
section.settings = [...section.settings, tabs.key]; section.settings = [...section.settings, tabs.key];
}
} }
} }),
}) );
);
} }
} }
@ -236,7 +260,9 @@ export default function patchSidebar() {
return () => {}; return () => {};
} }
console.log("[AccountSwitcher] Patching sidebar using custom patchSettingsPin..."); console.log(
"[AccountSwitcher] Patching sidebar using custom patchSettingsPin...",
);
try { try {
const unpatch = patchSettingsPin({ const unpatch = patchSettingsPin({
@ -249,7 +275,6 @@ export default function patchSidebar() {
console.log("[AccountSwitcher] Successfully patched sidebar"); console.log("[AccountSwitcher] Successfully patched sidebar");
return unpatch; return unpatch;
} catch (error) { } catch (error) {
console.error("[AccountSwitcher] Failed to patch sidebar:", error); console.error("[AccountSwitcher] Failed to patch sidebar:", error);
return () => {}; return () => {};