diff --git a/src/Router.tsx b/src/Router.tsx index f8ec890a5..16bb526d4 100644 --- a/src/Router.tsx +++ b/src/Router.tsx @@ -31,6 +31,7 @@ import { } from './lib/tauriFS' import { metadata, type Metadata } from 'tauri-plugin-fs-extra-api' import DownloadAppBanner from './components/DownloadAppBanner' +import { WasmErrBanner } from './components/WasmErrBanner' import { GlobalStateProvider } from './components/GlobalStateProvider' import { SETTINGS_PERSIST_KEY, @@ -150,6 +151,7 @@ const router = createBrowserRouter( + {!isTauri() && import.meta.env.PROD && } diff --git a/src/components/WasmErrBanner.tsx b/src/components/WasmErrBanner.tsx new file mode 100644 index 000000000..239c58e2d --- /dev/null +++ b/src/components/WasmErrBanner.tsx @@ -0,0 +1,63 @@ +import { Dialog } from '@headlessui/react' +import { useState } from 'react' +import { ActionButton } from './ActionButton' +import { faX } from '@fortawesome/free-solid-svg-icons' +import { useKclContext } from 'lang/KclSinglton' + +export function WasmErrBanner() { + const [isBannerDismissed, setBannerDismissed] = useState(false) + + const { wasmInitFailed } = useKclContext() + + if (!wasmInitFailed) return null + + return ( + ({})} + > + +
+

+ Problem with our WASM blob :( +

+ setBannerDismissed(true)} + icon={{ + icon: faX, + bgClassName: + 'bg-warn-70 hover:bg-warn-80 dark:bg-warn-70 dark:hover:bg-warn-80', + iconClassName: + 'text-warn-10 group-hover:text-warn-10 dark:text-warn-10 dark:group-hover:text-warn-10', + }} + className="!p-0 !bg-transparent !border-transparent" + /> +
+

+ + WASM or web assembly + {' '} + is core part of how our app works. It might because you OS is not + up-to-date. If you're able to update your OS to a later version, try + that. If not create an issue on{' '} + + our Github + + . +

+
+
+ ) +} diff --git a/src/lang/KclSinglton.tsx b/src/lang/KclSinglton.tsx index 7f8e7085b..cbd665096 100644 --- a/src/lang/KclSinglton.tsx +++ b/src/lang/KclSinglton.tsx @@ -40,6 +40,7 @@ class KclManager { private _logs: string[] = [] private _kclErrors: KCLError[] = [] private _isExecuting = false + private _wasmInitFailed = true engineCommandManager: EngineCommandManager private _defferer = deferExecution((code: string) => { @@ -47,12 +48,13 @@ class KclManager { this.executeAst(ast) }, 600) - private _isExecutingCallback: (a: boolean) => void = () => {} + private _isExecutingCallback: (arg: boolean) => void = () => {} private _codeCallBack: (arg: string) => void = () => {} private _astCallBack: (arg: Program) => void = () => {} private _programMemoryCallBack: (arg: ProgramMemory) => void = () => {} private _logsCallBack: (arg: string[]) => void = () => {} private _kclErrorsCallBack: (arg: KCLError[]) => void = () => {} + private _wasmInitFailedCallback: (arg: boolean) => void = () => {} get ast() { return this._ast @@ -106,6 +108,14 @@ class KclManager { this._isExecutingCallback(isExecuting) } + get wasmInitFailed() { + return this._wasmInitFailed + } + set wasmInitFailed(wasmInitFailed) { + this._wasmInitFailed = wasmInitFailed + this._wasmInitFailedCallback(wasmInitFailed) + } + constructor(engineCommandManager: EngineCommandManager) { this.engineCommandManager = engineCommandManager const storedCode = localStorage.getItem(PERSIST_CODE_TOKEN) @@ -131,6 +141,7 @@ class KclManager { setLogs, setKclErrors, setIsExecuting, + setWasmInitFailed, }: { setCode: (arg: string) => void setProgramMemory: (arg: ProgramMemory) => void @@ -138,6 +149,7 @@ class KclManager { setLogs: (arg: string[]) => void setKclErrors: (arg: KCLError[]) => void setIsExecuting: (arg: boolean) => void + setWasmInitFailed: (arg: boolean) => void }) { this._codeCallBack = setCode this._programMemoryCallBack = setProgramMemory @@ -145,11 +157,23 @@ class KclManager { this._logsCallBack = setLogs this._kclErrorsCallBack = setKclErrors this._isExecutingCallback = setIsExecuting + this._wasmInitFailedCallback = setWasmInitFailed + } + + async ensureWasmInit() { + try { + await initPromise + if (this.wasmInitFailed) { + this.wasmInitFailed = false + } + } catch (e) { + this.wasmInitFailed = true + } } async executeAst(ast: Program = this._ast, updateCode = false) { + await this.ensureWasmInit() this.isExecuting = true - await initPromise const { logs, errors, programMemory } = await executeAst({ ast, engineCommandManager: this.engineCommandManager, @@ -166,7 +190,7 @@ class KclManager { } } async executeAstMock(ast: Program = this._ast, updateCode = false) { - await initPromise + await this.ensureWasmInit() const newCode = recast(ast) const newAst = parse(newCode) await this?.engineCommandManager?.waitForReady @@ -186,7 +210,7 @@ class KclManager { this._programMemory = programMemory } async executeCode(code?: string) { - await initPromise + await this.ensureWasmInit() await this?.engineCommandManager?.waitForReady if (!this?.engineCommandManager?.planesInitialized()) return const result = await executeCode({ @@ -306,6 +330,7 @@ const KclContext = createContext({ isExecuting: kclManager.isExecuting, errors: kclManager.kclErrors, logs: kclManager.logs, + wasmInitFailed: kclManager.wasmInitFailed, }) export function useKclContext() { @@ -326,6 +351,7 @@ export function KclContextProvider({ const [isExecuting, setIsExecuting] = useState(false) const [errors, setErrors] = useState([]) const [logs, setLogs] = useState([]) + const [wasmInitFailed, setWasmInitFailed] = useState(false) useEffect(() => { kclManager.registerCallBacks({ @@ -335,6 +361,7 @@ export function KclContextProvider({ setLogs, setKclErrors: setErrors, setIsExecuting, + setWasmInitFailed, }) }, []) return ( @@ -346,6 +373,7 @@ export function KclContextProvider({ isExecuting, errors, logs, + wasmInitFailed, }} > {children}