mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
add webcontents id to helpview webview. (#969)
also allow contextmneu items to have sublabel, visible, and enabled
This commit is contained in:
parent
c8ecb3d034
commit
f05032bcd4
@ -51,7 +51,7 @@ function makeViewModel(blockId: string, blockView: string, nodeModel: NodeModel)
|
|||||||
return makeCpuPlotViewModel(blockId);
|
return makeCpuPlotViewModel(blockId);
|
||||||
}
|
}
|
||||||
if (blockView === "help") {
|
if (blockView === "help") {
|
||||||
return makeHelpViewModel();
|
return makeHelpViewModel(blockId);
|
||||||
}
|
}
|
||||||
return makeDefaultViewModel(blockId, blockView);
|
return makeDefaultViewModel(blockId, blockView);
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,16 @@ class ContextMenuModelType {
|
|||||||
role: item.role,
|
role: item.role,
|
||||||
type: item.type,
|
type: item.type,
|
||||||
label: item.label,
|
label: item.label,
|
||||||
|
sublabel: item.sublabel,
|
||||||
id: crypto.randomUUID(),
|
id: crypto.randomUUID(),
|
||||||
checked: item.checked,
|
checked: item.checked,
|
||||||
};
|
};
|
||||||
|
if (item.visible === false) {
|
||||||
|
electronItem.visible = false;
|
||||||
|
}
|
||||||
|
if (item.enabled === false) {
|
||||||
|
electronItem.enabled = false;
|
||||||
|
}
|
||||||
if (item.click) {
|
if (item.click) {
|
||||||
this.handlers.set(electronItem.id, item.click);
|
this.handlers.set(electronItem.id, item.click);
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,63 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
import { getApi } from "@/app/store/global";
|
import { getApi } from "@/app/store/global";
|
||||||
import { useState } from "react";
|
import { WebviewTag } from "electron";
|
||||||
|
import { createRef, useEffect, useState } from "react";
|
||||||
import "./helpview.less";
|
import "./helpview.less";
|
||||||
|
|
||||||
class HelpViewModel implements ViewModel {
|
class HelpViewModel implements ViewModel {
|
||||||
viewType: string;
|
viewType: string;
|
||||||
|
blockId: string;
|
||||||
|
webviewRef: React.RefObject<WebviewTag>;
|
||||||
|
|
||||||
constructor() {
|
constructor(blockId: string) {
|
||||||
this.viewType = "help";
|
this.viewType = "help";
|
||||||
|
this.blockId = blockId;
|
||||||
|
this.webviewRef = createRef<WebviewTag>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeHelpViewModel() {
|
function makeHelpViewModel(blockId: string) {
|
||||||
return new HelpViewModel();
|
return new HelpViewModel(blockId);
|
||||||
}
|
}
|
||||||
|
|
||||||
function HelpView({}: { model: HelpViewModel }) {
|
function HelpView({ model }: { model: HelpViewModel }) {
|
||||||
const [url] = useState(() => getApi().getDocsiteUrl());
|
const [url] = useState(() => getApi().getDocsiteUrl());
|
||||||
|
const [webContentsId, setWebContentsId] = useState(null);
|
||||||
|
const [domReady, setDomReady] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (model.webviewRef.current && domReady) {
|
||||||
|
const wcId = model.webviewRef.current.getWebContentsId?.();
|
||||||
|
if (wcId) {
|
||||||
|
setWebContentsId(wcId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [model.webviewRef.current, domReady]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const webview = model.webviewRef.current;
|
||||||
|
if (!webview) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const handleDomReady = () => {
|
||||||
|
setDomReady(true);
|
||||||
|
};
|
||||||
|
webview.addEventListener("dom-ready", handleDomReady);
|
||||||
|
return () => {
|
||||||
|
webview.removeEventListener("dom-ready", handleDomReady);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="help-view">
|
<div className="help-view">
|
||||||
<webview className="docsite-webview" src={url} />
|
<webview
|
||||||
|
ref={model.webviewRef}
|
||||||
|
data-blockid={model.blockId}
|
||||||
|
data-webcontentsid={webContentsId} // needed for emain
|
||||||
|
className="docsite-webview"
|
||||||
|
src={url}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -441,69 +441,69 @@ const WebView = memo(({ model }: WebViewProps) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const webview = model.webviewRef.current;
|
const webview = model.webviewRef.current;
|
||||||
|
if (!webview) {
|
||||||
if (webview) {
|
return;
|
||||||
const navigateListener = (e: any) => {
|
|
||||||
model.handleNavigate(e.url);
|
|
||||||
};
|
|
||||||
const newWindowHandler = (e: any) => {
|
|
||||||
e.preventDefault();
|
|
||||||
const newUrl = e.detail.url;
|
|
||||||
console.log("webview new-window event:", newUrl);
|
|
||||||
fireAndForget(() => openLink(newUrl, true));
|
|
||||||
};
|
|
||||||
const startLoadingHandler = () => {
|
|
||||||
model.setRefreshIcon("xmark-large");
|
|
||||||
model.setIsLoading(true);
|
|
||||||
webview.style.backgroundColor = "transparent";
|
|
||||||
};
|
|
||||||
const stopLoadingHandler = () => {
|
|
||||||
model.setRefreshIcon("rotate-right");
|
|
||||||
model.setIsLoading(false);
|
|
||||||
setBgColor();
|
|
||||||
};
|
|
||||||
const failLoadHandler = (e: any) => {
|
|
||||||
if (e.errorCode === -3) {
|
|
||||||
console.warn("Suppressed ERR_ABORTED error", e);
|
|
||||||
} else {
|
|
||||||
console.error(`Failed to load ${e.validatedURL}: ${e.errorDescription}`);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const webviewFocus = () => {
|
|
||||||
getApi().setWebviewFocus(webview.getWebContentsId());
|
|
||||||
model.nodeModel.focusNode();
|
|
||||||
};
|
|
||||||
const webviewBlur = () => {
|
|
||||||
getApi().setWebviewFocus(null);
|
|
||||||
};
|
|
||||||
const handleDomReady = () => {
|
|
||||||
setDomReady(true);
|
|
||||||
setBgColor();
|
|
||||||
};
|
|
||||||
|
|
||||||
webview.addEventListener("did-navigate-in-page", navigateListener);
|
|
||||||
webview.addEventListener("did-navigate", navigateListener);
|
|
||||||
webview.addEventListener("did-start-loading", startLoadingHandler);
|
|
||||||
webview.addEventListener("did-stop-loading", stopLoadingHandler);
|
|
||||||
webview.addEventListener("new-window", newWindowHandler);
|
|
||||||
webview.addEventListener("did-fail-load", failLoadHandler);
|
|
||||||
webview.addEventListener("focus", webviewFocus);
|
|
||||||
webview.addEventListener("blur", webviewBlur);
|
|
||||||
webview.addEventListener("dom-ready", handleDomReady);
|
|
||||||
|
|
||||||
// Clean up event listeners on component unmount
|
|
||||||
return () => {
|
|
||||||
webview.removeEventListener("did-navigate", navigateListener);
|
|
||||||
webview.removeEventListener("did-navigate-in-page", navigateListener);
|
|
||||||
webview.removeEventListener("new-window", newWindowHandler);
|
|
||||||
webview.removeEventListener("did-fail-load", failLoadHandler);
|
|
||||||
webview.removeEventListener("did-start-loading", startLoadingHandler);
|
|
||||||
webview.removeEventListener("did-stop-loading", stopLoadingHandler);
|
|
||||||
webview.removeEventListener("focus", webviewFocus);
|
|
||||||
webview.removeEventListener("blur", webviewBlur);
|
|
||||||
webview.removeEventListener("dom-ready", handleDomReady);
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
const navigateListener = (e: any) => {
|
||||||
|
model.handleNavigate(e.url);
|
||||||
|
};
|
||||||
|
const newWindowHandler = (e: any) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const newUrl = e.detail.url;
|
||||||
|
console.log("webview new-window event:", newUrl);
|
||||||
|
fireAndForget(() => openLink(newUrl, true));
|
||||||
|
};
|
||||||
|
const startLoadingHandler = () => {
|
||||||
|
model.setRefreshIcon("xmark-large");
|
||||||
|
model.setIsLoading(true);
|
||||||
|
webview.style.backgroundColor = "transparent";
|
||||||
|
};
|
||||||
|
const stopLoadingHandler = () => {
|
||||||
|
model.setRefreshIcon("rotate-right");
|
||||||
|
model.setIsLoading(false);
|
||||||
|
setBgColor();
|
||||||
|
};
|
||||||
|
const failLoadHandler = (e: any) => {
|
||||||
|
if (e.errorCode === -3) {
|
||||||
|
console.warn("Suppressed ERR_ABORTED error", e);
|
||||||
|
} else {
|
||||||
|
console.error(`Failed to load ${e.validatedURL}: ${e.errorDescription}`);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const webviewFocus = () => {
|
||||||
|
getApi().setWebviewFocus(webview.getWebContentsId());
|
||||||
|
model.nodeModel.focusNode();
|
||||||
|
};
|
||||||
|
const webviewBlur = () => {
|
||||||
|
getApi().setWebviewFocus(null);
|
||||||
|
};
|
||||||
|
const handleDomReady = () => {
|
||||||
|
setDomReady(true);
|
||||||
|
setBgColor();
|
||||||
|
};
|
||||||
|
|
||||||
|
webview.addEventListener("did-navigate-in-page", navigateListener);
|
||||||
|
webview.addEventListener("did-navigate", navigateListener);
|
||||||
|
webview.addEventListener("did-start-loading", startLoadingHandler);
|
||||||
|
webview.addEventListener("did-stop-loading", stopLoadingHandler);
|
||||||
|
webview.addEventListener("new-window", newWindowHandler);
|
||||||
|
webview.addEventListener("did-fail-load", failLoadHandler);
|
||||||
|
webview.addEventListener("focus", webviewFocus);
|
||||||
|
webview.addEventListener("blur", webviewBlur);
|
||||||
|
webview.addEventListener("dom-ready", handleDomReady);
|
||||||
|
|
||||||
|
// Clean up event listeners on component unmount
|
||||||
|
return () => {
|
||||||
|
webview.removeEventListener("did-navigate", navigateListener);
|
||||||
|
webview.removeEventListener("did-navigate-in-page", navigateListener);
|
||||||
|
webview.removeEventListener("new-window", newWindowHandler);
|
||||||
|
webview.removeEventListener("did-fail-load", failLoadHandler);
|
||||||
|
webview.removeEventListener("did-start-loading", startLoadingHandler);
|
||||||
|
webview.removeEventListener("did-stop-loading", stopLoadingHandler);
|
||||||
|
webview.removeEventListener("focus", webviewFocus);
|
||||||
|
webview.removeEventListener("blur", webviewBlur);
|
||||||
|
webview.removeEventListener("dom-ready", handleDomReady);
|
||||||
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
6
frontend/types/custom.d.ts
vendored
6
frontend/types/custom.d.ts
vendored
@ -86,6 +86,9 @@ declare global {
|
|||||||
type?: "separator" | "normal" | "submenu" | "checkbox" | "radio";
|
type?: "separator" | "normal" | "submenu" | "checkbox" | "radio";
|
||||||
submenu?: ElectronContextMenuItem[];
|
submenu?: ElectronContextMenuItem[];
|
||||||
checked?: boolean;
|
checked?: boolean;
|
||||||
|
visible?: boolean;
|
||||||
|
enabled?: boolean;
|
||||||
|
sublabel?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type ContextMenuItem = {
|
type ContextMenuItem = {
|
||||||
@ -95,6 +98,9 @@ declare global {
|
|||||||
click?: () => void; // not required if role is set
|
click?: () => void; // not required if role is set
|
||||||
submenu?: ContextMenuItem[];
|
submenu?: ContextMenuItem[];
|
||||||
checked?: boolean;
|
checked?: boolean;
|
||||||
|
visible?: boolean;
|
||||||
|
enabled?: boolean;
|
||||||
|
sublabel?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
type KeyPressDecl = {
|
type KeyPressDecl = {
|
||||||
|
Loading…
Reference in New Issue
Block a user