Compare commits

...

5 Commits

Author SHA1 Message Date
Evan Simkowitz 45e2db0739 Merge branch 'main' into evan/grid 2024-05-06 14:18:25 -07:00
Evan Simkowitz 1a9ba17a95 save 2024-05-06 14:17:54 -07:00
Evan Simkowitz fd2cb82065 remove more main window references 2024-05-06 12:27:50 -07:00
Evan Simkowitz 2d890e63a7 more cleanup 2024-05-06 12:24:42 -07:00
Evan Simkowitz 9b3f9cb419 Use native window ID to track main window instead of a ref 2024-05-06 12:16:14 -07:00
8 changed files with 178 additions and 1 deletions
+160
View File
@@ -0,0 +1,160 @@
// Copyright 2023, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import * as React from "react";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { clsx } from "clsx";
import { If } from "tsx-control-statements/components";
import { GlobalModel } from "@/models";
import { isBlank } from "@/util/util";
import { WorkspaceView } from "@/app/workspace/workspaceview";
import { PluginsView } from "@/app/pluginsview/pluginsview";
import { BookmarksView } from "@/app/bookmarks/bookmarks";
import { HistoryView } from "@/app/history/history";
import { ConnectionsView } from "@/app/connections/connections";
import { ClientSettingsView } from "@/app/clientsettings/clientsettings";
import { MainSideBar } from "@/app/sidebar/main";
import { RightSideBar } from "@/app/sidebar/right";
import { DisconnectedModal, ClientStopModal } from "@/modals";
import { ModalsProvider } from "@/modals/provider";
import { Button, TermStyleList } from "@/elements";
import { ErrorBoundary } from "@/common/error/errorboundary";
import "@/app/app.less";
export const App2: React.FC = mobxReact.observer(() => {
const [dcWait, setDcWait] = React.useState(false);
const mainContentRef = React.useRef<HTMLDivElement>(null);
const [termThemesLoaded, setTermThemesLoaded] = React.useState(false);
const handleContextMenu = (e: React.MouseEvent<HTMLElement>) => {
let isInNonTermInput = false;
const activeElem = document.activeElement;
if (activeElem != null && activeElem.nodeName == "TEXTAREA") {
if (!activeElem.classList.contains("xterm-helper-textarea")) {
isInNonTermInput = true;
}
}
if (activeElem != null && activeElem.nodeName == "INPUT" && activeElem.getAttribute("type") == "text") {
isInNonTermInput = true;
}
const opts: ContextMenuOpts = {};
if (isInNonTermInput) {
opts.showCut = true;
}
const sel = window.getSelection();
if (!isBlank(sel?.toString()) || isInNonTermInput) {
GlobalModel.contextEditMenu(e, opts);
}
};
const openMainSidebar = mobx.action(() => {
const mainSidebarModel = GlobalModel.mainSidebarModel;
const width = mainSidebarModel.getWidth(true);
mainSidebarModel.saveState(width, false);
});
const openRightSidebar = mobx.action(() => {
const rightSidebarModel = GlobalModel.rightSidebarModel;
const width = rightSidebarModel.getWidth(true);
rightSidebarModel.saveState(width, false);
});
const remotesModel = GlobalModel.remotesModel;
const disconnected = !GlobalModel.ws.open.get() || !GlobalModel.waveSrvRunning.get();
const hasClientStop = GlobalModel.getHasClientStop();
const platform = GlobalModel.getPlatform();
const clientData = GlobalModel.clientData.get();
// Previously, this is done in sidebar.tsx but it causes flicker when clientData is null cos screen-view shifts around.
// Doing it here fixes the flicker cos app is not rendered until clientData is populated.
// wait for termThemes as well (this actually means that the "connect" packet has been received)
if (clientData == null || GlobalModel.termThemes.get() == null) {
return null;
}
if (disconnected || hasClientStop) {
if (!dcWait) {
setTimeout(() => setDcWait(true), 1500);
}
return (
<div id="main" className={"platform-" + platform} onContextMenu={handleContextMenu}>
<div ref={mainContentRef} className="main-content">
<MainSideBar parentRef={mainContentRef} />
<div className="session-view" />
</div>
<If condition={dcWait}>
<If condition={disconnected}>
<DisconnectedModal />
</If>
<If condition={!disconnected && hasClientStop}>
<ClientStopModal />
</If>
</If>
</div>
);
}
if (dcWait) {
setTimeout(() => setDcWait(false), 0);
}
// used to force a full reload of the application
const renderVersion = GlobalModel.renderVersion.get();
const mainSidebarCollapsed = GlobalModel.mainSidebarModel.getCollapsed();
const rightSidebarCollapsed = GlobalModel.rightSidebarModel.getCollapsed();
const activeMainView = GlobalModel.activeMainView.get();
const lightDarkClass = GlobalModel.isDarkTheme.get() ? "is-dark" : "is-light";
const mainClassName = clsx(
"platform-" + platform,
{
"mainsidebar-collapsed": mainSidebarCollapsed,
"rightsidebar-collapsed": rightSidebarCollapsed,
},
lightDarkClass
);
return (
<>
<TermStyleList onRendered={() => setTermThemesLoaded(true)} />
<div
key={`version- + ${renderVersion}`}
id="main"
className={mainClassName}
onContextMenu={handleContextMenu}
>
<If condition={termThemesLoaded}>
<If condition={mainSidebarCollapsed}>
<div key="logo-button" className="logo-button-container">
<div className="logo-button-spacer" />
<div className="logo-button" onClick={openMainSidebar}>
<img src="public/logos/wave-logo.png" alt="logo" />
</div>
</div>
</If>
<If condition={GlobalModel.isDev && rightSidebarCollapsed && activeMainView == "session"}>
<div className="right-sidebar-triggers">
<Button className="secondary ghost right-sidebar-trigger" onClick={openRightSidebar}>
<i className="fa-sharp fa-solid fa-sidebar-flip"></i>
</Button>
</div>
</If>
<div ref={mainContentRef} className="main-content">
<MainSideBar parentRef={mainContentRef} />
<ErrorBoundary>
<PluginsView />
<WorkspaceView />
<HistoryView />
<BookmarksView />
<ConnectionsView model={remotesModel} />
<ClientSettingsView model={remotesModel} />
</ErrorBoundary>
<RightSideBar parentRef={mainContentRef} />
</div>
<ModalsProvider />
</If>
</div>
</>
);
});
+5
View File
@@ -520,6 +520,10 @@ electron.ipcMain.on("get-id", (event) => {
event.returnValue = instanceId + ":" + event.processId;
});
electron.ipcMain.on("get-window-id", (event) => {
event.returnValue = event.sender.id;
});
electron.ipcMain.on("get-platform", (event) => {
event.returnValue = unamePlatform;
});
@@ -985,6 +989,7 @@ function configureAutoUpdater(enabled: boolean) {
setTimeout(runActiveTimer, 5000); // start active timer, wait 5s just to be safe
await app.whenReady();
await createWindowWrap();
await createWindowWrap();
app.on("activate", () => {
if (electron.BrowserWindow.getAllWindows().length === 0) {
+1
View File
@@ -4,6 +4,7 @@ contextBridge.exposeInMainWorld("api", {
hideWindow: () => ipc.Renderer.send("hide-window"),
toggleDeveloperTools: () => ipcRenderer.send("toggle-developer-tools"),
getId: () => ipcRenderer.sendSync("get-id"),
getWindowId: () => ipcRenderer.sendSync("get-window-id"),
getPlatform: () => ipcRenderer.sendSync("get-platform"),
getIsDev: () => ipcRenderer.sendSync("get-isdev"),
getAuthKey: () => ipcRenderer.sendSync("get-authkey"),
+8 -1
View File
@@ -6,9 +6,11 @@ import * as React from "react";
import { createRoot } from "react-dom/client";
import { sprintf } from "sprintf-js";
import { App } from "@/app/app";
import { App2 } from "@/app2/app";
import * as DOMPurify from "dompurify";
import { loadFonts } from "@/util/fontutil";
import * as textmeasure from "@/util/textmeasure";
import { getApi } from "./models";
// @ts-ignore
let VERSION = __WAVETERM_VERSION__;
@@ -18,7 +20,12 @@ let BUILD = __WAVETERM_BUILD__;
loadFonts();
document.addEventListener("DOMContentLoaded", () => {
let reactElem = React.createElement(App, null, null);
let reactElem;
if (getApi().getWindowId() === 1) {
reactElem = React.createElement(App, null, null);
} else {
reactElem = React.createElement(App2, null, null);
}
let elem = document.getElementById("app");
let root = createRoot(elem);
document.fonts.ready.then(() => {
+1
View File
@@ -943,6 +943,7 @@ declare global {
hideWindow: () => void;
toggleDeveloperTools: () => void;
getId: () => string;
getWindowId: () => number;
getIsDev: () => boolean;
getPlatform: () => string;
getAuthKey: () => string;
+1
View File
@@ -16,6 +16,7 @@
"baseUrl": "./",
"paths": {
"@/app/*": ["src/app/*"], // Points to the src folder
"@/app2/*": ["src/app2/*"], // Points to the src folder
"@/util/*": ["src/util/*"], // Points to the src folder
"@/models": ["src/models/index"], // Points directly to the index file
"@/models/*": ["src/models/*"], // For everything else inside models
+1
View File
@@ -60,6 +60,7 @@ var electronCommon = {
extensions: [".ts", ".tsx", ".js"],
alias: {
"@/app": path.resolve(__dirname, "../src/app/"),
"@/app2": path.resolve(__dirname, "../src/app2/"),
"@/util": path.resolve(__dirname, "../src/util/"),
"@/models": path.resolve(__dirname, "../src/models/"),
"@/common": path.resolve(__dirname, "../src/app/common/"),
+1
View File
@@ -81,6 +81,7 @@ var webCommon = {
extensions: [".ts", ".tsx", ".js", ".mjs", ".cjs", ".wasm", ".json", ".less", ".css"],
alias: {
"@/app": path.resolve(__dirname, "../src/app/"),
"@/app2": path.resolve(__dirname, "../src/app2/"),
"@/util": path.resolve(__dirname, "../src/util/"),
"@/models": path.resolve(__dirname, "../src/models/"),
"@/common": path.resolve(__dirname, "../src/app/common/"),