diff --git a/src/ZenPinnedTabManager.mjs b/src/ZenPinnedTabManager.mjs index c8f04c4..b07fd36 100644 --- a/src/ZenPinnedTabManager.mjs +++ b/src/ZenPinnedTabManager.mjs @@ -1,160 +1,180 @@ -class ZenPinnedTabsObserver { - static ALL_EVENTS = ['TabPinned', 'TabUnpinned']; +{ + const lazy = {}; - #listeners = []; + XPCOMUtils.defineLazyPreferenceGetter(lazy, 'zenPinnedTabRestorePinnedTabsToPinnedUrl', 'zen.pinned-tab-manager.restore-pinned-tabs-to-pinned-url', false); + XPCOMUtils.defineLazyPreferenceGetter(lazy, 'zenPinnedTabResetOnCloseShortcut', 'zen.pinned-tab-manager.reset-pinned-tab-on-close-shortcut', false); - constructor() { - this.#listenPinnedTabEvents(); - } + class ZenPinnedTabsObserver { + static ALL_EVENTS = ['TabPinned', 'TabUnpinned']; - #listenPinnedTabEvents() { - const eventListener = this.#eventListener.bind(this); - for (const event of ZenPinnedTabsObserver.ALL_EVENTS) { - window.addEventListener(event, eventListener); + #listeners = []; + + constructor() { + this.#listenPinnedTabEvents(); } - window.addEventListener('unload', () => { + + #listenPinnedTabEvents() { + const eventListener = this.#eventListener.bind(this); for (const event of ZenPinnedTabsObserver.ALL_EVENTS) { - window.removeEventListener(event, eventListener); + window.addEventListener(event, eventListener); } - }); - } - - #eventListener(event) { - for (const listener of this.#listeners) { - listener(event.type, event); - } - } - - addPinnedTabListener(listener) { - this.#listeners.push(listener); - } -} - -class ZenPinnedTabManager { - init() { - this.observer = new ZenPinnedTabsObserver(); - this._initClosePinnedTabShortcut(); - this.insertItemsIntoTabContextMenu(); - this.observer.addPinnedTabListener(this._onPinnedTabEvent.bind(this)); - } - - _onPinnedTabEvent(action, event) { - const tab = event.target; - switch (action) { - case "TabPinned": - this._setPinnedAttributes(tab); - break; - case "TabUnpinned": - this._removePinnedAttributes(tab); - break; - default: - console.warn('ZenPinnedTabManager: Unhandled tab event', action); - break; - } - } - - resetPinnedTab(tab) { - - if(!tab){ - tab = TabContextMenu.contextTab; - } - - if (!tab || !tab.pinned) { - return; - } - - const url = tab.getAttribute("zen-pinned-url"); - const title = tab.getAttribute("zen-pinned-title"); - const icon = tab.getAttribute("zen-pinned-icon"); - - if (url) { - const tabState = SessionStore.getTabState(tab); - const state = JSON.parse(tabState); - - state.entries = [{url, title}]; - state.image = icon; - state.index = 0; - - SessionStore.setTabState(tab, state); - } - } - - replacePinnedUrlWithCurrent(){ - const tab = TabContextMenu.contextTab; - if (!tab || !tab.pinned) { - return; - } - - this._setPinnedAttributes(tab); - } - - _setPinnedAttributes(tab) { - tab.setAttribute("zen-pinned-url", tab.linkedBrowser.currentURI.spec); - tab.setAttribute("zen-pinned-title", tab.getAttribute("label")); - tab.setAttribute("zen-pinned-icon", tab.linkedBrowser.mIconURL); - } - - _removePinnedAttributes(tab) { - tab.removeAttribute("zen-pinned-url"); - tab.removeAttribute("zen-pinned-title"); - tab.removeAttribute("zen-pinned-icon"); - } - - _initClosePinnedTabShortcut() { - let cmdClose = document.getElementById('cmd_close'); - - if (cmdClose) { - cmdClose.addEventListener('command', this._onCloseTabShortcut.bind(this)); - } - } - - _onCloseTabShortcut(event) { - if ( - event && - (event.ctrlKey || event.metaKey || event.altKey) && - gBrowser.selectedTab.pinned - ) { - const selectedTab = gBrowser.selectedTab; - const url = selectedTab.getAttribute("zen-pinned-url"); - const title = selectedTab.getAttribute("zen-pinned-title"); - const icon = selectedTab.getAttribute("zen-pinned-icon"); - - let nextTab = gBrowser.tabContainer.findNextTab(selectedTab, { - direction: 1, - filter: tab => !tab.hidden && !tab.pinned, + window.addEventListener('unload', () => { + for (const event of ZenPinnedTabsObserver.ALL_EVENTS) { + window.removeEventListener(event, eventListener); + } }); + } - if (!nextTab) { - nextTab = gBrowser.tabContainer.findNextTab(selectedTab, { - direction: -1, + #eventListener(event) { + for (const listener of this.#listeners) { + listener(event.type, event); + } + } + + addPinnedTabListener(listener) { + this.#listeners.push(listener); + } + } + + class ZenPinnedTabManager { + init() { + this.observer = new ZenPinnedTabsObserver(); + this._initClosePinnedTabShortcut(); + this._insertItemsIntoTabContextMenu(); + this.observer.addPinnedTabListener(this._onPinnedTabEvent.bind(this)); + } + + _onPinnedTabEvent(action, event) { + const tab = event.target; + switch (action) { + case "TabPinned": + this._setPinnedAttributes(tab); + break; + case "TabUnpinned": + this._removePinnedAttributes(tab); + break; + default: + console.warn('ZenPinnedTabManager: Unhandled tab event', action); + break; + } + } + + resetPinnedTab(tab) { + + if (!tab) { + tab = TabContextMenu.contextTab; + } + + if (!tab || !tab.pinned) { + return; + } + + this._resetTabToStoredState(tab); + } + + replacePinnedUrlWithCurrent() { + const tab = TabContextMenu.contextTab; + if (!tab || !tab.pinned) { + return; + } + + this._setPinnedAttributes(tab); + } + + _setPinnedAttributes(tab) { + tab.setAttribute("zen-pinned-url", tab.linkedBrowser.currentURI.spec); + tab.setAttribute("zen-pinned-title", tab.getAttribute("label")); + tab.setAttribute("zen-pinned-icon", tab.linkedBrowser.mIconURL); + } + + _removePinnedAttributes(tab) { + tab.removeAttribute("zen-pinned-url"); + tab.removeAttribute("zen-pinned-title"); + tab.removeAttribute("zen-pinned-icon"); + } + + _initClosePinnedTabShortcut() { + let cmdClose = document.getElementById('cmd_close'); + + if (cmdClose) { + cmdClose.addEventListener('command', this._onCloseTabShortcut.bind(this)); + } + } + + setPinnedTabState(tabData, tab) { + tabData.zenPinnedUrl = tab.getAttribute("zen-pinned-url"); + tabData.zenPinnedTitle = tab.getAttribute("zen-pinned-title"); + tabData.zenPinnedIcon = tab.getAttribute("zen-pinned-icon"); + } + + updatePinnedTabForSessionRestore(tabData, tab) { + if (tabData.zenPinnedUrl) { + tab.setAttribute("zen-pinned-url", tabData.zenPinnedUrl); + } + + if (tabData.zenPinnedTitle) { + tab.setAttribute("zen-pinned-title", tabData.zenPinnedTitle); + } + + if(tabData.zenPinnedIcon) { + tab.setAttribute("zen-pinned-icon", tabData.zenPinnedIcon); + } + } + + _onCloseTabShortcut(event) { + if ( + event && + (event.ctrlKey || event.metaKey || event.altKey) && + gBrowser.selectedTab.pinned + ) { + const selectedTab = gBrowser.selectedTab; + + let nextTab = gBrowser.tabContainer.findNextTab(selectedTab, { + direction: 1, filter: tab => !tab.hidden && !tab.pinned, }); - } - if (selectedTab) { - gBrowser.selectedTab = nextTab; - - if (url && Services.prefs.getBoolPref('zen.pinned-tab-manager.reset-pinned-tab-on-close-shortcut',false)) { - const tabState = SessionStore.getTabState(selectedTab); - const state = JSON.parse(tabState); - - state.entries = [{url, title}]; - state.image = icon; - state.index = 0; - - SessionStore.setTabState(selectedTab, state); + if (!nextTab) { + nextTab = gBrowser.tabContainer.findNextTab(selectedTab, { + direction: -1, + filter: tab => !tab.hidden && !tab.pinned, + }); } - gBrowser.discardBrowser(selectedTab); + if (selectedTab) { + gBrowser.selectedTab = nextTab; - event.stopPropagation(); - event.preventDefault(); + if (lazy.zenPinnedTabResetOnCloseShortcut) { + this._resetTabToStoredState(selectedTab); + } + + gBrowser.discardBrowser(selectedTab); + + event.stopPropagation(); + event.preventDefault(); + } } } - } - insertItemsIntoTabContextMenu() { - const elements = window.MozXULElement.parseXULToFragment(` + _resetTabToStoredState(tab) { + const url = tab.getAttribute("zen-pinned-url"); + const title = tab.getAttribute("zen-pinned-title"); + const icon = tab.getAttribute("zen-pinned-icon"); + + if (url) { + const tabState = SessionStore.getTabState(tab); + const state = JSON.parse(tabState); + + state.entries = [{url, title}]; + state.image = icon; + state.index = 0; + + SessionStore.setTabState(tab, state); + } + } + + _insertItemsIntoTabContextMenu() { + const elements = window.MozXULElement.parseXULToFragment(`