From 2dfdf6616992e9716491c23675db3de75c72c9af Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 14 Nov 2024 11:03:10 -0800 Subject: [PATCH] Opening HelpView pages in external browser uses the public docsite equivalent (#1289) Before, when you clicked the "Open in External Browser" button from the `HelpView`, the browser would attempt to open the embedded url, which may or may not still exist, depending on whether the content was cached from the last time the app was opened (since the embedded docsite uses a random port). Now, we'll swap the embedded url for the public docsite equivalent when you open in an external browser. --- frontend/app/view/helpview/helpview.tsx | 20 +++++++++++++++++--- frontend/app/view/webview/webview.tsx | 4 +++- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/frontend/app/view/helpview/helpview.tsx b/frontend/app/view/helpview/helpview.tsx index f843c6ca9..942ff304a 100644 --- a/frontend/app/view/helpview/helpview.tsx +++ b/frontend/app/view/helpview/helpview.tsx @@ -9,13 +9,16 @@ import { atom, useAtomValue } from "jotai"; import { useCallback } from "react"; import "./helpview.less"; +const docsiteWebUrl = "https://docs.waveterm.dev/"; +const baseUrlRegex = /http[s]?:\/\/([^:\/])+(:\d+)?/; + class HelpViewModel extends WebViewModel { constructor(blockId: string, nodeModel: BlockNodeModel) { super(blockId, nodeModel); this.getSettingsMenuItems = undefined; this.viewText = atom((get) => { // force a dependency on meta.url so we re-render the buttons when the url changes - let url = get(this.blockAtom)?.meta?.url || get(this.homepageUrl); + get(this.blockAtom)?.meta?.url || get(this.homepageUrl); return [ { elemtype: "iconbutton", @@ -41,6 +44,19 @@ class HelpViewModel extends WebViewModel { this.viewType = "help"; this.viewIcon = atom("circle-question"); this.viewName = atom("Help"); + + /* + Add callback to take the current embedded docsite url and return the equivalent page in the public docsite. + The port used by the embedded docsite changes every time the app runs and the current page may be cached from a previous run so we can't trust that it matches the current embedded url. + We have a regex at the top of this file that can extract the base part of the url (i.e. http://127.0.0.1:53288). We'll use this regex to strip the base part of the url from both the current + page and the embedded docsite url. Because we host the embedded docsite at a subdirectory, we also need to strip that (hence the second replace). Then, we can build the public url from whatever's left. + */ + this.modifyExternalUrl = (url: string) => { + const strippedDocsiteUrl = getApi().getDocsiteUrl().replace(baseUrlRegex, ""); + const strippedCurUrl = url.replace(baseUrlRegex, "").replace(strippedDocsiteUrl, ""); + const newUrl = docsiteWebUrl + strippedCurUrl; + return newUrl; + }; } } @@ -48,8 +64,6 @@ function makeHelpViewModel(blockId: string, nodeModel: BlockNodeModel) { return new HelpViewModel(blockId, nodeModel); } -const baseUrlRegex = /http[s]?:\/\/([^:\/])+(:\d+)?/; - function HelpView({ model }: { model: HelpViewModel }) { const homepageUrl = useAtomValue(model.homepageUrl); diff --git a/frontend/app/view/webview/webview.tsx b/frontend/app/view/webview/webview.tsx index 42fa739e5..7a351c9c8 100644 --- a/frontend/app/view/webview/webview.tsx +++ b/frontend/app/view/webview/webview.tsx @@ -48,6 +48,7 @@ export class WebViewModel implements ViewModel { endIconButtons?: Atom; mediaPlaying: PrimitiveAtom; mediaMuted: PrimitiveAtom; + modifyExternalUrl?: (url: string) => string; constructor(blockId: string, nodeModel: BlockNodeModel) { this.nodeModel = nodeModel; @@ -142,7 +143,8 @@ export class WebViewModel implements ViewModel { title: "Open in External Browser", click: () => { if (url != null && url != "") { - return getApi().openExternal(url); + const externalUrl = this.modifyExternalUrl?.(url) ?? url; + return getApi().openExternal(externalUrl); } }, },