Skip to content

Commit da3bc5a

Browse files
committed
fix: renderer plugin load timing
MAGIC OF JAVASCRIPT
1 parent ee98344 commit da3bc5a

File tree

3 files changed

+70
-48
lines changed

3 files changed

+70
-48
lines changed

src/index.ts

+4-13
Original file line numberDiff line numberDiff line change
@@ -590,12 +590,12 @@ app.whenReady().then(async () => {
590590
}
591591
}
592592

593-
ipcMain.handle('load-renderer-plugins', async () => {
593+
ipcMain.on('get-renderer-script', (event) => {
594594
// Inject index.html file as string using insertAdjacentHTML
595595
// In dev mode, get string from process.env.VITE_DEV_SERVER_URL, else use fs.readFileSync
596596
if (is.dev() && process.env.ELECTRON_RENDERER_URL) {
597597
// HACK: to make vite work with electron renderer (supports hot reload)
598-
await mainWindow?.webContents.executeJavaScript(`
598+
event.returnValue = [null, `
599599
console.log('Loading vite from dev server');
600600
const viteScript = document.createElement('script');
601601
viteScript.type = 'module';
@@ -606,7 +606,7 @@ app.whenReady().then(async () => {
606606
document.body.appendChild(viteScript);
607607
document.body.appendChild(rendererScript);
608608
0
609-
`);
609+
`];
610610
} else {
611611
const rendererPath = path.join(__dirname, '..', 'renderer');
612612
const indexHTML = parse(
@@ -618,16 +618,7 @@ app.whenReady().then(async () => {
618618
scriptSrc.getAttribute('src')!,
619619
);
620620
const scriptString = fs.readFileSync(scriptPath, 'utf-8');
621-
await mainWindow?.webContents.executeJavaScriptInIsolatedWorld(
622-
0,
623-
[
624-
{
625-
code: scriptString + ';0',
626-
url: url.pathToFileURL(scriptPath).toString(),
627-
},
628-
],
629-
true,
630-
);
621+
event.returnValue = [url.pathToFileURL(scriptPath).toString(), scriptString + ';0'];
631622
}
632623
});
633624

src/preload.ts

+16-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
1+
import { contextBridge, ipcRenderer, IpcRendererEvent, webFrame } from 'electron';
22
import is from 'electron-is';
33

44
import config from './config';
@@ -54,4 +54,18 @@ contextBridge.exposeInMainWorld(
5454
process.env.ELECTRON_RENDERER_URL,
5555
);
5656

57-
ipcRenderer.invoke('load-renderer-plugins');
57+
const [path, script] = ipcRenderer.sendSync('get-renderer-script') as [string | null, string];
58+
let blocked = true;
59+
if (path) {
60+
webFrame.executeJavaScriptInIsolatedWorld(0, [
61+
{
62+
code: script,
63+
url: path,
64+
},
65+
], true, () => blocked = false);
66+
} else {
67+
webFrame.executeJavaScript(script, true, () => blocked = false);
68+
}
69+
70+
// HACK: Wait for the script to be executed
71+
while (blocked);

src/renderer.ts

+50-33
Original file line numberDiff line numberDiff line change
@@ -21,37 +21,6 @@ let isPluginLoaded = false;
2121
let isApiLoaded = false;
2222
let firstDataLoaded = false;
2323

24-
const observer = new MutationObserver(() => {
25-
const playerApi = document.querySelector<Element & YoutubePlayer>(
26-
'#movie_player',
27-
);
28-
if (playerApi) {
29-
observer.disconnect();
30-
31-
// Inject song-info provider
32-
setupSongInfo(playerApi);
33-
const dataLoadedListener = (name: string) => {
34-
if (!firstDataLoaded && name === 'dataloaded') {
35-
firstDataLoaded = true;
36-
playerApi.removeEventListener('videodatachange', dataLoadedListener);
37-
}
38-
};
39-
playerApi.addEventListener('videodatachange', dataLoadedListener);
40-
41-
if (isPluginLoaded && !isApiLoaded) {
42-
api = playerApi;
43-
isApiLoaded = true;
44-
45-
onApiLoaded();
46-
}
47-
}
48-
});
49-
50-
observer.observe(document.documentElement, {
51-
childList: true,
52-
subtree: true,
53-
});
54-
5524
async function listenForApiLoad() {
5625
if (!isApiLoaded) {
5726
api = document.querySelector('#movie_player');
@@ -176,14 +145,16 @@ const defineYTMDTransElements = () => {
176145
);
177146
};
178147

179-
(async () => {
148+
const preload = async () => {
180149
await loadI18n();
181150
await setLanguage(window.mainConfig.get('options.language') ?? 'en');
182151
window.i18n = {
183152
t: i18t.bind(i18next),
184153
};
185154
defineYTMDTransElements();
155+
};
186156

157+
const main = async () => {
187158
await loadAllRendererPlugins();
188159
isPluginLoaded = true;
189160

@@ -226,4 +197,50 @@ const defineYTMDTransElements = () => {
226197
console.log(JSON.parse(log));
227198
});
228199
}
229-
})();
200+
};
201+
202+
const initObserver = async () => {
203+
// check document.documentElement is ready
204+
await new Promise<void>((resolve) => {
205+
document.addEventListener(
206+
'DOMContentLoaded',
207+
() => {
208+
resolve();
209+
},
210+
{ once: true },
211+
);
212+
});
213+
214+
const observer = new MutationObserver(() => {
215+
const playerApi = document.querySelector<Element & YoutubePlayer>(
216+
'#movie_player',
217+
);
218+
if (playerApi) {
219+
observer.disconnect();
220+
221+
// Inject song-info provider
222+
setupSongInfo(playerApi);
223+
const dataLoadedListener = (name: string) => {
224+
if (!firstDataLoaded && name === 'dataloaded') {
225+
firstDataLoaded = true;
226+
playerApi.removeEventListener('videodatachange', dataLoadedListener);
227+
}
228+
};
229+
playerApi.addEventListener('videodatachange', dataLoadedListener);
230+
231+
if (isPluginLoaded && !isApiLoaded) {
232+
api = playerApi;
233+
isApiLoaded = true;
234+
235+
onApiLoaded();
236+
}
237+
}
238+
});
239+
240+
observer.observe(document.documentElement, {
241+
childList: true,
242+
subtree: true,
243+
});
244+
};
245+
246+
initObserver().then(preload).then(main);

0 commit comments

Comments
 (0)