Skip to content

Commit

Permalink
feat+refactor: Add empty list component and readd unproxied plugin wa…
Browse files Browse the repository at this point in the history
…rning
  • Loading branch information
pylixonly committed Aug 28, 2024
1 parent 7bd53f7 commit 8dc0b82
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 69 deletions.
1 change: 1 addition & 0 deletions src/core/i18n/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"CONFIRMATION_LINK_IS_A_TYPE": "This link is a **{urlType, select, plugin {Plugin} theme {Theme} other {Add-on}}**, would you like to install it?",
"CONNECT_TO_DEBUG_WEBSOCKET": "Connect to debug websocket",
"CONNECT_TO_REACT_DEVTOOLS": "Connect to React DevTools",
"CONTINUE": "Continue",
"COPIED_TO_CLIPBOARD": "Copied to clipboard",
"COPY_URL": "Copy URL",
"DEBUG": "Debug",
Expand Down
73 changes: 54 additions & 19 deletions src/core/ui/components/AddonPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ 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, IconButton } from "@metro/common/components";
import { Button, FlashList, FloatingActionButton, HelpMessage, IconButton, Text } 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";
import { ComponentType, ReactNode, useCallback, useMemo } from "react";
import { Image, View } from "react-native";

const { showSimpleActionSheet, hideActionSheet } = lazyDestructure(() => findByProps("showSimpleActionSheet"));

Expand All @@ -21,15 +21,19 @@ type SearchKeywords = Array<string | ((obj: any & {}) => string)>;
interface AddonPageProps<T extends object, I = any> {
title: string;
items: I[];
searchKeywords: SearchKeywords;
sortOptions?: Record<string, (a: I, b: I) => number>;
fetchFunction?: (url: string) => Promise<void>;
resolveItem?: (value: I) => T | undefined;
safeModeHint?: {
message?: string;
footer?: ReactNode;
}
searchKeywords: SearchKeywords;
onFabPress?: () => void;
installAction?: {
label?: string;
// Ignored when onPress is defined!
fetchFn?: (url: string) => Promise<void>;
onPress?: () => void;
}
CardComponent: ComponentType<CardWrapper<T>>;
ListHeaderComponent?: ComponentType<any>;
ListFooterComponent?: ComponentType<any>;
Expand All @@ -50,6 +54,42 @@ export default function AddonPage<T extends object>({ CardComponent, ...props }:
return fuzzysort.go(search, items, { keys: props.searchKeywords, all: true });
}, [props.items, sortFn, search]);

const onInstallPress = useCallback(() => {
if (!props.installAction) return () => {};
const { onPress, fetchFn } = props.installAction;
if (fetchFn) {
clipboard.getString().then((content: string) =>
showInputAlert({
title: props.installAction?.label,
initialValue: content.match(HTTP_REGEX_MULTI)?.[0] ?? "",
placeholder: Strings.URL_PLACEHOLDER,
onConfirm: (input: string) => fetchFn(input),
confirmText: Strings.INSTALL,
cancelText: Strings.CANCEL,
})
);
} else {
onPress?.();
}
}, []);

if (results.length === 0 && !search) {
return <View style={{ gap: 32, flexGrow: 1, justifyContent: "center", alignItems: "center" }}>
<View style={{ gap: 8, alignItems: "center" }}>
<Image source={findAssetId("empty_quick_switcher")} />
<Text variant="text-lg/semibold" color="text-normal">
Oops! Nothing to see here… yet!
</Text>
</View>
<Button
size="lg"
icon={findAssetId("DownloadIcon")}
text={props.installAction?.label ?? "Install"}
onPress={onInstallPress}
/>
</View>;
}

const headerElement = (
<View style={{ paddingBottom: 8 }}>
{props.ListHeaderComponent && <props.ListHeaderComponent />}
Expand Down Expand Up @@ -88,25 +128,20 @@ export default function AddonPage<T extends object>({ CardComponent, ...props }:
extraData={search}
estimatedItemSize={136}
ListHeaderComponent={headerElement}
ListEmptyComponent={() => <View style={{ gap: 12, padding: 12, alignItems: "center" }}>
<Image source={findAssetId("devices_not_found")} />
<Text variant="text-lg/semibold" color="text-normal">
Hmmm... could not find that!
</Text>
</View>}
contentContainerStyle={{ padding: 8, paddingHorizontal: 12 }}
ItemSeparatorComponent={() => <View style={{ height: 8 }} />}
ListFooterComponent={props.ListFooterComponent}
renderItem={({ item }: any) => <CardComponent item={item.obj} result={item} />}
/>
{(props.fetchFunction ?? props.onFabPress) && <FloatingActionButton
{props.installAction && <FloatingActionButton
icon={findAssetId("PlusLargeIcon")}
onPress={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,
})
);
})}
onPress={onInstallPress}
/>}
</ErrorBoundary>
);
Expand Down
41 changes: 0 additions & 41 deletions src/core/ui/components/InstallButton.tsx

