fix(plugins): handle unhandled cases
This commit is contained in:
parent
65d1f346b7
commit
61286d8980
6 changed files with 42 additions and 49 deletions
|
|
@ -4,12 +4,12 @@ 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, NavigationNative } from "@metro/common";
|
||||
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, useCallback, useMemo } from "react";
|
||||
import { ComponentType, ReactNode, useMemo } from "react";
|
||||
import { View } from "react-native";
|
||||
|
||||
type SearchKeywords = Array<string | ((obj: any & {}) => string)>;
|
||||
|
|
@ -30,14 +30,6 @@ interface AddonPageProps<T extends object> {
|
|||
export default function AddonPage<T extends object>({ card: CardComponent, ...props }: AddonPageProps<T>) {
|
||||
useProxy(settings);
|
||||
|
||||
const [, forceUpdate] = React.useReducer(s => ~s, 0);
|
||||
NavigationNative.useFocusEffect(
|
||||
useCallback(() => {
|
||||
console.log("giler", items);
|
||||
forceUpdate();
|
||||
}, [])
|
||||
);
|
||||
|
||||
const [search, setSearch] = React.useState("");
|
||||
|
||||
const items = useMemo(() => {
|
||||
|
|
@ -51,33 +43,26 @@ export default function AddonPage<T extends object>({ card: CardComponent, ...pr
|
|||
return fuzzysort.go(search, items, { keys: props.searchKeywords }).map(r => r.obj);
|
||||
}, [items, search]);
|
||||
|
||||
const headerElement = useMemo(() => (
|
||||
<View>
|
||||
const headerElement = (
|
||||
<View style={{ paddingBottom: 8 }}>
|
||||
{settings.safeMode?.enabled && <View style={{ marginBottom: 10 }}>
|
||||
<HelpMessage messageType={0}>{props.safeModeMessage}</HelpMessage>
|
||||
{props.safeModeExtras}
|
||||
</View>}
|
||||
<Search
|
||||
style={{ padding: 8 }}
|
||||
onChangeText={v => setSearch(v)}
|
||||
/>
|
||||
<Search onChangeText={v => setSearch(v)} />
|
||||
</View>
|
||||
), []);
|
||||
);
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
{/*
|
||||
I've spent countless hours on these, but FlashList and FlatList refuse to rerender (unless if you reopen the page)
|
||||
*even* if the data totally changed. Solutions online suggest putting extraData prop,
|
||||
but that doesn't work either. I wonder what could have caused this
|
||||
*/}
|
||||
<FlashList
|
||||
data={data}
|
||||
extraData={search}
|
||||
keyExtractor={(i: any) => i?.id}
|
||||
estimatedItemSize={136}
|
||||
ListHeaderComponent={headerElement}
|
||||
contentContainerStyle={{ paddingBottom: 90, paddingHorizontal: 5 }}
|
||||
contentContainerStyle={{ padding: 8, paddingHorizontal: 12 }}
|
||||
ItemSeparatorComponent={() => <View style={{ height: 8 }} />}
|
||||
ListFooterComponent={props.ListFooterComponent}
|
||||
renderItem={({ item }: any) => (
|
||||
<CardComponent item={item} />
|
||||
|
|
|
|||
|
|
@ -104,16 +104,12 @@ export default function Plugins() {
|
|||
]
|
||||
});
|
||||
|
||||
return <View
|
||||
style={{
|
||||
margin: 8,
|
||||
gap: 8,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
height: "100%"
|
||||
}}
|
||||
>
|
||||
<SegmentedControl state={state} />
|
||||
<SegmentedControlPages state={state} />
|
||||
</View>;
|
||||
return (
|
||||
<View style={{ alignItems: "center", justifyContent: "center", height: "100%" }}>
|
||||
<View style={{ padding: 8, paddingBottom: 0 }}>
|
||||
<SegmentedControl state={state} />
|
||||
</View>
|
||||
<SegmentedControlPages state={state} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ const storagePromiseSymbol = Symbol.for("bunny.storage.promise");
|
|||
|
||||
const _loadedPath = {} as Record<string, any>;
|
||||
|
||||
function createFileBackend<T>(filePath: string): StorageBackend<T> {
|
||||
function createFileBackend<T = any>(filePath: string): StorageBackend<T> {
|
||||
return {
|
||||
get: async () => {
|
||||
try {
|
||||
|
|
@ -187,13 +187,19 @@ export const createStorage = <T>(path: string, dflt = {} as T): T & { [key: symb
|
|||
};
|
||||
|
||||
export async function preloadStorageIfExists(path: string) {
|
||||
if (_loadedPath[path]) return;
|
||||
if (!await fileExists(path)) return;
|
||||
if (_loadedPath[path]) return _loadedPath[path];
|
||||
|
||||
const data = await createFileBackend<any>(path).get();
|
||||
_loadedPath[path] = data;
|
||||
const backend = createFileBackend(path);
|
||||
if (await backend.exists()) {
|
||||
return _loadedPath[path] = await backend.get();
|
||||
}
|
||||
|
||||
console.log("no " + path);
|
||||
}
|
||||
|
||||
export function getPreloadedStorage<T>(path: string): T {
|
||||
return _loadedPath[path];
|
||||
}
|
||||
export function awaitStorage(...proxies: any[]) {
|
||||
return Promise.all(proxies.map(proxy => proxy[storagePromiseSymbol]));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { getCorePlugins } from "@core/plugins";
|
||||
import { readFile, removeFile, writeFile } from "@lib/api/native/fs";
|
||||
import { awaitStorage, createStorage, preloadStorageIfExists, updateStorageAsync } from "@lib/api/storage/new";
|
||||
import { awaitStorage, createStorage, getPreloadedStorage, preloadStorageIfExists, updateStorageAsync } from "@lib/api/storage/new";
|
||||
import { safeFetch } from "@lib/utils";
|
||||
import { semver } from "@metro/common";
|
||||
|
||||
|
|
@ -155,19 +155,24 @@ export async function updateRepository(repoUrl: string) {
|
|||
}
|
||||
}
|
||||
|
||||
await Promise.all(Object.keys(repo).map(async plugin => {
|
||||
if (!storedRepo || !storedRepo[plugin] || repo[plugin].alwaysFetch || newerThan(repo[plugin].version, storedRepo[plugin].version)) {
|
||||
await Promise.all(Object.keys(repo).map(async pluginId => {
|
||||
if (!storedRepo || !storedRepo[pluginId] || repo[pluginId].alwaysFetch || newerThan(repo[pluginId].version, storedRepo[pluginId].version)) {
|
||||
updated = true;
|
||||
pluginRepositories[repoUrl][plugin] = repo[plugin];
|
||||
await updateAndWritePlugin(repoUrl, plugin, Boolean(storedRepo && pluginSettings[plugin]));
|
||||
pluginRepositories[repoUrl][pluginId] = repo[pluginId];
|
||||
await updateAndWritePlugin(repoUrl, pluginId, Boolean(storedRepo && pluginSettings[pluginId]));
|
||||
} else {
|
||||
await preloadStorageIfExists(`plugins/manifests/${plugin}.json`);
|
||||
const manifest = await preloadStorageIfExists(`plugins/manifests/${pluginId}.json`);
|
||||
if (manifest === undefined) { // File does not exist, so do refetch and stuff
|
||||
await updateAndWritePlugin(repoUrl, pluginId, Boolean(storedRepo && pluginSettings[pluginId]));
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
// Register plugins in this repository
|
||||
for (const id in repo) {
|
||||
const manifest = createStorage<t.BunnyPluginManifest>(`plugins/manifests/${id}.json`);
|
||||
const manifest = getPreloadedStorage<t.BunnyPluginManifest>(`plugins/manifests/${id}.json`);
|
||||
if (manifest === undefined) continue; // shouldn't happen, but just incase if it does
|
||||
|
||||
const existing = registeredPlugins.get(id);
|
||||
|
||||
// Skip if this version isn't any higher
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ import { Strings } from "@core/i18n";
|
|||
import { findAssetId } from "@lib/api/assets";
|
||||
import { TextInput } from "@metro/common/components";
|
||||
import ErrorBoundary from "@ui/components/ErrorBoundary";
|
||||
import { Image, View } from "react-native";
|
||||
import { Image, View, ViewStyle } from "react-native";
|
||||
|
||||
export interface SearchProps {
|
||||
onChangeText?: (v: string) => void;
|
||||
placeholder?: string;
|
||||
style?: import("react-native").TextStyle;
|
||||
style?: ViewStyle;
|
||||
}
|
||||
|
||||
function SearchIcon() {
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ export interface SegmentedControlState {
|
|||
|
||||
interface SegmentedControlProps {
|
||||
state: SegmentedControlState;
|
||||
variant?: string;
|
||||
}
|
||||
|
||||
export type SegmentedControl = React.FC<SegmentedControlProps>;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue