install special new handlers for Cmd+N and Cmd+T when no windows are open (#1839)

This commit is contained in:
Mike Sawka 2025-01-24 14:24:39 -08:00 committed by GitHub
parent bba94a62d0
commit 038ba8e132
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 73 additions and 4 deletions

30
emain/emain-events.ts Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2025, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import { EventEmitter } from "events";
interface GlobalEvents {
"windows-updated": () => void; // emitted whenever a window is opened/closed
}
class GlobalEventEmitter extends EventEmitter {
emit<K extends keyof GlobalEvents>(event: K, ...args: Parameters<GlobalEvents[K]>): boolean {
return super.emit(event, ...args);
}
on<K extends keyof GlobalEvents>(event: K, listener: GlobalEvents[K]): this {
return super.on(event, listener);
}
once<K extends keyof GlobalEvents>(event: K, listener: GlobalEvents[K]): this {
return super.once(event, listener);
}
off<K extends keyof GlobalEvents>(event: K, listener: GlobalEvents[K]): this {
return super.off(event, listener);
}
}
const globalEvents = new GlobalEventEmitter();
export { globalEvents };

View File

@ -5,6 +5,7 @@ import { ClientService, ObjectService, WindowService, WorkspaceService } from "@
import { RpcApi } from "@/app/store/wshclientapi";
import { fireAndForget } from "@/util/util";
import { BaseWindow, BaseWindowConstructorOptions, dialog, globalShortcut, ipcMain, screen } from "electron";
import { globalEvents } from "emain/emain-events";
import path from "path";
import { debounce } from "throttle-debounce";
import {
@ -293,6 +294,7 @@ export class WaveBrowserWindow extends BaseWindow {
console.log("win quitting or updating", this.waveWindowId);
return;
}
setTimeout(() => globalEvents.emit("windows-updated"), 50);
waveWindowMap.delete(this.waveWindowId);
if (focusedWaveWindow == this) {
focusedWaveWindow = null;
@ -309,6 +311,7 @@ export class WaveBrowserWindow extends BaseWindow {
}
});
waveWindowMap.set(waveWindow.oid, this);
setTimeout(() => globalEvents.emit("windows-updated"), 50);
}
private removeAllChildViews() {

View File

@ -3,6 +3,7 @@
import { RpcApi } from "@/app/store/wshclientapi";
import * as electron from "electron";
import { globalEvents } from "emain/emain-events";
import { FastAverageColor } from "fast-average-color";
import fs from "fs";
import * as child_process from "node:child_process";
@ -572,6 +573,17 @@ process.on("uncaughtException", (error) => {
electronApp.quit();
});
let lastWaveWindowCount = 0;
globalEvents.on("windows-updated", () => {
const wwCount = getAllWaveWindows().length;
if (wwCount == lastWaveWindowCount) {
return;
}
lastWaveWindowCount = wwCount;
console.log("windows-updated", wwCount);
makeAppMenu();
});
async function appMain() {
// Set disableHardwareAcceleration as early as possible, if required.
const launchSettings = getLaunchSettings();

View File

@ -10,6 +10,7 @@ import {
createNewWaveWindow,
createWorkspace,
focusedWaveWindow,
getAllWaveWindows,
getWaveWindowByWorkspaceId,
relaunchBrowserWindows,
WaveBrowserWindow,
@ -67,7 +68,11 @@ async function getWorkspaceMenu(ww?: WaveBrowserWindow): Promise<Electron.MenuIt
return workspaceMenu;
}
async function getAppMenu(callbacks: AppMenuCallbacks, workspaceId?: string): Promise<Electron.Menu> {
async function getAppMenu(
numWaveWindows: number,
callbacks: AppMenuCallbacks,
workspaceId?: string
): Promise<Electron.Menu> {
const ww = workspaceId && getWaveWindowByWorkspaceId(workspaceId);
const fileMenu: Electron.MenuItemConstructorOptions[] = [
{
@ -83,6 +88,22 @@ async function getAppMenu(callbacks: AppMenuCallbacks, workspaceId?: string): Pr
},
},
];
if (numWaveWindows == 0) {
fileMenu.push({
label: "New Window (hidden-1)",
accelerator: unamePlatform === "darwin" ? "Command+N" : "Alt+N",
acceleratorWorksWhenHidden: true,
visible: false,
click: () => fireAndForget(callbacks.createNewWaveWindow),
});
fileMenu.push({
label: "New Window (hidden-2)",
accelerator: unamePlatform === "darwin" ? "Command+T" : "Alt+T",
acceleratorWorksWhenHidden: true,
visible: false,
click: () => fireAndForget(callbacks.createNewWaveWindow),
});
}
const appMenu: Electron.MenuItemConstructorOptions[] = [
{
label: "About Wave Terminal",
@ -299,8 +320,9 @@ async function getAppMenu(callbacks: AppMenuCallbacks, workspaceId?: string): Pr
return electron.Menu.buildFromTemplate(menuTemplate);
}
export function instantiateAppMenu(workspaceId?: string): Promise<electron.Menu> {
export function instantiateAppMenu(numWindows: number, workspaceId?: string): Promise<electron.Menu> {
return getAppMenu(
numWindows,
{
createNewWaveWindow,
relaunchBrowserWindows,
@ -311,7 +333,8 @@ export function instantiateAppMenu(workspaceId?: string): Promise<electron.Menu>
export function makeAppMenu() {
fireAndForget(async () => {
const menu = await instantiateAppMenu();
const wwCount = getAllWaveWindows().length;
const menu = await instantiateAppMenu(wwCount);
electron.Menu.setApplicationMenu(menu);
});
}
@ -351,10 +374,11 @@ electron.ipcMain.on("contextmenu-show", (event, workspaceId: string, menuDefArr?
if (menuDefArr?.length === 0) {
return;
}
const wwCount = getAllWaveWindows().length;
fireAndForget(async () => {
const menu = menuDefArr
? convertMenuDefArrToMenu(workspaceId, menuDefArr)
: await instantiateAppMenu(workspaceId);
: await instantiateAppMenu(wwCount, workspaceId);
menu.popup();
});
event.returnValue = true;