hopefully fix iOS crash??
I guess no, but eh
This commit is contained in:
parent
c8bd5a4303
commit
2ee516b5fd
5 changed files with 40 additions and 177 deletions
|
|
@ -1,7 +1,3 @@
|
|||
{
|
||||
"languages": {
|
||||
"TypeScript": {
|
||||
"format_on_save": "off"
|
||||
}
|
||||
}
|
||||
"format_on_save": "off",
|
||||
}
|
||||
|
|
|
|||
31
bun.lock
31
bun.lock
|
|
@ -17,6 +17,7 @@
|
|||
"react-devtools": "^7.0.1",
|
||||
"react-native": "0.83.1",
|
||||
"react-native-reanimated": "^4.2.1",
|
||||
"react-native-webview": "^13.16.0",
|
||||
"spitroast": "^2.1.6",
|
||||
"type-fest": "^5.3.1",
|
||||
},
|
||||
|
|
@ -1366,6 +1367,8 @@
|
|||
|
||||
"react-native-reanimated": ["react-native-reanimated@4.2.1", "", { "dependencies": { "react-native-is-edge-to-edge": "1.2.1", "semver": "7.7.3" }, "peerDependencies": { "react": "*", "react-native": "*", "react-native-worklets": ">=0.7.0" } }, "sha512-/NcHnZMyOvsD/wYXug/YqSKw90P9edN0kEPL5lP4PFf1aQ4F1V7MKe/E0tvfkXKIajy3Qocp5EiEnlcrK/+BZg=="],
|
||||
|
||||
"react-native-webview": ["react-native-webview@13.16.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0", "invariant": "2.2.4" }, "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-Nh13xKZWW35C0dbOskD7OX01nQQavOzHbCw9XoZmar4eXCo7AvrYJ0jlUfRVVIJzqINxHlpECYLdmAdFsl9xDA=="],
|
||||
|
||||
"react-native-worklets": ["react-native-worklets@0.6.1", "", { "dependencies": { "@babel/plugin-transform-arrow-functions": "^7.0.0-0", "@babel/plugin-transform-class-properties": "^7.0.0-0", "@babel/plugin-transform-classes": "^7.0.0-0", "@babel/plugin-transform-nullish-coalescing-operator": "^7.0.0-0", "@babel/plugin-transform-optional-chaining": "^7.0.0-0", "@babel/plugin-transform-shorthand-properties": "^7.0.0-0", "@babel/plugin-transform-template-literals": "^7.0.0-0", "@babel/plugin-transform-unicode-regex": "^7.0.0-0", "@babel/preset-typescript": "^7.16.7", "convert-source-map": "^2.0.0", "semver": "7.7.2" }, "peerDependencies": { "@babel/core": "^7.0.0-0", "react": "*", "react-native": "*" } }, ""],
|
||||
|
||||
"react-refresh": ["react-refresh@0.14.2", "", {}, ""],
|
||||
|
|
@ -1708,7 +1711,7 @@
|
|||
|
||||
"@electron/get/fs-extra": ["fs-extra@8.1.0", "", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="],
|
||||
|
||||
"@electron/get/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
||||
"@electron/get/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, ""],
|
||||
|
||||
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, ""],
|
||||
|
||||
|
|
@ -1832,6 +1835,8 @@
|
|||
|
||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, ""],
|
||||
|
||||
"fdir/picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="],
|
||||
|
||||
"finalhandler/debug": ["debug@2.6.9", "", { "dependencies": { "ms": "2.0.0" } }, ""],
|
||||
|
||||
"finalhandler/encodeurl": ["encodeurl@1.0.2", "", {}, ""],
|
||||
|
|
@ -2256,7 +2261,7 @@
|
|||
|
||||
"send/statuses": ["statuses@2.0.1", "", {}, ""],
|
||||
|
||||
"signale/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, ""],
|
||||
"signale/chalk": ["chalk@2.4.2", "", { "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" } }, "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ=="],
|
||||
|
||||
"signale/figures": ["figures@2.0.0", "", { "dependencies": { "escape-string-regexp": "^1.0.5" } }, ""],
|
||||
|
||||
|
|
@ -2504,8 +2509,6 @@
|
|||
|
||||
"react-devtools/cross-spawn/which": ["which@1.3.1", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": "bin/which" }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="],
|
||||
|
||||
"react-native/react-devtools-core/ws": ["ws@7.5.10", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": "^5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, ""],
|
||||
|
||||
"react-native/yargs/cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, ""],
|
||||
|
||||
"react-native/yargs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, ""],
|
||||
|
|
@ -2534,13 +2537,13 @@
|
|||
|
||||
"send/debug/ms": ["ms@2.0.0", "", {}, ""],
|
||||
|
||||
"signale/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, ""],
|
||||
"signale/chalk/ansi-styles": ["ansi-styles@3.2.1", "", { "dependencies": { "color-convert": "^1.9.0" } }, "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA=="],
|
||||
|
||||
"signale/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, ""],
|
||||
"signale/chalk/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||
|
||||
"signale/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, ""],
|
||||
"signale/chalk/supports-color": ["supports-color@5.5.0", "", { "dependencies": { "has-flag": "^3.0.0" } }, "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow=="],
|
||||
|
||||
"signale/figures/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, ""],
|
||||
"signale/figures/escape-string-regexp": ["escape-string-regexp@1.0.5", "", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="],
|
||||
|
||||
"term-size/execa/cross-spawn": ["cross-spawn@5.1.0", "", { "dependencies": { "lru-cache": "^4.0.1", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A=="],
|
||||
|
||||
|
|
@ -2720,9 +2723,9 @@
|
|||
|
||||
"semantic-release/execa/npm-run-path/path-key": ["path-key@4.0.0", "", {}, ""],
|
||||
|
||||
"signale/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, ""],
|
||||
"signale/chalk/ansi-styles/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||
|
||||
"signale/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, ""],
|
||||
"signale/chalk/supports-color/has-flag": ["has-flag@3.0.0", "", {}, "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw=="],
|
||||
|
||||
"term-size/execa/cross-spawn/lru-cache": ["lru-cache@4.1.5", "", { "dependencies": { "pseudomap": "^1.0.2", "yallist": "^2.1.2" } }, "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g=="],
|
||||
|
||||
|
|
@ -2806,9 +2809,7 @@
|
|||
|
||||
"read-pkg-up/read-pkg/normalize-package-data/hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, ""],
|
||||
|
||||
"signale/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, ""],
|
||||
|
||||
"term-size/execa/cross-spawn/lru-cache/yallist": ["yallist@2.1.2", "", {}, "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A=="],
|
||||
"signale/chalk/ansi-styles/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||
|
||||
"term-size/execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="],
|
||||
|
||||
|
|
@ -2826,10 +2827,6 @@
|
|||
|
||||
"@saithodev/semantic-release-backmerge/semantic-release/@semantic-release/github/@octokit/plugin-throttling/@octokit/types/@octokit/openapi-types": ["@octokit/openapi-types@20.0.0", "", {}, ""],
|
||||
|
||||
"@saithodev/semantic-release-backmerge/semantic-release/@semantic-release/npm/read-pkg/normalize-package-data/hosted-git-info": ["hosted-git-info@7.0.2", "", { "dependencies": { "lru-cache": "^10.0.1" } }, ""],
|
||||
|
||||
"@semantic-release/release-notes-generator/read-package-up/read-pkg/normalize-package-data/hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, ""],
|
||||
|
||||
"@saithodev/semantic-release-backmerge/semantic-release/@semantic-release/npm/read-pkg/normalize-package-data/hosted-git-info/lru-cache": ["lru-cache@10.4.3", "", {}, ""],
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
"react-devtools": "^7.0.1",
|
||||
"react-native": "0.83.1",
|
||||
"react-native-reanimated": "^4.2.1",
|
||||
"react-native-webview": "^13.16.0",
|
||||
"spitroast": "^2.1.6",
|
||||
"type-fest": "^5.3.1"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -22,14 +22,13 @@ import {
|
|||
} from "@metro/common/components";
|
||||
import { ErrorBoundary, Search } from "@ui/components";
|
||||
import { isNotNil } from "es-toolkit";
|
||||
import fuzzysort from "fuzzysort";
|
||||
import {
|
||||
ComponentType,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { Image, ScrollView, View } from "react-native";
|
||||
|
||||
|
|
@ -199,27 +198,6 @@ export default function AddonPage<T extends object>({
|
|||
}
|
||||
}, [navigation]);
|
||||
|
||||
const fuzzysortRef = useRef<any>(null);
|
||||
const [fuzzLoaded, setFuzzLoaded] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
if (!fuzzysortRef.current) {
|
||||
import("fuzzysort")
|
||||
.then((m) => {
|
||||
if (cancelled) return;
|
||||
fuzzysortRef.current = m.default || m;
|
||||
setFuzzLoaded(true);
|
||||
})
|
||||
.catch(() => {
|
||||
// ignore dynamic import failures; we'll fallback to simple filtering
|
||||
});
|
||||
}
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const results = useMemo(() => {
|
||||
let values = props.items;
|
||||
if (props.resolveItem)
|
||||
|
|
@ -227,84 +205,11 @@ export default function AddonPage<T extends object>({
|
|||
const items = values.filter((i) => isNotNil(i) && typeof i === "object");
|
||||
if (!search && sortFn) items.sort(sortFn);
|
||||
|
||||
// Prefer fuzzysort when loaded and a search query exists
|
||||
if (fuzzysortRef.current && search) {
|
||||
try {
|
||||
return fuzzysortRef.current.go(search, items, {
|
||||
keys: props.searchKeywords,
|
||||
all: true,
|
||||
});
|
||||
} catch {
|
||||
// If fuzzysort throws for some reason, fall back to the simple filter below
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no search query, return items shaped similarly to fuzzysort results
|
||||
const makeFallbackResult = (obj: any, keys: any[]) => {
|
||||
const r: any = { obj };
|
||||
// current search query in the outer scope; only highlight when there's an active query
|
||||
const q = String(search ?? "")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
for (let k = 0; k < keys.length; k++) {
|
||||
const key = keys[k];
|
||||
let text = "";
|
||||
try {
|
||||
text =
|
||||
typeof key === "string" ? String(obj[key] ?? "") : String(key(obj));
|
||||
} catch {
|
||||
text = "";
|
||||
}
|
||||
r[k] = {
|
||||
target: text,
|
||||
highlight: (cb: any) => {
|
||||
// Do not highlight anything when there is no active search.
|
||||
if (!q) return [];
|
||||
const lower = text.toLowerCase();
|
||||
const idx = lower.indexOf(q);
|
||||
if (idx === -1) return [];
|
||||
// Split into before/match/after and invoke the callback for each segment so
|
||||
// consumers can render matched substring(s) with highlight styling while
|
||||
// preserving surrounding context.
|
||||
const parts: any[] = [];
|
||||
let i = 0;
|
||||
const before = text.slice(0, idx);
|
||||
const match = text.slice(idx, idx + q.length);
|
||||
const after = text.slice(idx + q.length);
|
||||
if (before) parts.push(cb(before, i++));
|
||||
parts.push(cb(match, i++));
|
||||
if (after) parts.push(cb(after, i++));
|
||||
return parts;
|
||||
},
|
||||
};
|
||||
}
|
||||
return r;
|
||||
};
|
||||
if (!search) {
|
||||
return items.map((obj: any) =>
|
||||
makeFallbackResult(obj, props.searchKeywords),
|
||||
);
|
||||
}
|
||||
|
||||
// Basic fallback: case-insensitive substring match across configured keys
|
||||
const q = String(search).toLowerCase();
|
||||
const filtered = items.filter((it: any) => {
|
||||
for (const key of props.searchKeywords) {
|
||||
try {
|
||||
const text =
|
||||
typeof key === "string" ? String(it[key] ?? "") : String(key(it));
|
||||
if (text.toLowerCase().includes(q)) return true;
|
||||
} catch {
|
||||
// ignore any accessor errors and continue
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return fuzzysort.go(search, items, {
|
||||
keys: props.searchKeywords,
|
||||
all: true,
|
||||
});
|
||||
|
||||
return filtered.map((obj: any) =>
|
||||
makeFallbackResult(obj, props.searchKeywords),
|
||||
);
|
||||
}, [props.items, sortFn, search, fuzzLoaded]);
|
||||
}, [props.items, sortFn, search]);
|
||||
|
||||
const onInstallPress = useCallback(() => {
|
||||
if (!props.installAction) return () => {};
|
||||
|
|
|
|||
|
|
@ -16,8 +16,9 @@ import {
|
|||
Text,
|
||||
} from "@metro/common/components";
|
||||
import { findByProps } from "@metro";
|
||||
import { useMemo, useState, useEffect } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { PixelRatio, View } from "react-native";
|
||||
import { WebView } from "react-native-webview";
|
||||
import previewHtml from "./preview.html";
|
||||
|
||||
import FontEditor from "./FontEditor";
|
||||
|
|
@ -35,7 +36,6 @@ const useStyles = createStyles({
|
|||
|
||||
function FontPreview({ font }: { font: FontDefinition }) {
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
const [WebViewComponent, setWebViewComponent] = useState<any>(null);
|
||||
const styles = useStyles();
|
||||
|
||||
const TEXT_DEFAULT = useToken(tokens.colors.TEXT_DEFAULT);
|
||||
|
|
@ -53,61 +53,25 @@ function FontPreview({ font }: { font: FontDefinition }) {
|
|||
[font.main, fontFamily, fontSize, TEXT_DEFAULT],
|
||||
);
|
||||
|
||||
// Memoize generated HTML to avoid string replacement on every render
|
||||
const html = useMemo(
|
||||
() => previewHtml.replace("$$props", JSON.stringify(props)),
|
||||
[props],
|
||||
);
|
||||
|
||||
// Lazy-load the WebView implementation so it's not included in the main bundle
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
import("react-native-webview")
|
||||
.then((m) => {
|
||||
if (cancelled) return;
|
||||
// support both default export and named WebView export
|
||||
setWebViewComponent(m.WebView || m.default || m);
|
||||
})
|
||||
.catch(() => {
|
||||
// ignore dynamic import failures; component will show placeholder
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View style={{ width: "100%", height: 64 }}>
|
||||
{WebViewComponent ? (
|
||||
<>
|
||||
<WebViewComponent
|
||||
onMessage={() => setLoaded(true)}
|
||||
source={{ html }}
|
||||
javaScriptEnabled
|
||||
scrollEnabled={false}
|
||||
overScrollMode="never"
|
||||
showsHorizontalScrollIndicator={false}
|
||||
showsVerticalScrollIndicator={false}
|
||||
pointerEvents="none"
|
||||
style={[
|
||||
styles.full,
|
||||
{ backgroundColor: "transparent", opacity: Number(loaded) },
|
||||
]}
|
||||
/>
|
||||
{!loaded && (
|
||||
<View
|
||||
style={[
|
||||
styles.full,
|
||||
{ justifyContent: "center", alignItems: "center" },
|
||||
]}
|
||||
>
|
||||
<Text color="text-muted" variant="heading-lg/semibold">
|
||||
Loading...
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<WebView
|
||||
onMessage={() => setLoaded(true)}
|
||||
source={{
|
||||
html: previewHtml.replace("$$props", JSON.stringify(props)),
|
||||
}}
|
||||
javaScriptEnabled
|
||||
scrollEnabled={false}
|
||||
overScrollMode="never"
|
||||
showsHorizontalScrollIndicator={false}
|
||||
showsVerticalScrollIndicator={false}
|
||||
pointerEvents="none"
|
||||
style={[
|
||||
styles.full,
|
||||
{ backgroundColor: "transparent", opacity: Number(loaded) },
|
||||
]}
|
||||
/>
|
||||
{!loaded && (
|
||||
<View
|
||||
style={[
|
||||
styles.full,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue