aboutsummaryrefslogtreecommitdiff
path: root/modules/firefox.home/chrome/loadingIndicator.uc.js
diff options
context:
space:
mode:
Diffstat (limited to 'modules/firefox.home/chrome/loadingIndicator.uc.js')
-rw-r--r--modules/firefox.home/chrome/loadingIndicator.uc.js109
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;
+})()
+