From 190940b41740dfe30dfc827efb452d54041a94f3 Mon Sep 17 00:00:00 2001 From: amsyarasyiq <82711525+amsyarasyiq@users.noreply.github.com> Date: Sat, 9 Mar 2024 04:06:41 +0800 Subject: [PATCH] Funny UI changes --- src/core/i18n/default.json | 1 + src/core/ui/components/AddonPage.tsx | 5 +- src/core/ui/components/Card.tsx | 174 +++++++++++++-------- src/core/ui/components/PluginCard.tsx | 13 +- src/core/ui/components/SettingsSection.tsx | 33 ---- src/core/ui/components/ThemeCard.tsx | 13 +- src/core/ui/settings/index.ts | 4 +- src/core/ui/settings/pages/About.tsx | 91 +++++++++++ src/core/ui/settings/pages/General.tsx | 118 ++++---------- src/core/ui/settings/pages/Themes.tsx | 1 + src/core/vendettaObject.ts | 2 +- src/lib/managers/themes.ts | 8 +- src/lib/ui/components/discord/Redesign.ts | 8 +- 13 files changed, 268 insertions(+), 203 deletions(-) delete mode 100644 src/core/ui/components/SettingsSection.tsx create mode 100644 src/core/ui/settings/pages/About.tsx diff --git a/src/core/i18n/default.json b/src/core/i18n/default.json index bbf7d39..09e58d6 100644 --- a/src/core/i18n/default.json +++ b/src/core/i18n/default.json @@ -1,4 +1,5 @@ { + "ABOUT": "About", "ACTIONS": "Actions", "ARE_YOU_SURE_TO_CLEAR_DATA": "Are you sure you wish to clear the data of {name}?", "ARE_YOU_SURE_TO_DELETE_PLUGIN": "Are you sure you wish to delete {name}? This will clear all of the plugin's data.", diff --git a/src/core/ui/components/AddonPage.tsx b/src/core/ui/components/AddonPage.tsx index 97a3e2d..cd95c6e 100644 --- a/src/core/ui/components/AddonPage.tsx +++ b/src/core/ui/components/AddonPage.tsx @@ -39,7 +39,7 @@ function getItemsByQuery(items: T[], query: string): const reanimated = findByProps("useSharedValue"); const { FloatingActionButton } = findByProps("FloatingActionButton"); -export default function AddonPage({ title, floatingButtonText, fetchFunction, items, safeModeMessage, safeModeExtras, card: CardComponent }: AddonPageProps) { +export default function AddonPage({ floatingButtonText, fetchFunction, items, safeModeMessage, safeModeExtras, card: CardComponent }: AddonPageProps) { useProxy(settings); useProxy(items); @@ -67,9 +67,8 @@ export default function AddonPage({ title, floatingButtonText, fetchFunction, collapseText.value = Number(e.nativeEvent.contentOffset.y > yOffset.current); yOffset.current = e.nativeEvent.contentOffset.y; }} - onMomentumScrollEnd={() => collapseText.value = 0} style={{ paddingHorizontal: 10, paddingTop: 10 }} - contentContainerStyle={{ paddingBottom: 70 }} + contentContainerStyle={{ paddingBottom: 90, paddingHorizontal: 5 }} data={getItemsByQuery(Object.values(items), search)} renderItem={({ item, index }) => } /> diff --git a/src/core/ui/components/Card.tsx b/src/core/ui/components/Card.tsx index fcbbbc7..cd9b7a7 100644 --- a/src/core/ui/components/Card.tsx +++ b/src/core/ui/components/Card.tsx @@ -1,41 +1,67 @@ import { getAssetIDByName } from "@lib/api/assets"; -import { TableCheckboxRow, TableRow, TableRowGroup, TableRowIcon, TableSwitchRow } from "@lib/ui/components/discord/Redesign"; +import { FormRow } from "@lib/ui/components/discord/Forms"; +import { FormCheckbox, FormSwitch, IconButton } from "@lib/ui/components/discord/Redesign"; +import { createStyles, TextStyleSheet } from "@lib/ui/styles"; +import { ReactNative as RN } from "@metro/common"; +import { findByProps } from "@metro/filters"; import { semanticColors } from "@ui/color"; -import ContextMenu from "@ui/components/ContextMenu"; -import { createStyles } from "@ui/styles"; -import { Image, TouchableOpacity, View } from "react-native"; +import { ImageBackground, View } from "react-native"; + +const { hideActionSheet } = findByProps("openLazy", "hideActionSheet"); +const { showSimpleActionSheet } = findByProps("showSimpleActionSheet"); // TODO: These styles work weirdly. iOS has cramped text, Android with low DPI probably does too. Fix? const useStyles = createStyles({ card: { - backgroundColor: semanticColors?.BACKGROUND_SECONDARY, - borderRadius: 15, + backgroundColor: semanticColors?.CARD_SECONDARY_BG, + borderRadius: 12, overflow: "hidden" }, header: { padding: 0, - backgroundColor: semanticColors?.BACKGROUND_TERTIARY, + }, + headerLeading: { + flexDirection: "column", + justifyContent: "center", + scale: 1.2 + }, + headerTrailing: { + display: "flex", + flexDirection: "row", + gap: 15, + alignItems: "center" + }, + headerLabel: { + ...TextStyleSheet["heading-md/semibold"], + color: semanticColors.TEXT_NORMAL, + }, + headerSubtitle: { + ...TextStyleSheet["text-md/semibold"], + color: semanticColors.TEXT_MUTED, + }, + descriptionLabel: { + ...TextStyleSheet["text-md/semibold"], + color: semanticColors.TEXT_NORMAL, }, actions: { flexDirection: "row-reverse", alignItems: "center", + gap: 5 }, - actionIcon: { - width: 22, - height: 22, - marginLeft: 5, - tintColor: semanticColors?.INTERACTIVE_NORMAL, - }, - icon: { - width: 22, - height: 22, - marginLeft: 5, - tintColor: semanticColors?.INTERACTIVE_NORMAL, + iconStyle: { + tintColor: semanticColors.LOGO_PRIMARY, + opacity: 0.2, + height: 64, + width: 64, + left: void 0, + right: "30%", + top: "-10%" } }); interface Action { icon: string; + disabled?: boolean; onPress: () => void; } @@ -51,69 +77,89 @@ export interface CardWrapper { interface CardProps { index?: number; - headerLabel: string | React.ComponentType; + headerLabel: string; + headerSublabel?: string; headerIcon?: string; toggleType?: "switch" | "radio"; toggleValue?: boolean; onToggleChange?: (v: boolean) => void; - descriptionLabel?: string | React.ComponentType; - /** @deprecated use overflowActions */ + descriptionLabel?: string; actions?: Action[]; overflowTitle?: string; overflowActions?: OverflowAction[]; - overflowIcon?: string; } export default function Card(props: CardProps) { const styles = useStyles(); - let pressableState = props.toggleValue ?? false; - - const headerProps = { - style: styles.header, - label: props.headerLabel, - icon: props.headerIcon && - }; return ( - - - {props.toggleType && (props.toggleType === "switch" ? - : props.toggleType === "radio" ? - { - pressableState = !pressableState; - props.onToggleChange?.(pressableState); - }} - checked={props.toggleValue} - /> : undefined) || } - + + + {props.headerLabel} + {props.headerSublabel && ( + {props.headerSublabel} + )} + + } trailing={ - - {props.overflowActions && - ({ - label: i.label, - iconSource: getAssetIDByName(i.icon), - action: i.onPress - }))} - align="auto" - title={props.overflowTitle!!} - children={props => - - } + + + {props.overflowActions && + showSimpleActionSheet({ + key: "CardOverflow", + header: { + title: props.overflowTitle, + icon: props.headerIcon && , + onClose: () => hideActionSheet(), + }, + options: props.overflowActions?.map(i => ({ ...i, icon: getAssetIDByName(i.icon) })), + })} + size="sm" + variant="secondary" + icon={getAssetIDByName("CircleInformationIcon")} + />} + {props.actions?.map(({ icon, onPress, disabled }) => ( + + ))} + + {props.toggleType && (props.toggleType === "switch" ? + - } + : + { + props.onToggleChange?.(!props.toggleValue); + }}> + + + )} } /> - - + + {props.descriptionLabel} + + } + /> + + ); } diff --git a/src/core/ui/components/PluginCard.tsx b/src/core/ui/components/PluginCard.tsx index a8c50f6..35e8c18 100644 --- a/src/core/ui/components/PluginCard.tsx +++ b/src/core/ui/components/PluginCard.tsx @@ -29,8 +29,9 @@ export default function PluginCard({ item: plugin, index }: CardWrapper i.name).join(", ")}`} - headerIcon={plugin.manifest.vendetta?.icon || "ic_application_command_24px"} + headerLabel={`${plugin.manifest.name}`} + headerSublabel={plugin.manifest.authors?.[0] && `by ${plugin.manifest.authors.map(i => i.name).join(", ")}`} + headerIcon={plugin.manifest.vendetta?.icon} toggleType="switch" toggleValue={plugin.enabled} onToggleChange={(v: boolean) => { @@ -42,6 +43,14 @@ export default function PluginCard({ item: plugin, index }: CardWrapper navigation.push("VendettaCustomPage", { + title: plugin.manifest.name, + render: settings, + }) + }]} overflowActions={[ ...(settings ? [{ label: Strings.OVERFLOW_PLUGIN_SETTINGS, diff --git a/src/core/ui/components/SettingsSection.tsx b/src/core/ui/components/SettingsSection.tsx deleted file mode 100644 index 76214ad..0000000 --- a/src/core/ui/components/SettingsSection.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import { Strings } from "@core/i18n"; -import { getScreens } from "@core/ui/settings/data"; -import { getAssetIDByName } from "@lib/api/assets"; -import { useProxy } from "@lib/api/storage"; -import { settings } from "@lib/settings"; -import { FormDivider, FormRow, FormSection } from "@lib/ui/components/discord/Forms"; -import { NavigationNative } from "@metro/common"; -import { ErrorBoundary } from "@ui/components"; - -export default function SettingsSection() { - const navigation = NavigationNative.useNavigation(); - useProxy(settings); - - const screens = getScreens(); - - return ( - - - {screens.filter(s => (s.shouldRender?.() ?? true)).map((s, i) => ( - <> - } - trailing={FormRow.Arrow} - onPress={() => navigation.push(s.key)} - /> - {i !== screens.length - 1 && } - - ))} - - - ); -} diff --git a/src/core/ui/components/ThemeCard.tsx b/src/core/ui/components/ThemeCard.tsx index d01bce3..18c067f 100644 --- a/src/core/ui/components/ThemeCard.tsx +++ b/src/core/ui/components/ThemeCard.tsx @@ -12,11 +12,8 @@ import { showToast } from "@ui/toasts"; async function selectAndApply(value: boolean, id: string) { try { - await selectTheme(value ? id : "default"); - value ? applyTheme(themes[id]) : applyTheme(null); - - // TODO: Implement native side reload-less & check if it's applied by 100% - showToast(Strings.THEMES_RELOAD_FOR_CHANGES, getAssetIDByName("yellow-alert")); + await selectTheme(value ? id : null); + applyTheme(value ? themes[id] : null); } catch (e: any) { console.error("Error while selectAndApply,", e); } @@ -25,6 +22,8 @@ async function selectAndApply(value: boolean, id: string) { export default function ThemeCard({ item: theme, index }: CardWrapper) { useProxy(theme); + // little hack, our useProxy is kinda not reliable here + const [, forceUpdate] = React.useReducer(n => ~n, 0); const [removed, setRemoved] = React.useState(false); // This is needed because of Reactâ„¢ @@ -35,12 +34,14 @@ export default function ThemeCard({ item: theme, index }: CardWrapper) { return ( i.name).join(", ")}` : ""}`} + headerLabel={theme.data.name} + headerSublabel={authors ? `by ${authors.map(i => i.name).join(", ")}` : ""} descriptionLabel={theme.data.description ?? "No description."} toggleType={!settings.safeMode?.enabled ? "radio" : undefined} toggleValue={theme.selected} onToggleChange={(v: boolean) => { selectAndApply(v, theme.id); + forceUpdate(); }} overflowTitle={theme.data.name} overflowActions={[ diff --git a/src/core/ui/settings/index.ts b/src/core/ui/settings/index.ts index de6e792..8580bd2 100644 --- a/src/core/ui/settings/index.ts +++ b/src/core/ui/settings/index.ts @@ -7,7 +7,9 @@ import { registerSection } from "@lib/ui/settings"; import { version } from "bunny-build"; // @ts-ignore -import PyoncordIcon from "../../../assets/icons/pyon64.png"; +import _PyoncordIcon from "../../../assets/icons/pyon64.png"; + +export const PyoncordIcon = _PyoncordIcon as string; export default function initSettings() { registerSection({ diff --git a/src/core/ui/settings/pages/About.tsx b/src/core/ui/settings/pages/About.tsx new file mode 100644 index 0000000..3cc9966 --- /dev/null +++ b/src/core/ui/settings/pages/About.tsx @@ -0,0 +1,91 @@ +import { Strings } from "@core/i18n"; +import Version from "@core/ui/components/Version"; +import { useProxy } from "@lib/api/storage"; +import { getDebugInfo } from "@lib/debug"; +import { settings } from "@lib/settings"; +import { Stack, TableRowGroup } from "@lib/ui/components/discord/Redesign"; +import { Platform, ScrollView } from "react-native"; + +export default function About() { + const debugInfo = getDebugInfo(); + useProxy(settings); + + const versions = [ + { + label: Strings.BUNNY, + version: debugInfo.bunny.version, + icon: "ic_progress_wrench_24px", + }, + { + label: "Discord", + version: `${debugInfo.discord.version} (${debugInfo.discord.build})`, + icon: "Discord", + }, + { + label: "React", + version: debugInfo.react.version, + icon: "ic_category_16px", + }, + { + label: "React Native", + version: debugInfo.react.nativeVersion, + icon: "mobile", + }, + { + label: Strings.BYTECODE, + version: debugInfo.hermes.bytecodeVersion, + icon: "ic_server_security_24px", + }, + ]; + + const platformInfo = [ + { + label: Strings.LOADER, + version: debugInfo.bunny.loader, + icon: "ic_download_24px", + }, + { + label: Strings.OPERATING_SYSTEM, + version: `${debugInfo.os.name} ${debugInfo.os.version}`, + icon: "ic_cog_24px" + }, + ...(debugInfo.os.sdk ? [{ + label: "SDK", + version: debugInfo.os.sdk, + icon: "pencil" + }] : []), + { + label: Strings.MANUFACTURER, + version: debugInfo.device.manufacturer, + icon: "ic_badge_staff" + }, + { + label: Strings.BRAND, + version: debugInfo.device.brand, + icon: "ic_settings_boost_24px" + }, + { + label: Strings.MODEL, + version: debugInfo.device.model, + icon: "ic_phonelink_24px" + }, + { + label: Platform.select({ android: Strings.CODENAME, ios: Strings.MACHINE_ID })!, + version: debugInfo.device.codename, + icon: "ic_compose_24px" + } + ]; + + return ( + + + + {versions.map(v => )} + + + {platformInfo.map(p => )} + + + + ); +} diff --git a/src/core/ui/settings/pages/General.tsx b/src/core/ui/settings/pages/General.tsx index cd3584b..1bf3e39 100644 --- a/src/core/ui/settings/pages/General.tsx +++ b/src/core/ui/settings/pages/General.tsx @@ -1,99 +1,47 @@ import { Strings } from "@core/i18n"; -import Version from "@core/ui/components/Version"; +import { PyoncordIcon } from "@core/ui/settings"; import { getAssetIDByName } from "@lib/api/assets"; import { useProxy } from "@lib/api/storage"; import { _toggleSafeMode, getDebugInfo } from "@lib/debug"; import { settings } from "@lib/settings"; -import { Stack, TableRow, TableRowGroup, TableSwitchRow } from "@lib/ui/components/discord/Redesign"; +import { Stack, TableRow, TableRowGroup, TableSwitchRow, useNavigation } from "@lib/ui/components/discord/Redesign"; import { DISCORD_SERVER, GITHUB } from "@lib/utils/constants"; import { url } from "@metro/common"; -import { semanticColors } from "@ui/color"; -import { Summary } from "@ui/components"; -import { createStyles } from "@ui/styles"; -import { NativeModules, Platform, ScrollView } from "react-native"; +import { NativeModules, ScrollView } from "react-native"; -const debugInfo = getDebugInfo(); - -const useStyles = createStyles({ - container: { - flex: 1, - backgroundColor: semanticColors.BACKGROUND_MOBILE_SECONDARY, - } -}); +import About from "./About"; export default function General() { - const styles = useStyles(); useProxy(settings); - const versions = [ - { - label: Strings.BUNNY, - version: debugInfo.bunny.version, - icon: "ic_progress_wrench_24px", - }, - { - label: "Discord", - version: `${debugInfo.discord.version} (${debugInfo.discord.build})`, - icon: "Discord", - }, - { - label: "React", - version: debugInfo.react.version, - icon: "ic_category_16px", - }, - { - label: "React Native", - version: debugInfo.react.nativeVersion, - icon: "mobile", - }, - { - label: Strings.BYTECODE, - version: debugInfo.hermes.bytecodeVersion, - icon: "ic_server_security_24px", - }, - ]; - - const platformInfo = [ - { - label: Strings.LOADER, - version: debugInfo.bunny.loader, - icon: "ic_download_24px", - }, - { - label: Strings.OPERATING_SYSTEM, - version: `${debugInfo.os.name} ${debugInfo.os.version}`, - icon: "ic_cog_24px" - }, - ...(debugInfo.os.sdk ? [{ - label: "SDK", - version: debugInfo.os.sdk, - icon: "pencil" - }] : []), - { - label: Strings.MANUFACTURER, - version: debugInfo.device.manufacturer, - icon: "ic_badge_staff" - }, - { - label: Strings.BRAND, - version: debugInfo.device.brand, - icon: "ic_settings_boost_24px" - }, - { - label: Strings.MODEL, - version: debugInfo.device.model, - icon: "ic_phonelink_24px" - }, - { - label: Platform.select({ android: Strings.CODENAME, ios: Strings.MACHINE_ID })!, - version: debugInfo.device.codename, - icon: "ic_compose_24px" - } - ]; + const debugInfo = getDebugInfo(); + const navigation = useNavigation(); return ( - + + + } + trailing={} + /> + } + trailing={} + /> + } + trailing={TableRow.Arrow} + onPress={() => navigation.push("VendettaCustomPage", { + title: Strings.ABOUT, + render: () => , + })} + /> + - - - {versions.map(v => )} - - - {platformInfo.map(p => )} - - ); diff --git a/src/core/ui/settings/pages/Themes.tsx b/src/core/ui/settings/pages/Themes.tsx index 4897fb9..2c04d8e 100644 --- a/src/core/ui/settings/pages/Themes.tsx +++ b/src/core/ui/settings/pages/Themes.tsx @@ -9,6 +9,7 @@ import { Button } from "@ui/components/discord"; export default function Themes() { useProxy(settings); + useProxy(themes); return ( diff --git a/src/core/vendettaObject.ts b/src/core/vendettaObject.ts index 1df775a..afb3aab 100644 --- a/src/core/vendettaObject.ts +++ b/src/core/vendettaObject.ts @@ -128,7 +128,7 @@ export const createVendettaObject = (unloads: any[]): any => ({ themes: themes.themes, fetchTheme: (id: string, selected?: boolean) => themes.fetchTheme(id, selected), installTheme: (id: string) => themes.installTheme(id), - selectTheme: (id: string) => themes.selectTheme(id), + selectTheme: (id: string) => themes.selectTheme(id === "default" ? null : id), removeTheme: (id: string) => themes.removeTheme(id), getCurrentTheme: () => themes._getThemeFromLoader(), updateThemes: () => themes.updateThemes() diff --git a/src/lib/managers/themes.ts b/src/lib/managers/themes.ts index 83471c5..85c4eca 100644 --- a/src/lib/managers/themes.ts +++ b/src/lib/managers/themes.ts @@ -177,11 +177,13 @@ export async function installTheme(id: string) { await fetchTheme(id); } -export async function selectTheme(id: string) { +export async function selectTheme(id: string | null) { Object.values(themes).forEach(s => s.selected = s.id === id); - if (id === "default") { + if (id === null) { return await writeTheme({}); + } else { + themes[id].selected = true; } await writeTheme(themes[id]); @@ -189,7 +191,7 @@ export async function selectTheme(id: string) { export async function removeTheme(id: string) { const theme = themes[id]; - if (theme.selected) await selectTheme("default"); + if (theme.selected) await selectTheme(null); delete themes[id]; return theme.selected; diff --git a/src/lib/ui/components/discord/Redesign.ts b/src/lib/ui/components/discord/Redesign.ts index c1978a7..2b14e3b 100644 --- a/src/lib/ui/components/discord/Redesign.ts +++ b/src/lib/ui/components/discord/Redesign.ts @@ -1,6 +1,8 @@ -import { findByProps } from "@lib/metro"; +import { find, findByProps } from "@lib/metro"; import { RedesignModuleKeys } from "@lib/ui/types"; +const findSingular = (prop: string) => find(m => m[prop] && Object.keys(m).length === 1)?.[prop]; + export const Redesign = findByProps("TableRow") as Record; export const CompatfulRedesign = findByProps("ActionSheetRow") as unknown as { @@ -8,6 +10,10 @@ export const CompatfulRedesign = findByProps("ActionSheetRow") as unknown as { [key: string]: any; }; +export const FormSwitch = findSingular("FormSwitch"); +export const FormRadio = findSingular("FormRadio"); +export const FormCheckbox = findSingular("FormCheckbox"); + export const { AlertActionButton, AlertModal,