From e99da222ad08cc61c521482b38f68b3484860d74 Mon Sep 17 00:00:00 2001 From: Beef Date: Sun, 21 May 2023 23:09:25 +0100 Subject: [PATCH] [UI > YouTab] Fix some of the glaring issues --- .../settings/components/SettingsSection.tsx | 6 ++-- src/ui/settings/data.tsx | 32 ++++++++++++------- src/ui/settings/index.ts | 2 +- src/ui/settings/patches/you.tsx | 8 +++-- 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/ui/settings/components/SettingsSection.tsx b/src/ui/settings/components/SettingsSection.tsx index c0993a6..5a7174f 100644 --- a/src/ui/settings/components/SettingsSection.tsx +++ b/src/ui/settings/components/SettingsSection.tsx @@ -1,7 +1,7 @@ import { NavigationNative } from "@metro/common"; import { useProxy } from "@lib/storage"; import { getAssetIDByName } from "@ui/assets"; -import { getScreens } from "@ui/settings/data"; +import { getRenderableScreens } from "@ui/settings/data"; import { ErrorBoundary, Forms } from "@ui/components"; import settings from "@lib/settings"; @@ -11,12 +11,12 @@ export default function SettingsSection() { const navigation = NavigationNative.useNavigation(); useProxy(settings); - const screens = getScreens(); + const screens = getRenderableScreens() return ( - {screens.filter(s => s.shouldRender ?? true).map((s, i) => ( + {screens.map((s, i) => ( <> boolean; options?: Record; render: React.ComponentType; } const styles = stylesheet.createThemedStyleSheet({ container: { flex: 1, backgroundColor: semanticColors.BACKGROUND_MOBILE_PRIMARY } }); const formatKey = (key: string, youKeys: boolean) => youKeys ? lodash.snakeCase(key).toUpperCase() : key; +// If a function is passed, it is called with the screen object, and the return value is mapped. If a string is passed, we map to the value of the property with that name on the screen. Else, just map to the given data. +// Question: Isn't this overengineered? +// Answer: Maybe. +const keyMap = (screens: Screen[], data: string | ((s: Screen) => any) | null) => Object.fromEntries(screens.map(s => [s.key, typeof data === "function" ? data(s) : typeof data === "string" ? s[data] : data])); export const getScreens = (youKeys = false): Screen[] => [ { @@ -45,7 +49,8 @@ export const getScreens = (youKeys = false): Screen[] => [ key: formatKey("VendettaThemes", youKeys), title: "Themes", icon: "ic_theme_24px", - shouldRender: window.__vendetta_loader?.features.hasOwnProperty("themes"), + // TODO: bad + shouldRender: () => window.__vendetta_loader?.features.hasOwnProperty("themes") ?? false, options: { headerRight: () => !settings.safeMode?.enabled && , }, @@ -55,13 +60,13 @@ export const getScreens = (youKeys = false): Screen[] => [ key: formatKey("VendettaDeveloper", youKeys), title: "Developer", icon: "ic_progress_wrench_24px", - shouldRender: settings.developerSettings, + shouldRender: () => settings.developerSettings ?? false, render: Developer, }, { key: formatKey("VendettaCustomPage", youKeys), title: "Vendetta Page", - shouldRender: false, + shouldRender: () => false, render: ({ render: PageView, noErrorBoundary, ...options }: { render: React.ComponentType, noErrorBoundary: boolean } & Record) => { const navigation = NavigationNative.useNavigation(); @@ -71,20 +76,23 @@ export const getScreens = (youKeys = false): Screen[] => [ } ] -export const getPanelsScreens = () => Object.fromEntries(getScreens().map(s => [s.key, { +export const getRenderableScreens = (youKeys = false) => getScreens(youKeys).filter(s => s.shouldRender?.() ?? true); + +export const getPanelsScreens = () => keyMap(getScreens(), (s => ({ title: s.title, render: s.render, ...s.options, -}])); +}))); export const getYouData = () => { const screens = getScreens(true); + const renderableScreens = getRenderableScreens(true); return { - layout: { title: "Vendetta", settings: screens.filter(s => s.shouldRender ?? true).map(s => s.key) }, - titleConfig: Object.fromEntries(screens.map(s => [s.key, s.title])), - relationships: Object.fromEntries(screens.map(s => [s.key, null])), - rendererConfigs: Object.fromEntries(screens.map(s => [s.key, { + layout: { title: "Vendetta", settings: renderableScreens.map(s => s.key) }, // We can't use our keyMap function here since `settings` is an array not an object + titleConfig: keyMap(screens, "title"), + relationships: keyMap(screens, null), + rendererConfigs: keyMap(screens, (s) => ({ type: "route", icon: s.icon ? getAssetIDByName(s.icon) : null, screen: { @@ -93,10 +101,10 @@ export const getYouData = () => { route: lodash.chain(s.key).camelCase().upperFirst().value(), getComponent: () => ({ navigation, route }: any) => { navigation.addListener("focus", () => navigation.setOptions(s.options)); - // TODO: Some ungodly issue causes the keyboard to automatically close in TextInputs. Why?! + // TODO: Some ungodly issue causes the keyboard to automatically close in TextInputs on Android. Why?! return ; } } - }])) + })) } } \ No newline at end of file diff --git a/src/ui/settings/index.ts b/src/ui/settings/index.ts index d8bcd32..dc4e8e1 100644 --- a/src/ui/settings/index.ts +++ b/src/ui/settings/index.ts @@ -5,7 +5,7 @@ import patchYou from "@ui/settings/patches/you"; export default function initSettings() { const patches = [ patchPanels(), - ...(findByProps("useOverviewSettings") ? [patchYou()] : []), + ...(findByProps("getSettingSearchListItems") ? [patchYou()] : []), ] return () => patches.forEach(p => p()); diff --git a/src/ui/settings/patches/you.tsx b/src/ui/settings/patches/you.tsx index faef78a..0f0dcb1 100644 --- a/src/ui/settings/patches/you.tsx +++ b/src/ui/settings/patches/you.tsx @@ -1,7 +1,7 @@ import { i18n } from "@metro/common"; import { findByProps } from "@metro/filters"; import { after } from "@lib/patcher"; -import { getScreens, getYouData } from "@ui/settings/data"; +import { getRenderableScreens, getScreens, getYouData } from "@ui/settings/data"; const layoutModule = findByProps("useOverviewSettings"); const titleConfigModule = findByProps("getSettingTitleConfig"); @@ -11,6 +11,7 @@ const miscModule = findByProps("SETTING_RELATIONSHIPS", "SETTING_RENDERER_CONFIG export default function patchYou() { const patches = new Array; const screens = getScreens(true); + const renderableScreens = getRenderableScreens(true); const data = getYouData(); patches.push(after("useOverviewSettings", layoutModule, (_, ret) => { @@ -29,7 +30,7 @@ export default function patchYou() { }))); patches.push(after("getSettingSearchListItems", gettersModule, ([settings], ret) => [ - ...(screens.filter(s => settings.includes(s.key) && (s.shouldRender ?? true))).map(s => ({ + ...(renderableScreens.filter(s => settings.includes(s.key))).map(s => ({ type: "setting_search_result", ancestorRendererData: data.rendererConfigs[s.key], setting: s.key, @@ -42,8 +43,9 @@ export default function patchYou() { // TODO: We could use a proxy for these const oldRelationships = miscModule.SETTING_RELATIONSHIPS; - const oldRendererConfigs = miscModule.SETTING_RENDERER_CONFIGS; miscModule.SETTING_RELATIONSHIPS = { ...oldRelationships, ...data.relationships }; + + const oldRendererConfigs = miscModule.SETTING_RENDERER_CONFIGS; miscModule.SETTING_RENDERER_CONFIGS = { ...oldRendererConfigs, ...data.rendererConfigs }; return () => {