Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
21d3a5be0d
7 changed files with 207 additions and 123 deletions
12
.github/workflows/release.yml
vendored
12
.github/workflows/release.yml
vendored
|
|
@ -42,14 +42,14 @@ jobs:
|
|||
echo '--- scripts/build.mjs (snippet) ---' >&2
|
||||
sed -n '1,200p' scripts/build.mjs >&2 || true
|
||||
|
||||
# Primary extraction: find the first quoted semver (may include prerelease suffix, but we strip it)
|
||||
raw=$(grep -m1 -oE '\"[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?\"' scripts/build.mjs | tr -d '\"' | head -n1 || true)
|
||||
# Primary extraction: find the first quoted version (supports major.minor.patch or major.minor.patch.patch formats, may include prerelease suffix)
|
||||
raw=$(grep -m1 -oE '\"[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?(-[0-9A-Za-z.-]+)?\"' scripts/build.mjs | tr -d '\"' | head -n1 || true)
|
||||
|
||||
# Strip any prerelease suffix, keep only major.minor.patch
|
||||
version=$(printf '%s' "$raw" | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+).*/\1/')
|
||||
# Strip any prerelease suffix, keep only major.minor.patch or major.minor.patch.patch
|
||||
version=$(printf '%s' "$raw" | sed -E 's/^([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?).*/\1/')
|
||||
|
||||
# Validate final result is exactly major.minor.patch
|
||||
if ! printf '%s' "$version" | grep -xE '^[0-9]+\.[0-9]+\.[0-9]+$' >/dev/null; then
|
||||
# Validate final result is either major.minor.patch or major.minor.patch.patch
|
||||
if ! printf '%s' "$version" | grep -xE '^[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?$' >/dev/null; then
|
||||
echo "Failed to extract a valid base version from scripts/build.mjs" >&2
|
||||
sed -n '1,200p' scripts/build.mjs >&2 || true
|
||||
exit 1
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ const config = {
|
|||
constModules: {
|
||||
globals: {
|
||||
"bunny-build-info": {
|
||||
version: `"1.4.1"`,
|
||||
version: `"1.4.1.1"`,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
"ARE_YOU_SURE_TO_DELETE_PLUGIN": "Are you sure you wish to delete {name}? This will clear all of the plugin's data.",
|
||||
"ARE_YOU_SURE_TO_DELETE_THEME": "Are you sure you wish to delete {name}?",
|
||||
"ASSET_BROWSER": "Asset Browser",
|
||||
"ASSET_TYPES": "Asset Types",
|
||||
"IMAGE_FILES": "Image Files",
|
||||
"TEXT_FILES": "Text Files",
|
||||
"BRAND": "Brand",
|
||||
"SHIGGYCORD": "💦GoonCord💦",
|
||||
"SHIGGYCORD_URL": "GoonCord URL",
|
||||
|
|
|
|||
|
|
@ -1,21 +1,111 @@
|
|||
import AssetDisplay from "@core/ui/settings/pages/Developer/AssetDisplay";
|
||||
import { iterateAssets } from "@lib/api/assets";
|
||||
import { Text } from "@metro/common/components";
|
||||
import { findAssetId } from "@lib/api/assets";
|
||||
import { Strings } from "@core/i18n";
|
||||
import { IconButton, TableCheckboxRow, TableRowGroup, ActionSheet, BottomSheetTitleHeader } from "@metro/common/components";
|
||||
import { ErrorBoundary, Search } from "@ui/components";
|
||||
import { useMemo } from "react";
|
||||
import { showSheet } from "@lib/ui/sheets";
|
||||
import { useProxy, createProxy } from "@core/vendetta/storage";
|
||||
import { useState, useMemo, useCallback } from "react";
|
||||
import { FlatList, View } from "react-native";
|
||||
|
||||
const IMAGE_FILES = [
|
||||
{ id: "png", label: "PNG", defaultEnabled: true },
|
||||
{ id: "jpg", label: "JPG", defaultEnabled: true },
|
||||
{ id: "jpeg", label: "JPEG", defaultEnabled: true },
|
||||
{ id: "svg", label: "SVG", defaultEnabled: true },
|
||||
{ id: "gif", label: "GIF", defaultEnabled: true },
|
||||
];
|
||||
|
||||
const TEXT_FILES = [
|
||||
{ id: "jsona", label: "JSONA", defaultEnabled: false },
|
||||
{ id: "json", label: "JSON", defaultEnabled: false },
|
||||
{ id: "lottie", label: "Lottie", defaultEnabled: false },
|
||||
];
|
||||
|
||||
const ALL_FILE_TYPES = [...IMAGE_FILES, ...TEXT_FILES];
|
||||
|
||||
// Create initial enabled filters state
|
||||
const createInitialFilters = () => {
|
||||
const filters: Record<string, boolean> = {};
|
||||
ALL_FILE_TYPES.forEach(type => {
|
||||
filters[type.id] = type.defaultEnabled;
|
||||
});
|
||||
return filters;
|
||||
};
|
||||
|
||||
const { proxy: assetBrowserStorage } = createProxy({
|
||||
enabledFilters: createInitialFilters()
|
||||
});
|
||||
|
||||
export default function AssetBrowser() {
|
||||
const [search, setSearch] = React.useState("");
|
||||
const all = useMemo(() => Array.from(iterateAssets()), []);
|
||||
const [search, setSearch] = useState("");
|
||||
const [updateTick, setUpdateTick] = useState(0);
|
||||
|
||||
// Use useProxy to make the state reactive
|
||||
useProxy(assetBrowserStorage);
|
||||
|
||||
const getFilteredAssets = useCallback(() => {
|
||||
return Array.from(iterateAssets()).filter((asset) => {
|
||||
const type = String(asset.type ?? "").toLowerCase();
|
||||
return assetBrowserStorage.enabledFilters[type] === true;
|
||||
});
|
||||
}, [updateTick]);
|
||||
|
||||
const all = useMemo(() => getFilteredAssets(), [getFilteredAssets]);
|
||||
|
||||
const toggleFilter = (filterId: string) => {
|
||||
assetBrowserStorage.enabledFilters[filterId] = !assetBrowserStorage.enabledFilters[filterId];
|
||||
setUpdateTick(prev => prev + 1);
|
||||
};
|
||||
|
||||
const handleFilterPress = () => {
|
||||
showSheet("AssetBrowserFilter", () => {
|
||||
useProxy(assetBrowserStorage);
|
||||
|
||||
return (
|
||||
<ActionSheet>
|
||||
<BottomSheetTitleHeader title={Strings.ASSET_TYPES} />
|
||||
<TableRowGroup title={Strings.IMAGE_FILES}>
|
||||
{IMAGE_FILES.map(fileType => (
|
||||
<TableCheckboxRow
|
||||
key={fileType.id}
|
||||
label={fileType.label}
|
||||
checked={assetBrowserStorage.enabledFilters[fileType.id] === true}
|
||||
onPress={() => toggleFilter(fileType.id)}
|
||||
/>
|
||||
))}
|
||||
</TableRowGroup>
|
||||
<TableRowGroup title={Strings.TEXT_FILES}>
|
||||
{TEXT_FILES.map(fileType => (
|
||||
<TableCheckboxRow
|
||||
key={fileType.id}
|
||||
label={fileType.label}
|
||||
checked={assetBrowserStorage.enabledFilters[fileType.id] === true}
|
||||
onPress={() => toggleFilter(fileType.id)}
|
||||
/>
|
||||
))}
|
||||
</TableRowGroup>
|
||||
</ActionSheet>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<View style={{ flex: 1 }}>
|
||||
<Search
|
||||
style={{ margin: 10 }}
|
||||
onChangeText={(v: string) => setSearch(v)}
|
||||
/>
|
||||
<View style={{ flexDirection: "row", margin: 10, gap: 8, alignItems: "center" }}>
|
||||
<Search
|
||||
style={{ flex: 1 }}
|
||||
isRound
|
||||
onChangeText={(v: string) => setSearch(v)}
|
||||
/>
|
||||
<IconButton
|
||||
icon={findAssetId("FileIcon")}
|
||||
variant="tertiary"
|
||||
onPress={handleFilterPress}
|
||||
/>
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
|
|
@ -25,18 +115,9 @@ export default function AssetBrowser() {
|
|||
backgroundColor: "transparent",
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
variant="text-sm/medium"
|
||||
style={{
|
||||
marginBottom: 16,
|
||||
color: "var(--text-muted)",
|
||||
}}
|
||||
>
|
||||
Some assets types cannot be displayed and will be marked in red.
|
||||
</Text>
|
||||
<FlatList
|
||||
data={all.filter(
|
||||
(a) => a.name.includes(search) || a.id.toString() === search,
|
||||
(a) => (a.name.includes(search) || a.id.toString() === search),
|
||||
)}
|
||||
renderItem={({ item }: any) => <AssetDisplay asset={item} />}
|
||||
contentContainerStyle={{
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ import {
|
|||
connectToDebugger,
|
||||
disconnectFromDebugger,
|
||||
isConnectedToDebugger,
|
||||
connectRdt,
|
||||
disconnectRdt,
|
||||
useIsRdtConnected,
|
||||
} from "@lib/api/debug";
|
||||
import {
|
||||
getReactDevToolsProp,
|
||||
|
|
@ -33,7 +36,7 @@ import { ErrorBoundary } from "@ui/components";
|
|||
import ErrorBoundaryScreen from "@core/ui/reporter/components/ErrorBoundaryScreen";
|
||||
import { createStyles, TextStyleSheet } from "@ui/styles";
|
||||
import { NativeModules } from "react-native";
|
||||
import { ScrollView, StyleSheet } from "react-native";
|
||||
import { ScrollView } from "react-native";
|
||||
import { showToast } from "@ui/toasts";
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
|
|
@ -72,6 +75,7 @@ export default function Developer() {
|
|||
const [isDebuggerConnected, setIsDebuggerConnected] = useState(
|
||||
isConnectedToDebugger(),
|
||||
);
|
||||
const isRdtConnected = useIsRdtConnected();
|
||||
|
||||
const styles = useStyles();
|
||||
const navigation = NavigationNative.useNavigation();
|
||||
|
|
@ -96,6 +100,18 @@ export default function Developer() {
|
|||
}
|
||||
};
|
||||
|
||||
const handleReactDevToolsConnect = () => {
|
||||
if (isRdtConnected) {
|
||||
disconnectRdt();
|
||||
} else {
|
||||
if (!settings.devToolsUrl?.trim()) {
|
||||
showToast("Invalid devTools URL!", findAssetId("Small"));
|
||||
return;
|
||||
}
|
||||
connectRdt(settings.devToolsUrl);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<ScrollView
|
||||
|
|
@ -106,108 +122,90 @@ export default function Developer() {
|
|||
style={{ paddingVertical: 24, paddingHorizontal: 12 }}
|
||||
spacing={24}
|
||||
>
|
||||
<TableRowGroup title={Strings.DEBUGGER_URL}>
|
||||
<TextInput
|
||||
placeholder="127.0.0.1:9090"
|
||||
size="md"
|
||||
leadingIcon={() => (
|
||||
<LegacyFormText style={styles.leadingText}>
|
||||
ws://
|
||||
</LegacyFormText>
|
||||
)}
|
||||
defaultValue={settings.debuggerUrl}
|
||||
onChange={(v: string) => (settings.debuggerUrl = v)}
|
||||
/>
|
||||
<TableSwitchRow
|
||||
label={Strings.AUTO_DEBUGGER}
|
||||
icon={<TableRow.Icon source={findAssetId("copy")} />}
|
||||
value={settings.autoDebugger}
|
||||
onValueChange={(v: boolean) => {
|
||||
settings.autoDebugger = v;
|
||||
}}
|
||||
/>
|
||||
<TableRow
|
||||
label={Strings.CONNECT_TO_DEBUG_WEBSOCKET}
|
||||
subLabel="Connect to Chrome DevTools for debugging"
|
||||
icon={<TableRow.Icon source={findAssetId("WrenchIcon")} />}
|
||||
onPress={() => connectToDebugger(settings.debuggerUrl)}
|
||||
/>
|
||||
</TableRowGroup>
|
||||
<Stack spacing={4}>
|
||||
<TableRowGroup title={Strings.DEBUGGER_URL}>
|
||||
<Stack spacing={4}>
|
||||
<TextInput
|
||||
placeholder="127.0.0.1:9090"
|
||||
size="md"
|
||||
leadingIcon={() => (
|
||||
<LegacyFormText style={styles.leadingText}>
|
||||
ws://
|
||||
</LegacyFormText>
|
||||
)}
|
||||
defaultValue={settings.debuggerUrl}
|
||||
onChange={(v: string) => (settings.debuggerUrl = v)}
|
||||
/>
|
||||
</Stack>
|
||||
</TableRowGroup>
|
||||
|
||||
{isReactDevToolsPreloaded() && (
|
||||
<TableRowGroup title="React Development">
|
||||
<TextInput
|
||||
placeholder="127.0.0.1:8097"
|
||||
size="md"
|
||||
leadingIcon={() => (
|
||||
<LegacyFormText style={styles.leadingText}>
|
||||
ws://
|
||||
</LegacyFormText>
|
||||
)}
|
||||
defaultValue={settings.devToolsUrl}
|
||||
onChange={(v: string) => (settings.devToolsUrl = v)}
|
||||
/>
|
||||
<TableRowGroup>
|
||||
<TableSwitchRow
|
||||
label={Strings.AUTO_DEVTOOLS}
|
||||
icon={<TableRow.Icon source={findAssetId("ic_badge_staff")} />}
|
||||
value={settings.autoDevTools}
|
||||
label={Strings.AUTO_DEBUGGER}
|
||||
icon={<TableRow.Icon source={findAssetId("copy")} />}
|
||||
value={settings.autoDebugger}
|
||||
onValueChange={(v: boolean) => {
|
||||
settings.autoDevTools = v;
|
||||
settings.autoDebugger = v;
|
||||
}}
|
||||
/>
|
||||
<TableRow
|
||||
label={Strings.CONNECT_TO_REACT_DEVTOOLS}
|
||||
subLabel="Connect React DevTools for component debugging"
|
||||
icon={<TableRow.Icon source={findAssetId("ic_badge_staff")} />}
|
||||
onPress={async () => {
|
||||
if (!settings.devToolsUrl?.trim()) {
|
||||
showToast("Invalid devTools URL!", findAssetId("Small"));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const devTools =
|
||||
window[getReactDevToolsProp() || "__vendetta_rdc"];
|
||||
|
||||
if (!devTools?.connectToDevTools) {
|
||||
showToast(
|
||||
"React DevTools not available",
|
||||
findAssetId("Small"),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
await devTools.connectToDevTools({
|
||||
host: settings.devToolsUrl.split(":")?.[0],
|
||||
resolveRNStyle: StyleSheet.flatten,
|
||||
});
|
||||
showToast(
|
||||
"Connected to React DevTools!",
|
||||
findAssetId("Check"),
|
||||
);
|
||||
} catch (error) {
|
||||
showToast(
|
||||
"Failed to connect to React DevTools",
|
||||
findAssetId("Small"),
|
||||
);
|
||||
}
|
||||
}}
|
||||
label={Strings.CONNECT_TO_DEBUG_WEBSOCKET}
|
||||
subLabel="Connect DevTools for debugging"
|
||||
icon={<TableRow.Icon source={findAssetId("WrenchIcon")} />}
|
||||
onPress={handleDebuggerConnect}
|
||||
/>
|
||||
</TableRowGroup>
|
||||
</Stack>
|
||||
|
||||
{isLoaderConfigSupported() && isVendettaLoader() && (
|
||||
{isReactDevToolsPreloaded() && (
|
||||
<Stack spacing={4}>
|
||||
<TableRowGroup title="React Development">
|
||||
<Stack spacing={4}>
|
||||
<TextInput
|
||||
placeholder="127.0.0.1:8097"
|
||||
size="md"
|
||||
leadingIcon={() => (
|
||||
<LegacyFormText style={styles.leadingText}>
|
||||
ws://
|
||||
</LegacyFormText>
|
||||
)}
|
||||
defaultValue={settings.devToolsUrl}
|
||||
onChange={(v: string) => (settings.devToolsUrl = v)}
|
||||
/>
|
||||
</Stack>
|
||||
</TableRowGroup>
|
||||
|
||||
<TableRowGroup>
|
||||
<TableSwitchRow
|
||||
label={Strings.LOAD_REACT_DEVTOOLS}
|
||||
subLabel={`${Strings.VERSION}: ${getReactDevToolsVersion()}`}
|
||||
icon={
|
||||
<TableRow.Icon source={findAssetId("ic_badge_staff")} />
|
||||
}
|
||||
value={loaderConfig.loadReactDevTools}
|
||||
label={Strings.AUTO_DEVTOOLS}
|
||||
icon={<TableRow.Icon source={findAssetId("ic_badge_staff")} />}
|
||||
value={settings.autoDevTools}
|
||||
onValueChange={(v: boolean) => {
|
||||
loaderConfig.loadReactDevTools = v;
|
||||
settings.autoDevTools = v;
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</TableRowGroup>
|
||||
<TableRow
|
||||
label={Strings.CONNECT_TO_REACT_DEVTOOLS}
|
||||
subLabel="Connect React DevTools for component debugging"
|
||||
icon={<TableRow.Icon source={findAssetId("ic_badge_staff")} />}
|
||||
onPress={handleReactDevToolsConnect}
|
||||
/>
|
||||
|
||||
{isLoaderConfigSupported() && isVendettaLoader() && (
|
||||
<TableSwitchRow
|
||||
label={Strings.LOAD_REACT_DEVTOOLS}
|
||||
subLabel={`${Strings.VERSION}: ${getReactDevToolsVersion()}`}
|
||||
icon={
|
||||
<TableRow.Icon source={findAssetId("ic_badge_staff")} />
|
||||
}
|
||||
value={loaderConfig.loadReactDevTools}
|
||||
onValueChange={(v: boolean) => {
|
||||
loaderConfig.loadReactDevTools = v;
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</TableRowGroup>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
{isLoaderConfigSupported() && (
|
||||
|
|
|
|||
|
|
@ -224,13 +224,14 @@ export function connectToDebugger(url: string) {
|
|||
}
|
||||
});
|
||||
|
||||
socket.addEventListener("close", () => {
|
||||
showToast("Disconnected from debugger.", findAssetId("Small"));
|
||||
socket.addEventListener("close", (e: any) => {
|
||||
logger.error(`Debugger disconnected. (${e?.code}, ${e?.reason || "no reason specified"})`);
|
||||
unpatchConsoleAndLogger();
|
||||
});
|
||||
|
||||
socket.addEventListener("error", (err: any) => {
|
||||
console.log(`Debugger error: ${err.message}`);
|
||||
socket.addEventListener("error", (e: any) => {
|
||||
const err = e?.message || e?.error?.message || "WebSocket Connection Errored";
|
||||
logger.error('Debugger error:', err);
|
||||
showToast("An error occurred with the debugger connection!", findAssetId("Small"));
|
||||
unpatchConsoleAndLogger();
|
||||
});
|
||||
|
|
@ -281,13 +282,14 @@ export function connectRdt(url: string, quiet?: boolean) {
|
|||
bump();
|
||||
});
|
||||
|
||||
ws.addEventListener('close', () => {
|
||||
ws.addEventListener('close', (e: any) => {
|
||||
logger.error(`React DevTools disconnected. (${e?.code}, ${e?.reason || "no reason specified"})`);
|
||||
cleanupRdt();
|
||||
});
|
||||
|
||||
ws.addEventListener('error', (e: any) => {
|
||||
cleanupRdt();
|
||||
const err = e?.message ?? e?.stack ?? String(e);
|
||||
const err = e?.message || e?.error?.message || "WebSocket Connection Errored";
|
||||
logger.error('React DevTools error:', err);
|
||||
if (!quiet) showToast(err, findAssetId("CircleXIcon-primary"));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ interface TableRowIconProps {
|
|||
export type TableRowIcon = React.FC<TableRowIconProps>;
|
||||
|
||||
interface TableRowGroupProps {
|
||||
title: string;
|
||||
title?: string;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue