diff --git a/browser/components/tabbrowser/content/tabgroup.js b/browser/components/tabbrowser/content/tabgroup.js index caea196b22b4689f55780a528661d87b52f4e728..725a2dfb10216df3e63d7980e2f1c99bf10038d7 100644 --- a/browser/components/tabbrowser/content/tabgroup.js +++ b/browser/components/tabbrowser/content/tabgroup.js @@ -13,10 +13,12 @@ class MozTabbrowserTabGroup extends MozXULElement { static markup = ` - + - + + + + @@ -57,20 +59,28 @@ } connectedCallback() { + if (this.group && this._lastGroup != this.group) { + this._lastGroup = this.group; + this.group.dispatchEvent( + new CustomEvent("FolderGrouped", { + bubbles: true, + detail: this, + }) + ); + } else if (!this.group) { + this._lastGroup = null; + } // Always set the mutation observer to listen for tab change events, even // if we are already initialized. // This is needed to ensure events continue to fire even if the tab group is // moved from the horizontal to vertical tab layout or vice-versa, which // causes the component to be repositioned in the DOM. - this.#observeTabChanges(); // Similar to above, always set up TabSelect listener, as this gets // removed in disconnectedCallback this.ownerGlobal.addEventListener("TabSelect", this); - if (this._initialized) { - return; - } + if (!this._initialized) { this._initialized = true; this.saveOnWindowClose = true; @@ -97,11 +107,14 @@ this.#labelElement.container = gBrowser.tabContainer; this.#labelElement.group = this; - this.#labelElement.addEventListener("contextmenu", e => { - e.preventDefault(); - gBrowser.tabGroupMenu.openEditModal(this); - return false; - }); + this.appendChild = function (child) { + this.querySelector(".tab-group-container").appendChild(child); + for (let tab of this.tabs) { + if (tab.hasAttribute("zen-empty-tab") && tab.group === this) { + this.querySelector(".zen-tab-group-start").after(tab); + } + } + }; this.#updateLabelAriaAttributes(); this.#updateCollapsedAriaAttributes(); @@ -127,6 +140,8 @@ // mounts after getting created by `Tabbrowser.adoptTabGroup`. this.#wasCreatedByAdoption = false; } + this.#observeTabChanges(); + } resetDefaultGroupName = () => { this.#defaultGroupName = ""; @@ -197,7 +212,10 @@ } }); } - this.#tabChangeObserver.observe(this, { childList: true }); + const container = this.querySelector(".tab-group-container"); + if (container) { + this.#tabChangeObserver.observe(container, { childList: true }); + } } get color() { @@ -285,6 +303,9 @@ } set collapsed(val) { + if (this.hasAttribute("split-view-group")) { + return; + } if (!!val == this.collapsed) { return; } @@ -338,12 +359,61 @@ tabGroupName, }) .then(result => { - this.dataset.tooltip = result; }); } get tabs() { - return Array.from(this.children).filter(node => node.matches("tab")); + // add other group tabs if they are under this group + let childs = Array.from(this.querySelector(".tab-group-container")?.children ?? []); + const tabsCollect = []; + for (let item of childs) { + tabsCollect.push(item); + if (gBrowser.isTabGroup(item)) { + tabsCollect.push(...item.tabs); + } + } + return tabsCollect.filter(node => node.matches("tab")); + } + + get childGroupsAndTabs() { + const result = []; + const container = this.querySelector(".tab-group-container"); + + for (const item of Array.from(container.children)) { + if (gBrowser.isTab(item)) { + result.push(item); + } else if (gBrowser.isTabGroup(item)) { + const labelContainer = item.labelElement; + labelContainer.visible = item.visible; + if (gBrowser.isTabGroupLabel(labelContainer)) { + result.push(labelContainer); + } + result.push(...item.childGroupsAndTabs); + } + } + return result; + } + + get group() { + if (gBrowser.isTabGroup(this.parentElement?.parentElement)) { + return this.parentElement.parentElement; + } + return null; + } + + get visible() { + let currentGroup = this; + while (currentGroup?.group) { + currentGroup = currentGroup?.group; + if (currentGroup.collapsed) { + return false; + } + } + return true; + } + + get level() { + return this.group?.level + 1 || 0; } /** @@ -374,7 +444,6 @@ addTabs(tabs, metricsContext) { for (let tab of tabs) { if (tab.pinned) { - tab.ownerGlobal.gBrowser.unpinTab(tab); } let tabToMove = this.ownerGlobal === tab.ownerGlobal @@ -437,7 +506,7 @@ */ on_click(event) { let isToggleElement = - event.target === this.#labelElement || + this.labelElement.parentElement.contains(event.target) || event.target === this.#overflowCountLabel; if (isToggleElement && event.button === 0) { event.preventDefault(); @@ -470,5 +539,6 @@ } } + window.MozTabbrowserTabGroup = MozTabbrowserTabGroup; customElements.define("tab-group", MozTabbrowserTabGroup); }