From ed2a3455552d5ed0fb42e3902ef24cbb1924660f Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 11 Jan 2024 20:49:13 -0500 Subject: [PATCH] Add support for opening web links in the default browser (#221) * Add support for opening web links in the default browser * require modifier key to click * undo emain change * remove newline --- package.json | 3 ++- src/electron/emain.ts | 8 ++++++++ src/electron/preload.js | 1 + src/model/model.ts | 11 +++++++++++ src/plugins/terminal/term.ts | 18 ++++++++++++++++++ yarn.lock | 5 +++++ 6 files changed, 45 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 66db33ea3..9779edc70 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,8 @@ "tsx-control-statements": "^4.1.1", "uuid": "^9.0.0", "winston": "^3.8.2", - "xterm": "^5.0.0" + "xterm": "^5.0.0", + "xterm-addon-web-links": "^0.9.0" }, "devDependencies": { "@babel/cli": "^7.17.10", diff --git a/src/electron/emain.ts b/src/electron/emain.ts index 4f4602fa6..70f0691c1 100644 --- a/src/electron/emain.ts +++ b/src/electron/emain.ts @@ -485,6 +485,14 @@ electron.ipcMain.on("reload-window", (event) => { return; }); +electron.ipcMain.on("open-external-link", async (_, url) => { + try { + await electron.shell.openExternal(url); + } catch (err) { + console.warn("error opening external link", err); + } +}); + electron.ipcMain.on("get-last-logs", async (event, numberOfLines) => { try { const logPath = path.join(getWaveHomeDir(), "wavesrv.log"); diff --git a/src/electron/preload.js b/src/electron/preload.js index 1abe03611..c58eafc11 100644 --- a/src/electron/preload.js +++ b/src/electron/preload.js @@ -12,6 +12,7 @@ contextBridge.exposeInMainWorld("api", { }, restartWaveSrv: () => ipcRenderer.sendSync("restart-server"), reloadWindow: () => ipcRenderer.sendSync("reload-window"), + openExternalLink: (url) => ipcRenderer.send("open-external-link", url), onTCmd: (callback) => ipcRenderer.on("t-cmd", callback), onICmd: (callback) => ipcRenderer.on("i-cmd", callback), onLCmd: (callback) => ipcRenderer.on("l-cmd", callback), diff --git a/src/model/model.ts b/src/model/model.ts index f7cc0d56b..29b6487e4 100644 --- a/src/model/model.ts +++ b/src/model/model.ts @@ -196,6 +196,7 @@ type ElectronApi = { getWaveSrvStatus: () => boolean; restartWaveSrv: () => boolean; reloadWindow: () => void; + openExternalLink: (url: string) => void; onTCmd: (callback: (mods: KeyModsType) => void) => void; onICmd: (callback: (mods: KeyModsType) => void) => void; onLCmd: (callback: (mods: KeyModsType) => void) => void; @@ -3424,6 +3425,16 @@ class Model { getApi().reloadWindow(); } + /** + * Opens a new default browser window to the given url + * @param {string} url The url to open + */ + openExternalLink(url: string): void { + console.log("opening external link: " + url); + getApi().openExternalLink(url); + console.log("finished opening external link"); + } + refocus() { // givefocus() give back focus to cmd or input let activeScreen = this.getActiveScreen(); diff --git a/src/plugins/terminal/term.ts b/src/plugins/terminal/term.ts index 446fb24f0..8c9d4ca88 100644 --- a/src/plugins/terminal/term.ts +++ b/src/plugins/terminal/term.ts @@ -3,10 +3,13 @@ import * as mobx from "mobx"; import { Terminal } from "xterm"; +//TODO: replace with `@xterm/addon-web-links` when it's available as stable +import { WebLinksAddon } from "xterm-addon-web-links"; import { sprintf } from "sprintf-js"; import { boundMethod } from "autobind-decorator"; import { windowWidthToCols, windowHeightToRows } from "../../util/textmeasure"; import { boundInt } from "../../util/util"; +import { GlobalModel } from "../../model/model" import type { TermContextUnion, TermOptsType, @@ -96,6 +99,21 @@ class TermWrap { fontFamily: "JetBrains Mono", theme: { foreground: terminal.foreground, background: terminal.background }, }); + this.terminal.loadAddon(new WebLinksAddon((e, uri) => { + e.preventDefault(); + switch (GlobalModel.platform) { + case "darwin": + if (e.metaKey) { + GlobalModel.openExternalLink(uri); + } + break; + default: + if (e.ctrlKey) { + GlobalModel.openExternalLink(uri); + } + break; + } + })); this.terminal._core._inputHandler._parser.setErrorHandler((state) => { this.numParseErrors++; return state; diff --git a/yarn.lock b/yarn.lock index 7c077f71b..0e033fd54 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8466,6 +8466,11 @@ xmlbuilder@^15.1.1: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5" integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg== +xterm-addon-web-links@^0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.9.0.tgz#c65b18588d1f613e703eb6feb7f129e7ff1c63e7" + integrity sha512-LIzi4jBbPlrKMZF3ihoyqayWyTXAwGfu4yprz1aK2p71e9UKXN6RRzVONR0L+Zd+Ik5tPVI9bwp9e8fDTQh49Q== + xterm@^5.0.0: version "5.3.0" resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0.tgz#867daf9cc826f3d45b5377320aabd996cb0fce46"