Pop-up dictionary browser extension for language learning. Successor to Yomichan. (PERSONAL FORK)

Application main updates (#708)

* Move waitForBackendReady

* Add option to wait for DOM before running main

* Move script load to be earlier

authored by

toasted-nutbread and committed by
GitHub
65fa65fc cfc65c31

+61 -70
+1 -3
ext/action-popup.html
··· 12 12 <link rel="icon" type="image/png" href="/images/icon64.png" sizes="64x64"> 13 13 <link rel="icon" type="image/png" href="/images/icon128.png" sizes="128x128"> 14 14 <link rel="stylesheet" type="text/css" href="/css/action-popup.css"> 15 + <script src="/js/pages/action-popup-main.js" type="module"></script> 15 16 </head> 16 17 <body> 17 18 ··· 80 81 <span class="link-group-icon" data-icon="chevron"></span><span class="link-group-label">Information</span> 81 82 </a> 82 83 </div> 83 - 84 - <!-- Scripts --> 85 - <script src="/js/pages/action-popup-main.js" type="module"></script> 86 84 87 85 </body> 88 86 </html>
+1 -3
ext/background.html
··· 12 12 <link rel="icon" type="image/png" href="/images/icon64.png" sizes="64x64"> 13 13 <link rel="icon" type="image/png" href="/images/icon128.png" sizes="128x128"> 14 14 <link rel="stylesheet" type="text/css" href="/css/background.css"> 15 + <script src="/js/background/background-main.js" type="module"></script> 15 16 </head> 16 17 <body> 17 18 18 19 <textarea id="clipboard-paste-target"></textarea> 19 - 20 - <!-- Scripts --> 21 - <script src="/js/background/background-main.js" type="module"></script> 22 20 23 21 <!-- 24 22 Due to a Firefox bug, this next element is purposefully terminated incorrectly.
+1 -3
ext/info.html
··· 13 13 <link rel="icon" type="image/png" href="/images/icon128.png" sizes="128x128"> 14 14 <link rel="stylesheet" type="text/css" href="/css/material.css"> 15 15 <link rel="stylesheet" type="text/css" href="/css/settings.css"> 16 + <script src="/js/pages/info-main.js" type="module"></script> 16 17 </head> 17 18 <body> 18 19 ··· 58 59 </div> 59 60 <div class="content-right"></div> 60 61 </div></div> 61 - 62 - <!-- Scripts --> 63 - <script src="/js/pages/info-main.js" type="module"></script> 64 62 65 63 </body> 66 64 </html>
+1 -3
ext/issues.html
··· 13 13 <link rel="icon" type="image/png" href="/images/icon128.png" sizes="128x128"> 14 14 <link rel="stylesheet" type="text/css" href="/css/material.css"> 15 15 <link rel="stylesheet" type="text/css" href="/css/settings.css"> 16 + <script src="/js/pages/generic-page-main.js" type="module"></script> 16 17 </head> 17 18 <body> 18 19 ··· 74 75 </div> 75 76 <div class="content-right"></div> 76 77 </div></div> 77 - 78 - <!-- Scripts --> 79 - <script src="/js/pages/generic-page-main.js" type="module"></script> 80 78 81 79 </body> 82 80 </html>
+1 -1
ext/js/app/content-script-main.js
··· 21 21 import {Frontend} from './frontend.js'; 22 22 import {PopupFactory} from './popup-factory.js'; 23 23 24 - await Application.main(async (application) => { 24 + await Application.main(false, async (application) => { 25 25 const hotkeyHandler = new HotkeyHandler(); 26 26 hotkeyHandler.prepare(application.crossFrame); 27 27
+39 -20
ext/js/application.js
··· 52 52 } 53 53 54 54 /** 55 + * @param {WebExtension} webExtension 56 + */ 57 + async function waitForBackendReady(webExtension) { 58 + const {promise, resolve} = /** @type {import('core').DeferredPromiseDetails<void>} */ (deferPromise()); 59 + /** @type {import('application').ApiMap} */ 60 + const apiMap = createApiMap([['applicationBackendReady', () => { resolve(); }]]); 61 + /** @type {import('extension').ChromeRuntimeOnMessageCallback<import('application').ApiMessageAny>} */ 62 + const onMessage = ({action, params}, _sender, callback) => invokeApiMapHandler(apiMap, action, params, [], callback); 63 + chrome.runtime.onMessage.addListener(onMessage); 64 + try { 65 + await webExtension.sendMessagePromise({action: 'requestBackendReadySignal'}); 66 + await promise; 67 + } finally { 68 + chrome.runtime.onMessage.removeListener(onMessage); 69 + } 70 + } 71 + 72 + /** 73 + * @returns {Promise<void>} 74 + */ 75 + function waitForDomContentLoaded() { 76 + return new Promise((resolve) => { 77 + if (document.readyState !== 'loading') { 78 + resolve(); 79 + return; 80 + } 81 + const onDomContentLoaded = () => { 82 + document.removeEventListener('DOMContentLoaded', onDomContentLoaded); 83 + resolve(); 84 + }; 85 + document.addEventListener('DOMContentLoaded', onDomContentLoaded); 86 + }); 87 + } 88 + 89 + /** 55 90 * The Yomitan class is a core component through which various APIs are handled and invoked. 56 91 * @augments EventDispatcher<import('application').Events> 57 92 */ ··· 151 186 } 152 187 153 188 /** 189 + * @param {boolean} waitForDom 154 190 * @param {(application: Application) => (Promise<void>)} mainFunction 155 191 */ 156 - static async main(mainFunction) { 192 + static async main(waitForDom, mainFunction) { 157 193 const webExtension = new WebExtension(); 158 194 log.configure(webExtension.extensionName); 159 195 const api = new API(webExtension); 160 - await this.waitForBackendReady(webExtension); 196 + await waitForBackendReady(webExtension); 161 197 const {tabId, frameId} = await api.frameInformationGet(); 162 198 const crossFrameApi = new CrossFrameAPI(api, tabId, frameId); 163 199 crossFrameApi.prepare(); 164 200 const application = new Application(api, crossFrameApi); 165 201 application.prepare(); 202 + if (waitForDom) { await waitForDomContentLoaded(); } 166 203 try { 167 204 await mainFunction(application); 168 205 } catch (error) { 169 206 log.error(error); 170 207 } finally { 171 208 application.ready(); 172 - } 173 - } 174 - 175 - /** 176 - * @param {WebExtension} webExtension 177 - */ 178 - static async waitForBackendReady(webExtension) { 179 - const {promise, resolve} = /** @type {import('core').DeferredPromiseDetails<void>} */ (deferPromise()); 180 - /** @type {import('application').ApiMap} */ 181 - const apiMap = createApiMap([['applicationBackendReady', () => { resolve(); }]]); 182 - /** @type {import('extension').ChromeRuntimeOnMessageCallback<import('application').ApiMessageAny>} */ 183 - const onMessage = ({action, params}, _sender, callback) => invokeApiMapHandler(apiMap, action, params, [], callback); 184 - chrome.runtime.onMessage.addListener(onMessage); 185 - try { 186 - await webExtension.sendMessagePromise({action: 'requestBackendReadySignal'}); 187 - await promise; 188 - } finally { 189 - chrome.runtime.onMessage.removeListener(onMessage); 190 209 } 191 210 } 192 211
+1 -1
ext/js/display/popup-main.js
··· 25 25 import {DisplayResizer} from './display-resizer.js'; 26 26 import {Display} from './display.js'; 27 27 28 - await Application.main(async (application) => { 28 + await Application.main(true, async (application) => { 29 29 const documentFocusController = new DocumentFocusController(); 30 30 documentFocusController.prepare(); 31 31
+1 -1
ext/js/display/search-main.js
··· 26 26 import {SearchDisplayController} from './search-display-controller.js'; 27 27 import {SearchPersistentStateController} from './search-persistent-state-controller.js'; 28 28 29 - await Application.main(async (application) => { 29 + await Application.main(true, async (application) => { 30 30 const documentFocusController = new DocumentFocusController('#search-textbox'); 31 31 documentFocusController.prepare(); 32 32
+1 -1
ext/js/pages/action-popup-main.js
··· 306 306 } 307 307 } 308 308 309 - await Application.main(async (application) => { 309 + await Application.main(true, async (application) => { 310 310 application.api.logIndicatorClear(); 311 311 312 312 const displayController = new DisplayController(application.api);
+1 -1
ext/js/pages/info-main.js
··· 115 115 container.appendChild(fragment); 116 116 } 117 117 118 - await Application.main(async (application) => { 118 + await Application.main(true, async (application) => { 119 119 const documentFocusController = new DocumentFocusController(); 120 120 documentFocusController.prepare(); 121 121
+1 -1
ext/js/pages/permissions-main.js
··· 86 86 } 87 87 } 88 88 89 - await Application.main(async (application) => { 89 + await Application.main(true, async (application) => { 90 90 const documentFocusController = new DocumentFocusController(); 91 91 documentFocusController.prepare(); 92 92
+1 -1
ext/js/pages/settings/popup-preview-frame-main.js
··· 21 21 import {HotkeyHandler} from '../../input/hotkey-handler.js'; 22 22 import {PopupPreviewFrame} from './popup-preview-frame.js'; 23 23 24 - await Application.main(async (application) => { 24 + await Application.main(true, async (application) => { 25 25 const hotkeyHandler = new HotkeyHandler(); 26 26 hotkeyHandler.prepare(application.crossFrame); 27 27
+1 -1
ext/js/pages/settings/settings-main.js
··· 58 58 await genericSettingController.refresh(); 59 59 } 60 60 61 - await Application.main(async (application) => { 61 + await Application.main(true, async (application) => { 62 62 const documentFocusController = new DocumentFocusController(); 63 63 documentFocusController.prepare(); 64 64
+1 -1
ext/js/pages/welcome-main.js
··· 49 49 await genericSettingController.refresh(); 50 50 } 51 51 52 - await Application.main(async (application) => { 52 + await Application.main(true, async (application) => { 53 53 const documentFocusController = new DocumentFocusController(); 54 54 documentFocusController.prepare(); 55 55
+1 -3
ext/legal.html
··· 14 14 <link rel="icon" type="image/png" href="/images/icon128.png" sizes="128x128"> 15 15 <link rel="stylesheet" type="text/css" href="/css/material.css"> 16 16 <link rel="stylesheet" type="text/css" href="/css/settings.css"> 17 + <script src="/js/pages/generic-page-main.js" type="module"></script> 17 18 </head> 18 19 19 20 <body> ··· 89 90 <div class="content-right"></div> 90 91 </div> 91 92 </div> 92 - 93 - <!-- Scripts --> 94 - <script src="/js/pages/generic-page-main.js" type="module"></script> 95 93 96 94 </body> 97 95
+1 -3
ext/offscreen.html
··· 12 12 <link rel="icon" type="image/png" href="/images/icon64.png" sizes="64x64"> 13 13 <link rel="icon" type="image/png" href="/images/icon128.png" sizes="128x128"> 14 14 <link rel="stylesheet" type="text/css" href="/css/background.css"> 15 + <script src="/js/background/offscreen-main.js" type="module"></script> 15 16 </head> 16 17 <body> 17 18 18 19 <textarea id="clipboard-paste-target"></textarea> 19 - 20 - <!-- Scripts --> 21 - <script src="/js/background/offscreen-main.js" type="module"></script> 22 20 23 21 <!-- 24 22 Due to a Firefox bug, this next element is purposefully terminated incorrectly.
+1 -4
ext/permissions.html
··· 14 14 <link rel="stylesheet" type="text/css" href="/css/material.css"> 15 15 <link rel="stylesheet" type="text/css" href="/css/settings.css"> 16 16 <link rel="stylesheet" type="text/css" href="/css/permissions.css"> 17 + <script src="/js/pages/permissions-main.js" type="module"></script> 17 18 </head> 18 19 <body> 19 20 ··· 226 227 <button type="button" class="low-emphasis" data-modal-action="hide">Close</button> 227 228 </div> 228 229 </div></div> 229 - 230 - 231 - <!-- Scripts --> 232 - <script src="/js/pages/permissions-main.js" type="module"></script> 233 230 234 231 </body> 235 232 </html>
+1 -3
ext/popup-preview.html
··· 13 13 <link rel="icon" type="image/png" href="/images/icon128.png" sizes="128x128"> 14 14 <link rel="stylesheet" type="text/css" href="/css/popup-preview.css"> 15 15 <link rel="stylesheet" type="text/css" href="/css/popup-outer.css" id="popup-outer-css"> 16 + <script src="/js/pages/settings/popup-preview-frame-main.js" type="module"></script> 16 17 </head> 17 18 <body> 18 19 ··· 33 34 If you see this message, make sure you have a dictionary installed. 34 35 </div></div> 35 36 </div></div> 36 - 37 - <!-- Scripts --> 38 - <script src="/js/pages/settings/popup-preview-frame-main.js" type="module"></script> 39 37 40 38 </body> 41 39 </html>
+1 -3
ext/popup.html
··· 15 15 <link rel="stylesheet" type="text/css" href="/css/display.css"> 16 16 <link rel="stylesheet" type="text/css" href="/css/display-pronunciation.css"> 17 17 <link rel="stylesheet" type="text/css" href="/css/structured-content.css"> 18 + <script src="/js/display/popup-main.js" type="module"></script> 18 19 </head> 19 20 <body> 20 21 ··· 91 92 </div> 92 93 93 94 <div id="popup-menus"></div> 94 - 95 - <!-- Scripts --> 96 - <script src="/js/display/popup-main.js" type="module"></script> 97 95 98 96 </body> 99 97 </html>
+1 -3
ext/search.html
··· 16 16 <link rel="stylesheet" type="text/css" href="/css/display-pronunciation.css"> 17 17 <link rel="stylesheet" type="text/css" href="/css/structured-content.css"> 18 18 <link rel="stylesheet" type="text/css" href="/css/search.css"> 19 + <script src="/js/display/search-main.js" type="module"></script> 19 20 </head> 20 21 <body> 21 22 ··· 81 82 </div> 82 83 83 84 <div id="popup-menus"></div> 84 - 85 - <!-- Scripts --> 86 - <script src="/js/display/search-main.js" type="module"></script> 87 85 88 86 </body> 89 87 </html>
+1 -4
ext/settings.html
··· 14 14 <link rel="stylesheet" type="text/css" href="/css/material.css"> 15 15 <link rel="stylesheet" type="text/css" href="/css/settings.css"> 16 16 <link rel="stylesheet" type="text/css" href="/css/display-pronunciation.css"> 17 + <script src="/js/pages/settings/settings-main.js" type="module"></script> 17 18 </head> 18 19 <body> 19 20 ··· 3430 3431 <button type="button" class="danger" id="hotkey-list-reset" data-modal-action="hide">Reset All</button> 3431 3432 </div> 3432 3433 </div></div> 3433 - 3434 - 3435 - <!-- Scripts --> 3436 - <script src="/js/pages/settings/settings-main.js" type="module"></script> 3437 3434 3438 3435 </body> 3439 3436 </html>
+1 -3
ext/template-renderer.html
··· 11 11 <link rel="icon" type="image/png" href="/images/icon48.png" sizes="48x48"> 12 12 <link rel="icon" type="image/png" href="/images/icon64.png" sizes="64x64"> 13 13 <link rel="icon" type="image/png" href="/images/icon128.png" sizes="128x128"> 14 + <script src="/js/templates/sandbox/template-renderer-frame-main.js" type="module"></script> 14 15 </head> 15 16 <body> 16 - 17 - <!-- Scripts --> 18 - <script src="/js/templates/sandbox/template-renderer-frame-main.js" type="module"></script> 19 17 20 18 </body> 21 19 </html>
+1 -3
ext/welcome.html
··· 13 13 <link rel="icon" type="image/png" href="/images/icon128.png" sizes="128x128"> 14 14 <link rel="stylesheet" type="text/css" href="/css/material.css"> 15 15 <link rel="stylesheet" type="text/css" href="/css/settings.css"> 16 + <script src="/js/pages/welcome-main.js" type="module"></script> 16 17 </head> 17 18 <body> 18 19 ··· 424 425 <button type="button" data-modal-action="hide" id="dictionary-move-button">Move</button> 425 426 </div> 426 427 </div></div> 427 - 428 - <!-- Scripts --> 429 - <script src="/js/pages/welcome-main.js" type="module"></script> 430 428 431 429 </body> 432 430 </html>