mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
Replace logo with platform-dependent button to open app menu (#239)
Replace the logo in the tab bar with an ellipsis icon that shows on Linux and Windows and, when clicked, opens up the system menus. This also fixes an issue I noticed where the context menus were set to the wrong coordinates when a window was zoomed in. ![image](https://github.com/user-attachments/assets/1be77cad-73a6-4cb8-b545-08ec908f1d9a) ![image](https://github.com/user-attachments/assets/0beef938-15f8-4084-b7bd-7d9f995187ef)
This commit is contained in:
parent
18e2c7ed92
commit
03587184a0
@ -587,12 +587,16 @@ async function createNewWaveWindow() {
|
|||||||
|
|
||||||
electron.ipcMain.on("openNewWindow", () => fireAndForget(createNewWaveWindow));
|
electron.ipcMain.on("openNewWindow", () => fireAndForget(createNewWaveWindow));
|
||||||
|
|
||||||
electron.ipcMain.on("contextmenu-show", (event, menuDefArr: ElectronContextMenuItem[], { x, y }) => {
|
electron.ipcMain.on("contextmenu-show", (event, menuDefArr?: ElectronContextMenuItem[]) => {
|
||||||
if (menuDefArr == null || menuDefArr.length == 0) {
|
const window = electron.BrowserWindow.fromWebContents(event.sender);
|
||||||
|
if (menuDefArr?.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const menu = convertMenuDefArrToMenu(menuDefArr);
|
const menu = menuDefArr ? convertMenuDefArrToMenu(menuDefArr) : getAppMenu();
|
||||||
menu.popup({ x, y });
|
const { x, y } = electron.screen.getCursorScreenPoint();
|
||||||
|
const windowPos = window.getPosition();
|
||||||
|
|
||||||
|
menu.popup({ window, x: x - windowPos[0], y: y - windowPos[1] });
|
||||||
event.returnValue = true;
|
event.returnValue = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -640,7 +644,7 @@ function convertMenuDefArrToMenu(menuDefArr: ElectronContextMenuItem[]): electro
|
|||||||
return electron.Menu.buildFromTemplate(menuItems);
|
return electron.Menu.buildFromTemplate(menuItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeAppMenu() {
|
function getAppMenu() {
|
||||||
const fileMenu: Electron.MenuItemConstructorOptions[] = [
|
const fileMenu: Electron.MenuItemConstructorOptions[] = [
|
||||||
{
|
{
|
||||||
label: "New Window",
|
label: "New Window",
|
||||||
@ -668,19 +672,15 @@ function makeAppMenu() {
|
|||||||
{
|
{
|
||||||
type: "separator",
|
type: "separator",
|
||||||
},
|
},
|
||||||
|
];
|
||||||
|
if (unamePlatform === "darwin") {
|
||||||
|
appMenu.push(
|
||||||
{
|
{
|
||||||
role: "services",
|
role: "services",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "separator",
|
type: "separator",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
label: "Toggle Menu Bar Visibility",
|
|
||||||
visible: unamePlatform != "darwin",
|
|
||||||
click: (_, window) => {
|
|
||||||
window.autoHideMenuBar = !window.autoHideMenuBar;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
role: "hide",
|
role: "hide",
|
||||||
},
|
},
|
||||||
@ -689,11 +689,12 @@ function makeAppMenu() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "separator",
|
type: "separator",
|
||||||
},
|
}
|
||||||
{
|
);
|
||||||
|
}
|
||||||
|
appMenu.push({
|
||||||
role: "quit",
|
role: "quit",
|
||||||
},
|
});
|
||||||
];
|
|
||||||
const viewMenu: Electron.MenuItemConstructorOptions[] = [
|
const viewMenu: Electron.MenuItemConstructorOptions[] = [
|
||||||
{
|
{
|
||||||
role: "forceReload",
|
role: "forceReload",
|
||||||
@ -776,8 +777,11 @@ function makeAppMenu() {
|
|||||||
submenu: windowMenu,
|
submenu: windowMenu,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const menu = electron.Menu.buildFromTemplate(menuTemplate);
|
return electron.Menu.buildFromTemplate(menuTemplate);
|
||||||
electron.Menu.setApplicationMenu(menu);
|
}
|
||||||
|
|
||||||
|
function makeAppMenu() {
|
||||||
|
electron.Menu.setApplicationMenu(getAppMenu());
|
||||||
}
|
}
|
||||||
|
|
||||||
electronApp.on("window-all-closed", () => {
|
electronApp.on("window-all-closed", () => {
|
||||||
|
@ -28,32 +28,21 @@
|
|||||||
height: 33px;
|
height: 33px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dev-label {
|
.dev-label,
|
||||||
|
.app-menu-button {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
margin-top: 2px;
|
margin: 2px 2px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dev-label {
|
||||||
color: var(--accent-color);
|
color: var(--accent-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.prod-label {
|
|
||||||
font-size: 26px;
|
|
||||||
width: 1.25em;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
img {
|
|
||||||
height: 26px;
|
|
||||||
width: 26px;
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.add-tab-btn {
|
.add-tab-btn {
|
||||||
width: 22px;
|
width: 22px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -3,13 +3,12 @@
|
|||||||
|
|
||||||
import { WindowDrag } from "@/element/windowdrag";
|
import { WindowDrag } from "@/element/windowdrag";
|
||||||
import { deleteLayoutModelForTab } from "@/layout/index";
|
import { deleteLayoutModelForTab } from "@/layout/index";
|
||||||
import { atoms, getApi, isDev } from "@/store/global";
|
import { atoms, getApi, isDev, PLATFORM } from "@/store/global";
|
||||||
import * as services from "@/store/services";
|
import * as services from "@/store/services";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { OverlayScrollbars } from "overlayscrollbars";
|
import { OverlayScrollbars } from "overlayscrollbars";
|
||||||
import React, { createRef, useCallback, useEffect, useRef, useState } from "react";
|
import React, { createRef, useCallback, useEffect, useRef, useState } from "react";
|
||||||
import { debounce } from "throttle-debounce";
|
import { debounce } from "throttle-debounce";
|
||||||
import logoPng from "../../../public/logos/wave-logo.png";
|
|
||||||
import { Button } from "../element/button";
|
import { Button } from "../element/button";
|
||||||
import { Tab } from "./tab";
|
import { Tab } from "./tab";
|
||||||
import "./tabbar.less";
|
import "./tabbar.less";
|
||||||
@ -482,21 +481,22 @@ const TabBar = React.memo(({ workspace }: TabBarProps) => {
|
|||||||
return tabIds.indexOf(tabId) === tabIds.indexOf(activetabid) - 1;
|
return tabIds.indexOf(tabId) === tabIds.indexOf(activetabid) - 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function onEllipsisClick() {
|
||||||
|
getApi().showContextMenu();
|
||||||
|
}
|
||||||
|
|
||||||
const tabsWrapperWidth = tabIds.length * tabWidthRef.current;
|
const tabsWrapperWidth = tabIds.length * tabWidthRef.current;
|
||||||
let waveLabel: React.ReactNode = null;
|
const devLabel = isDev() ? (
|
||||||
if (isDev()) {
|
|
||||||
waveLabel = (
|
|
||||||
<div className="dev-label">
|
<div className="dev-label">
|
||||||
<i className="fa fa-brands fa-dev fa-fw" />
|
<i className="fa fa-brands fa-dev fa-fw" />
|
||||||
</div>
|
</div>
|
||||||
);
|
) : undefined;
|
||||||
} else {
|
const appMenuButton =
|
||||||
waveLabel = (
|
PLATFORM !== "darwin" ? (
|
||||||
<div className="prod-label">
|
<div className="app-menu-button" onClick={onEllipsisClick}>
|
||||||
<img src={logoPng} />
|
<i className="fa fa-ellipsis" />
|
||||||
</div>
|
</div>
|
||||||
);
|
) : undefined;
|
||||||
}
|
|
||||||
|
|
||||||
function onUpdateAvailableClick() {
|
function onUpdateAvailableClick() {
|
||||||
getApi().installAppUpdate();
|
getApi().installAppUpdate();
|
||||||
@ -519,7 +519,8 @@ const TabBar = React.memo(({ workspace }: TabBarProps) => {
|
|||||||
return (
|
return (
|
||||||
<div ref={tabbarWrapperRef} className="tab-bar-wrapper">
|
<div ref={tabbarWrapperRef} className="tab-bar-wrapper">
|
||||||
<WindowDrag ref={draggerLeftRef} className="left" />
|
<WindowDrag ref={draggerLeftRef} className="left" />
|
||||||
{waveLabel}
|
{appMenuButton}
|
||||||
|
{devLabel}
|
||||||
<div className="tab-bar" ref={tabBarRef} data-overlayscrollbars-initialize>
|
<div className="tab-bar" ref={tabBarRef} data-overlayscrollbars-initialize>
|
||||||
<div className="tabs-wrapper" ref={tabsWrapperRef} style={{ width: `${tabsWrapperWidth}px` }}>
|
<div className="tabs-wrapper" ref={tabsWrapperRef} style={{ width: `${tabsWrapperWidth}px` }}>
|
||||||
{tabIds.map((tabId, index) => {
|
{tabIds.map((tabId, index) => {
|
||||||
|
2
frontend/types/custom.d.ts
vendored
2
frontend/types/custom.d.ts
vendored
@ -58,7 +58,7 @@ declare global {
|
|||||||
getPlatform: () => NodeJS.Platform;
|
getPlatform: () => NodeJS.Platform;
|
||||||
getEnv: (varName: string) => string;
|
getEnv: (varName: string) => string;
|
||||||
|
|
||||||
showContextMenu: (menu: ElectronContextMenuItem[], position: { x: number; y: number }) => void;
|
showContextMenu: (menu?: ElectronContextMenuItem[]) => void;
|
||||||
onContextMenuClick: (callback: (id: string) => void) => void;
|
onContextMenuClick: (callback: (id: string) => void) => void;
|
||||||
onNavigate: (callback: (url: string) => void) => void;
|
onNavigate: (callback: (url: string) => void) => void;
|
||||||
onIframeNavigate: (callback: (url: string) => void) => void;
|
onIframeNavigate: (callback: (url: string) => void) => void;
|
||||||
|
Loading…
Reference in New Issue
Block a user