[SafeMode] Initial implementation (#61)
* [UI > Components] Add Discord's button * [SafeMode] Initial work, basic ErrorBoundary patch * [SafeMode] Custom error boundary (#57) * [SafeMode] Add mostly complete custom error boundary * [SafeMode] Use Button from @ui/components in error boundary * [SafeMode] Wrap the error boundary in our own error boundary * [SafeMode > ErrorBoundary] Code-style changes --------- Co-authored-by: Beef <beefers@riseup.net> * [TS] Add basic type for Discord's button * [UI] Move Codeblock to components, and use it * [UI > Settings] Allow disabling the ErrorBoundary in CustomPage * [UI > Settings] Move the ErrorBoundary triggers to Developer * [TS] Add Codeblock to types * [TS] Use ButtonColors in Button type * [SafeMode > ErrorBoundary] Rework * [UI] Add HelpMessage to components * [SafeMode] Proper implementation * [Global] SafeMode is optional (#59) * [UI > Developer] Restore the balance * [SafeMode > ErrorBoundary] Optimise for tablet UI * [SafeMode] Last-minute fixes --------- Co-authored-by: Jack <30497388+FieryFlames@users.noreply.github.com> Co-authored-by: Jack Matthews <jm5112356@gmail.com>
This commit is contained in:
parent
f85fc4b00c
commit
5344f0017a
16 changed files with 293 additions and 47 deletions
|
@ -1,12 +1,27 @@
|
|||
import { RNConstants } from "@types";
|
||||
import { ReactNative as RN } from "@metro/common";
|
||||
import { after } from "@lib/patcher";
|
||||
import { ClientInfoManager, DeviceManager } from "@lib/native";
|
||||
import { ClientInfoManager, DeviceManager, BundleUpdaterManager } from "@lib/native";
|
||||
import { getCurrentTheme, selectTheme } from "@lib/themes";
|
||||
import { getAssetIDByName } from "@ui/assets";
|
||||
import { showToast } from "@ui/toasts";
|
||||
import settings from "@lib/settings";
|
||||
import logger from "@lib/logger";
|
||||
export let socket: WebSocket;
|
||||
|
||||
export async function toggleSafeMode() {
|
||||
settings.safeMode = { ...settings.safeMode, enabled: !settings.safeMode?.enabled }
|
||||
if (window.__vendetta_loader?.features.themes) {
|
||||
if (getCurrentTheme()?.id) settings.safeMode!.currentThemeId = getCurrentTheme()!.id;
|
||||
if (settings.safeMode?.enabled) {
|
||||
await selectTheme("default");
|
||||
} else if (settings.safeMode?.currentThemeId) {
|
||||
await selectTheme(settings.safeMode?.currentThemeId);
|
||||
}
|
||||
}
|
||||
setTimeout(BundleUpdaterManager.reload);
|
||||
}
|
||||
|
||||
export function connectToDebugger(url: string) {
|
||||
if (socket !== undefined && socket.readyState !== WebSocket.CLOSED) socket.close();
|
||||
|
||||
|
@ -16,7 +31,7 @@ export function connectToDebugger(url: string) {
|
|||
}
|
||||
|
||||
socket = new WebSocket(`ws://${url}`);
|
||||
|
||||
|
||||
socket.addEventListener("open", () => showToast("Connected to debugger.", getAssetIDByName("Check")));
|
||||
socket.addEventListener("message", (message: any) => {
|
||||
try {
|
||||
|
@ -32,7 +47,7 @@ export function connectToDebugger(url: string) {
|
|||
});
|
||||
}
|
||||
|
||||
export function patchLogHook() {
|
||||
export function patchLogHook() {
|
||||
const unpatch = after("nativeLoggingHook", globalThis, (args) => {
|
||||
if (socket?.readyState === WebSocket.OPEN) socket.send(JSON.stringify({ message: args[0], level: args[1] }));
|
||||
logger.log(args[0]);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { Indexable, PluginManifest, Plugin } from "@types";
|
||||
import { awaitSyncWrapper, createMMKVBackend, createStorage, wrapSync } from "@lib/storage";
|
||||
import { MMKVManager } from "@lib/native";
|
||||
import settings from "@lib/settings";
|
||||
import logger, { logModule } from "@lib/logger";
|
||||
import safeFetch from "@utils/safeFetch";
|
||||
|
||||
|
@ -76,9 +77,11 @@ export async function startPlugin(id: string) {
|
|||
if (!plugin) throw new Error("Attempted to start non-existent plugin");
|
||||
|
||||
try {
|
||||
const pluginRet: EvaledPlugin = await evalPlugin(plugin);
|
||||
loadedPlugins[id] = pluginRet;
|
||||
pluginRet.onLoad?.();
|
||||
if (!settings.safeMode?.enabled) {
|
||||
const pluginRet: EvaledPlugin = await evalPlugin(plugin);
|
||||
loadedPlugins[id] = pluginRet;
|
||||
pluginRet.onLoad?.();
|
||||
}
|
||||
plugin.enabled = true;
|
||||
} catch(e) {
|
||||
logger.error(`Plugin ${plugin.id} errored whilst loading, and will be unloaded`, e);
|
||||
|
@ -99,15 +102,17 @@ export function stopPlugin(id: string, disable = true) {
|
|||
const plugin = plugins[id];
|
||||
const pluginRet = loadedPlugins[id];
|
||||
if (!plugin) throw new Error("Attempted to stop non-existent plugin");
|
||||
if (!pluginRet) throw new Error("Attempted to stop a non-started plugin");
|
||||
|
||||
try {
|
||||
pluginRet.onUnload?.();
|
||||
} catch(e) {
|
||||
logger.error(`Plugin ${plugin.id} errored whilst unloading`, e);
|
||||
if (!settings.safeMode?.enabled) {
|
||||
try {
|
||||
pluginRet?.onUnload?.();
|
||||
} catch(e) {
|
||||
logger.error(`Plugin ${plugin.id} errored whilst unloading`, e);
|
||||
}
|
||||
|
||||
delete loadedPlugins[id];
|
||||
}
|
||||
|
||||
delete loadedPlugins[id];
|
||||
disable && (plugin.enabled = false);
|
||||
}
|
||||
|
||||
|
@ -120,13 +125,16 @@ export function removePlugin(id: string) {
|
|||
}
|
||||
|
||||
export async function initPlugins() {
|
||||
await awaitSyncWrapper(settings);
|
||||
await awaitSyncWrapper(plugins);
|
||||
const allIds = Object.keys(plugins);
|
||||
|
||||
// Loop over any plugin that is enabled, update it if allowed, then start it.
|
||||
await Promise.allSettled(allIds.filter(pl => plugins[pl].enabled).map(async (pl) => (plugins[pl].update && await fetchPlugin(pl), await startPlugin(pl))));
|
||||
// Wait for the above to finish, then update all disabled plugins that are allowed to.
|
||||
allIds.filter(pl => !plugins[pl].enabled && plugins[pl].update).forEach(pl => fetchPlugin(pl));
|
||||
if (!settings.safeMode?.enabled) {
|
||||
// Loop over any plugin that is enabled, update it if allowed, then start it.
|
||||
await Promise.allSettled(allIds.filter(pl => plugins[pl].enabled).map(async (pl) => (plugins[pl].update && await fetchPlugin(pl), await startPlugin(pl))));
|
||||
// Wait for the above to finish, then update all disabled plugins that are allowed to.
|
||||
allIds.filter(pl => !plugins[pl].enabled && plugins[pl].update).forEach(pl => fetchPlugin(pl));
|
||||
};
|
||||
|
||||
return stopAllPlugins;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ export default async (unloads: any[]): Promise<VendettaObject> => ({
|
|||
metro: { ...metro, common: { ...common } },
|
||||
constants,
|
||||
utils,
|
||||
debug: utils.without(debug, "versionHash", "patchLogHook"),
|
||||
debug: utils.without(debug, "versionHash", "patchLogHook", "toggleSafeMode"),
|
||||
ui: {
|
||||
components,
|
||||
toasts,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue