default url, default search, open in external browser (#794)

This commit is contained in:
Mike Sawka 2024-09-20 11:24:37 -07:00 committed by GitHub
parent 78f838439a
commit 047513bf3a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 61 additions and 11 deletions

View File

@ -1,8 +1,10 @@
// Copyright 2024, Command Line Inc. // Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { getApi, openLink } from "@/app/store/global"; import { getApi, openLink, useSettingsKeyAtom } from "@/app/store/global";
import { getSimpleControlShiftAtom } from "@/app/store/keymodel"; import { getSimpleControlShiftAtom } from "@/app/store/keymodel";
import { RpcApi } from "@/app/store/wshclientapi";
import { WindowRpcClient } from "@/app/store/wshrpcutil";
import { NodeModel } from "@/layout/index"; import { NodeModel } from "@/layout/index";
import { WOS, globalStore } from "@/store/global"; import { WOS, globalStore } from "@/store/global";
import * as services from "@/store/services"; import * as services from "@/store/services";
@ -30,6 +32,7 @@ export class WebViewModel implements ViewModel {
webviewRef: React.RefObject<WebviewTag>; webviewRef: React.RefObject<WebviewTag>;
urlInputRef: React.RefObject<HTMLInputElement>; urlInputRef: React.RefObject<HTMLInputElement>;
nodeModel: NodeModel; nodeModel: NodeModel;
endIconButtons?: jotai.Atom<IconButtonDecl[]>;
constructor(blockId: string, nodeModel: NodeModel) { constructor(blockId: string, nodeModel: NodeModel) {
this.nodeModel = nodeModel; this.nodeModel = nodeModel;
@ -48,7 +51,8 @@ export class WebViewModel implements ViewModel {
this.webviewRef = React.createRef<WebviewTag>(); this.webviewRef = React.createRef<WebviewTag>();
this.viewText = jotai.atom((get) => { this.viewText = jotai.atom((get) => {
let url = get(this.blockAtom)?.meta?.url || ""; const defaultUrlAtom = useSettingsKeyAtom("web:defaulturl");
let url = get(this.blockAtom)?.meta?.url || get(defaultUrlAtom);
const currUrl = get(this.url); const currUrl = get(this.url);
if (currUrl !== undefined) { if (currUrl !== undefined) {
url = currUrl; url = currUrl;
@ -91,6 +95,22 @@ export class WebViewModel implements ViewModel {
}, },
] as HeaderElem[]; ] as HeaderElem[];
}); });
this.endIconButtons = jotai.atom((get) => {
return [
{
elemtype: "iconbutton",
icon: "arrow-up-right-from-square",
title: "Open in External Browser",
click: () => {
const url = this.getUrl();
if (url != null && url != "") {
return getApi().openExternal(this.getUrl());
}
},
},
];
});
} }
/** /**
@ -199,7 +219,11 @@ export class WebViewModel implements ViewModel {
globalStore.set(this.url, url); globalStore.set(this.url, url);
} }
ensureUrlScheme(url: string) { ensureUrlScheme(url: string, searchTemplate: string) {
if (url == null) {
url = "";
}
if (/^(http|https):/.test(url)) { if (/^(http|https):/.test(url)) {
// If the URL starts with http: or https:, return it as is // If the URL starts with http: or https:, return it as is
return url; return url;
@ -223,8 +247,11 @@ export class WebViewModel implements ViewModel {
} }
// Otherwise, treat it as a search query // Otherwise, treat it as a search query
if (searchTemplate == null) {
return `https://www.google.com/search?q=${encodeURIComponent(url)}`; return `https://www.google.com/search?q=${encodeURIComponent(url)}`;
} }
return searchTemplate.replace("{query}", encodeURIComponent(url));
}
normalizeUrl(url: string) { normalizeUrl(url: string) {
if (!url) { if (!url) {
@ -247,7 +274,9 @@ export class WebViewModel implements ViewModel {
* @param newUrl The new URL to load in the webview. * @param newUrl The new URL to load in the webview.
*/ */
loadUrl(newUrl: string, reason: string) { loadUrl(newUrl: string, reason: string) {
const nextUrl = this.ensureUrlScheme(newUrl); const defaultSearchAtom = useSettingsKeyAtom("web:defaultsearch");
const searchTemplate = globalStore.get(defaultSearchAtom);
const nextUrl = this.ensureUrlScheme(newUrl, searchTemplate);
console.log("webview loadUrl", reason, nextUrl, "cur=", this.webviewRef?.current.getURL()); console.log("webview loadUrl", reason, nextUrl, "cur=", this.webviewRef?.current.getURL());
if (newUrl != nextUrl) { if (newUrl != nextUrl) {
globalStore.set(this.url, nextUrl); globalStore.set(this.url, nextUrl);
@ -317,8 +346,20 @@ export class WebViewModel implements ViewModel {
return false; return false;
} }
getSettingsMenuItems() { getSettingsMenuItems(): ContextMenuItem[] {
return [ return [
{
label: "Set Homepage",
click: async () => {
const url = this.getUrl();
if (url != null && url != "") {
RpcApi.SetConfigCommand(WindowRpcClient, { "web:defaulturl": url });
}
},
},
{
type: "separator",
},
{ {
label: this.webviewRef.current?.isDevToolsOpened() ? "Close DevTools" : "Open DevTools", label: this.webviewRef.current?.isDevToolsOpened() ? "Close DevTools" : "Open DevTools",
click: async () => { click: async () => {
@ -347,7 +388,9 @@ interface WebViewProps {
const WebView = memo(({ model }: WebViewProps) => { const WebView = memo(({ model }: WebViewProps) => {
const blockData = jotai.useAtomValue(model.blockAtom); const blockData = jotai.useAtomValue(model.blockAtom);
const metaUrl = blockData?.meta?.url; const defaultUrlAtom = useSettingsKeyAtom("web:defaulturl");
const defaultUrl = jotai.useAtomValue(defaultUrlAtom);
const metaUrl = blockData?.meta?.url || defaultUrl;
const metaUrlRef = React.useRef(metaUrl); const metaUrlRef = React.useRef(metaUrl);
// The initial value of the block metadata URL when the component first renders. Used to set the starting src value for the webview. // The initial value of the block metadata URL when the component first renders. Used to set the starting src value for the webview.

View File

@ -421,6 +421,8 @@ declare global {
"editor:stickyscrollenabled"?: boolean; "editor:stickyscrollenabled"?: boolean;
"web:*"?: boolean; "web:*"?: boolean;
"web:openlinksinternally"?: boolean; "web:openlinksinternally"?: boolean;
"web:defaulturl"?: string;
"web:defaultsearch"?: string;
"blockheader:*"?: boolean; "blockheader:*"?: boolean;
"blockheader:showblockids"?: boolean; "blockheader:showblockids"?: boolean;
"autoupdate:*"?: boolean; "autoupdate:*"?: boolean;

View File

@ -27,8 +27,7 @@
"label": "web", "label": "web",
"blockdef": { "blockdef": {
"meta": { "meta": {
"view": "web", "view": "web"
"url": "https://waveterm.dev/"
} }
} }
}, },

View File

@ -6,6 +6,8 @@
"autoupdate:installonquit": true, "autoupdate:installonquit": true,
"autoupdate:intervalms": 3600000, "autoupdate:intervalms": 3600000,
"editor:minimapenabled": true, "editor:minimapenabled": true,
"web:defaulturl": "https://github.com/wavetermdev/waveterm",
"web:defaultsearch": "https://www.google.com/search?q={query}",
"window:tilegapsize": 3, "window:tilegapsize": 3,
"telemetry:enabled": true "telemetry:enabled": true
} }

View File

@ -24,6 +24,8 @@ const (
ConfigKey_WebClear = "web:*" ConfigKey_WebClear = "web:*"
ConfigKey_WebOpenLinksInternally = "web:openlinksinternally" ConfigKey_WebOpenLinksInternally = "web:openlinksinternally"
ConfigKey_WebDefaultUrl = "web:defaulturl"
ConfigKey_WebDefaultSearch = "web:defaultsearch"
ConfigKey_BlockHeaderClear = "blockheader:*" ConfigKey_BlockHeaderClear = "blockheader:*"
ConfigKey_BlockHeaderShowBlockIds = "blockheader:showblockids" ConfigKey_BlockHeaderShowBlockIds = "blockheader:showblockids"

View File

@ -56,6 +56,8 @@ type SettingsType struct {
WebClear bool `json:"web:*,omitempty"` WebClear bool `json:"web:*,omitempty"`
WebOpenLinksInternally bool `json:"web:openlinksinternally,omitempty"` WebOpenLinksInternally bool `json:"web:openlinksinternally,omitempty"`
WebDefaultUrl string `json:"web:defaulturl,omitempty"`
WebDefaultSearch string `json:"web:defaultsearch,omitempty"`
BlockHeaderClear bool `json:"blockheader:*,omitempty"` BlockHeaderClear bool `json:"blockheader:*,omitempty"`
BlockHeaderShowBlockIds bool `json:"blockheader:showblockids,omitempty"` BlockHeaderShowBlockIds bool `json:"blockheader:showblockids,omitempty"`