refactor(ui): the work begin
This commit is contained in:
parent
dd6742d08d
commit
e8f60c92cf
27 changed files with 297 additions and 278 deletions
|
|
@ -7,9 +7,9 @@ import { installPlugin, plugins, removePlugin } from "@lib/managers/plugins";
|
|||
import { installTheme, removeTheme, themes } from "@lib/managers/themes";
|
||||
import { DISCORD_SERVER_ID, HTTP_REGEX_MULTI, PLUGINS_CHANNEL_ID, PROXY_PREFIX, THEMES_CHANNEL_ID } from "@lib/utils/constants";
|
||||
import { lazyDestructure } from "@lib/utils/lazy";
|
||||
import { Button } from "@metro/common/components";
|
||||
import { findByProps, findByPropsProxy } from "@metro/utils";
|
||||
import { ErrorBoundary } from "@ui/components";
|
||||
import { Button } from "@ui/components/discord/Redesign";
|
||||
import { showToast } from "@ui/toasts";
|
||||
|
||||
type PostType = "Plugin" | "Theme";
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import { settings } from "@lib/settings";
|
|||
import { HTTP_REGEX_MULTI } from "@lib/utils/constants";
|
||||
import { lazyDestructure } from "@lib/utils/lazy";
|
||||
import { clipboard } from "@metro/common";
|
||||
import { HelpMessage } from "@metro/common/components";
|
||||
import { findByProps, findByPropsProxy } from "@metro/utils";
|
||||
import { showInputAlert } from "@ui/alerts";
|
||||
import { ErrorBoundary, Search } from "@ui/components";
|
||||
import { HelpMessage } from "@ui/components/discord";
|
||||
import fuzzysort from "fuzzysort";
|
||||
import { createContext } from "react";
|
||||
import { FlatList, View } from "react-native";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Asset } from "@lib/api/assets";
|
||||
import { clipboard } from "@metro/common";
|
||||
import { FormRow } from "@ui/components/discord/Forms";
|
||||
import { LegacyFormRow } from "@metro/common/components";
|
||||
import { showToast } from "@ui/toasts";
|
||||
import { Image } from "react-native";
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ interface AssetDisplayProps { asset: Asset; }
|
|||
|
||||
export default function AssetDisplay({ asset }: AssetDisplayProps) {
|
||||
return (
|
||||
<FormRow
|
||||
<LegacyFormRow
|
||||
label={`${asset.name} - ${asset.id}`}
|
||||
trailing={<Image source={asset.id} style={{ width: 32, height: 32 }} />}
|
||||
onPress={() => {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
import { requireAssetIndex } from "@lib/api/assets";
|
||||
import { lazyDestructure } from "@lib/utils/lazy";
|
||||
import { ReactNative as RN } from "@metro/common";
|
||||
import { FormCheckbox, FormSwitch, IconButton, LegacyFormRow } from "@metro/common/components";
|
||||
import { findByProps } from "@metro/utils";
|
||||
import { semanticColors } from "@ui/color";
|
||||
import { FormRow } from "@ui/components/discord/Forms";
|
||||
import { FormCheckbox, FormSwitch, IconButton } from "@ui/components/discord/Redesign";
|
||||
import { createStyles, TextStyleSheet } from "@ui/styles";
|
||||
import { ImageBackground, View } from "react-native";
|
||||
|
||||
|
|
@ -100,7 +99,7 @@ export default function Card(props: CardProps) {
|
|||
resizeMode="cover"
|
||||
imageStyle={styles.iconStyle}
|
||||
>
|
||||
<FormRow
|
||||
<LegacyFormRow
|
||||
style={styles.header}
|
||||
label={
|
||||
<View style={styles.headerLeading}>
|
||||
|
|
@ -119,7 +118,7 @@ export default function Card(props: CardProps) {
|
|||
key: "CardOverflow",
|
||||
header: {
|
||||
title: props.overflowTitle,
|
||||
icon: props.headerIcon && <FormRow.Icon style={{ marginRight: 8 }} source={requireAssetIndex(props.headerIcon)} />,
|
||||
icon: props.headerIcon && <LegacyFormRow.Icon style={{ marginRight: 8 }} source={requireAssetIndex(props.headerIcon)} />,
|
||||
onClose: () => hideActionSheet(),
|
||||
},
|
||||
options: props.overflowActions?.map(i => ({ ...i, icon: requireAssetIndex(i.icon) })),
|
||||
|
|
@ -153,7 +152,7 @@ export default function Card(props: CardProps) {
|
|||
</View>
|
||||
}
|
||||
/>
|
||||
<FormRow
|
||||
<LegacyFormRow
|
||||
label={
|
||||
<RN.View>
|
||||
<RN.Text style={styles.descriptionLabel}>{props.descriptionLabel}</RN.Text>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { CardWrapper } from "@core/ui/components/Card";
|
|||
import { requireAssetIndex } from "@lib/api/assets";
|
||||
import { useProxy } from "@lib/api/storage";
|
||||
import { FontDefinition, fonts, removeFont, selectFont } from "@lib/managers/fonts";
|
||||
import { FormCheckbox, IconButton, TableRow, TableRowGroup } from "@ui/components/discord/Redesign";
|
||||
import { FormCheckbox, IconButton, TableRow, TableRowGroup } from "@metro/common/components";
|
||||
import { showToast } from "@ui/toasts";
|
||||
import { useContext } from "react";
|
||||
import { Pressable, View } from "react-native";
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { requireAssetIndex } from "@lib/api/assets";
|
||||
import { clipboard } from "@metro/common";
|
||||
import { FormText } from "@ui/components/discord/Forms";
|
||||
import { TableRow } from "@ui/components/discord/Redesign";
|
||||
import { LegacyFormText, TableRow } from "@metro/common/components";
|
||||
import { showToast } from "@ui/toasts";
|
||||
|
||||
interface VersionProps {
|
||||
|
|
@ -15,7 +14,7 @@ export default function Version({ label, version, icon }: VersionProps) {
|
|||
<TableRow
|
||||
label={label}
|
||||
icon={<TableRow.Icon source={requireAssetIndex(icon)} />}
|
||||
trailing={<FormText>{version}</FormText>}
|
||||
trailing={<LegacyFormText>{version}</LegacyFormText>}
|
||||
onPress={() => {
|
||||
clipboard.setString(`${label} - ${version}`);
|
||||
showToast.showCopyToClipboard();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ 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 "@ui/components/discord/Redesign";
|
||||
import { Stack, TableRowGroup } from "@metro/common/components";
|
||||
import { Platform, ScrollView } from "react-native";
|
||||
|
||||
export default function About() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import AssetDisplay from "@core/ui/components/AssetDisplay";
|
||||
import { assetsMap } from "@lib/api/assets";
|
||||
import { LegacyFormDivider } from "@metro/common/components";
|
||||
import { ErrorBoundary, Search } from "@ui/components";
|
||||
import { FormDivider } from "@ui/components/discord/Forms";
|
||||
import { FlatList, View } from "react-native";
|
||||
|
||||
export default function AssetBrowser() {
|
||||
|
|
@ -17,7 +17,7 @@ export default function AssetBrowser() {
|
|||
<FlatList
|
||||
data={Object.values(assetsMap).filter(a => a.name.includes(search) || a.id.toString() === search)}
|
||||
renderItem={({ item }) => <AssetDisplay asset={item} />}
|
||||
ItemSeparatorComponent={FormDivider}
|
||||
ItemSeparatorComponent={LegacyFormDivider}
|
||||
keyExtractor={item => item.name}
|
||||
/>
|
||||
</View>
|
||||
|
|
|
|||
|
|
@ -8,11 +8,10 @@ import { connectToDebugger } from "@lib/debug";
|
|||
import { loaderConfig, settings } from "@lib/settings";
|
||||
import { lazyDestructure } from "@lib/utils/lazy";
|
||||
import { NavigationNative } from "@metro/common";
|
||||
import { Button, LegacyFormText, Stack, TableRow, TableRowGroup, TableSwitchRow, TextInput } from "@metro/common/components";
|
||||
import { findByProps } from "@metro/utils";
|
||||
import { semanticColors } from "@ui/color";
|
||||
import { ErrorBoundary } from "@ui/components";
|
||||
import { FormText } from "@ui/components/discord/Forms";
|
||||
import { Button, Stack, TableRow, TableRowGroup, TableSwitchRow, TextInput } from "@ui/components/discord/Redesign";
|
||||
import { createStyles, TextStyleSheet } from "@ui/styles";
|
||||
import { ScrollView, StyleSheet } from "react-native";
|
||||
|
||||
|
|
@ -46,7 +45,7 @@ export default function Developer() {
|
|||
label={Strings.DEBUGGER_URL}
|
||||
placeholder="127.0.0.1:9090"
|
||||
size="md"
|
||||
leadingIcon={() => <FormText style={styles.leadingText}>ws://</FormText>}
|
||||
leadingIcon={() => <LegacyFormText style={styles.leadingText}>ws://</LegacyFormText>}
|
||||
defaultValue={settings.debuggerUrl}
|
||||
onChange={(v: string) => settings.debuggerUrl = v}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -4,9 +4,10 @@ import { createProxy, useProxy } from "@lib/api/storage";
|
|||
import { FontDefinition, saveFont, validateFont } from "@lib/managers/fonts";
|
||||
import { getCurrentTheme } from "@lib/managers/themes";
|
||||
import { safeFetch } from "@lib/utils";
|
||||
import { NavigationNative } from "@metro/common";
|
||||
import { ActionSheet, BottomSheetTitleHeader, Button, IconButton, Stack, TableRow, TableRowGroup, Text, TextInput } from "@metro/common/components";
|
||||
import { findByPropsProxy } from "@metro/utils";
|
||||
import { ErrorBoundary } from "@ui/components";
|
||||
import { ActionSheet, BottomSheetTitleHeader, Button, IconButton, Stack, TableRow, TableRowGroup, Text, TextInput, useNavigation } from "@ui/components/discord/Redesign";
|
||||
import { useMemo, useRef, useState } from "react";
|
||||
import { ScrollView, View } from "react-native";
|
||||
|
||||
|
|
@ -35,7 +36,7 @@ function RevengeFontsExtractor({ fonts, setName }: {
|
|||
const themeFonts = currentTheme!.fonts as Record<string, string>;
|
||||
|
||||
const [fontName, setFontName] = useState(guessFontName(Object.values(themeFonts)));
|
||||
const [error, setError] = useState<string | void>(undefined);
|
||||
const [error, setError] = useState<string | undefined>(undefined);
|
||||
|
||||
return <View style={{ padding: 8, paddingBottom: 16, gap: 12 }}>
|
||||
<TextInput
|
||||
|
|
@ -84,7 +85,7 @@ function JsonFontImporter({ fonts, setName }: {
|
|||
}) {
|
||||
const [fontLink, setFontLink] = useState<string>("");
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [error, setError] = useState<string | void>(undefined);
|
||||
const [error, setError] = useState<string | undefined>(undefined);
|
||||
|
||||
return <View style={{ padding: 8, paddingBottom: 16, gap: 12 }}>
|
||||
<TextInput
|
||||
|
|
@ -144,7 +145,7 @@ function EntryRow({ fontEntry }: { fontEntry: Record<string, string>; }) {
|
|||
const urlRef = useRef<string>();
|
||||
|
||||
const [nameSet, setNameSet] = useState(false);
|
||||
const [error, setError] = useState<string | void>();
|
||||
const [error, setError] = useState<string | undefined>();
|
||||
|
||||
return <View style={{ flexDirection: "row", gap: 8, justifyContent: "flex-start" }}>
|
||||
<View style={{ flex: 1 }}>
|
||||
|
|
@ -203,7 +204,7 @@ export default function FontImporter() {
|
|||
const memoEntry = useMemo(() => createProxy({}).proxy, []);
|
||||
const fontEntries: Record<string, string> = useProxy(memoEntry);
|
||||
|
||||
const navigation = useNavigation();
|
||||
const navigation = NavigationNative.useNavigation();
|
||||
|
||||
return <ScrollView style={{ flex: 1 }} contentContainerStyle={{ paddingBottom: 38 }}>
|
||||
<Stack style={{ paddingVertical: 24, paddingHorizontal: 12 }} spacing={12}>
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import FontCard from "@core/ui/components/FontCard";
|
|||
import { useProxy } from "@lib/api/storage";
|
||||
import { FontDefinition, fonts, installFont } from "@lib/managers/fonts";
|
||||
import { settings } from "@lib/settings";
|
||||
import { FormText } from "@ui/components/discord/Forms";
|
||||
import { useNavigation } from "@ui/components/discord/Redesign";
|
||||
import { NavigationNative } from "@metro/common";
|
||||
import { LegacyFormText } from "@metro/common/components";
|
||||
import { useEffect, useState } from "react";
|
||||
import { TouchableOpacity } from "react-native";
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ export default function Plugins() {
|
|||
|
||||
const [removeMode, setRemoveMode] = useState(false);
|
||||
|
||||
const navigation = useNavigation();
|
||||
const navigation = NavigationNative.useNavigation();
|
||||
|
||||
useEffect(() => {
|
||||
const onPressCallback = () => {
|
||||
|
|
@ -26,9 +26,9 @@ export default function Plugins() {
|
|||
|
||||
navigation.setOptions({
|
||||
headerRight: () => <TouchableOpacity onPress={onPressCallback}>
|
||||
<FormText style={{ marginRight: 12 }}>
|
||||
<LegacyFormText style={{ marginRight: 12 }}>
|
||||
{removeMode ? Strings.DONE : Strings.REMOVE}
|
||||
</FormText>
|
||||
</LegacyFormText>
|
||||
</TouchableOpacity>
|
||||
});
|
||||
}, [removeMode]);
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import { useProxy } from "@lib/api/storage";
|
|||
import { getDebugInfo, toggleSafeMode } from "@lib/debug";
|
||||
import { settings } from "@lib/settings";
|
||||
import { DISCORD_SERVER, GITHUB } from "@lib/utils/constants";
|
||||
import { url } from "@metro/common";
|
||||
import { Stack, TableRow, TableRowGroup, TableSwitchRow, useNavigation } from "@ui/components/discord/Redesign";
|
||||
import { NavigationNative, url } from "@metro/common";
|
||||
import { Stack, TableRow, TableRowGroup, TableSwitchRow } from "@metro/common/components";
|
||||
import { NativeModules, ScrollView } from "react-native";
|
||||
|
||||
import About from "./About";
|
||||
|
|
@ -15,7 +15,7 @@ export default function General() {
|
|||
useProxy(settings);
|
||||
|
||||
const debugInfo = getDebugInfo();
|
||||
const navigation = useNavigation();
|
||||
const navigation = NavigationNative.useNavigation();
|
||||
|
||||
return (
|
||||
<ScrollView style={{ flex: 1 }} contentContainerStyle={{ paddingBottom: 38 }}>
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { useProxy } from "@lib/api/storage";
|
|||
import { installTheme, Theme, themes } from "@lib/managers/themes";
|
||||
import { settings } from "@lib/settings";
|
||||
import { ButtonColors } from "@lib/utils/types";
|
||||
import { Button } from "@ui/components/discord";
|
||||
import { Button } from "@metro/common/components";
|
||||
|
||||
export default function Themes() {
|
||||
useProxy(settings);
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ import { loaderConfig, settings } from "@lib/settings";
|
|||
import * as utils from "@lib/utils";
|
||||
import * as metro from "@metro";
|
||||
import * as common from "@metro/common";
|
||||
import { Forms } from "@metro/common/components";
|
||||
import * as commonComponents from "@metro/common/components";
|
||||
import * as alerts from "@ui/alerts";
|
||||
import * as color from "@ui/color";
|
||||
import * as components from "@ui/components";
|
||||
import { Forms } from "@ui/components/discord/Forms";
|
||||
import { CompatfulRedesign } from "@ui/components/discord/Redesign";
|
||||
import { createThemedStyleSheet } from "@ui/styles";
|
||||
import * as toasts from "@ui/toasts";
|
||||
import SparkMD5 from "spark-md5";
|
||||
|
|
@ -64,7 +64,6 @@ export const initVendettaObject = (): any => {
|
|||
url: common.url,
|
||||
toasts: common.toasts,
|
||||
stylesheet: {
|
||||
...CompatfulRedesign,
|
||||
createThemedStyleSheet
|
||||
},
|
||||
clipboard: common.clipboard,
|
||||
|
|
@ -109,10 +108,10 @@ export const initVendettaObject = (): any => {
|
|||
components: {
|
||||
Forms,
|
||||
General: common.ReactNative,
|
||||
Alert: components.discord.Alert,
|
||||
Button: components.discord.Button,
|
||||
HelpMessage: components.discord.HelpMessage,
|
||||
SafeAreaView: components.discord.SafeAreaView,
|
||||
Alert: commonComponents.Alert,
|
||||
Button: commonComponents.Button,
|
||||
HelpMessage: commonComponents.HelpMessage,
|
||||
SafeAreaView: commonComponents.SafeAreaView,
|
||||
Summary: components.Summary,
|
||||
ErrorBoundary: components.ErrorBoundary,
|
||||
Codeblock: components.Codeblock,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import { Strings } from "@core/i18n";
|
||||
import { React } from "@metro/common";
|
||||
import { Button, LegacyFormText } from "@metro/common/components";
|
||||
import { Codeblock } from "@ui/components";
|
||||
import { Button } from "@ui/components/discord";
|
||||
import { FormText } from "@ui/components/discord/Forms";
|
||||
import { createThemedStyleSheet } from "@ui/styles";
|
||||
import { ScrollView } from "react-native";
|
||||
|
||||
|
|
@ -43,16 +42,15 @@ export default class ErrorBoundary extends React.Component<ErrorBoundaryProps, E
|
|||
|
||||
return (
|
||||
<ScrollView style={styles.view}>
|
||||
<FormText style={styles.title}>{Strings.UH_OH}</FormText>
|
||||
<LegacyFormText style={styles.title}>{Strings.UH_OH}</LegacyFormText>
|
||||
<Codeblock selectable style={{ marginBottom: 5 }}>{this.state.error.name}</Codeblock>
|
||||
<Codeblock selectable style={{ marginBottom: 5 }}>{this.state.error.message}</Codeblock>
|
||||
{this.state.error.stack && <ScrollView style={{ maxHeight: 420, marginBottom: 5 }}>
|
||||
<Codeblock selectable>{this.state.error.stack}</Codeblock>
|
||||
</ScrollView>}
|
||||
<Button
|
||||
color={Button.Colors.RED}
|
||||
size={Button.Sizes.MEDIUM}
|
||||
look={Button.Looks.FILLED}
|
||||
size="md"
|
||||
variant="destructive"
|
||||
onPress={() => this.setState({ hasErr: false })}
|
||||
text={Strings.RETRY}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { ButtonColors } from "@lib/utils/types";
|
||||
import { Alert, LegacyFormInput } from "@metro/common/components";
|
||||
import { findByPropsProxy } from "@metro/utils";
|
||||
import { Alert } from "@ui/components/discord";
|
||||
import { FormInput } from "@ui/components/discord/Forms";
|
||||
|
||||
const Alerts = findByPropsProxy("openLazy", "close");
|
||||
|
||||
|
|
@ -40,7 +39,7 @@ export default function InputAlert({ title, confirmText, confirmColor, onConfirm
|
|||
cancelText={cancelText}
|
||||
onCancel={() => Alerts.close()}
|
||||
>
|
||||
<FormInput
|
||||
<LegacyFormInput
|
||||
placeholder={placeholder}
|
||||
value={value}
|
||||
onChange={(v: string | { text: string; }) => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Strings } from "@core/i18n";
|
||||
import { requireAssetIndex } from "@lib/api/assets";
|
||||
import { TextInput } from "@ui/components/discord/Redesign";
|
||||
import { TextInput } from "@metro/common/components";
|
||||
import ErrorBoundary from "@ui/components/ErrorBoundary";
|
||||
import { Image, View } from "react-native";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { requireAssetIndex } from "@lib/api/assets";
|
||||
import { FormRow } from "@ui/components/discord/Forms";
|
||||
import { TableRow } from "@ui/components/discord/Redesign";
|
||||
import { LegacyFormRow, TableRow } from "@metro/common/components";
|
||||
import { LayoutAnimation, View } from "react-native";
|
||||
|
||||
export interface SummaryProps {
|
||||
|
|
@ -19,7 +18,7 @@ export default function Summary({ label, icon, noPadding = false, noAnimation =
|
|||
<TableRow
|
||||
label={label}
|
||||
icon={icon && <TableRow.Icon source={requireAssetIndex(icon)} />}
|
||||
trailing={<FormRow.Arrow style={{ transform: [{ rotate: `${hidden ? 180 : 90}deg` }] }} />}
|
||||
trailing={<LegacyFormRow.Arrow style={{ transform: [{ rotate: `${hidden ? 180 : 90}deg` }] }} />}
|
||||
onPress={() => {
|
||||
setHidden(!hidden);
|
||||
if (!noAnimation) LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
import { lazyDestructure } from "@lib/utils/lazy";
|
||||
import { findByPropsProxy } from "@metro/utils";
|
||||
|
||||
export const Forms = findByPropsProxy("Form", "FormSection");
|
||||
|
||||
export const {
|
||||
Form,
|
||||
FormArrow,
|
||||
FormCTA,
|
||||
FormCTAButton,
|
||||
FormCardSection,
|
||||
FormCheckbox,
|
||||
FormCheckboxRow,
|
||||
FormCheckmark,
|
||||
FormDivider,
|
||||
FormHint,
|
||||
FormIcon,
|
||||
FormInput,
|
||||
FormLabel,
|
||||
FormRadio,
|
||||
FormRadioGroup,
|
||||
FormRadioRow,
|
||||
FormRow,
|
||||
FormSection,
|
||||
FormSelect,
|
||||
FormSliderRow,
|
||||
FormSubLabel,
|
||||
FormSwitch,
|
||||
FormSwitchRow,
|
||||
FormTernaryCheckBox,
|
||||
FormText,
|
||||
FormTitle
|
||||
} = lazyDestructure(() => Forms);
|
||||
|
|
@ -1,170 +0,0 @@
|
|||
import { lazyDestructure, proxyLazy } from "@lib/utils/lazy";
|
||||
import { findExports } from "@metro";
|
||||
import { createFilterDefinition, findByPropsProxy } from "@metro/utils";
|
||||
import { RedesignModuleKeys } from "@ui/types";
|
||||
import { useEffect } from "react";
|
||||
import { View } from "react-native";
|
||||
|
||||
const bySingularProp = createFilterDefinition<[string]>(
|
||||
([prop], m) => m[prop] && Object.keys(m).length === 1,
|
||||
prop => `bunny.ui.bySingularProp(${prop})`
|
||||
);
|
||||
|
||||
const findSingular = (prop: string) => proxyLazy(() => findExports(bySingularProp(prop))?.[prop]);
|
||||
|
||||
export const Redesign = findByPropsProxy("TableRow") as Record<RedesignModuleKeys, any>;
|
||||
|
||||
export const CompatfulRedesign = findByPropsProxy("ActionSheetRow") as unknown as {
|
||||
TextStyleSheet: typeof import("@ui/styles").TextStyleSheet;
|
||||
[key: string]: any;
|
||||
};
|
||||
|
||||
// Funny polyfill, hopefully same props :3
|
||||
CompatfulRedesign.ActionSheetTitleHeader ??= CompatfulRedesign.BottomSheetTitleHeader;
|
||||
CompatfulRedesign.ActionSheetContentContainer ??= ({ children }: any) => {
|
||||
useEffect(() => console.warn("Discord has removed 'ActionSheetContentContainer', please move into something else. It has been temporarily replaced with View"), []);
|
||||
return <View>{children}</View>;
|
||||
};
|
||||
|
||||
export const FormSwitch = findSingular("FormSwitch");
|
||||
export const FormRadio = findSingular("FormRadio");
|
||||
export const FormCheckbox = findSingular("FormCheckbox");
|
||||
|
||||
export const {
|
||||
AlertActionButton,
|
||||
AlertModal,
|
||||
AlertModalContainer,
|
||||
AvatarDuoPile,
|
||||
AvatarPile,
|
||||
Backdrop,
|
||||
Button,
|
||||
Card,
|
||||
ContextMenu,
|
||||
ContextMenuContainer,
|
||||
FauxHeader,
|
||||
FloatingActionButton,
|
||||
GhostInput,
|
||||
GuildIconPile,
|
||||
HeaderActionButton,
|
||||
HeaderButton,
|
||||
HeaderSubmittingIndicator,
|
||||
IconButton,
|
||||
Input,
|
||||
InputButton,
|
||||
InputContainer,
|
||||
LayerContext,
|
||||
LayerScope,
|
||||
Modal,
|
||||
ModalActionButton,
|
||||
ModalContent,
|
||||
ModalDisclaimer,
|
||||
ModalFloatingAction,
|
||||
ModalFloatingActionSpacer,
|
||||
ModalFooter,
|
||||
ModalScreen,
|
||||
ModalStepIndicator,
|
||||
Navigator,
|
||||
NavigatorHeader,
|
||||
NavigatorScreen,
|
||||
Pile,
|
||||
PileOverflow,
|
||||
RedesignCompat,
|
||||
RedesignCompatContext,
|
||||
RowButton,
|
||||
SceneLoadingIndicator,
|
||||
SearchField,
|
||||
SegmentedControl,
|
||||
SegmentedControlPages,
|
||||
Slider,
|
||||
Stack,
|
||||
StepModal,
|
||||
StickyContext,
|
||||
StickyHeader,
|
||||
StickyWrapper,
|
||||
TableCheckboxRow,
|
||||
TableRadioGroup,
|
||||
TableRadioRow,
|
||||
TableRow,
|
||||
TableRowGroup,
|
||||
TableRowGroupTitle,
|
||||
TableRowIcon,
|
||||
TableSwitchRow,
|
||||
Tabs,
|
||||
TextArea,
|
||||
TextField,
|
||||
TextInput,
|
||||
Toast,
|
||||
dismissAlerts,
|
||||
getHeaderBackButton,
|
||||
getHeaderCloseButton,
|
||||
getHeaderConditionalBackButton,
|
||||
getHeaderNoTitle,
|
||||
getHeaderTextButton,
|
||||
hideContextMenu,
|
||||
navigatorShouldCrossfade,
|
||||
openAlert,
|
||||
useAccessibilityNativeStackOptions,
|
||||
useAndroidNavScrim,
|
||||
useCoachmark,
|
||||
useFloatingActionButtonScroll,
|
||||
useFloatingActionButtonState,
|
||||
useNativeStackNavigation,
|
||||
useNavigation,
|
||||
useNavigationTheme,
|
||||
useNavigatorBackPressHandler,
|
||||
useNavigatorScreens,
|
||||
useNavigatorShouldCrossfade,
|
||||
useSegmentedControlState,
|
||||
useStackNavigation,
|
||||
useTabNavigation,
|
||||
useTooltip
|
||||
} = lazyDestructure(() => Redesign);
|
||||
|
||||
export const {
|
||||
AccessibilityAnnouncer,
|
||||
AccessibilityPreferencesContext,
|
||||
AccessibilityView,
|
||||
AccessibilityViewAnimated,
|
||||
ActionSheet,
|
||||
ActionSheetCloseButton,
|
||||
ActionSheetIconHeader,
|
||||
ActionSheetPresenter,
|
||||
ActionSheetRow,
|
||||
ActionSheetSwitchRow,
|
||||
AnimatedEnterExitItem,
|
||||
BottomSheetTitleHeader,
|
||||
BottomSheetTextInput,
|
||||
Dialog,
|
||||
DisableCustomTheme,
|
||||
Menu,
|
||||
MenuGroup,
|
||||
MenuItem,
|
||||
MenuPopout,
|
||||
RootThemeContextProvider,
|
||||
SimpleActionSheet,
|
||||
Text,
|
||||
TextStyleSheet,
|
||||
ThemeContextFlags,
|
||||
ThemeContextForLegacyStyles,
|
||||
ThemeContextProvider,
|
||||
TransitionGroup,
|
||||
TransitionItem,
|
||||
TransitionStates,
|
||||
UseThemeContext,
|
||||
WCAGContrastRatios,
|
||||
createLegacyClassComponentStyles,
|
||||
createNativeStyleProperties,
|
||||
createStyleProperties,
|
||||
createStyles,
|
||||
darkenColor,
|
||||
experimental_createToken,
|
||||
getContrastingColor,
|
||||
getSemanticColorContextFromThemeContext,
|
||||
hasThemeFlag,
|
||||
setColorOpacity,
|
||||
setThemeFlag,
|
||||
showSimpleActionSheet,
|
||||
useLegacyClassComponentStyles,
|
||||
useThemeContext,
|
||||
useToken
|
||||
} = lazyDestructure(() => CompatfulRedesign);
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
import { findByDisplayNameProxy, findByNameProxy, findByPropsProxy } from "@metro/utils";
|
||||
|
||||
export * as Forms from "./Forms";
|
||||
export * as Redesign from "./Redesign";
|
||||
|
||||
// Discord
|
||||
export const Alert = findByDisplayNameProxy("FluxContainer(Alert)");
|
||||
export const Button = findByPropsProxy("Looks", "Colors", "Sizes") as React.ComponentType<any> & { Looks: any, Colors: any, Sizes: any; };
|
||||
export const HelpMessage = findByNameProxy("HelpMessage");
|
||||
// React Native's included SafeAreaView only adds padding on iOS.
|
||||
export const SafeAreaView = findByPropsProxy("useSafeAreaInsets").SafeAreaView as any;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
// Discord
|
||||
export * as discord from "./discord";
|
||||
// export * as discord from "./discord";
|
||||
|
||||
// Vendetta
|
||||
export { default as Codeblock } from "@ui/components/Codeblock";
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ import { toggleSafeMode } from "@lib/debug";
|
|||
import { settings } from "@lib/settings";
|
||||
import { lazyDestructure } from "@lib/utils/lazy";
|
||||
import { ButtonColors } from "@lib/utils/types";
|
||||
import { Button, SafeAreaView } from "@metro/common/components";
|
||||
import { findByNameProxy, findByProps } from "@metro/utils";
|
||||
import { semanticColors } from "@ui/color";
|
||||
import { Codeblock, ErrorBoundary as _ErrorBoundary } from "@ui/components";
|
||||
import { Button, SafeAreaView } from "@ui/components/discord";
|
||||
import { createThemedStyleSheet, TextStyleSheet } from "@ui/styles";
|
||||
import { Text, View } from "react-native";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { after } from "@lib/api/patcher";
|
||||
import { findInReactTree } from "@lib/utils";
|
||||
import { i18n, NavigationNative } from "@metro/common";
|
||||
import { LegacyFormIcon, LegacyFormRow, LegacyFormSection } from "@metro/common/components";
|
||||
import { findByNameProxy } from "@metro/utils";
|
||||
import { FormIcon, FormRow, FormSection } from "@ui/components/discord/Forms";
|
||||
import { registeredSections } from "@ui/settings";
|
||||
|
||||
import { CustomPageRenderer, wrapOnPress } from "./shared";
|
||||
|
|
@ -12,17 +12,17 @@ function SettingsSection() {
|
|||
|
||||
return <>
|
||||
{Object.keys(registeredSections).map(sect => (
|
||||
<FormSection key={sect} title={sect}>
|
||||
<LegacyFormSection key={sect} title={sect}>
|
||||
{ /** Is usePredicate here safe? */}
|
||||
{registeredSections[sect].filter(r => r.usePredicate?.() ?? true).map(row => (
|
||||
<FormRow
|
||||
<LegacyFormRow
|
||||
label={row.title()}
|
||||
leading={<FormIcon source={row.icon} />}
|
||||
trailing={FormRow.Arrow}
|
||||
leading={<LegacyFormIcon source={row.icon} />}
|
||||
trailing={LegacyFormRow.Arrow}
|
||||
onPress={wrapOnPress(row.onPress, navigation, row.render, row.title())}
|
||||
/>
|
||||
))}
|
||||
</FormSection>
|
||||
</LegacyFormSection>
|
||||
))}
|
||||
</>;
|
||||
}
|
||||
|
|
@ -49,7 +49,7 @@ export function patchPanelUI(unpatches: (() => void | boolean)[]) {
|
|||
|
||||
const sections = findInReactTree(
|
||||
res.props.children,
|
||||
n => n?.children?.[1]?.type === FormSection
|
||||
n => n?.children?.[1]?.type === LegacyFormSection
|
||||
).children;
|
||||
|
||||
const index = sections.findIndex((c: any) => titles.includes(c?.props.label));
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
import { lazyDestructure } from "@lib/utils/lazy";
|
||||
import { findByProps } from "@metro/utils";
|
||||
import { findByProps, findByPropsProxy } from "@metro/utils";
|
||||
import { isSemanticColor, resolveSemanticColor } from "@ui/color";
|
||||
import { CompatfulRedesign } from "@ui/components/discord/Redesign";
|
||||
import { DiscordTextStyles } from "@ui/types";
|
||||
import { ImageStyle, StyleSheet, TextStyle, ViewStyle } from "react-native";
|
||||
|
||||
type NamedStyles<T> = { [P in keyof T]: ViewStyle | TextStyle | ImageStyle };
|
||||
|
||||
const CompatfulRedesign = findByPropsProxy("createStyles");
|
||||
|
||||
export const { TextStyleSheet } = lazyDestructure(() => findByProps("TextStyleSheet")) as unknown as {
|
||||
TextStyleSheet: { [key in DiscordTextStyles]: TextStyle; };
|
||||
};
|
||||
|
|
|
|||
95
src/metro/common/components.ts
Normal file
95
src/metro/common/components.ts
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/* eslint-disable prefer-destructuring */
|
||||
import { lazyDestructure, proxyLazy } from "@lib/utils/lazy";
|
||||
import { findExports } from "@metro/finders";
|
||||
import { createFilterDefinition, findByDisplayNameProxy, findByNameProxy, findByProps, findByPropsProxy } from "@metro/utils";
|
||||
|
||||
import * as t from "./types/components";
|
||||
|
||||
const bySingularProp = createFilterDefinition<[string]>(
|
||||
([prop], m) => m[prop] && Object.keys(m).length === 1,
|
||||
prop => `bunny.metro.common.components.bySingularProp(${prop})`
|
||||
);
|
||||
|
||||
const findSingular = (prop: string) => proxyLazy(() => findExports(bySingularProp(prop))?.[prop]);
|
||||
const findProp = (prop: string) => proxyLazy(() => findByProps(prop)[prop]);
|
||||
|
||||
// Discord
|
||||
export const Alert = findByDisplayNameProxy("FluxContainer(Alert)");
|
||||
export const CompatButton = findByPropsProxy("Looks", "Colors", "Sizes");
|
||||
export const HelpMessage = findByNameProxy("HelpMessage");
|
||||
// React Native's included SafeAreaView only adds padding on iOS.
|
||||
export const SafeAreaView = proxyLazy(() => findByProps("useSafeAreaInsets").SafeAreaView);
|
||||
|
||||
// Buttons
|
||||
export const Button = findSingular("Button") as t.Button;
|
||||
export const TwinButtons = findProp("TwinButtons");
|
||||
export const IconButton = findSingular("IconButton") as t.IconButton;
|
||||
export const RowButton = findProp("RowButton") as t.RowButton;
|
||||
|
||||
export const PressableScale = findProp("PressableScale");
|
||||
|
||||
// Tables
|
||||
export const TableRow = findProp("TableRow");
|
||||
export const TableRowIcon = findProp("TableRowIcon");
|
||||
export const TableRowTrailingText = findProp("TableRowTrailingText");
|
||||
export const TableRowGroup = findProp("TableRowGroup");
|
||||
export const TableSwitchRow = findProp("TableSwitchRow");
|
||||
export const TableSwitch = findSingular("FormSwitch");
|
||||
export const TableRadio = findSingular("FormRadio");
|
||||
export const TableCheckbox = findSingular("FormCheckbox");
|
||||
|
||||
export const FormSwitch = findSingular("FormSwitch");
|
||||
export const FormRadio = findSingular("FormRadio");
|
||||
export const FormCheckbox = findSingular("FormCheckbox");
|
||||
|
||||
// Card
|
||||
export const Card = findProp("Card");
|
||||
export const RedesignCompat = proxyLazy(() => findByProps("RedesignCompat").RedesignCompat);
|
||||
|
||||
// Misc.
|
||||
export const Stack = findProp("Stack") as t.Stack;
|
||||
|
||||
// Inputs
|
||||
export const TextInput = findSingular("TextInput") as t.TextInput;
|
||||
|
||||
// SegmentedControl
|
||||
export const SegmentedControl = findProp("SegmentedControl") as t.SegmentedControl;
|
||||
export const CompatSegmentedControl = findProp("CompatSegmentedControl") as t.CompatSegmentedControl;
|
||||
|
||||
export const FloatingActionButton = findProp("FloatingActionButton") as t.FloatingActionButton;
|
||||
export const ActionSheet = findProp("ActionSheet");
|
||||
export const BottomSheetTitleHeader = findProp("BottomSheetTitleHeader");
|
||||
|
||||
const textsModule = findByPropsProxy("Text", "LegacyText");
|
||||
export const Text = proxyLazy(() => textsModule.Text) as t.Text;
|
||||
|
||||
export const Forms = findByPropsProxy("Form", "FormSection");
|
||||
|
||||
export const {
|
||||
Form: LegacyForm,
|
||||
FormArrow: LegacyFormArrow,
|
||||
FormCTA: LegacyFormCTA,
|
||||
FormCTAButton: LegacyFormCTAButton,
|
||||
FormCardSection: LegacyFormCardSection,
|
||||
FormCheckbox: LegacyFormCheckbox,
|
||||
FormCheckboxRow: LegacyFormCheckboxRow,
|
||||
FormCheckmark: LegacyFormCheckmark,
|
||||
FormDivider: LegacyFormDivider,
|
||||
FormHint: LegacyFormHint,
|
||||
FormIcon: LegacyFormIcon,
|
||||
FormInput: LegacyFormInput,
|
||||
FormLabel: LegacyFormLabel,
|
||||
FormRadio: LegacyFormRadio,
|
||||
FormRadioGroup: LegacyFormRadioGroup,
|
||||
FormRadioRow: LegacyFormRadioRow,
|
||||
FormRow: LegacyFormRow,
|
||||
FormSection: LegacyFormSection,
|
||||
FormSelect: LegacyFormSelect,
|
||||
FormSliderRow: LegacyFormSliderRow,
|
||||
FormSubLabel: LegacyFormSubLabel,
|
||||
FormSwitch: LegacyFormSwitch,
|
||||
FormSwitchRow: LegacyFormSwitchRow,
|
||||
FormTernaryCheckBox: LegacyFormTernaryCheckBox,
|
||||
FormText: LegacyFormText,
|
||||
FormTitle: LegacyFormTitle
|
||||
} = lazyDestructure(() => Forms);
|
||||
144
src/metro/common/types/components.ts
Normal file
144
src/metro/common/types/components.ts
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
import { DiscordTextStyles } from "@lib/ui/types";
|
||||
import { Nullish } from "@lib/utils/types";
|
||||
import { ReactNode } from "react";
|
||||
import type * as RN from "react-native";
|
||||
import { ImageSourcePropType, PressableProps } from "react-native";
|
||||
import { LiteralUnion } from "type-fest";
|
||||
|
||||
// Abandon all hope, ye who enter here
|
||||
type Style = RN.ViewStyle & RN.ImageStyle & RN.TextStyle;
|
||||
|
||||
type InteractiveSize = "sm" | "md" | "lg";
|
||||
|
||||
// Buttons
|
||||
type ButtonVariant = "primary" | "secondary" | "tertiary" | "destructive" | "active";
|
||||
|
||||
interface ButtonProps {
|
||||
disabled?: boolean;
|
||||
onPress: () => void;
|
||||
loading?: boolean;
|
||||
variant?: LiteralUnion<ButtonVariant, string>;
|
||||
text?: string;
|
||||
size?: LiteralUnion<InteractiveSize, string>;
|
||||
iconPosition?: "start" | "end";
|
||||
scaleAmountInPx?: number;
|
||||
icon?: ImageSourcePropType | ReactNode;
|
||||
style?: Style;
|
||||
}
|
||||
|
||||
export type Button = React.ForwardRefExoticComponent<ButtonProps>;
|
||||
|
||||
// Segmented Control
|
||||
interface SegmentedControlItem {
|
||||
id: string;
|
||||
label: string;
|
||||
page: JSX.Element | null;
|
||||
}
|
||||
|
||||
interface SegmentedControlProps {
|
||||
state: any;
|
||||
// state: {
|
||||
// activeIndex: SharedValue<number>;
|
||||
// pagerRef: RefObject<View>;
|
||||
// scrollTarget: SharedValue<number>;
|
||||
// scrollOverflow: SharedValue<number>;
|
||||
// scrollOffset: SharedValue<number>;
|
||||
// items: SegmentedControlItem[];
|
||||
// itemDimensions: SharedValue<unknown[]>;
|
||||
// pageWidth: number;
|
||||
// pressedIndex: SharedValue<number>;
|
||||
// onPageChangeRef: MutableRefObject<unknown>; // { current: undefined }
|
||||
// setActiveIndex: (index: number) => void;
|
||||
// setItemDimensions: (index: number, dimensions: unknown[]) => void;
|
||||
// useReducedMotion: boolean;
|
||||
// };
|
||||
}
|
||||
|
||||
export type SegmentedControl = React.FC<SegmentedControlProps>;
|
||||
|
||||
interface CompatSegmentedControlProps {
|
||||
values: string[];
|
||||
selectedSegmentIndex?: number;
|
||||
onValueChange?: (index: number) => void;
|
||||
onSetActiveIndex?: (index: number) => void;
|
||||
}
|
||||
|
||||
export type CompatSegmentedControl = React.FC<CompatSegmentedControlProps>;
|
||||
|
||||
// TODO: Confirm if this is real
|
||||
interface TextInputProps extends Omit<RN.TextInputProps, "onChange" | "onChangeText" | "value"> {
|
||||
defaultValue?: string;
|
||||
description?: string;
|
||||
editable?: boolean;
|
||||
errorMessage?: string;
|
||||
focusable?: boolean;
|
||||
grow?: boolean;
|
||||
isCentered?: boolean;
|
||||
isClearable?: boolean;
|
||||
isDisabled?: boolean;
|
||||
isRound?: boolean;
|
||||
label?: string;
|
||||
leadingIcon?: React.FC<any>;
|
||||
leadingPressableProps?: PressableProps;
|
||||
leadingText?: string;
|
||||
onChange?: (text: string) => void;
|
||||
size?: "sm" | "md" | "lg";
|
||||
status?: "error" | "default";
|
||||
style?: Style;
|
||||
trailingIcon?: React.FC<any>;
|
||||
trailingPressableProps?: PressableProps;
|
||||
trailingText?: string;
|
||||
value?: string | Nullish;
|
||||
}
|
||||
|
||||
export type TextInput = React.FC<TextInputProps>;
|
||||
|
||||
interface RowButtonProps {
|
||||
variant?: LiteralUnion<ButtonVariant, string>;
|
||||
style?: Style;
|
||||
icon?: ImageSourcePropType | ReactNode;
|
||||
label: string | ReactNode;
|
||||
subLabel?: string | ReactNode;
|
||||
onPress: () => void;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
export type RowButton = React.FC<RowButtonProps>;
|
||||
|
||||
interface StackProps {
|
||||
/** defaults to vertical */
|
||||
direction?: "vertical" | "horizontal";
|
||||
/** defaults to 8 */
|
||||
spacing?: number;
|
||||
}
|
||||
|
||||
export type Stack = React.FC<React.PropsWithChildren<StackProps> & RN.ViewProps>;
|
||||
|
||||
interface FABProps {
|
||||
icon: ImageSourcePropType | ReactNode;
|
||||
style?: Style;
|
||||
onPress: () => void;
|
||||
}
|
||||
|
||||
export type FloatingActionButton = React.FC<FABProps>;
|
||||
|
||||
type TextProps = React.ComponentProps<typeof RN.Text> & {
|
||||
variant?: DiscordTextStyles;
|
||||
color?: string; // TODO: type this
|
||||
lineClamp?: number;
|
||||
maxFontSizeMultiplier?: number;
|
||||
style?: Style;
|
||||
};
|
||||
|
||||
export type Text = React.FC<TextProps>;
|
||||
|
||||
interface IconButtonProps {
|
||||
icon: ImageSourcePropType | ReactNode;
|
||||
onPress: () => void;
|
||||
disabled?: boolean;
|
||||
size?: InteractiveSize;
|
||||
variant?: ButtonVariant;
|
||||
style?: Style;
|
||||
}
|
||||
|
||||
export type IconButton = React.FC<IconButtonProps>;
|
||||
Loading…
Add table
Reference in a new issue