diff --git a/src/lib/storage/index.ts b/src/lib/storage/index.ts index fb72e35..07d4072 100644 --- a/src/lib/storage/index.ts +++ b/src/lib/storage/index.ts @@ -3,6 +3,7 @@ import createEmitter from "@lib/emitter"; const emitterSymbol = Symbol.for("vendetta.storage.emitter"); const syncAwaitSymbol = Symbol.for("vendetta.storage.accessor"); +const storageErrorSymbol = Symbol.for("vendetta.storage.error"); export function createProxy(target: any = {}): { proxy: any; emitter: Emitter } { const emitter = createEmitter(); @@ -56,8 +57,12 @@ export function createProxy(target: any = {}): { proxy: any; emitter: Emitter } }; } -export function useProxy(storage: T): T { - const emitter = (storage as any)[emitterSymbol] as Emitter; +export function useProxy(storage: T & { [key: symbol]: any }): T { + if (storage[storageErrorSymbol]) throw storage[storageErrorSymbol]; + + const emitter = storage[emitterSymbol] as Emitter; + + if (!emitter) throw new Error("InvalidArgumentExcpetion - storage[emitterSymbol] is " + typeof emitter); const [, forceUpdate] = React.useReducer((n) => ~n, 0); @@ -89,6 +94,7 @@ export async function createStorage(backend: StorageBackend): Promise>(store: T): Awaited { let awaited: any = undefined; + let error: any = undefined; const awaitQueue: (() => void)[] = []; const awaitInit = (cb: () => void) => (awaited ? cb() : awaitQueue.push(cb)); @@ -96,6 +102,8 @@ export function wrapSync>(store: T): Awaited { store.then((v) => { awaited = v; awaitQueue.forEach((cb) => cb()); + }).catch((e) => { + error = e; }); return new Proxy({} as Awaited, { @@ -105,6 +113,7 @@ export function wrapSync>(store: T): Awaited { .map((k) => [k, (t: T, ...a: any[]) => Reflect[k](awaited ?? t, ...a)]) ), get(target, prop, recv) { + if (prop === storageErrorSymbol) return error; if (prop === syncAwaitSymbol) return awaitInit; return Reflect.get(awaited ?? target, prop, recv); }, diff --git a/src/ui/safeMode.tsx b/src/ui/safeMode.tsx index c3f7806..22ade9e 100644 --- a/src/ui/safeMode.tsx +++ b/src/ui/safeMode.tsx @@ -2,7 +2,7 @@ import { ButtonColors } from "@types"; import { ReactNative as RN, stylesheet } from "@metro/common"; import { findByName, findByProps, findByStoreName } from "@metro/filters"; import { after } from "@lib/patcher"; -import { toggleSafeMode } from "@lib/debug"; +import { getDebugInfo, toggleSafeMode } from "@lib/debug"; import { DeviceManager } from "@lib/native"; import { semanticColors } from "@ui/color"; import { Button, Codeblock, ErrorBoundary as _ErrorBoundary, SafeAreaView } from "@ui/components"; @@ -13,8 +13,6 @@ const ErrorBoundary = findByName("ErrorBoundary"); // Let's just pray they have this. const { BadgableTabBar } = findByProps("BadgableTabBar"); -const ThemeStore = findByStoreName("ThemeStore"); - const { TextStyleSheet } = findByProps("TextStyleSheet"); const styles = stylesheet.createThemedStyleSheet({ container: { @@ -70,6 +68,8 @@ const tabs: Tab[] = [ export default () => after("render", ErrorBoundary.prototype, function (this: any, _, ret) { if (!this.state.error) return; + const debugInfo = getDebugInfo(); + // Not using setState here as we don't want to cause a re-render, we want this to be set in the initial render this.state.activeTab ??= "message"; const tabData = tabs.find(t => t.id === this.state.activeTab); @@ -86,7 +86,7 @@ export default () => after("render", ErrorBoundary.prototype, function (this: an <_ErrorBoundary> - + {ret.props.Illustration && } {ret.props.title} {ret.props.body} @@ -101,6 +101,15 @@ export default () => after("render", ErrorBoundary.prototype, function (this: an onTabSelected={(tab: string) => { this.setState({ activeTab: tab }) }} /> + + {[ + `Discord: ${debugInfo.discord.build} (${debugInfo.os.name})`, + `Vendetta: ${debugInfo.vendetta.version}` + ].join("\n")} +