From 7bd53f7985013dae6b81eacc1dd0e26b7cb02654 Mon Sep 17 00:00:00 2001 From: amsyarasyiq <82711525+amsyarasyiq@users.noreply.github.com> Date: Wed, 28 Aug 2024 20:47:35 +0800 Subject: [PATCH] feat(AddonPage): Add sort options --- src/core/ui/components/AddonPage.tsx | 53 +++++++++++++++----- src/core/ui/settings/pages/Fonts/index.tsx | 8 ++- src/core/ui/settings/pages/Plugins/index.tsx | 8 ++- src/core/ui/settings/pages/Themes/index.tsx | 22 +++++--- src/lib/ui/components/Search.tsx | 4 +- 5 files changed, 70 insertions(+), 25 deletions(-) diff --git a/src/core/ui/components/AddonPage.tsx b/src/core/ui/components/AddonPage.tsx index ac524c4..335fa78 100644 --- a/src/core/ui/components/AddonPage.tsx +++ b/src/core/ui/components/AddonPage.tsx @@ -4,51 +4,80 @@ 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 { lazyDestructure } from "@lib/utils/lazy"; +import { findByProps } from "@metro"; import { clipboard } from "@metro/common"; -import { FlashList, FloatingActionButton, HelpMessage } from "@metro/common/components"; +import { FlashList, FloatingActionButton, HelpMessage, IconButton } 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"; +const { showSimpleActionSheet, hideActionSheet } = lazyDestructure(() => findByProps("showSimpleActionSheet")); + type SearchKeywords = Array string)>; -interface AddonPageProps { +interface AddonPageProps { title: string; + items: I[]; + sortOptions?: Record number>; fetchFunction?: (url: string) => Promise; - items: any[]; - resolveItem?: (value: any) => T | undefined; - safeModeMessage: string; - safeModeExtras?: ReactNode; - card: ComponentType>; + resolveItem?: (value: I) => T | undefined; + safeModeHint?: { + message?: string; + footer?: ReactNode; + } searchKeywords: SearchKeywords; onFabPress?: () => void; + CardComponent: ComponentType>; ListHeaderComponent?: ComponentType; ListFooterComponent?: ComponentType; } -export default function AddonPage({ card: CardComponent, ...props }: AddonPageProps) { +export default function AddonPage({ CardComponent, ...props }: AddonPageProps) { useProxy(settings); const [search, setSearch] = React.useState(""); + const [sortFn, setSortFn] = React.useState<((a: unknown, b: unknown) => number) | null>(() => null); const results = useMemo(() => { let values = props.items; if (props.resolveItem) values = values.map(props.resolveItem); const items = values.filter(i => i && typeof i === "object"); + if (!search && sortFn) items.sort(sortFn); return fuzzysort.go(search, items, { keys: props.searchKeywords, all: true }); - }, [props.items, search]); + }, [props.items, sortFn, search]); const headerElement = ( {props.ListHeaderComponent && } {settings.safeMode?.enabled && - {props.safeModeMessage} - {props.safeModeExtras} + + {props.safeModeHint?.message} + + {props.safeModeHint?.footer} } - setSearch(v)} /> + + setSearch(v)} /> + {props.sortOptions && showSimpleActionSheet({ + key: "AddonListSortOptions", + header: { + title: "Sort Options", + onClose: () => hideActionSheet("AddonListSortOptions"), + }, + options: Object.entries(props.sortOptions!).map(([name, fn]) => ({ + label: name, + onPress: () => setSortFn(() => fn) + })) + })} + />} + ); diff --git a/src/core/ui/settings/pages/Fonts/index.tsx b/src/core/ui/settings/pages/Fonts/index.tsx index 913071d..0b3c2b6 100644 --- a/src/core/ui/settings/pages/Fonts/index.tsx +++ b/src/core/ui/settings/pages/Fonts/index.tsx @@ -18,10 +18,14 @@ export default function Fonts() { title={Strings.FONTS} searchKeywords={["name", "description"]} + sortOptions={{ + "Name (A-Z)": (a, b) => a.name.localeCompare(b.name), + "Name (Z-A)": (a, b) => b.name.localeCompare(a.name) + }} fetchFunction={installFont} items={Object.values(fonts)} - safeModeMessage={Strings.SAFE_MODE_NOTICE_FONTS} - card={FontCard} + safeModeHint={{ message: Strings.SAFE_MODE_NOTICE_FONTS }} + CardComponent={FontCard} onFabPress={() => { navigation.push("BUNNY_CUSTOM_PAGE", { title: "Import Font", diff --git a/src/core/ui/settings/pages/Plugins/index.tsx b/src/core/ui/settings/pages/Plugins/index.tsx index 38d00f8..b664492 100644 --- a/src/core/ui/settings/pages/Plugins/index.tsx +++ b/src/core/ui/settings/pages/Plugins/index.tsx @@ -39,7 +39,7 @@ function PluginPage(props: PluginPageProps) { const items = props.useItems(); return - card={PluginCard} + CardComponent={PluginCard} title={Strings.PLUGINS} searchKeywords={[ "name", @@ -48,7 +48,11 @@ function PluginPage(props: PluginPageProps) { (a: Author | string) => typeof a === "string" ? a : a.name ).join() ]} - safeModeMessage={Strings.SAFE_MODE_NOTICE_PLUGINS} + sortOptions={{ + "Name (A-Z)": (a, b) => a.name.localeCompare(b.name), + "Name (Z-A)": (a, b) => b.name.localeCompare(a.name) + }} + safeModeHint={{ message: Strings.SAFE_MODE_NOTICE_PLUGINS }} items={items} {...props} />; diff --git a/src/core/ui/settings/pages/Themes/index.tsx b/src/core/ui/settings/pages/Themes/index.tsx index 602426f..aee7850 100644 --- a/src/core/ui/settings/pages/Themes/index.tsx +++ b/src/core/ui/settings/pages/Themes/index.tsx @@ -19,16 +19,22 @@ export default function Themes() { "data.description", p => p.data.authors?.map((a: Author) => a.name).join(", ") ]} + sortOptions={{ + "Name (A-Z)": (a, b) => a.name.localeCompare(b.name), + "Name (Z-A)": (a, b) => b.name.localeCompare(a.name) + }} fetchFunction={installTheme} items={Object.values(themes)} - safeModeMessage={formatString("SAFE_MODE_NOTICE_THEMES", { enabled: Boolean(settings.safeMode?.currentThemeId) })} - safeModeExtras={settings.safeMode?.currentThemeId ?