diff --git a/packages/app/src/App.jsx b/packages/app/src/App.jsx index a3c4bbbb..d0e01506 100644 --- a/packages/app/src/App.jsx +++ b/packages/app/src/App.jsx @@ -51,7 +51,7 @@ import { StatusBar, Style } from "@capacitor/status-bar" import { Translation } from "react-i18next" import { Session, User } from "models" -import { API, SettingsController, Render, Splash, Theme, Sound, Notifications, i18n } from "extensions" +import { API, SettingsController, Render, Splash, Theme, Sound, Notifications, i18n, Debug } from "extensions" import config from "config" import { NotFound, RenderError, Crash, Settings, Navigation } from "components" @@ -176,7 +176,10 @@ class App { content: "Connection restored", }) } - } + }, + "appLoadError": function (error) { + + }, } static windowContext() { @@ -328,7 +331,7 @@ class App { await Promise.tasked(initializationTasks).catch((reason) => { console.error(`[App] Initialization failed: ${reason.cause}`) - window.app.eventBus.emit("crash", reason.cause, reason.details) + window.app.eventBus.emit("appLoadError", reason.cause, reason.details) }) } @@ -399,5 +402,6 @@ export default CreateEviteApp(App, { Render.extension, Theme.extension, SplashExtension, + Debug, ], }) \ No newline at end of file diff --git a/packages/app/src/extensions/debug/index.jsx b/packages/app/src/extensions/debug/index.jsx new file mode 100644 index 00000000..5f19a237 --- /dev/null +++ b/packages/app/src/extensions/debug/index.jsx @@ -0,0 +1,135 @@ +import React from "react" +import { Window } from "components" +import { Skeleton, Tabs } from "antd" + +class DebuggerUI extends React.Component { + state = { + loading: true, + error: null, + debuggers: null, + active: null, + } + + toogleLoading = (to = !this.state.loading ?? false) => { + this.setState({ loading: to }) + } + + loadDebuggers = async () => { + this.toogleLoading(true) + + const debuggers = await import(`~/debugComponents`) + let renders = {} + + Object.keys(debuggers).forEach((key) => { + renders[key] = debuggers[key] + }) + + this.setState({ debuggers: renders }, () => { + this.toogleLoading(false) + }) + } + + componentDidMount = async () => { + await this.loadDebuggers() + } + + componentDidCatch = (error, info) => { + this.setState({ error }) + } + + onChangeTab = (key) => { + console.debug(`Changing tab to ${key}`) + this.setState({ active: key, error: null }) + } + + renderError = (key, error) => { + return ( +
+

Debugger Error

+ +

+ Catch on [{key}] +

+
+ `{error.message}` +
+ {error.stack} +
+ ) + } + + renderTabs = () => { + return Object.keys(this.state.debuggers).map((key) => { + return + }) + } + + renderDebugger = (_debugger) => { + try { + return React.createElement(window.app.bindContexts(_debugger)) + } catch (error) { + return this.renderError(key, error) + } + } + + render() { + const { loading, error } = this.state + + if (loading) { + return + } + + return ( +
+ + {this.renderTabs()} + + {error && this.renderError(this.state.active, error)} + {!this.state.active ? ( +
Select an debugger to start
+ ) : ( + this.renderDebugger(this.state.debuggers[this.state.active]) + )} +
+ ) + } +} + +class Debugger { + constructor(mainContext, params = {}) { + this.mainContext = mainContext + this.params = { ...params } + + this.bindings = {} + } + + openWindow = () => { + new Window.DOMWindow({ id: "debugger", children: window.app.bindContexts(DebuggerUI) }).create() + } + + bind = (id, binding) => { + this.bindings[id] = binding + + return binding + } + + unbind = (id) => { + delete this.bindings[id] + } +} + +export default { + key: "visualDebugger", + expose: [ + { + initialization: [ + async (app, main) => { + main.setToWindowContext("debug", new Debugger(main)) + }, + ], + }, + ], +} \ No newline at end of file diff --git a/packages/app/src/extensions/index.js b/packages/app/src/extensions/index.js index bee6d830..0db8f5d1 100644 --- a/packages/app/src/extensions/index.js +++ b/packages/app/src/extensions/index.js @@ -6,4 +6,5 @@ export * as i18n from "./i18n" export * as Notifications from "./notifications" export { default as SettingsController } from "./settings" -export { default as API } from "./api" \ No newline at end of file +export { default as API } from "./api" +export { default as Debug } from "./debug" \ No newline at end of file