This file was deleted.

16 changes: 9 additions & 7 deletions src/core/ui/settings/pages/Fonts/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import AddonPage from "@core/ui/components/AddonPage";
import FontEditor from "@core/ui/settings/pages/Fonts/FontEditor";
import { settings } from "@lib/api/settings";
import { useProxy } from "@lib/api/storage";
import { FontDefinition, fonts, installFont } from "@lib/fonts";
import { FontDefinition, fonts } from "@lib/fonts";
import { NavigationNative } from "@metro/common";

import FontCard from "./FontCard";
Expand All @@ -22,15 +22,17 @@ export default function Fonts() {
"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)}
safeModeHint={{ message: Strings.SAFE_MODE_NOTICE_FONTS }}
CardComponent={FontCard}
onFabPress={() => {
navigation.push("BUNNY_CUSTOM_PAGE", {
title: "Import Font",
render: () => <FontEditor />
});
installAction={{
label: "Install a font",
onPress: () => {
navigation.push("BUNNY_CUSTOM_PAGE", {
title: "Import Font",
render: () => <FontEditor />
});
}
}}
/>
);
Expand Down
26 changes: 25 additions & 1 deletion src/core/ui/settings/pages/Plugins/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ import { Strings } from "@core/i18n";
import AddonPage from "@core/ui/components/AddonPage";
import PluginCard from "@core/ui/settings/pages/Plugins/components/PluginCard";
import { VdPluginManager } from "@core/vendetta/plugins";
import { findAssetId } from "@lib/api/assets";
import { settings } from "@lib/api/settings";
import { useProxy } from "@lib/api/storage";
import { showConfirmationAlert } from "@lib/ui/alerts";
import { showToast } from "@lib/ui/toasts";
import { BUNNY_PROXY_PREFIX, VD_PROXY_PREFIX } from "@lib/utils/constants";
import { Author } from "@lib/utils/types";
import { ComponentProps } from "react";

Expand Down Expand Up @@ -64,7 +68,27 @@ export default function Plugins() {
return <PluginPage
useItems={() => useProxy(VdPluginManager.plugins) && Object.values(VdPluginManager.plugins)}
resolveItem={unifyVdPlugin}
fetchFunction={(url: string) => VdPluginManager.installPlugin(url)}
installAction={{
label: "Install a plugin",
fetchFn: async (url: string) => {
const install = () =>
VdPluginManager.installPlugin(url)
.then(() => showToast(Strings.TOASTS_INSTALLED_PLUGIN, findAssetId("Check")))
.catch(x => showToast(x?.message ?? `${x}`, findAssetId("Small")));

if (!url.startsWith(VD_PROXY_PREFIX) && !url.startsWith(BUNNY_PROXY_PREFIX) && !settings.developerSettings)
setImmediate(() => showConfirmationAlert({
title: Strings.MODAL_UNPROXIED_PLUGIN_HEADER,
content: Strings.MODAL_UNPROXIED_PLUGIN_DESC,
confirmText: Strings.CONTINUE,
onConfirm: install,
cancelText: Strings.CANCEL
}));
else {
return await install();
}
}
}}
/>;

// const navigation = NavigationNative.useNavigation();
Expand Down
5 changes: 4 additions & 1 deletion src/core/ui/settings/pages/Themes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ export default function Themes() {
"Name (A-Z)": (a, b) => a.name.localeCompare(b.name),
"Name (Z-A)": (a, b) => b.name.localeCompare(a.name)
}}
fetchFunction={installTheme}
installAction={{
label: "Install a theme",
fetchFn: installTheme
}}
items={Object.values(themes)}
safeModeHint={{
message: formatString("SAFE_MODE_NOTICE_THEMES", { enabled: Boolean(settings.safeMode?.currentThemeId) }),
Expand Down

0 comments on commit 8dc0b82

Please sign in to comment.