webview fixes (#83)

This commit is contained in:
Red J Adaya 2024-06-28 09:09:30 +08:00 committed by GitHub
parent f1c8d63ab2
commit 4d4e026749
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 70 additions and 18 deletions

View File

@ -281,6 +281,12 @@ function createBrowserWindow(clientId: string, waveWindow: WaveWindow): WaveBrow
}); });
win.webContents.on("will-navigate", shNavHandler); win.webContents.on("will-navigate", shNavHandler);
win.webContents.on("will-frame-navigate", shFrameNavHandler); win.webContents.on("will-frame-navigate", shFrameNavHandler);
win.webContents.on("did-attach-webview", (event, wc) => {
wc.setWindowOpenHandler((details) => {
win.webContents.send("webview-new-window", wc.id, details);
return { action: "deny" };
});
});
win.on( win.on(
"resize", "resize",
debounce(400, (e) => mainResizeHandler(e, waveWindow.oid, win)) debounce(400, (e) => mainResizeHandler(e, waveWindow.oid, win))
@ -418,10 +424,21 @@ electron.ipcMain.on("isDevServer", (event) => {
event.returnValue = isDevServer; event.returnValue = isDevServer;
}); });
electron.ipcMain.on("getPlatform", (event) => { electron.ipcMain.on("getPlatform", (event, url) => {
event.returnValue = unamePlatform; event.returnValue = unamePlatform;
}); });
// Listen for the open-external event from the renderer process
electron.ipcMain.on("open-external", (event, url) => {
if (url && typeof url === "string") {
electron.shell.openExternal(url).catch((err) => {
console.error(`Failed to open URL ${url}:`, err);
});
} else {
console.error("Invalid URL received in open-external event:", url);
}
});
electron.ipcMain.on("download", (event, payload) => { electron.ipcMain.on("download", (event, payload) => {
const window = electron.BrowserWindow.fromWebContents(event.sender); const window = electron.BrowserWindow.fromWebContents(event.sender);
const baseName = payload.filePath.split(/[\\/]/).pop(); const baseName = payload.filePath.split(/[\\/]/).pop();
@ -535,7 +552,6 @@ async function appMain() {
} }
const ready = await waveSrvReady; const ready = await waveSrvReady;
console.log("wavesrv ready signal received", ready, Date.now() - startTs, "ms"); console.log("wavesrv ready signal received", ready, Date.now() - startTs, "ms");
console.log("get client data"); console.log("get client data");
let clientData = await services.ClientService.GetClientData(); let clientData = await services.ClientService.GetClientData();
console.log("client data ready"); console.log("client data ready");

View File

@ -12,4 +12,17 @@ contextBridge.exposeInMainWorld("api", {
showContextMenu: (menu, position) => ipcRenderer.send("contextmenu-show", menu, position), showContextMenu: (menu, position) => ipcRenderer.send("contextmenu-show", menu, position),
onContextMenuClick: (callback) => ipcRenderer.on("contextmenu-click", callback), onContextMenuClick: (callback) => ipcRenderer.on("contextmenu-click", callback),
downloadFile: (filePath) => ipcRenderer.send("download", { filePath }), downloadFile: (filePath) => ipcRenderer.send("download", { filePath }),
openExternal: (url) => {
if (url && typeof url === "string") {
ipcRenderer.send("open-external", url);
} else {
console.error("Invalid URL passed to openExternal:", url);
}
},
});
// Custom event for "new-window"
ipcRenderer.on("webview-new-window", (e, webContentsId, details) => {
const event = new CustomEvent("new-window", { detail: details });
document.getElementById("webview").dispatchEvent(event);
}); });

View File

@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
import { Button } from "@/app/element/button"; import { Button } from "@/app/element/button";
import { getApi } from "@/app/store/global";
import { WebviewTag } from "electron"; import { WebviewTag } from "electron";
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
@ -23,10 +24,15 @@ const WebView = ({ parentRef, initialUrl }: WebViewProps) => {
const historyStack = useRef<string[]>([]); const historyStack = useRef<string[]>([]);
const historyIndex = useRef<number>(-1); const historyIndex = useRef<number>(-1);
useEffect(() => { const getWebViewHeight = () => {
const inputHeight = inputRef.current?.getBoundingClientRect().height + 25; const inputHeight = inputRef.current?.getBoundingClientRect().height;
const parentHeight = parentRef.current?.getBoundingClientRect().height; const parentHeight = parentRef.current?.getBoundingClientRect().height;
setWebViewHeight(parentHeight - inputHeight); return parentHeight - (inputHeight + 35);
};
useEffect(() => {
const webviewHeight = getWebViewHeight();
setWebViewHeight(webviewHeight);
historyStack.current.push(initialUrl); historyStack.current.push(initialUrl);
historyIndex.current = 0; historyIndex.current = 0;
@ -57,8 +63,8 @@ const WebView = ({ parentRef, initialUrl }: WebViewProps) => {
// Handle new-window event // Handle new-window event
webview.addEventListener("new-window", (event: any) => { webview.addEventListener("new-window", (event: any) => {
event.preventDefault(); event.preventDefault();
const newUrl = event.url; const newUrl = event.detail.url;
webview.src = newUrl; getApi().openExternal(newUrl);
}); });
// Suppress errors // Suppress errors
@ -100,21 +106,31 @@ const WebView = ({ parentRef, initialUrl }: WebViewProps) => {
}; };
const handleResize = () => { const handleResize = () => {
const parentHeight = parentRef.current?.getBoundingClientRect().height; const webviewHeight = getWebViewHeight();
setWebViewHeight(parentHeight); setWebViewHeight(webviewHeight);
}; };
const parentElement = parentRef.current; const parentElement = parentRef.current;
if (parentElement) { if (parentElement) {
parentElement.addEventListener("keydown", handleKeyDown); parentElement.addEventListener("keydown", handleKeyDown);
} }
window.addEventListener("resize", handleResize);
// Use ResizeObserver to observe changes in the height of parentRef
const resizeObserver = new ResizeObserver((entries) => {
for (let entry of entries) {
if (entry.target === parentElement) {
handleResize();
}
}
});
resizeObserver.observe(parentElement);
return () => { return () => {
if (parentElement) { if (parentElement) {
parentElement.removeEventListener("keydown", handleKeyDown); parentElement.removeEventListener("keydown", handleKeyDown);
} }
window.removeEventListener("resize", handleResize); resizeObserver.disconnect();
}; };
}, []); }, []);
@ -221,7 +237,13 @@ const WebView = ({ parentRef, initialUrl }: WebViewProps) => {
/> />
</div> </div>
</div> </div>
<webview className="webview" ref={webviewRef} src={url} style={{ height: webViewHeight }}></webview> <webview
id="webview"
className="webview"
ref={webviewRef}
src={url}
style={{ height: webViewHeight }}
></webview>
</div> </div>
); );
}; };

