From ca0dc2624af9248222894ca22165735a2a3f1f2a Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Fri, 19 Jul 2024 13:44:32 -0700 Subject: [PATCH] more well defined 'init' for global.ts (#125) --- emain/emain.ts | 3 + frontend/app/store/global.ts | 163 ++++++++++++++++++----------------- frontend/types/custom.d.ts | 13 +++ frontend/wave.ts | 7 +- 4 files changed, 105 insertions(+), 81 deletions(-) diff --git a/emain/emain.ts b/emain/emain.ts index b9aa84ec9..086fea132 100644 --- a/emain/emain.ts +++ b/emain/emain.ts @@ -1,6 +1,7 @@ // Copyright 2024, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 +import { initGlobal } from "@/app/store/global"; import { WaveDevVarName, WaveDevViteVarName } from "@/util/isdev"; import * as electron from "electron"; import { autoUpdater } from "electron-updater"; @@ -98,6 +99,8 @@ if (isDev) { console.log("waveterm-app WAVETERM_DEV set"); } +initGlobal({ windowId: null, clientId: null, platform: unamePlatform, environment: "electron" }); + function getElectronAppBasePath(): string { return path.dirname(__dirname); } diff --git a/frontend/app/store/global.ts b/frontend/app/store/global.ts index e8f727c57..7e4317837 100644 --- a/frontend/app/store/global.ts +++ b/frontend/app/store/global.ts @@ -16,86 +16,91 @@ import * as WOS from "./wos"; import { WSControl } from "./ws"; let PLATFORM: NodeJS.Platform = "darwin"; +const globalStore = jotai.createStore(); +let atoms: GlobalAtomsType; +let globalEnvironment: "electron" | "renderer"; + +type GlobalInitOptions = { + platform: NodeJS.Platform; + windowId: string; + clientId: string; + environment: "electron" | "renderer"; +}; + +function initGlobal(initOpts: GlobalInitOptions) { + globalEnvironment = initOpts.environment; + setPlatform(initOpts.platform); + initGlobalAtoms(initOpts); +} function setPlatform(platform: NodeJS.Platform) { PLATFORM = platform; } -// TODO remove the window dependency completely -// we should have the initialization be more orderly -- proceed directly from wave.ts instead of on its own. -const globalStore = jotai.createStore(); -let globalWindowId: string = null; -let globalClientId: string = null; -if (typeof window !== "undefined") { - // this if statement allows us to use the code in nodejs as well - const urlParams = new URLSearchParams(window.location.search); - globalWindowId = urlParams.get("windowid"); - globalClientId = urlParams.get("clientid"); -} -const windowIdAtom = jotai.atom(null) as jotai.PrimitiveAtom; -const clientIdAtom = jotai.atom(null) as jotai.PrimitiveAtom; -globalStore.set(windowIdAtom, globalWindowId); -globalStore.set(clientIdAtom, globalClientId); -const uiContextAtom = jotai.atom((get) => { - const windowData = get(windowDataAtom); - const uiContext: UIContext = { - windowid: get(atoms.windowId), - activetabid: windowData?.activetabid, - }; - return uiContext; -}) as jotai.Atom; -const clientAtom: jotai.Atom = jotai.atom((get) => { - const clientId = get(clientIdAtom); - if (clientId == null) { - return null; - } - return WOS.getObjectValue(WOS.makeORef("client", clientId), get); -}); -const windowDataAtom: jotai.Atom = jotai.atom((get) => { - const windowId = get(windowIdAtom); - if (windowId == null) { - return null; - } - const rtn = WOS.getObjectValue(WOS.makeORef("window", windowId), get); - return rtn; -}); -const workspaceAtom: jotai.Atom = jotai.atom((get) => { - const windowData = get(windowDataAtom); - if (windowData == null) { - return null; - } - return WOS.getObjectValue(WOS.makeORef("workspace", windowData.workspaceid), get); -}); -const settingsConfigAtom = jotai.atom(null) as jotai.PrimitiveAtom; -const tabAtom: jotai.Atom = jotai.atom((get) => { - const windowData = get(windowDataAtom); - if (windowData == null) { - return null; - } - return WOS.getObjectValue(WOS.makeORef("tab", windowData.activetabid), get); -}); -const activeTabIdAtom: jotai.Atom = jotai.atom((get) => { - const windowData = get(windowDataAtom); - if (windowData == null) { - return null; - } - return windowData.activetabid; -}); -const userInputAtom = jotai.atom([]) as jotai.PrimitiveAtom>; +function initGlobalAtoms(initOpts: GlobalInitOptions) { + const windowIdAtom = jotai.atom(initOpts.windowId) as jotai.PrimitiveAtom; + const clientIdAtom = jotai.atom(initOpts.clientId) as jotai.PrimitiveAtom; + const uiContextAtom = jotai.atom((get) => { + const windowData = get(windowDataAtom); + const uiContext: UIContext = { + windowid: get(atoms.windowId), + activetabid: windowData?.activetabid, + }; + return uiContext; + }) as jotai.Atom; -const atoms = { - // initialized in wave.ts (will not be null inside of application) - windowId: windowIdAtom, - clientId: clientIdAtom, - uiContext: uiContextAtom, - client: clientAtom, - waveWindow: windowDataAtom, - workspace: workspaceAtom, - settingsConfigAtom: settingsConfigAtom, - tabAtom: tabAtom, - activeTabId: activeTabIdAtom, - userInput: userInputAtom, -}; + const clientAtom: jotai.Atom = jotai.atom((get) => { + const clientId = get(clientIdAtom); + if (clientId == null) { + return null; + } + return WOS.getObjectValue(WOS.makeORef("client", clientId), get); + }); + const windowDataAtom: jotai.Atom = jotai.atom((get) => { + const windowId = get(windowIdAtom); + if (windowId == null) { + return null; + } + const rtn = WOS.getObjectValue(WOS.makeORef("window", windowId), get); + return rtn; + }); + const workspaceAtom: jotai.Atom = jotai.atom((get) => { + const windowData = get(windowDataAtom); + if (windowData == null) { + return null; + } + return WOS.getObjectValue(WOS.makeORef("workspace", windowData.workspaceid), get); + }); + const settingsConfigAtom = jotai.atom(null) as jotai.PrimitiveAtom; + const tabAtom: jotai.Atom = jotai.atom((get) => { + const windowData = get(windowDataAtom); + if (windowData == null) { + return null; + } + return WOS.getObjectValue(WOS.makeORef("tab", windowData.activetabid), get); + }); + const activeTabIdAtom: jotai.Atom = jotai.atom((get) => { + const windowData = get(windowDataAtom); + if (windowData == null) { + return null; + } + return windowData.activetabid; + }); + const userInputAtom = jotai.atom([]) as jotai.PrimitiveAtom>; + atoms = { + // initialized in wave.ts (will not be null inside of application) + windowId: windowIdAtom, + clientId: clientIdAtom, + uiContext: uiContextAtom, + client: clientAtom, + waveWindow: windowDataAtom, + workspace: workspaceAtom, + settingsConfigAtom: settingsConfigAtom, + tabAtom: tabAtom, + activeTabId: activeTabIdAtom, + userInput: userInputAtom, + }; +} // key is "eventType" or "eventType|oref" const eventSubjects = new Map>(); @@ -168,7 +173,7 @@ function useSettingsAtom(name: string, settingsFn: (settings: SettingsConfigT let atom = settingsAtomCache.get(name); if (atom == null) { atom = jotai.atom((get) => { - const settings = get(settingsConfigAtom); + const settings = get(atoms.settingsConfigAtom); if (settings == null) { return null; } @@ -205,7 +210,7 @@ function handleWSEventMessage(msg: WSEventType) { } if (msg.eventtype == "config") { const data: WatcherUpdate = msg.data; - globalStore.set(settingsConfigAtom, data.update); + globalStore.set(atoms.settingsConfigAtom, data.update); console.log("config", data); return; @@ -214,7 +219,7 @@ function handleWSEventMessage(msg: WSEventType) { // handle user input const data: UserInputRequest = msg.data; console.log(data); - globalStore.set(userInputAtom, (prev) => [...prev, data]); + globalStore.set(atoms.userInput, (prev) => [...prev, data]); return; } if (msg.eventtype == "blockfile") { @@ -279,7 +284,8 @@ function handleWSMessage(msg: any) { } function initWS() { - globalWS = new WSControl(getWSServerEndpoint(), globalStore, globalWindowId, "", (msg) => { + let windowId = globalStore.get(atoms.windowId); + globalWS = new WSControl(getWSServerEndpoint(), globalStore, windowId, "", (msg) => { handleWSMessage(msg); }); globalWS.connectNow("initWS"); @@ -388,6 +394,7 @@ export { getObjectId, globalStore, globalWS, + initGlobal, initWS, sendWSCommand, setBlockFocus, diff --git a/frontend/types/custom.d.ts b/frontend/types/custom.d.ts index 0625872b6..3408c9357 100644 --- a/frontend/types/custom.d.ts +++ b/frontend/types/custom.d.ts @@ -5,6 +5,19 @@ import type * as jotai from "jotai"; import type * as rxjs from "rxjs"; declare global { + type GlobalAtomsType = { + windowId: jotai.Atom; // readonly + clientId: jotai.Atom; // readonly + client: jotai.Atom; // driven from WOS + uiContext: jotai.Atom; // driven from windowId, activetabid, etc. + waveWindow: jotai.Atom; // driven from WOS + workspace: jotai.Atom; // driven from WOS + settingsConfigAtom: jotai.PrimitiveAtom; // driven from WOS, settings -- updated via WebSocket + tabAtom: jotai.Atom; // driven from WOS + activeTabId: jotai.Atom; // derrived from windowDataAtom + userInput: jotai.PrimitiveAtom>; + }; + type TabLayoutData = { blockId: string; }; diff --git a/frontend/wave.ts b/frontend/wave.ts index 122c2977c..2c4d50c83 100644 --- a/frontend/wave.ts +++ b/frontend/wave.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { WshServer } from "@/app/store/wshserver"; -import { atoms, getApi, globalStore, globalWS, initWS, setPlatform } from "@/store/global"; +import { atoms, getApi, globalStore, globalWS, initGlobal, initWS } from "@/store/global"; import * as services from "@/store/services"; import * as WOS from "@/store/wos"; import * as keyutil from "@/util/keyutil"; @@ -11,6 +11,7 @@ import { createRoot } from "react-dom/client"; import { App } from "./app/app"; import { loadFonts } from "./util/fontutil"; +const platform = getApi().getPlatform(); const urlParams = new URLSearchParams(window.location.search); const windowId = urlParams.get("windowid"); const clientId = urlParams.get("clientid"); @@ -18,8 +19,8 @@ const clientId = urlParams.get("clientid"); console.log("Wave Starting"); console.log("clientid", clientId, "windowid", windowId); -const platform = getApi().getPlatform(); -setPlatform(platform); +initGlobal({ clientId, windowId, platform, environment: "renderer" }); + keyutil.setKeyUtilPlatform(platform); loadFonts();