mirror of
https://github.com/getpaseo/paseo.git
synced 2026-07-29 12:01:31 +00:00
Fix desktop terminal link and context menu behavior
This commit is contained in:
@@ -565,6 +565,18 @@ export default function TerminalEmulator({
|
||||
const handleInsetTop = Math.max(0, (thumbRegionHeight - scrollbarGeometry.handleSize) / 2);
|
||||
const handleTravelDurationMs =
|
||||
isDraggingScrollbar || isScrollActive ? 0 : SCROLLBAR_HANDLE_TRAVEL_DURATION_MS;
|
||||
const handleContextMenu = () => {
|
||||
const showContextMenu = window.paseoDesktop?.menu?.showContextMenu;
|
||||
if (typeof showContextMenu !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
const hasSelection = Boolean(window.getSelection()?.toString());
|
||||
void showContextMenu({
|
||||
kind: "terminal",
|
||||
hasSelection,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -586,6 +598,10 @@ export default function TerminalEmulator({
|
||||
onPointerDown={() => {
|
||||
runtimeRef.current?.focus();
|
||||
}}
|
||||
onContextMenu={(event) => {
|
||||
event.preventDefault();
|
||||
handleContextMenu();
|
||||
}}
|
||||
>
|
||||
<div
|
||||
ref={hostRef}
|
||||
|
||||
@@ -37,6 +37,13 @@ export interface DesktopOpenerBridge {
|
||||
openUrl?: (url: string) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface DesktopMenuBridge {
|
||||
showContextMenu?: (input?: {
|
||||
kind?: "terminal";
|
||||
hasSelection?: boolean;
|
||||
}) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface DesktopWindowBridge {
|
||||
label?: string;
|
||||
startMove?: (screenX: number, screenY: number) => void;
|
||||
@@ -73,6 +80,7 @@ export interface DesktopHostBridge {
|
||||
dialog?: DesktopDialogBridge;
|
||||
notification?: DesktopNotificationBridge;
|
||||
opener?: DesktopOpenerBridge;
|
||||
menu?: DesktopMenuBridge;
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
@@ -8,6 +8,7 @@ import { WebLinksAddon } from "@xterm/addon-web-links";
|
||||
import { WebglAddon } from "@xterm/addon-webgl";
|
||||
import { Terminal, type ITheme } from "@xterm/xterm";
|
||||
import type { TerminalState } from "@server/shared/messages";
|
||||
import { openExternalUrl } from "@/utils/open-external-url";
|
||||
import {
|
||||
type PendingTerminalModifiers,
|
||||
isTerminalModifierDomKey,
|
||||
@@ -168,7 +169,12 @@ export class TerminalEmulatorRuntime {
|
||||
let webglAddon: WebglAddon | null = null;
|
||||
terminal.loadAddon(fitAddon);
|
||||
terminal.loadAddon(unicode11Addon);
|
||||
terminal.loadAddon(new WebLinksAddon());
|
||||
terminal.loadAddon(
|
||||
new WebLinksAddon((event, uri) => {
|
||||
event.preventDefault();
|
||||
void openExternalUrl(uri);
|
||||
}),
|
||||
);
|
||||
terminal.loadAddon(new SearchAddon({ highlightLimit: 20_000 }));
|
||||
terminal.loadAddon(new ClipboardAddon());
|
||||
try {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import { app, Menu, BrowserWindow } from "electron";
|
||||
import { app, Menu, BrowserWindow, ipcMain } from "electron";
|
||||
|
||||
type ShowContextMenuInput = {
|
||||
kind?: "terminal";
|
||||
hasSelection?: boolean;
|
||||
};
|
||||
|
||||
function withBrowserWindow(
|
||||
callback: (win: BrowserWindow) => void,
|
||||
@@ -89,4 +94,36 @@ export function setupApplicationMenu(): void {
|
||||
|
||||
const menu = Menu.buildFromTemplate(template);
|
||||
Menu.setApplicationMenu(menu);
|
||||
|
||||
ipcMain.handle("paseo:menu:showContextMenu", (event, input?: ShowContextMenuInput) => {
|
||||
const win = BrowserWindow.fromWebContents(event.sender);
|
||||
if (!win) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (input?.kind !== "terminal") {
|
||||
return;
|
||||
}
|
||||
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: "Copy",
|
||||
role: "copy",
|
||||
enabled: input.hasSelection === true,
|
||||
},
|
||||
{
|
||||
label: "Paste",
|
||||
role: "paste",
|
||||
},
|
||||
{
|
||||
type: "separator",
|
||||
},
|
||||
{
|
||||
label: "Select All",
|
||||
role: "selectAll",
|
||||
},
|
||||
]);
|
||||
|
||||
menu.popup({ window: win });
|
||||
});
|
||||
}
|
||||
|
||||
@@ -51,4 +51,8 @@ contextBridge.exposeInMainWorld("paseoDesktop", {
|
||||
opener: {
|
||||
openUrl: (url: string) => ipcRenderer.invoke("paseo:opener:openUrl", url),
|
||||
},
|
||||
menu: {
|
||||
showContextMenu: (input?: Record<string, unknown>) =>
|
||||
ipcRenderer.invoke("paseo:menu:showContextMenu", input),
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user