diff --git a/src/core/ui/components/AddonPage.tsx b/src/core/ui/components/AddonPage.tsx index fa1ed89..18f8375 100644 --- a/src/core/ui/components/AddonPage.tsx +++ b/src/core/ui/components/AddonPage.tsx @@ -25,6 +25,7 @@ interface AddonPageProps { card: React.ComponentType>; isRemoveMode?: boolean; headerComponent?: JSX.Element; + onFABPress?: () => void; } function getItemsByQuery["items"][string]>(items: T[], query: string): T[] { @@ -45,7 +46,7 @@ function getItemsByQuery["items"][string]>(ite const reanimated = findByProps("useSharedValue"); const { FloatingActionButton } = findByProps("FloatingActionButton"); -export default function AddonPage({ floatingButtonText, fetchFunction, items, safeModeMessage, safeModeExtras, card: CardComponent, isRemoveMode, headerComponent }: AddonPageProps) { +export default function AddonPage({ floatingButtonText, fetchFunction, items, safeModeMessage, safeModeExtras, card: CardComponent, isRemoveMode, headerComponent, onFABPress }: AddonPageProps) { useProxy(items); useProxy(settings); @@ -83,9 +84,9 @@ export default function AddonPage({ floatingButtonText, fetchFunction, items, /> { + onPress={onFABPress ?? (() => { // from ./InstallButton.tsx clipboard.getString().then(content => showInputAlert({ @@ -97,7 +98,7 @@ export default function AddonPage({ floatingButtonText, fetchFunction, items, cancelText: Strings.CANCEL, }) ); - }} + })} /> ); diff --git a/src/core/ui/components/Card.tsx b/src/core/ui/components/Card.tsx index cd9b7a7..df0a2c1 100644 --- a/src/core/ui/components/Card.tsx +++ b/src/core/ui/components/Card.tsx @@ -125,7 +125,7 @@ export default function Card(props: CardProps) { })} size="sm" variant="secondary" - icon={getAssetIDByName("CircleInformationIcon")} + icon={getAssetIDByName("CircleInformationIcon-primary")} />} {props.actions?.map(({ icon, onPress, disabled }) => ( { selectFont(selected ? null : font.name).then(() => { diff --git a/src/core/ui/settings/pages/FontImporter.tsx b/src/core/ui/settings/pages/FontImporter.tsx new file mode 100644 index 0000000..561906b --- /dev/null +++ b/src/core/ui/settings/pages/FontImporter.tsx @@ -0,0 +1,274 @@ +import { formatString, Strings } from "@core/i18n"; +import { getAssetIDByName } from "@lib/api/assets"; +import { createProxy, useProxy } from "@lib/api/storage"; +import { FontDefinition, saveFont, validateFont } from "@lib/managers/fonts"; +import { getCurrentTheme } from "@lib/managers/themes"; +import { findByProps } from "@lib/metro"; +import { ErrorBoundary } from "@lib/ui/components"; +import { ActionSheet, BottomSheetTitleHeader, Button, IconButton, Stack, TableRow, TableRowGroup, Text, TextInput, useNavigation } from "@lib/ui/components/discord/Redesign"; +import { safeFetch } from "@lib/utils"; +import { useMemo, useRef, useState } from "react"; +import { ScrollView, View } from "react-native"; + +const actionSheet = findByProps("hideActionSheet"); + +function guessFontName(urls: string[]) { + const fileNames = urls.map(url => { + const { pathname } = new URL(url); + const fileName = pathname.replace(/\.[^/.]+$/, ""); + return fileName.split("/").pop(); + }).filter(Boolean) as string[]; + + const shortest = fileNames.reduce((shortest, name) => { + return name.length < shortest.length ? name : shortest; + }, fileNames[0] || ""); + + return shortest?.replace(/-[A-Za-z]*$/, "") || null; +} + +function RevengeFontsExtractor({ fonts, setName }: { + fonts: Record; + setName: (name: string) => void; +}) { + const currentTheme = getCurrentTheme()!.data; + // @ts-ignore + const themeFonts = currentTheme!.fonts as Record; + + const [fontName, setFontName] = useState(guessFontName(Object.values(themeFonts))); + const [error, setError] = useState(undefined); + + return + + + {formatString("THEME_EXTRACTOR_DESC", { + fonts: Object.keys(themeFonts).join(Strings.SEPARATOR) + })} + +