11diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
2- index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad0c761fb5 100644
2+ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..1bf95403333f914f082b38441d31326cbd973686 100644
33--- a/browser/components/tabbrowser/content/tabbrowser.js
44+++ b/browser/components/tabbrowser/content/tabbrowser.js
55@@ -450,15 +450,64 @@
@@ -420,10 +420,10 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
420420+ gZenWorkspaces._initialTab._shouldRemove = true;
421421+ }
422422+ }
423- }
423+ + }
424424+ else {
425425+ gZenWorkspaces._tabToRemoveForEmpty = this.selectedTab;
426- + }
426+ }
427427+ this._hasAlreadyInitializedZenSessionStore = true;
428428
429429 if (tabs.length > 1 || !tabs[0].selected) {
@@ -490,15 +490,27 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
490490 if (this.isTab(itemAfter) && itemAfter.group == tabGroup) {
491491 // Place at the front of, or between tabs in, the same tab group
492492 this.tabContainer.insertBefore(tab, itemAfter);
493- @@ -4346,6 +4473,7 @@
493+ @@ -4338,7 +4465,11 @@
494+ const tabContainer = pinned
495+ ? this.tabContainer.pinnedTabsContainer
496+ : this.tabContainer;
497+ + if (itemAfter) {
498+ + itemAfter.before(tab);
499+ + } else {
500+ tabContainer.insertBefore(tab, itemAfter);
501+ + }
502+ }
503+
504+ this._updateTabsAfterInsert();
505+ @@ -4346,6 +4477,7 @@
494506 if (pinned) {
495507 this._updateTabBarForPinnedTabs();
496508 }
497509+ gZenWorkspaces.fixTabInsertLocation(tab, itemAfter);
498510
499511 TabBarVisibility.update();
500512 }
501- @@ -4635,6 +4763 ,9 @@
513+ @@ -4635,6 +4767 ,9 @@
502514 return;
503515 }
504516
@@ -508,23 +520,23 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
508520 this.removeTabs(selectedTabs, { isUserTriggered, telemetrySource });
509521 }
510522
511- @@ -4896,6 +5027 ,7 @@
523+ @@ -4896,6 +5031 ,7 @@
512524 telemetrySource,
513525 } = {}
514526 ) {
515527+ tabs = tabs.filter(tab => !tab.hasAttribute("zen-empty-tab"));
516528 // When 'closeWindowWithLastTab' pref is enabled, closing all tabs
517529 // can be considered equivalent to closing the window.
518530 if (
519- @@ -4985,6 +5117 ,7 @@
531+ @@ -4985,6 +5121 ,7 @@
520532 if (lastToClose) {
521533 this.removeTab(lastToClose, aParams);
522534 }
523535+ gZenUIManager.onTabClose(undefined);
524536 } catch (e) {
525537 console.error(e);
526538 }
527- @@ -5023,6 +5156 ,12 @@
539+ @@ -5023,6 +5160 ,12 @@
528540 aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start();
529541 }
530542
@@ -537,7 +549,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
537549 // Handle requests for synchronously removing an already
538550 // asynchronously closing tab.
539551 if (!animate && aTab.closing) {
540- @@ -5037,6 +5176 ,9 @@
552+ @@ -5037,6 +5180 ,9 @@
541553 // state).
542554 let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width;
543555 let isLastTab = this.#isLastTabInWindow(aTab);
@@ -547,7 +559,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
547559 if (
548560 !this._beginRemoveTab(aTab, {
549561 closeWindowFastpath: true,
550- @@ -5085,7 +5227 ,13 @@
562+ @@ -5085,7 +5231 ,13 @@
551563 // We're not animating, so we can cancel the animation stopwatch.
552564 Glean.browserTabclose.timeAnim.cancel(aTab._closeTimeAnimTimerId);
553565 aTab._closeTimeAnimTimerId = null;
@@ -562,7 +574,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
562574 return;
563575 }
564576
565- @@ -5219,7 +5367 ,7 @@
577+ @@ -5219,7 +5371 ,7 @@
566578 closeWindowWithLastTab != null
567579 ? closeWindowWithLastTab
568580 : !window.toolbar.visible ||
@@ -571,15 +583,15 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
571583
572584 if (closeWindow) {
573585 // We've already called beforeunload on all the relevant tabs if we get here,
574- @@ -5243,6 +5391 ,7 @@
586+ @@ -5243,6 +5395 ,7 @@
575587
576588 newTab = true;
577589 }
578590+ gZenWorkspaces._removedByStartupPage = false;
579591 aTab._endRemoveArgs = [closeWindow, newTab];
580592
581593 // swapBrowsersAndCloseOther will take care of closing the window without animation.
582- @@ -5283,13 +5432 ,7 @@
594+ @@ -5283,13 +5436 ,7 @@
583595 aTab._mouseleave();
584596
585597 if (newTab) {
@@ -594,23 +606,23 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
594606 } else {
595607 TabBarVisibility.update();
596608 }
597- @@ -5422,6 +5565 ,7 @@
609+ @@ -5422,6 +5569 ,7 @@
598610 this.tabs[i]._tPos = i;
599611 }
600612
601613+ gZenWorkspaces.updateTabsContainers();
602614 if (!this._windowIsClosing) {
603615 // update tab close buttons state
604616 this.tabContainer._updateCloseButtons();
605- @@ -5643,6 +5787 ,7 @@
617+ @@ -5643,6 +5791 ,7 @@
606618 }
607619
608620 let excludeTabs = new Set(aExcludeTabs);
609621+ gZenWorkspaces.getTabsToExclude(aTab).forEach(tab => excludeTabs.add(tab));
610622
611623 // If this tab has a successor, it should be selectable, since
612624 // hiding or closing a tab removes that tab as a successor.
613- @@ -5655,13 +5800 ,13 @@
625+ @@ -5655,13 +5804 ,13 @@
614626 !excludeTabs.has(aTab.owner) &&
615627 Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")
616628 ) {
@@ -626,7 +638,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
626638 );
627639
628640 let tab = this.tabContainer.findNextTab(aTab, {
629- @@ -5677,7 +5822 ,7 @@
641+ @@ -5677,7 +5826 ,7 @@
630642 }
631643
632644 if (tab) {
@@ -635,7 +647,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
635647 }
636648
637649 // If no qualifying visible tab was found, see if there is a tab in
638- @@ -5698,7 +5843 ,7 @@
650+ @@ -5698,7 +5847 ,7 @@
639651 });
640652 }
641653
@@ -644,7 +656,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
644656 }
645657
646658 _blurTab(aTab) {
647- @@ -6104,10 +6249 ,10 @@
659+ @@ -6104,10 +6253 ,10 @@
648660 SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
649661 }
650662
@@ -657,15 +669,15 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
657669 aTab.selected ||
658670 aTab.closing ||
659671 // Tabs that are sharing the screen, microphone or camera cannot be hidden.
660- @@ -6166,6 +6311 ,7 @@
672+ @@ -6166,6 +6315 ,7 @@
661673 * @param {MozTabbrowserTab|MozTabbrowserTabGroup|MozTabbrowserTabGroup.labelElement} aTab
662674 */
663675 replaceTabWithWindow(aTab, aOptions) {
664676+ if (!this.isTab(aTab)) return; // TODO: Handle tab groups
665677 if (this.tabs.length == 1) {
666678 return null;
667679 }
668- @@ -6299,7 +6445 ,7 @@
680+ @@ -6299,7 +6449 ,7 @@
669681 * `true` if element is a `<tab-group>`
670682 */
671683 isTabGroup(element) {
@@ -674,7 +686,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
674686 }
675687
676688 /**
677- @@ -6375,8 +6521 ,8 @@
689+ @@ -6375,8 +6525 ,8 @@
678690 }
679691
680692 // Don't allow mixing pinned and unpinned tabs.
@@ -685,7 +697,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
685697 } else {
686698 tabIndex = Math.max(tabIndex, this.pinnedTabCount);
687699 }
688- @@ -6402,10 +6548 ,16 @@
700+ @@ -6402,10 +6552 ,16 @@
689701 this.#handleTabMove(
690702 element,
691703 () => {
@@ -704,7 +716,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
704716 if (neighbor && this.isTab(element) && tabIndex > element._tPos) {
705717 neighbor.after(element);
706718 } else {
707- @@ -6463,23 +6615 ,28 @@
719+ @@ -6463,23 +6619 ,28 @@
708720 #moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) {
709721 if (this.isTabGroupLabel(targetElement)) {
710722 targetElement = targetElement.group;
@@ -739,7 +751,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
739751 } else if (!element.pinned && targetElement && targetElement.pinned) {
740752 // If the caller asks to move an unpinned element next to a pinned
741753 // tab, move the unpinned element to be the first unpinned element
742- @@ -6492,14 +6649 ,34 @@
754+ @@ -6492,14 +6653 ,34 @@
743755 // move the tab group right before the first unpinned tab.
744756 // 4. Moving a tab group and the first unpinned tab is grouped:
745757 // move the tab group right before the first unpinned tab's tab group.
@@ -775,7 +787,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
775787 element.pinned
776788 ? this.tabContainer.pinnedTabsContainer
777789 : this.tabContainer;
778- @@ -6508,7 +6685 ,7 @@
790+ @@ -6508,7 +6689 ,7 @@
779791 element,
780792 () => {
781793 if (moveBefore) {
@@ -784,7 +796,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
784796 } else if (targetElement) {
785797 targetElement.after(element);
786798 } else {
787- @@ -6580,10 +6757 ,10 @@
799+ @@ -6580,10 +6761 ,10 @@
788800 * @param {TabMetricsContext} [metricsContext]
789801 */
790802 moveTabToGroup(aTab, aGroup, metricsContext) {
@@ -797,15 +809,15 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
797809 return;
798810 }
799811 if (aTab.group && aTab.group.id === aGroup.id) {
800- @@ -6613,6 +6790 ,7 @@
812+ @@ -6613,6 +6794 ,7 @@
801813
802814 let state = {
803815 tabIndex: tab._tPos,
804816+ workspaceId: tab.getAttribute("zen-workspace-id")
805817 };
806818 if (tab.visible) {
807819 state.elementIndex = tab.elementIndex;
808- @@ -6639,7 +6817 ,7 @@
820+ @@ -6639,7 +6821 ,7 @@
809821 let changedTabGroup =
810822 previousTabState.tabGroupId != currentTabState.tabGroupId;
811823
@@ -814,7 +826,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
814826 tab.dispatchEvent(
815827 new CustomEvent("TabMove", {
816828 bubbles: true,
817- @@ -6676,6 +6854 ,10 @@
829+ @@ -6676,6 +6858 ,10 @@
818830
819831 moveActionCallback();
820832
@@ -825,7 +837,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
825837 // Clear tabs cache after moving nodes because the order of tabs may have
826838 // changed.
827839 this.tabContainer._invalidateCachedTabs();
828- @@ -7576,7 +7758 ,7 @@
840+ @@ -7576,7 +7762 ,7 @@
829841 // preventDefault(). It will still raise the window if appropriate.
830842 break;
831843 }
@@ -834,23 +846,23 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
834846 window.focus();
835847 aEvent.preventDefault();
836848 break;
837- @@ -7593,7 +7775 ,6 @@
849+ @@ -7593,7 +7779 ,6 @@
838850 }
839851 case "TabGroupCollapse":
840852 aEvent.target.tabs.forEach(tab => {
841853- this.removeFromMultiSelectedTabs(tab);
842854 });
843855 break;
844856 case "TabGroupCreateByUser":
845- @@ -8542,6 +8723 ,7 @@
857+ @@ -8542,6 +8727 ,7 @@
846858 aWebProgress.isTopLevel
847859 ) {
848860 this.mTab.setAttribute("busy", "true");
849861+ if (!this.mTab.selected) this.mTab.setAttribute("unread", "true");
850862 gBrowser._tabAttrModified(this.mTab, ["busy"]);
851863 this.mTab._notselectedsinceload = !this.mTab.selected;
852864 }
853- @@ -9543,7 +9725 ,7 @@ var TabContextMenu = {
865+ @@ -9543,7 +9729 ,7 @@ var TabContextMenu = {
854866 );
855867 contextUnpinSelectedTabs.hidden =
856868 !this.contextTab.pinned || !this.multiselected;
@@ -859,7 +871,7 @@ index c0eafd4faf8d57b8486c5bf8917375850ec8147e..2ab3908f421d6bc126eb7a0f886646ad
859871 // Build Ask Chat items
860872 TabContextMenu.GenAI.buildTabMenu(
861873 document.getElementById("context_askChat"),
862- @@ -9863,6 +10045 ,7 @@ var TabContextMenu = {
874+ @@ -9863,6 +10049 ,7 @@ var TabContextMenu = {
863875 )
864876 );
865877 } else {
0 commit comments