fix: renderer plugin load timing

MAGIC OF JAVASCRIPT
This commit is contained in:
JellyBrick
2023-12-18 18:41:36 +09:00
parent ee98344064
commit da3bc5aeb7
3 changed files with 70 additions and 48 deletions

View File

@ -590,12 +590,12 @@ app.whenReady().then(async () => {
}
}
ipcMain.handle('load-renderer-plugins', async () => {
ipcMain.on('get-renderer-script', (event) => {
// Inject index.html file as string using insertAdjacentHTML
// In dev mode, get string from process.env.VITE_DEV_SERVER_URL, else use fs.readFileSync
if (is.dev() && process.env.ELECTRON_RENDERER_URL) {
// HACK: to make vite work with electron renderer (supports hot reload)
await mainWindow?.webContents.executeJavaScript(`
event.returnValue = [null, `
console.log('Loading vite from dev server');
const viteScript = document.createElement('script');
viteScript.type = 'module';
@ -606,7 +606,7 @@ app.whenReady().then(async () => {
document.body.appendChild(viteScript);
document.body.appendChild(rendererScript);
0
`);
`];
} else {
const rendererPath = path.join(__dirname, '..', 'renderer');
const indexHTML = parse(
@ -618,16 +618,7 @@ app.whenReady().then(async () => {
scriptSrc.getAttribute('src')!,
);
const scriptString = fs.readFileSync(scriptPath, 'utf-8');
await mainWindow?.webContents.executeJavaScriptInIsolatedWorld(
0,
[
{
code: scriptString + ';0',
url: url.pathToFileURL(scriptPath).toString(),
},
],
true,
);
event.returnValue = [url.pathToFileURL(scriptPath).toString(), scriptString + ';0'];
}
});

View File

@ -1,4 +1,4 @@
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
import { contextBridge, ipcRenderer, IpcRendererEvent, webFrame } from 'electron';
import is from 'electron-is';
import config from './config';
@ -54,4 +54,18 @@ contextBridge.exposeInMainWorld(
process.env.ELECTRON_RENDERER_URL,
);
ipcRenderer.invoke('load-renderer-plugins');
const [path, script] = ipcRenderer.sendSync('get-renderer-script') as [string | null, string];
let blocked = true;
if (path) {
webFrame.executeJavaScriptInIsolatedWorld(0, [
{
code: script,
url: path,
},
], true, () => blocked = false);
} else {
webFrame.executeJavaScript(script, true, () => blocked = false);
}
// HACK: Wait for the script to be executed
while (blocked);

View File

@ -21,37 +21,6 @@ let isPluginLoaded = false;
let isApiLoaded = false;
let firstDataLoaded = false;
const observer = new MutationObserver(() => {
const playerApi = document.querySelector<Element & YoutubePlayer>(
'#movie_player',
);
if (playerApi) {
observer.disconnect();
// Inject song-info provider
setupSongInfo(playerApi);
const dataLoadedListener = (name: string) => {
if (!firstDataLoaded && name === 'dataloaded') {
firstDataLoaded = true;
playerApi.removeEventListener('videodatachange', dataLoadedListener);
}
};
playerApi.addEventListener('videodatachange', dataLoadedListener);
if (isPluginLoaded && !isApiLoaded) {
api = playerApi;
isApiLoaded = true;
onApiLoaded();
}
}
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
async function listenForApiLoad() {
if (!isApiLoaded) {
api = document.querySelector('#movie_player');
@ -176,14 +145,16 @@ const defineYTMDTransElements = () => {
);
};
(async () => {
const preload = async () => {
await loadI18n();
await setLanguage(window.mainConfig.get('options.language') ?? 'en');
window.i18n = {
t: i18t.bind(i18next),
};
defineYTMDTransElements();
};
const main = async () => {
await loadAllRendererPlugins();
isPluginLoaded = true;
@ -226,4 +197,50 @@ const defineYTMDTransElements = () => {
console.log(JSON.parse(log));
});
}
})();
};
const initObserver = async () => {
// check document.documentElement is ready
await new Promise<void>((resolve) => {
document.addEventListener(
'DOMContentLoaded',
() => {
resolve();
},
{ once: true },
);
});
const observer = new MutationObserver(() => {
const playerApi = document.querySelector<Element & YoutubePlayer>(
'#movie_player',
);
if (playerApi) {
observer.disconnect();
// Inject song-info provider
setupSongInfo(playerApi);
const dataLoadedListener = (name: string) => {
if (!firstDataLoaded && name === 'dataloaded') {
firstDataLoaded = true;
playerApi.removeEventListener('videodatachange', dataLoadedListener);
}
};
playerApi.addEventListener('videodatachange', dataLoadedListener);
if (isPluginLoaded && !isApiLoaded) {
api = playerApi;
isApiLoaded = true;
onApiLoaded();
}
}
});
observer.observe(document.documentElement, {
childList: true,
subtree: true,
});
};
initObserver().then(preload).then(main);