diff --git a/.gitignore b/.gitignore index a1c7240b5a..a56b777457 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,6 @@ test-results.xml docsite/ .kilo-format-temp-* +.superpowers +docs/superpowers +.claude diff --git a/emain/emain-ipc.ts b/emain/emain-ipc.ts index 09830b9315..d812ad059d 100644 --- a/emain/emain-ipc.ts +++ b/emain/emain-ipc.ts @@ -236,6 +236,14 @@ export function initIpcHandlers() { menu.popup(); }); + electron.ipcMain.on("webview-mouse-navigate", (event: electron.IpcMainEvent, direction: string) => { + if (direction === "back") { + event.sender.goBack(); + } else if (direction === "forward") { + event.sender.goForward(); + } + }); + electron.ipcMain.on("download", (event, payload) => { const baseName = encodeURIComponent(path.basename(payload.filePath)); const streamingUrl = diff --git a/emain/emain-window.ts b/emain/emain-window.ts index 8dfd31789e..65361c0af8 100644 --- a/emain/emain-window.ts +++ b/emain/emain-window.ts @@ -22,7 +22,7 @@ import { delay, ensureBoundsAreVisible, waveKeyToElectronKey } from "./emain-uti import { ElectronWshClient } from "./emain-wsh"; import { updater } from "./updater"; -const DevInitTimeoutMs = 5000; +const DevInitTimeoutMs = 15000; export type WindowOpts = { unamePlatform: NodeJS.Platform; @@ -395,7 +395,7 @@ export class WaveBrowserWindow extends BaseWindow { const clientId = await getClientId(); await this.awaitWithDevTimeout(tabView.initPromise, "initPromise", tabView.waveTabId); const winBounds = this.getContentBounds(); - tabView.setBounds({ x: 0, y: 0, width: winBounds.width, height: winBounds.height }); + tabView.positionTabOffScreen(winBounds); this.contentView.addChildView(tabView); const initOpts: WaveInitOpts = { tabId: tabView.waveTabId, @@ -461,6 +461,15 @@ export class WaveBrowserWindow extends BaseWindow { console.log("initializing a new tab", primaryStartupTab ? "(primary startup)" : ""); await this.initializeTab(tabView, primaryStartupTab); this.finalizePositioning(); + } else if (tabView.isWaveReady) { + if (tabView.savedInitOpts?.windowId !== this.waveWindowId) { + console.log("reusing wave-ready tab with stale windowId, reinitializing", tabView.waveTabId); + tabView.savedInitOpts = { ...tabView.savedInitOpts, windowId: this.waveWindowId }; + tabView.webContents.send("wave-init", tabView.savedInitOpts); + } else { + console.log("reusing wave-ready tab, skipping reinit", tabView.waveTabId); + } + this.finalizePositioning(); } else { console.log("reusing an existing tab, calling wave-init", tabView.waveTabId); tabView.webContents.send("wave-init", tabView.savedInitOpts); // reinit diff --git a/emain/preload-webview.ts b/emain/preload-webview.ts index da60a6ea54..e2a39a3b4e 100644 --- a/emain/preload-webview.ts +++ b/emain/preload-webview.ts @@ -25,4 +25,15 @@ document.addEventListener("contextmenu", (event) => { // do nothing }); +document.addEventListener("mouseup", (event) => { + // Mouse button 3 = back, button 4 = forward + if (!event.isTrusted) { + return; + } + if (event.button === 3 || event.button === 4) { + event.preventDefault(); + ipcRenderer.send("webview-mouse-navigate", event.button === 3 ? "back" : "forward"); + } +}); + console.log("loaded wave preload-webview.ts"); diff --git a/frontend/app/tab/tabbar.tsx b/frontend/app/tab/tabbar.tsx index 62e9052e31..b404afcb7e 100644 --- a/frontend/app/tab/tabbar.tsx +++ b/frontend/app/tab/tabbar.tsx @@ -189,7 +189,8 @@ const TabBar = memo(({ workspace, noTabs }: TabBarProps) => { const addBtnWidth = getOuterWidth(addBtnRef.current); const appMenuButtonWidth = appMenuButtonRef.current?.getBoundingClientRect().width ?? 0; const workspaceSwitcherWidth = workspaceSwitcherRef.current?.getBoundingClientRect().width ?? 0; - const waveAIButtonWidth = waveAIButtonRef.current != null ? getOuterWidth(waveAIButtonRef.current) : 0; + const waveAIButtonWidth = + !hideAiButton && waveAIButtonRef.current != null ? getOuterWidth(waveAIButtonRef.current) : 0; const nonTabElementsWidth = windowDragLeftWidth + @@ -276,7 +277,7 @@ const TabBar = memo(({ workspace, noTabs }: TabBarProps) => { // Check if all tabs are loaded const allLoaded = tabIds.length > 0 && tabIds.every((id) => tabsLoaded[id]); if (allLoaded) { - setSizeAndPosition(newTabId === null && prevAllLoadedRef.current); + setSizeAndPosition(false); saveTabsPosition(); if (!prevAllLoadedRef.current) { prevAllLoadedRef.current = true; diff --git a/pkg/util/shellutil/shellutil.go b/pkg/util/shellutil/shellutil.go index e6f6c21f38..ec62c455d1 100644 --- a/pkg/util/shellutil/shellutil.go +++ b/pkg/util/shellutil/shellutil.go @@ -222,6 +222,9 @@ func WaveshellLocalEnvVars(termType string) map[string]string { } // these are not necessary since they should be set with the swap token, but no harm in setting them here rtn["TERM_PROGRAM"] = "waveterm" + if os.Getenv("COLORTERM") == "" { + rtn["COLORTERM"] = "truecolor" + } rtn["WAVETERM"], _ = os.Executable() rtn["WAVETERM_VERSION"] = wavebase.WaveVersion rtn["WAVETERM_WSHBINDIR"] = filepath.Join(wavebase.GetWaveDataDir(), WaveHomeBinDir)