[UI > YouTab] Fix some of the glaring issues

This commit is contained in:
Beef 2023-05-21 23:09:25 +01:00
parent fda8e31bb1
commit e99da222ad
4 changed files with 29 additions and 19 deletions

View file

@ -1,7 +1,7 @@
import { NavigationNative } from "@metro/common"; import { NavigationNative } from "@metro/common";
import { useProxy } from "@lib/storage"; import { useProxy } from "@lib/storage";
import { getAssetIDByName } from "@ui/assets"; import { getAssetIDByName } from "@ui/assets";
import { getScreens } from "@ui/settings/data"; import { getRenderableScreens } from "@ui/settings/data";
import { ErrorBoundary, Forms } from "@ui/components"; import { ErrorBoundary, Forms } from "@ui/components";
import settings from "@lib/settings"; import settings from "@lib/settings";
@ -11,12 +11,12 @@ export default function SettingsSection() {
const navigation = NavigationNative.useNavigation(); const navigation = NavigationNative.useNavigation();
useProxy(settings); useProxy(settings);
const screens = getScreens(); const screens = getRenderableScreens()
return ( return (
<ErrorBoundary> <ErrorBoundary>
<FormSection key="Vendetta" title={`Vendetta${settings.safeMode?.enabled ? " (Safe Mode)" : ""}`}> <FormSection key="Vendetta" title={`Vendetta${settings.safeMode?.enabled ? " (Safe Mode)" : ""}`}>
{screens.filter(s => s.shouldRender ?? true).map((s, i) => ( {screens.map((s, i) => (
<> <>
<FormRow <FormRow
label={s.title} label={s.title}

View file

@ -17,13 +17,17 @@ interface Screen {
key: string, key: string,
title: string; title: string;
icon?: string; icon?: string;
shouldRender?: boolean; shouldRender?: () => boolean;
options?: Record<string, any>; options?: Record<string, any>;
render: React.ComponentType<any>; render: React.ComponentType<any>;
} }
const styles = stylesheet.createThemedStyleSheet({ container: { flex: 1, backgroundColor: semanticColors.BACKGROUND_MOBILE_PRIMARY } }); const styles = stylesheet.createThemedStyleSheet({ container: { flex: 1, backgroundColor: semanticColors.BACKGROUND_MOBILE_PRIMARY } });
const formatKey = (key: string, youKeys: boolean) => youKeys ? lodash.snakeCase(key).toUpperCase() : key; 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[] => [ export const getScreens = (youKeys = false): Screen[] => [
{ {
@ -45,7 +49,8 @@ export const getScreens = (youKeys = false): Screen[] => [
key: formatKey("VendettaThemes", youKeys), key: formatKey("VendettaThemes", youKeys),
title: "Themes", title: "Themes",
icon: "ic_theme_24px", icon: "ic_theme_24px",
shouldRender: window.__vendetta_loader?.features.hasOwnProperty("themes"), // TODO: bad
shouldRender: () => window.__vendetta_loader?.features.hasOwnProperty("themes") ?? false,
options: { options: {
headerRight: () => !settings.safeMode?.enabled && <InstallButton alertTitle="Install Theme" installFunction={installTheme} />, headerRight: () => !settings.safeMode?.enabled && <InstallButton alertTitle="Install Theme" installFunction={installTheme} />,
}, },
@ -55,13 +60,13 @@ export const getScreens = (youKeys = false): Screen[] => [
key: formatKey("VendettaDeveloper", youKeys), key: formatKey("VendettaDeveloper", youKeys),
title: "Developer", title: "Developer",
icon: "ic_progress_wrench_24px", icon: "ic_progress_wrench_24px",
shouldRender: settings.developerSettings, shouldRender: () => settings.developerSettings ?? false,
render: Developer, render: Developer,
}, },
{ {
key: formatKey("VendettaCustomPage", youKeys), key: formatKey("VendettaCustomPage", youKeys),
title: "Vendetta Page", title: "Vendetta Page",
shouldRender: false, shouldRender: () => false,
render: ({ render: PageView, noErrorBoundary, ...options }: { render: React.ComponentType, noErrorBoundary: boolean } & Record<string, object>) => { render: ({ render: PageView, noErrorBoundary, ...options }: { render: React.ComponentType, noErrorBoundary: boolean } & Record<string, object>) => {
const navigation = NavigationNative.useNavigation(); 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, title: s.title,
render: s.render, render: s.render,
...s.options, ...s.options,
}])); })));
export const getYouData = () => { export const getYouData = () => {
const screens = getScreens(true); const screens = getScreens(true);
const renderableScreens = getRenderableScreens(true);
return { return {
layout: { title: "Vendetta", settings: screens.filter(s => s.shouldRender ?? true).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: Object.fromEntries(screens.map(s => [s.key, s.title])), titleConfig: keyMap(screens, "title"),
relationships: Object.fromEntries(screens.map(s => [s.key, null])), relationships: keyMap(screens, null),
rendererConfigs: Object.fromEntries(screens.map(s => [s.key, { rendererConfigs: keyMap(screens, (s) => ({
type: "route", type: "route",
icon: s.icon ? getAssetIDByName(s.icon) : null, icon: s.icon ? getAssetIDByName(s.icon) : null,
screen: { screen: {
@ -93,10 +101,10 @@ export const getYouData = () => {
route: lodash.chain(s.key).camelCase().upperFirst().value(), route: lodash.chain(s.key).camelCase().upperFirst().value(),
getComponent: () => ({ navigation, route }: any) => { getComponent: () => ({ navigation, route }: any) => {
navigation.addListener("focus", () => navigation.setOptions(s.options)); 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 <RN.View style={styles.container}><s.render {...route.params} /></RN.View>; return <RN.View style={styles.container}><s.render {...route.params} /></RN.View>;
} }
} }
}])) }))
} }
} }

View file

@ -5,7 +5,7 @@ import patchYou from "@ui/settings/patches/you";
export default function initSettings() { export default function initSettings() {
const patches = [ const patches = [
patchPanels(), patchPanels(),
...(findByProps("useOverviewSettings") ? [patchYou()] : []), ...(findByProps("getSettingSearchListItems") ? [patchYou()] : []),
] ]
return () => patches.forEach(p => p()); return () => patches.forEach(p => p());

View file

@ -1,7 +1,7 @@
import { i18n } from "@metro/common"; import { i18n } from "@metro/common";
import { findByProps } from "@metro/filters"; import { findByProps } from "@metro/filters";
import { after } from "@lib/patcher"; 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 layoutModule = findByProps("useOverviewSettings");
const titleConfigModule = findByProps("getSettingTitleConfig"); const titleConfigModule = findByProps("getSettingTitleConfig");
@ -11,6 +11,7 @@ const miscModule = findByProps("SETTING_RELATIONSHIPS", "SETTING_RENDERER_CONFIG
export default function patchYou() { export default function patchYou() {
const patches = new Array<Function>; const patches = new Array<Function>;
const screens = getScreens(true); const screens = getScreens(true);
const renderableScreens = getRenderableScreens(true);
const data = getYouData(); const data = getYouData();
patches.push(after("useOverviewSettings", layoutModule, (_, ret) => { patches.push(after("useOverviewSettings", layoutModule, (_, ret) => {
@ -29,7 +30,7 @@ export default function patchYou() {
}))); })));
patches.push(after("getSettingSearchListItems", gettersModule, ([settings], ret) => [ 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", type: "setting_search_result",
ancestorRendererData: data.rendererConfigs[s.key], ancestorRendererData: data.rendererConfigs[s.key],
setting: s.key, setting: s.key,
@ -42,8 +43,9 @@ export default function patchYou() {
// TODO: We could use a proxy for these // TODO: We could use a proxy for these
const oldRelationships = miscModule.SETTING_RELATIONSHIPS; const oldRelationships = miscModule.SETTING_RELATIONSHIPS;
const oldRendererConfigs = miscModule.SETTING_RENDERER_CONFIGS;
miscModule.SETTING_RELATIONSHIPS = { ...oldRelationships, ...data.relationships }; miscModule.SETTING_RELATIONSHIPS = { ...oldRelationships, ...data.relationships };
const oldRendererConfigs = miscModule.SETTING_RENDERER_CONFIGS;
miscModule.SETTING_RENDERER_CONFIGS = { ...oldRendererConfigs, ...data.rendererConfigs }; miscModule.SETTING_RENDERER_CONFIGS = { ...oldRendererConfigs, ...data.rendererConfigs };
return () => { return () => {