webview preload

This commit is contained in:
sawka 2024-10-04 15:43:25 -07:00
parent a73ca23229
commit a513072ff6
7 changed files with 75 additions and 0 deletions

View File

@ -38,6 +38,7 @@ export default defineConfig({
rollupOptions: {
input: {
index: "emain/preload.ts",
"preload-webview": "emain/preload-webview.ts",
},
output: {
format: "cjs",

View File

@ -582,6 +582,41 @@ electron.ipcMain.on("open-external", (event, url) => {
}
});
function getUrlInSession(session: Electron.Session, url: string): Readable {
const request = electron.net.request({
url,
method: "GET",
session,
});
const readable = new Readable({
read() {}, // No-op, we'll push data manually
});
request.on("response", (response) => {
response.on("data", (chunk) => {
readable.push(chunk);
});
response.on("end", () => {
readable.push(null);
});
});
request.on("error", (err) => {
console.error("Request error:", err);
readable.destroy(err);
});
request.end();
return readable;
}
electron.ipcMain.on("save-image", (event: electron.IpcMainEvent, payload: { src: string }) => {
console.log("save-image", payload.src);
const wc = event.sender;
if (wc == null) {
return;
}
getUrlInSession(wc.session, payload.src);
});
electron.ipcMain.on("download", (event, payload) => {
const window = electron.BrowserWindow.fromWebContents(event.sender);
const streamingUrl = getWebServerEndpoint() + "/wave/stream-file?path=" + encodeURIComponent(payload.filePath);

View File

@ -36,6 +36,9 @@ ipcMain.on("get-user-name", (event) => {
ipcMain.on("get-host-name", (event) => {
event.returnValue = os.hostname();
});
ipcMain.on("get-webview-preload", (event) => {
event.returnValue = path.join(getElectronAppBasePath(), "preload", "preload-webview.cjs");
});
// must match golang
function getWaveHomeDir() {

20
emain/preload-webview.ts Normal file
View File

@ -0,0 +1,20 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
const { ipcRenderer } = require("electron");
document.addEventListener("contextmenu", (event) => {
console.log("contextmenu event", event);
if (event.target == null) {
return;
}
const targetElement = event.target as HTMLElement;
// Check if the right-click is on an image
if (targetElement.tagName === "IMG") {
const imgElem = targetElement as HTMLImageElement;
const imageUrl = imgElem.src;
ipcRenderer.send("save-image", { src: imageUrl });
}
});
console.log("loaded wave preload-webview.ts");

View File

@ -12,6 +12,7 @@ contextBridge.exposeInMainWorld("api", {
getHostName: () => ipcRenderer.sendSync("get-host-name"),
getAboutModalDetails: () => ipcRenderer.sendSync("get-about-modal-details"),
getDocsiteUrl: () => ipcRenderer.sendSync("get-docsite-url"),
getWebviewPreload: () => ipcRenderer.sendSync("get-webview-preload"),
openNewWindow: () => ipcRenderer.send("open-new-window"),
showContextMenu: (menu, position) => ipcRenderer.send("contextmenu-show", menu, position),
onContextMenuClick: (callback) => ipcRenderer.on("contextmenu-click", (_event, id) => callback(id)),

View File

@ -16,6 +16,19 @@ import * as jotai from "jotai";
import React, { memo, useEffect, useState } from "react";
import "./webview.less";
let webviewPreloadUrl = null;
function getWebviewPreloadUrl() {
if (webviewPreloadUrl == null) {
webviewPreloadUrl = getApi().getWebviewPreload();
console.log("webviewPreloadUrl", webviewPreloadUrl);
}
if (webviewPreloadUrl == null) {
return null;
}
return "file://" + webviewPreloadUrl;
}
export class WebViewModel implements ViewModel {
viewType: string;
blockId: string;
@ -501,6 +514,7 @@ const WebView = memo(({ model }: WebViewProps) => {
src={metaUrlInitial}
data-blockid={model.blockId}
data-webcontentsid={webContentsId} // needed for emain
preload={getWebviewPreloadUrl()}
// @ts-ignore This is a discrepancy between the React typing and the Chromium impl for webviewTag. Chrome webviewTag expects a string, while React expects a boolean.
allowpopups="true"
></webview>

View File

@ -57,6 +57,7 @@ declare global {
getEnv: (varName: string) => string;
getUserName: () => string;
getHostName: () => string;
getWebviewPreload: () => string;
getAboutModalDetails: () => AboutModalDetails;
getDocsiteUrl: () => string;
showContextMenu: (menu?: ElectronContextMenuItem[]) => void;