diff --git a/src/core/debug/safeMode.ts b/src/core/debug/safeMode.ts
new file mode 100644
index 0000000..f44bf06
--- /dev/null
+++ b/src/core/debug/safeMode.ts
@@ -0,0 +1,17 @@
+import { getCurrentTheme, writeThemeToNative } from "@lib/addons/themes";
+import { BundleUpdaterManager } from "@lib/api/native/modules";
+import { settings } from "@lib/api/settings";
+
+export function isSafeMode() {
+ return settings.safeMode?.enabled === true;
+}
+
+export async function toggleSafeMode({
+ to = !isSafeMode(),
+ reload = true
+} = {}) {
+ const enabled = (settings.safeMode ??= { enabled: to }).enabled = to;
+ const currentColor = getCurrentTheme();
+ await writeThemeToNative(enabled ? {} : currentColor?.data ?? {});
+ if (reload) setTimeout(() => BundleUpdaterManager.reload(), 500);
+}
diff --git a/src/core/ui/settings/pages/General/index.tsx b/src/core/ui/settings/pages/General/index.tsx
index 6535325..c021a85 100644
--- a/src/core/ui/settings/pages/General/index.tsx
+++ b/src/core/ui/settings/pages/General/index.tsx
@@ -1,14 +1,17 @@
+import { isSafeMode, toggleSafeMode } from "@core/debug/safeMode";
import { Strings } from "@core/i18n";
import { PyoncordIcon } from "@core/ui/settings";
import About from "@core/ui/settings/pages/General/About";
import { useProxy } from "@core/vendetta/storage";
import { findAssetId } from "@lib/api/assets";
-import { getDebugInfo, toggleSafeMode } from "@lib/api/debug";
+import { getDebugInfo } from "@lib/api/debug";
+import { BundleUpdaterManager } from "@lib/api/native/modules";
import { settings } from "@lib/api/settings";
+import { openAlert } from "@lib/ui/alerts";
import { DISCORD_SERVER, GITHUB } from "@lib/utils/constants";
import { NavigationNative, url } from "@metro/common";
-import { Stack, TableRow, TableRowGroup, TableSwitchRow } from "@metro/common/components";
-import { NativeModules, ScrollView } from "react-native";
+import { AlertActionButton, AlertActions, AlertModal, Stack, TableRow, TableRowGroup, TableSwitchRow } from "@metro/common/components";
+import { ScrollView } from "react-native";
export default function General() {
useProxy(settings);
@@ -27,14 +30,13 @@ export default function General() {
/>
}
+ icon={}
trailing={}
/>
}
- trailing={TableRow.Arrow}
+ icon={}
onPress={() => navigation.push("BUNNY_CUSTOM_PAGE", {
title: Strings.ABOUT,
render: () => ,
@@ -43,33 +45,51 @@ export default function General() {
}
- trailing={TableRow.Arrow}
+ icon={}
onPress={() => url.openDeeplink(DISCORD_SERVER)}
/>
}
- trailing={TableRow.Arrow}
+ icon={}
onPress={() => url.openURL(GITHUB)}
/>
}
- onPress={() => NativeModules.BundleUpdaterManager.reload()}
+ icon={}
+ onPress={() => BundleUpdaterManager.reload()}
/>
- }
- onPress={toggleSafeMode}
+ }
+ value={isSafeMode()}
+ onValueChange={(to: boolean) => {
+ toggleSafeMode({ to, reload: false });
+ openAlert(
+ "bunny-reload-safe-mode",
+
+ BundleUpdaterManager.reload()}
+ />
+
+ }
+ />
+ );
+ }}
/>
}
+ icon={}
value={settings.developerSettings}
onValueChange={(v: boolean) => {
settings.developerSettings = v;
@@ -80,7 +100,7 @@ export default function General() {
}
+ icon={}
value={settings.enableDiscordDeveloperSettings}
onValueChange={(v: boolean) => {
settings.enableDiscordDeveloperSettings = v;
diff --git a/src/core/ui/settings/pages/Plugins/index.tsx b/src/core/ui/settings/pages/Plugins/index.tsx
index 05f852e..da2c11c 100644
--- a/src/core/ui/settings/pages/Plugins/index.tsx
+++ b/src/core/ui/settings/pages/Plugins/index.tsx
@@ -13,7 +13,7 @@ import { BUNNY_PROXY_PREFIX, VD_PROXY_PREFIX } from "@lib/utils/constants";
import { lazyDestructure } from "@lib/utils/lazy";
import { findByProps } from "@metro";
import { NavigationNative } from "@metro/common";
-import { Card, FlashList, IconButton, Text } from "@metro/common/components";
+import { Button, Card, FlashList, IconButton, Text } from "@metro/common/components";
import { ComponentProps } from "react";
import { View } from "react-native";
@@ -53,7 +53,7 @@ function PluginPage(props: PluginPageProps) {
"description",
p => p.authors?.map(
(a: Author | string) => typeof a === "string" ? a : a.name
- ).join()
+ ).join() || ""
]}
sortOptions={{
"Name (A-Z)": (a, b) => a.name.localeCompare(b.name),
@@ -119,6 +119,20 @@ export default function Plugins() {
;
}}
+ ListFooterComponent={() => (
+
+ )}
installAction={{
label: "Install a plugin",
fetchFn: async (url: string) => {
diff --git a/src/lib/addons/themes/index.ts b/src/lib/addons/themes/index.ts
index e898926..5028e2b 100644
--- a/src/lib/addons/themes/index.ts
+++ b/src/lib/addons/themes/index.ts
@@ -19,7 +19,10 @@ export interface VdThemeInfo {
export const themes = wrapSync(createStorage>(createMMKVBackend("VENDETTA_THEMES")));
-async function writeTheme(theme: VdThemeInfo | {}) {
+/**
+ * @internal
+ */
+export async function writeThemeToNative(theme: VdThemeInfo | {}) {
if (typeof theme !== "object") throw new Error("Theme must be an object");
// Save the current theme as current-theme.json. When supported by loader,
@@ -73,7 +76,7 @@ export async function fetchTheme(id: string, selected = false) {
};
if (selected) {
- writeTheme(themes[id]);
+ writeThemeToNative(themes[id]);
updateBunnyColor(themes[id].data, { update: true });
}
}
@@ -91,10 +94,10 @@ export function selectTheme(theme: VdThemeInfo | null, write = true) {
if (theme == null && write) {
updateBunnyColor(null, { update: true });
- return writeTheme({});
+ return writeThemeToNative({});
} else if (theme) {
updateBunnyColor(theme.data, { update: true });
- return writeTheme(theme);
+ return writeThemeToNative(theme);
}
}
diff --git a/src/metro/common/types/components.ts b/src/metro/common/types/components.ts
index b801625..52657f5 100644
--- a/src/metro/common/types/components.ts
+++ b/src/metro/common/types/components.ts
@@ -25,6 +25,7 @@ interface ButtonProps {
scaleAmountInPx?: number;
icon?: ImageSourcePropType | ReactNode;
style?: Style;
+ grow?: boolean;
}
export type Button = React.ForwardRefExoticComponent;