View File

@ -37,6 +37,7 @@ declare global {
onNavigate: (callback: (url: string) => void) => void; onNavigate: (callback: (url: string) => void) => void;
onIframeNavigate: (callback: (url: string) => void) => void; onIframeNavigate: (callback: (url: string) => void) => void;
downloadFile: (path: string) => void; downloadFile: (path: string) => void;
openExternal: (url: string) => void;
}; };
type ElectronContextMenuItem = { type ElectronContextMenuItem = {

View File

@ -63,7 +63,7 @@
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"dayjs": "^1.11.11", "dayjs": "^1.11.11",
"electron": "^30.1.0", "electron": "^31.1.0",
"html-to-image": "^1.11.11", "html-to-image": "^1.11.11",
"immer": "^10.1.1", "immer": "^10.1.1",
"jotai": "^2.8.0", "jotai": "^2.8.0",

View File

@ -6499,16 +6499,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"electron@npm:^30.1.0": "electron@npm:^31.1.0":
version: 30.1.0 version: 31.1.0
resolution: "electron@npm:30.1.0" resolution: "electron@npm:31.1.0"
dependencies: dependencies:
"@electron/get": "npm:^2.0.0" "@electron/get": "npm:^2.0.0"
"@types/node": "npm:^20.9.0" "@types/node": "npm:^20.9.0"
extract-zip: "npm:^2.0.1" extract-zip: "npm:^2.0.1"
bin: bin:
electron: cli.js electron: cli.js
checksum: 10c0/e17c5fdf275f8cd457086adfa05db7507d08dd9264024d80eae8e55eb01927d062b63223a1a15b3ac024ebe2c34cc4b3ceb5cc0ac3ded4721c4ac9be4e5fe33c checksum: 10c0/b9ae6f9d1a13e15cf0b7981f1231dc2c79f3465c4db822750daf6f2533524fe2ddf6f0b173c8d0c3549ef6bf21a9ff3eb362838b06deb4f795e71d5e5a307f16
languageName: node languageName: node
linkType: hard linkType: hard
@ -12336,7 +12336,7 @@ __metadata:
base64-js: "npm:^1.5.1" base64-js: "npm:^1.5.1"
clsx: "npm:^2.1.1" clsx: "npm:^2.1.1"
dayjs: "npm:^1.11.11" dayjs: "npm:^1.11.11"
electron: "npm:^30.1.0" electron: "npm:^31.1.0"
electron-vite: "npm:^2.2.0" electron-vite: "npm:^2.2.0"
eslint: "npm:^9.2.0" eslint: "npm:^9.2.0"
eslint-config-prettier: "npm:^9.1.0" eslint-config-prettier: "npm:^9.1.0"