import { Strings } from "@core/i18n"; import { CardWrapper } from "@core/ui/components/AddonCard"; import { findAssetId } from "@lib/api/assets"; import { settings } from "@lib/api/settings"; import { useProxy } from "@lib/api/storage"; import { HTTP_REGEX_MULTI } from "@lib/utils/constants"; import { clipboard } from "@metro/common"; import { FlashList, FloatingActionButton, HelpMessage } from "@metro/common/components"; import { showInputAlert } from "@ui/alerts"; import { ErrorBoundary, Search } from "@ui/components"; import fuzzysort from "fuzzysort"; import { ComponentType, ReactNode, useMemo } from "react"; import { View } from "react-native"; type SearchKeywords = Array string)>; interface AddonPageProps { title: string; fetchFunction?: (url: string) => Promise; items: any[]; resolveItem?: (value: any) => T | undefined; safeModeMessage: string; safeModeExtras?: ReactNode; card: ComponentType>; searchKeywords: SearchKeywords; onFabPress?: () => void; ListHeaderComponent?: ComponentType; ListFooterComponent?: ComponentType; } export default function AddonPage({ card: CardComponent, ...props }: AddonPageProps) { useProxy(settings); const [search, setSearch] = React.useState(""); const results = useMemo(() => { let values = props.items; if (props.resolveItem) values = values.map(props.resolveItem); const items = values.filter(i => i && typeof i === "object"); return fuzzysort.go(search, items, { keys: props.searchKeywords, all: true }); }, [props.items, search]); const headerElement = ( {props.ListHeaderComponent && } {settings.safeMode?.enabled && {props.safeModeMessage} {props.safeModeExtras} } setSearch(v)} /> ); return ( } ListFooterComponent={props.ListFooterComponent} renderItem={({ item }: any) => } /> {(props.fetchFunction ?? props.onFabPress) && { // from ./InstallButton.tsx clipboard.getString().then((content: string) => showInputAlert({ initialValue: content.match(HTTP_REGEX_MULTI)?.[0] ?? "", placeholder: Strings.URL_PLACEHOLDER, onConfirm: (input: string) => props.fetchFunction!(input), confirmText: Strings.INSTALL, cancelText: Strings.CANCEL, }) ); })} />} ); }