While developing my TypeScript code that is linked to the HTML being executed by my application, I encountered an issue with creating a new window for my settings. It seems that the preloaded script is loaded onto the new window upon opening, but the window fails to receive IPC messages from the main script.
Here is the snippet of the preloaded script:
const { contextBridge, ipcRenderer } = require("electron");
console.log("preloaded!");
contextBridge.exposeInMainWorld("api", {
send: (channel, data) => {
let validChannels = ["toMain", "select-dirs", "toSettings", "fromSettings"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
let validChannels = ["fromMain", "toSettings", "fromSettings"];
if (validChannels.includes(channel)) {
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
},
});
And here is the TypeScript file attached to the second window's HTML:
(<any>window).api.receive("toSettings", (data: any) => {
console.log(data);
})
var closeButton: HTMLButtonElement;
var settings = "";
var settignsDir = "";
document.onreadystatechange = () => {
if (document.readyState == "interactive") {
(<any>window).api.send("fromSettings", "ready")
closeButton = <HTMLButtonElement>document.getElementById("closeButton");
closeButton.addEventListener("click", () => {
(<any>window).api.send("toMain", "refresh");
self.close();
});
}
};
Although the same preloaded script works fine for my renderer and allows me to send IPC messages from the second window to the main process, it does not allow receiving messages on the second window. I suspect that I need to preload the file directly to the second window through the features array in window.open()
. Here is the code responsible for opening the settings window:
window.open(
"./html/settings.html",
"_blank",
"top=200,left=600,frame=false,nodeIntegration=no"
);
The Electron documentation suggests including a preload in the third-string parameter, but lacks examples which makes it difficult to implement. If anyone can provide guidance or example code, it would be greatly appreciated.
In response to Kdau's query:
Below is the requested code snippet:
(<any>window).api.receive("fromSettings", (data: any) => {
(<any>window).api.send("toSettings", "WHAT!");
})
I used this code to test if the settings or child window indeed receives the message. Please clarify what you meant by addressing the child window, as I assumed the preload script would handle routing messages appropriately.
Regarding the error returned in your provided code snippet, I am unsure how to resolve it:
"Argument of type '({ url }: HandlerDetails) => { frame: boolean; webPreferences: { nodeIntegration: boolean; preload: string; }; } | undefined' is not assignable to parameter of type '(details: HandlerDetails) => { action: "deny"; } | { action: "allow"; overrideBrowserWindowOptions?: BrowserWindowConstructorOptions | undefined; }'. Type '{ frame: boolean; webPreferences: { nodeIntegration: boolean; preload: string; }; } | undefined' is not assignable to type '{ action: "deny"; } | { action: "allow"; overrideBrowserWindowOptions?: BrowserWindowConstructorOptions | undefined; }'. Type 'undefined' is not assignable to type '{ action: "deny"; } | { action: "allow"; overrideBrowserWindowOptions?: BrowserWindowConstructorOptions | undefined; }'."
Your assistance in resolving this issue would be greatly appreciated.