diff options
Diffstat (limited to '')
| -rw-r--r-- | modules/firefox.home/chrome/loadingIndicator.uc.js | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/modules/firefox.home/chrome/loadingIndicator.uc.js b/modules/firefox.home/chrome/loadingIndicator.uc.js new file mode 100644 index 0000000..61ba50b --- /dev/null +++ b/modules/firefox.home/chrome/loadingIndicator.uc.js @@ -0,0 +1,109 @@ +// ==UserScript== +// @name Loading indicator +// @version 1.0 +// @description Loading indicator for the url bar +// @startup UC.loadingIndicator.init(win) +// @shutdown UC.loadingIndicator.destroy() +// ==/UserScript== + +(() => { + const ENABLED = true; + + class TabProgressListener { + static instances = []; + + static createListener(tab, onStateChange) { + const oldListener = TabProgressListener.instances.find(l => l.tab === tab) + if (oldListener) return oldListener; + const listener = new TabProgressListener(tab, onStateChange); + TabProgressListener.instances.push(listener); + listener.attach(); + return listener; + } + + static cleanup() { + TabProgressListener.instances.forEach(l => l.cleanup()) + } + + loadedPercentage = 0; + constructor(tab, onStateChange) { + this.tab = tab; + this._stateChange = onStateChange; + } + + attach() { + const browser = this.tab.linkedBrowser; + browser.webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_ALL) + } + + cleanup() { + try { + const index = TabProgressListener.instances.indexOf(this); + if (index !== -1) + TabProgressListener.instances.splice(index, 1); + } finally { + this.tab.linkedBrowser.webProgress.removeProgressListener(this); + } + } + + // Start query listener methods + + QueryInterface = ChromeUtils.generateQI(['nsIWebProgressListener', 'nsISupportsWeakReference']) + + onStateChange(_webProgress, _request, stateFlags, _status) { + if (stateFlags & Ci.nsIWebProgressListener.STATE_START) { + this._stateChange?.('loading'); + } else if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) { + this._stateChange?.('loaded'); + } + } + } + + const module = { + onProgressStateUpdate: (win, state) => { + /** @type {HTMLElement} */ + const urlBar = win.gURLBar.textbox; + console.log(state, urlBar); + if (!urlBar) return; + + // urlBar.style.setProperty('--ff-urlbar-progress', perc); + urlBar.dataset.pageProgress = state; + }, + + setupTab: (tab, win) => { + const listener = TabProgressListener.createListener(tab, (state) => module.onProgressStateUpdate(win, state)); + + tab.addEventListener('TabClose', () => listener.cleanup()); + }, + + setupWindow: win => { + win.gBrowser.tabs.forEach(tab => module.setupTab(tab, win)); + win.gBrowser.tabContainer.addEventListener('TabOpen', event => { + module.setupTab(event.target, win); + }); + win.gBrowser.tabContainer.addEventListener('TabSelect', _event => { + const isLoading = gBrowser.selectedTab.linkedBrowser.webProgress.isLoadingDocument + module.onProgressStateUpdate(win, isLoading ? 'loading' : 'loaded'); + }); + }, + + init(win) { + if (!ENABLED) return; + + const handle = () => { + Services.obs.removeObserver(handle, 'browser-window-before-show'); + module.setupWindow(win); + } + + if (win.__SSi) handle(); + else Services.obs.addObserver(handle, 'browser-window-before-show'); + }, + + destroy() { + TabProgressListener.cleanup(); + }, + }; + + UC.loadingIndicator = module; +})() + |
