mirror of
https://github.com/zen-browser/desktop.git
synced 2025-11-23 10:36:16 +00:00
feat: Zen Folders, p=#9355, c=folders
* Start working on zen folders * Rework zen-folder SessionStore * Refactor restoreDataFromSessionStore * fix linter * Fix preserve folder order on restore * Feat allow dragging tabs into zen-folder * Fix ensure collapsed folders are hidden on session restore * Feat store parentId nested folders * feat: Implement tabs list popup * refactor: Move tabs popup to `popups.inc` * feat: Implement drag-and-drop folder into folder * feat: Improved UI for search panel, b=no-bug, c=folders * fix: Add extra margin when animating collapsed folders, b=no-bug, c=folders * feat: Implement tab group rename and other UI changes, b=no-bug, c=folders, common * feat: Add animated folder dots and adaptive search popup positioning * fix: resolve conflicts * fix: Correct active state indication for collapsed folders * feat: Allow folders to be double clicked, b=no-bug, c=common, folders * fix: incorrect tab order * chore: Update prefs to the rust version, b=no-bug, c=folders * fix: better handling of subfolders * chore: Improve dynamic spacing when drag and dropping and fixed split views UI, b=no-bug, c=tabs, folders * feat: Empty tab and improve drag and drop * fix: add tab search event once * fix: Empty tab should always be at first position * feat: improve drag and drop interaction with folders * feat: Improve drag-and-drop interaction for zen folders * fix: Improve zen folder session restoration and visibility * fix: Correct visible element indexing * fix: Correct restore subfolder order * feat: Use empty tabs and dont highlight current folder we currently are in, b=no-bug, c=tabs, folders * feat: persist and restore split-view group state in subfolders * fix: npm run pretty * fix: dropIndicator and transform for split-view-group * fix: Formatting * fix: improve split group and folder drag-and-drop and persistence * chore: Fix lint issues and merge with dev, b=no-bug, c=folders * chore: Move folder element to a different location, b=no-bug, c=folders * feat: Added a simple folders context menu and simplified patches, b=no-bug, c=tabs, folders * fix: Correct active tab position in folders collapse animation * feat: Add ungroup and delete folder actions * fix: Fixed empty tabs not being able to be pinned, b=no-bug, c=workspaces * feat: Added folder -> space conversion and pref checks, b=no-bug, c=folders, workspaces * Update locales/en-US/browser/browser/zen-folders.ftl Co-authored-by: Patrik Egyed <pregnor@gmail.com> Signed-off-by: mr. m <91018726+mr-cheffy@users.noreply.github.com> * fix: Fixed folders not expanding when dragging another folder inside, b=no-bug, c=folders * refactor: Refactor and improve tab group expansion logic * feat: New folder dots * test: Added simple folder creation test, b=no-bug, c=folders, tests * fix: Don't expand folder when a tab inside it is selected * feat: Added change folder to space menu item, b=no-bug, c=folders, workspaces * feat: Added a menu item to create folders more easily, b=no-bug, c=workspaces, common, folders * feat: Improved animations for collapsing active folders, b=no-bug, c=folders * fix: Insert folder before pinned separator * test: Improve folder and welcome testing, b=no-bug, c=folders, tests, welcome * test: Fixed welcome tests, b=no-bug, c=folders, tests, welcome * chore: lint, b=no-bug, c=tests, welcome * feat: Add better selected UI, b=no-bug, c=folders * feat: Emoji icons * fix: Better handling of drag-and-drop folder highlighting * fix: Single quotes * fix: Hide emoji when folder has selected tab * feat: Improved icons and animations, b=no-bug, c=folders, tabs * fix: Fixed fetching the wrong prefs, b=no-bug, c=tabs, folders * fix: Smoother dot animations * fix: dragOverFolderThreshold condition and linter * feat: visually collapse/expand active tab groups on drag/drop * fix: Correctly transform folder with selected tab * feat: Added better icons picker to support SVG, b=no-bug, c=common, folders, workspaces * fix: Correctly transform tabs after moving them * fix: Fixed not handling properly pinned tab count, b=no-bug, c=tabs, common, folders * chore: Small formatting, b=no-bug, c=folders * feat: Support SVG for folder icons * fix: Formatting * fix: Performance improvements for SVG icons * fix: Shift up the folder icon * fix: Handle null/undefined user icon values defensively * feat: Improved icon sizes and fixed bug when collapsing folders with collapsed folders, b=no-bug, c=common, folders, workspaces * chore: Tweaked the transform values for icons, b=no-bug, c=folders * feat: Added support for collapsed mode (experimental), b=no-bug, c=folders * fix: ungroup split view * fix: Improve handling of special tabs during folder creation and drag-and-drop * fix: Formatting * feat: Imrpoved hardware accelaration for the icons and folder height calculation, b=no-bug, c=tabs, folders * refactor: Extract dragover logic for tab group labels * fix: Small fixes to the folders UI, b=no-bug, c=tabs, folders * feat: Improved icons opacity and dialog, b=no-bug, c=common, workspaces * test: Added subfolders basic test, b=no-bug, c=folders, tests * fix: Drop indicator for folder targets * feat: Improved drag and drop handling from normal to pinned tabs, b=no-bug, c=folders, tabs * fix: Fixed moving split views into pinned tabs container, b=no-bug, c=folders, tabs * feat: Improved new drag and drop offset, b=no-bug, c=tabs * feat: Refine folder drop behavior with new thresholds * fix: tabs.js extra space in patch * fix: Properly handle has-active state * fix: Add optional chaining for activeGroups length check * fix: Fixed moving tabs to the workspace indicator not showing any feedback, b=no-bug, c=tabs * feat: Change svg stroke width, b=no-bug, c=folders, tabs * feat: Remove aspect ratio for the folder icon, b=no-bug, c=folders, tabs * feat: Don't reset transform when pining tabs, b=no-bug, c=tabs * feat: Ungroup tabs when dragging and make sure to animate tabs after the selected one, b=no-bug, c=tabs, folders * fix: Transform folder with active tab * fix: Fixed expand animation not working for the first time, b=no-bug, c=folders * feat: Add expand to selected functionality for folders * fix: Formatting * Update src/zen/folders/ZenFolder.mjs Signed-off-by: mr. m <91018726+mr-cheffy@users.noreply.github.com> * Update src/zen/workspaces/ZenWorkspaces.mjs Signed-off-by: mr. m <91018726+mr-cheffy@users.noreply.github.com> * fix: Set icon for new workspace * fix: Formatting * fix: Hide the icon if empty * fix: Optimize tab drag-over transitions * feat: Lower the drag and drop threshold, b=no-bug, c=tabs, folders * feat: Hide search panel when theres no visible tabs, b=no-bug, c=tabs, folders * fix: Adapt tab-group to new changes * fix: Fixed expanding split views as folders, b=no-bug, c=folders * feat(tabs): Implement tab grouping persistence for pinned tabs This commit introduces the ability to group pinned tabs for better organization. Changes include: - Added `createGroup` to create new tab groups. - Added `addTabToGroup` to add existing tabs to a group. - Added `removeTabFromGroup` to remove a tab from a group (moving it to the root level). - Added `moveTabBetweenGroups` to move tabs between different groups or to the root level. - Added `getAllGroups` to retrieve all tab groups, optionally filtered by workspace. - Added `getGroupInfo` to retrieve information about a specific group, including its child count. - Added `reorderTabsInGroup` to reorder tabs within a specific group. These functions provide a comprehensive API for managing tab groups within the Zen Browser. Error handling and input validation are included for robustness. Database transactions are used to ensure data consistency. Observers are notified of changes to notify the sync engine. * feat: Improve stroke colors for light mode, b=no-bug, c=folders * perf: cache and optimize animation updates * fix: Expand folder after drop * fix: Update active state on tab change * feat: Sync groups to new windows, b=no-bug, c=folders, tabs, workspaces * feat: Finish window syncing for new folders, b=no-bug, c=tabs, folders, workspaces * feat: Make sure SVG icons use the context fill instead of the current color, b=no-bug, c=common, folders * feat: Added support for drag and drop in collapsed mode, b=no-bug, c=tabs, folders * fix: Clean up tab attributes and styles on workspace transfer * fix: Fixed svg icons being always dark, b=no-bug, c=workspaces --------- Signed-off-by: mr. m <91018726+mr-cheffy@users.noreply.github.com> Co-authored-by: mr. m <91018726+mr-cheffy@users.noreply.github.com> Co-authored-by: Mr. M <mr.m@tuta.com> Co-authored-by: Patrik Egyed <pregnor@gmail.com> Co-authored-by: Kristijan Ribarić <kriba13@gmail.com>
This commit is contained in:
@@ -1,28 +1,39 @@
|
||||
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022dd09884ba 100644
|
||||
index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..3918e7c17dd686bd99e1fdb49750db7946304382 100644
|
||||
--- a/browser/components/tabbrowser/content/tabbrowser.js
|
||||
+++ b/browser/components/tabbrowser/content/tabbrowser.js
|
||||
@@ -422,15 +422,49 @@
|
||||
@@ -422,15 +422,60 @@
|
||||
return this.tabContainer.visibleTabs;
|
||||
}
|
||||
|
||||
+ get _numVisiblePinTabsWithoutCollapsed() {
|
||||
+ let i = 0;
|
||||
+ for (let item of this.tabContainer.ariaFocusableItems) {
|
||||
+ if (this.isTabGroupLabel(item) && item.closest("tab-group")?.pinned) {
|
||||
+ if (this.isTabGroupLabel(item) && item.group?.pinned) {
|
||||
+ i += 1;
|
||||
+ continue;
|
||||
+ }
|
||||
+ if (!item.pinned && !item.hasAttribute("zen-glance-tab")) {
|
||||
+ break;
|
||||
+ }
|
||||
+ if ((!item.group?.hasAttribute("split-view-group") && !item.group?.collapsed) && !item.hidden) {
|
||||
+ if (item.visible) {
|
||||
+ i += !item.hasAttribute("zen-glance-tab");
|
||||
+ }
|
||||
+ }
|
||||
+ return i;
|
||||
+ }
|
||||
+
|
||||
+ ungroupTabsUntilNoActive(tab) {
|
||||
+ if (!tab || !tab.group) return;
|
||||
+ const activeGroups = tab.group.activeGroups;
|
||||
+ if (activeGroups?.length) {
|
||||
+ const lastActiveGroup = activeGroups[activeGroups.length - 1];
|
||||
+ this.#handleTabMove(tab, () => {
|
||||
+ lastActiveGroup.after(tab);
|
||||
+ });
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ get _numZenEssentials() {
|
||||
+ let i = 0;
|
||||
+ for (let tab of this.tabs) {
|
||||
@@ -54,7 +65,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
set selectedTab(val) {
|
||||
if (
|
||||
gSharedTabWarning.willShowSharedTabWarning(val) ||
|
||||
@@ -578,6 +612,7 @@
|
||||
@@ -578,6 +623,7 @@
|
||||
this.tabpanels.appendChild(panel);
|
||||
|
||||
let tab = this.tabs[0];
|
||||
@@ -62,13 +73,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
tab.linkedPanel = uniqueId;
|
||||
this._selectedTab = tab;
|
||||
this._selectedBrowser = browser;
|
||||
@@ -858,14 +893,18 @@
|
||||
aTab,
|
||||
{ telemetrySource = this.TabMetrics.METRIC_SOURCE.UNKNOWN } = {}
|
||||
) {
|
||||
- if (aTab.pinned || aTab == FirefoxViewHandler.tab) {
|
||||
+ if (aTab.pinned || aTab == FirefoxViewHandler.tab || aTab.hasAttribute("zen-empty-tab")) {
|
||||
return;
|
||||
@@ -863,9 +909,13 @@
|
||||
}
|
||||
|
||||
this.showTab(aTab);
|
||||
@@ -83,7 +88,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
|
||||
aTab.setAttribute("pinned", "true");
|
||||
this._updateTabBarForPinnedTabs();
|
||||
@@ -878,11 +917,15 @@
|
||||
@@ -878,11 +928,15 @@
|
||||
}
|
||||
|
||||
this.#handleTabMove(aTab, () => {
|
||||
@@ -100,7 +105,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
});
|
||||
|
||||
aTab.style.marginInlineStart = "";
|
||||
@@ -1060,6 +1103,8 @@
|
||||
@@ -1060,6 +1114,8 @@
|
||||
|
||||
let LOCAL_PROTOCOLS = ["chrome:", "about:", "resource:", "data:"];
|
||||
|
||||
@@ -109,7 +114,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (
|
||||
aIconURL &&
|
||||
!aLoadingPrincipal &&
|
||||
@@ -1070,6 +1115,9 @@
|
||||
@@ -1070,6 +1126,9 @@
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -119,7 +124,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
|
||||
let browser = this.getBrowserForTab(aTab);
|
||||
browser.mIconURL = aIconURL;
|
||||
@@ -1319,6 +1367,7 @@
|
||||
@@ -1319,6 +1378,7 @@
|
||||
if (!this._previewMode) {
|
||||
newTab.recordTimeFromUnloadToReload();
|
||||
newTab.updateLastAccessed();
|
||||
@@ -127,7 +132,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
oldTab.updateLastAccessed();
|
||||
// if this is the foreground window, update the last-seen timestamps.
|
||||
if (this.ownerGlobal == BrowserWindowTracker.getTopWindow()) {
|
||||
@@ -1471,6 +1520,9 @@
|
||||
@@ -1471,6 +1531,9 @@
|
||||
}
|
||||
|
||||
let activeEl = document.activeElement;
|
||||
@@ -137,7 +142,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
// If focus is on the old tab, move it to the new tab.
|
||||
if (activeEl == oldTab) {
|
||||
newTab.focus();
|
||||
@@ -1794,7 +1846,8 @@
|
||||
@@ -1794,7 +1857,8 @@
|
||||
}
|
||||
|
||||
_setTabLabel(aTab, aLabel, { beforeTabOpen, isContentTitle, isURL } = {}) {
|
||||
@@ -147,7 +152,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1902,7 +1955,7 @@
|
||||
@@ -1902,7 +1966,7 @@
|
||||
newIndex = this.selectedTab._tPos + 1;
|
||||
}
|
||||
|
||||
@@ -156,7 +161,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (this.isTabGroupLabel(targetTab)) {
|
||||
throw new Error(
|
||||
"Replacing a tab group label with a tab is not supported"
|
||||
@@ -2166,6 +2219,7 @@
|
||||
@@ -2166,6 +2230,7 @@
|
||||
uriIsAboutBlank,
|
||||
userContextId,
|
||||
skipLoad,
|
||||
@@ -164,7 +169,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
} = {}) {
|
||||
let b = document.createXULElement("browser");
|
||||
// Use the JSM global to create the permanentKey, so that if the
|
||||
@@ -2239,8 +2293,7 @@
|
||||
@@ -2239,8 +2304,7 @@
|
||||
// we use a different attribute name for this?
|
||||
b.setAttribute("name", name);
|
||||
}
|
||||
@@ -174,7 +179,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
b.setAttribute("transparent", "true");
|
||||
}
|
||||
|
||||
@@ -2405,7 +2458,7 @@
|
||||
@@ -2405,7 +2469,7 @@
|
||||
|
||||
let panel = this.getPanel(browser);
|
||||
let uniqueId = this._generateUniquePanelID();
|
||||
@@ -183,7 +188,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
aTab.linkedPanel = uniqueId;
|
||||
|
||||
// Inject the <browser> into the DOM if necessary.
|
||||
@@ -2464,8 +2517,8 @@
|
||||
@@ -2464,8 +2528,8 @@
|
||||
// If we transitioned from one browser to two browsers, we need to set
|
||||
// hasSiblings=false on both the existing browser and the new browser.
|
||||
if (this.tabs.length == 2) {
|
||||
@@ -194,7 +199,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
} else {
|
||||
aTab.linkedBrowser.browsingContext.hasSiblings = this.tabs.length > 1;
|
||||
}
|
||||
@@ -2709,6 +2762,8 @@
|
||||
@@ -2709,6 +2773,8 @@
|
||||
schemelessInput,
|
||||
hasValidUserGestureActivation = false,
|
||||
textDirectiveUserActivation = false,
|
||||
@@ -203,7 +208,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
} = {}
|
||||
) {
|
||||
// all callers of addTab that pass a params object need to pass
|
||||
@@ -2719,6 +2774,12 @@
|
||||
@@ -2719,6 +2785,12 @@
|
||||
);
|
||||
}
|
||||
|
||||
@@ -216,7 +221,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (!UserInteraction.running("browser.tabs.opening", window)) {
|
||||
UserInteraction.start("browser.tabs.opening", "initting", window);
|
||||
}
|
||||
@@ -2782,6 +2843,19 @@
|
||||
@@ -2782,6 +2854,19 @@
|
||||
noInitialLabel,
|
||||
skipBackgroundNotify,
|
||||
});
|
||||
@@ -236,15 +241,18 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (insertTab) {
|
||||
// Insert the tab into the tab container in the correct position.
|
||||
this.#insertTabAtIndex(t, {
|
||||
@@ -2790,6 +2864,7 @@
|
||||
@@ -2790,8 +2875,9 @@
|
||||
ownerTab,
|
||||
openerTab,
|
||||
pinned,
|
||||
+ essential,
|
||||
bulkOrderedOpen,
|
||||
tabGroup: tabGroup ?? openerTab?.group,
|
||||
- tabGroup: tabGroup ?? openerTab?.group,
|
||||
+ tabGroup: tabGroup,
|
||||
});
|
||||
@@ -2808,6 +2883,7 @@
|
||||
}
|
||||
|
||||
@@ -2808,6 +2894,7 @@
|
||||
openWindowInfo,
|
||||
skipLoad,
|
||||
triggeringRemoteType,
|
||||
@@ -252,12 +260,12 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
}));
|
||||
|
||||
if (focusUrlBar) {
|
||||
@@ -2928,6 +3004,12 @@
|
||||
@@ -2928,6 +3015,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
+ if (typeof window.gZenVerticalTabsManager !== "undefined") {
|
||||
+ gZenVerticalTabsManager.animateTab(t);
|
||||
+ gZenVerticalTabsManager.animateItemOpen(t);
|
||||
+ }
|
||||
+ if (typeof window.gZenCompactModeManager !== "undefined" && !skipLoad && insertTab) {
|
||||
+ gZenCompactModeManager._onTabOpen(t, inBackground);
|
||||
@@ -265,7 +273,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
// Additionally send pinned tab events
|
||||
if (pinned) {
|
||||
this.#notifyPinnedStatus(t);
|
||||
@@ -3016,10 +3098,10 @@
|
||||
@@ -3016,10 +3109,10 @@
|
||||
isAdoptingGroup = false,
|
||||
isUserTriggered = false,
|
||||
telemetryUserCreateSource = "unknown",
|
||||
@@ -277,7 +285,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
}
|
||||
|
||||
if (!color) {
|
||||
@@ -3040,7 +3122,12 @@
|
||||
@@ -3040,7 +3133,12 @@
|
||||
label,
|
||||
isAdoptingGroup
|
||||
);
|
||||
@@ -291,7 +299,16 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
group,
|
||||
insertBefore?.group ?? insertBefore
|
||||
);
|
||||
@@ -3357,6 +3444,7 @@
|
||||
@@ -3163,7 +3261,7 @@
|
||||
}
|
||||
|
||||
this.#handleTabMove(tab, () =>
|
||||
- gBrowser.tabContainer.insertBefore(tab, tab.group.nextElementSibling)
|
||||
+ tab.group.after(tab)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3357,6 +3455,7 @@
|
||||
openWindowInfo,
|
||||
skipLoad,
|
||||
triggeringRemoteType,
|
||||
@@ -299,7 +316,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
}
|
||||
) {
|
||||
// If we don't have a preferred remote type (or it is `NOT_REMOTE`), and
|
||||
@@ -3426,6 +3514,7 @@
|
||||
@@ -3426,6 +3525,7 @@
|
||||
openWindowInfo,
|
||||
name,
|
||||
skipLoad,
|
||||
@@ -307,7 +324,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3613,7 +3702,7 @@
|
||||
@@ -3613,7 +3713,7 @@
|
||||
// Add a new tab if needed.
|
||||
if (!tab) {
|
||||
let createLazyBrowser =
|
||||
@@ -316,7 +333,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
|
||||
let url = "about:blank";
|
||||
if (tabData.entries?.length) {
|
||||
@@ -3650,8 +3739,10 @@
|
||||
@@ -3650,8 +3750,10 @@
|
||||
insertTab: false,
|
||||
skipLoad: true,
|
||||
preferredRemoteType,
|
||||
@@ -328,7 +345,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (select) {
|
||||
tabToSelect = tab;
|
||||
}
|
||||
@@ -3663,7 +3754,8 @@
|
||||
@@ -3663,7 +3765,8 @@
|
||||
this.pinTab(tab);
|
||||
// Then ensure all the tab open/pinning information is sent.
|
||||
this._fireTabOpen(tab, {});
|
||||
@@ -338,7 +355,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
let { groupId } = tabData;
|
||||
const tabGroup = tabGroupWorkingData.get(groupId);
|
||||
// if a tab refers to a tab group we don't know, skip any group
|
||||
@@ -3677,7 +3769,10 @@
|
||||
@@ -3677,7 +3780,10 @@
|
||||
tabGroup.stateData.id,
|
||||
tabGroup.stateData.color,
|
||||
tabGroup.stateData.collapsed,
|
||||
@@ -350,7 +367,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
);
|
||||
tabsFragment.appendChild(tabGroup.node);
|
||||
}
|
||||
@@ -3722,9 +3817,23 @@
|
||||
@@ -3722,9 +3828,23 @@
|
||||
// to remove the old selected tab.
|
||||
if (tabToSelect) {
|
||||
let leftoverTab = this.selectedTab;
|
||||
@@ -366,15 +383,15 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
+ gZenWorkspaces._initialTab._shouldRemove = true;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ else {
|
||||
+ gZenWorkspaces._tabToRemoveForEmpty = this.selectedTab;
|
||||
}
|
||||
+ }
|
||||
+ this._hasAlreadyInitializedZenSessionStore = true;
|
||||
|
||||
if (tabs.length > 1 || !tabs[0].selected) {
|
||||
this._updateTabsAfterInsert();
|
||||
@@ -3919,7 +4028,7 @@
|
||||
@@ -3919,7 +4039,7 @@
|
||||
// Ensure we have an index if one was not provided.
|
||||
if (typeof elementIndex != "number" && typeof tabIndex != "number") {
|
||||
// Move the new tab after another tab if needed, to the end otherwise.
|
||||
@@ -383,7 +400,16 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (
|
||||
!bulkOrderedOpen &&
|
||||
((openerTab &&
|
||||
@@ -3942,7 +4051,7 @@
|
||||
@@ -3931,7 +4051,7 @@
|
||||
let lastRelatedTab =
|
||||
openerTab && this._lastRelatedTabMap.get(openerTab);
|
||||
let previousTab = lastRelatedTab || openerTab || this.selectedTab;
|
||||
- if (!tabGroup) {
|
||||
+ if (!tabGroup && pinned === previousTab.group?.pinned) {
|
||||
tabGroup = previousTab.group;
|
||||
}
|
||||
if (
|
||||
@@ -3942,7 +4062,7 @@
|
||||
) {
|
||||
elementIndex = Infinity;
|
||||
} else if (previousTab.visible) {
|
||||
@@ -392,7 +418,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
} else if (previousTab == FirefoxViewHandler.tab) {
|
||||
elementIndex = 0;
|
||||
}
|
||||
@@ -3970,14 +4079,14 @@
|
||||
@@ -3970,14 +4090,14 @@
|
||||
}
|
||||
// Ensure index is within bounds.
|
||||
if (tab.pinned) {
|
||||
@@ -411,7 +437,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
|
||||
// Prevent a flash of unstyled content by setting up the tab content
|
||||
// and inherited attributes before appending it (see Bug 1592054):
|
||||
@@ -3985,7 +4094,7 @@
|
||||
@@ -3985,7 +4105,7 @@
|
||||
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
|
||||
@@ -420,7 +446,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (this.isTab(itemAfter) && itemAfter.group == tabGroup) {
|
||||
// Place at the front of, or between tabs in, the same tab group
|
||||
this.tabContainer.insertBefore(tab, itemAfter);
|
||||
@@ -4018,6 +4127,7 @@
|
||||
@@ -4018,6 +4138,7 @@
|
||||
if (pinned) {
|
||||
this._updateTabBarForPinnedTabs();
|
||||
}
|
||||
@@ -428,7 +454,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
|
||||
TabBarVisibility.update();
|
||||
}
|
||||
@@ -4307,6 +4417,9 @@
|
||||
@@ -4307,6 +4428,9 @@
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -438,7 +464,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
this.removeTabs(selectedTabs, { isUserTriggered, telemetrySource });
|
||||
}
|
||||
|
||||
@@ -4568,6 +4681,7 @@
|
||||
@@ -4568,6 +4692,7 @@
|
||||
telemetrySource,
|
||||
} = {}
|
||||
) {
|
||||
@@ -446,7 +472,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
// When 'closeWindowWithLastTab' pref is enabled, closing all tabs
|
||||
// can be considered equivalent to closing the window.
|
||||
if (
|
||||
@@ -4657,6 +4771,7 @@
|
||||
@@ -4657,6 +4782,7 @@
|
||||
if (lastToClose) {
|
||||
this.removeTab(lastToClose, aParams);
|
||||
}
|
||||
@@ -454,7 +480,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
@@ -4695,6 +4810,12 @@
|
||||
@@ -4695,6 +4821,12 @@
|
||||
aTab._closeTimeNoAnimTimerId = Glean.browserTabclose.timeNoAnim.start();
|
||||
}
|
||||
|
||||
@@ -467,7 +493,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
// Handle requests for synchronously removing an already
|
||||
// asynchronously closing tab.
|
||||
if (!animate && aTab.closing) {
|
||||
@@ -4709,6 +4830,9 @@
|
||||
@@ -4709,6 +4841,9 @@
|
||||
// state).
|
||||
let tabWidth = window.windowUtils.getBoundsWithoutFlushing(aTab).width;
|
||||
let isLastTab = this.#isLastTabInWindow(aTab);
|
||||
@@ -477,7 +503,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (
|
||||
!this._beginRemoveTab(aTab, {
|
||||
closeWindowFastpath: true,
|
||||
@@ -4891,7 +5015,7 @@
|
||||
@@ -4891,7 +5026,7 @@
|
||||
closeWindowWithLastTab != null
|
||||
? closeWindowWithLastTab
|
||||
: !window.toolbar.visible ||
|
||||
@@ -486,7 +512,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
|
||||
if (closeWindow) {
|
||||
// We've already called beforeunload on all the relevant tabs if we get here,
|
||||
@@ -4915,6 +5039,7 @@
|
||||
@@ -4915,6 +5050,7 @@
|
||||
|
||||
newTab = true;
|
||||
}
|
||||
@@ -494,7 +520,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
aTab._endRemoveArgs = [closeWindow, newTab];
|
||||
|
||||
// swapBrowsersAndCloseOther will take care of closing the window without animation.
|
||||
@@ -4955,9 +5080,7 @@
|
||||
@@ -4955,9 +5091,7 @@
|
||||
aTab._mouseleave();
|
||||
|
||||
if (newTab) {
|
||||
@@ -505,7 +531,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
} else {
|
||||
TabBarVisibility.update();
|
||||
}
|
||||
@@ -5090,6 +5213,7 @@
|
||||
@@ -5090,6 +5224,7 @@
|
||||
this.tabs[i]._tPos = i;
|
||||
}
|
||||
|
||||
@@ -513,7 +539,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (!this._windowIsClosing) {
|
||||
// update tab close buttons state
|
||||
this.tabContainer._updateCloseButtons();
|
||||
@@ -5302,6 +5426,7 @@
|
||||
@@ -5302,6 +5437,7 @@
|
||||
}
|
||||
|
||||
let excludeTabs = new Set(aExcludeTabs);
|
||||
@@ -521,7 +547,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
|
||||
// If this tab has a successor, it should be selectable, since
|
||||
// hiding or closing a tab removes that tab as a successor.
|
||||
@@ -5314,13 +5439,13 @@
|
||||
@@ -5314,13 +5450,13 @@
|
||||
!excludeTabs.has(aTab.owner) &&
|
||||
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")
|
||||
) {
|
||||
@@ -537,7 +563,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
);
|
||||
|
||||
let tab = this.tabContainer.findNextTab(aTab, {
|
||||
@@ -5336,7 +5461,7 @@
|
||||
@@ -5336,7 +5472,7 @@
|
||||
}
|
||||
|
||||
if (tab) {
|
||||
@@ -546,7 +572,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
}
|
||||
|
||||
// If no qualifying visible tab was found, see if there is a tab in
|
||||
@@ -5357,7 +5482,7 @@
|
||||
@@ -5357,7 +5493,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
@@ -555,7 +581,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
}
|
||||
|
||||
_blurTab(aTab) {
|
||||
@@ -5759,10 +5884,10 @@
|
||||
@@ -5759,10 +5895,10 @@
|
||||
SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
|
||||
}
|
||||
|
||||
@@ -568,7 +594,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
aTab.selected ||
|
||||
aTab.closing ||
|
||||
// Tabs that are sharing the screen, microphone or camera cannot be hidden.
|
||||
@@ -5952,7 +6077,7 @@
|
||||
@@ -5952,7 +6088,7 @@
|
||||
* `true` if element is a `<tab-group>`
|
||||
*/
|
||||
isTabGroup(element) {
|
||||
@@ -577,7 +603,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -6029,7 +6154,7 @@
|
||||
@@ -6029,7 +6165,7 @@
|
||||
|
||||
// Don't allow mixing pinned and unpinned tabs.
|
||||
if (this.isTab(element) && element.pinned) {
|
||||
@@ -586,7 +612,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
} else {
|
||||
tabIndex = Math.max(tabIndex, this.pinnedTabCount);
|
||||
}
|
||||
@@ -6055,10 +6180,16 @@
|
||||
@@ -6055,10 +6191,16 @@
|
||||
this.#handleTabMove(
|
||||
element,
|
||||
() => {
|
||||
@@ -605,7 +631,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (neighbor && this.isTab(element) && tabIndex > element._tPos) {
|
||||
neighbor.after(element);
|
||||
} else {
|
||||
@@ -6116,13 +6247,13 @@
|
||||
@@ -6116,22 +6258,26 @@
|
||||
#moveTabNextTo(element, targetElement, moveBefore = false, metricsContext) {
|
||||
if (this.isTabGroupLabel(targetElement)) {
|
||||
targetElement = targetElement.group;
|
||||
@@ -619,9 +645,9 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
- if (this.isTabGroupLabel(element)) {
|
||||
+ if (this.isTabGroupLabel(element) || element.group?.hasAttribute("split-view-group")) {
|
||||
element = element.group;
|
||||
if (targetElement?.group) {
|
||||
targetElement = targetElement.group;
|
||||
@@ -6130,8 +6261,15 @@
|
||||
- if (targetElement?.group) {
|
||||
- targetElement = targetElement.group;
|
||||
- }
|
||||
}
|
||||
|
||||
// Don't allow mixing pinned and unpinned tabs.
|
||||
@@ -638,7 +664,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
moveBefore = false;
|
||||
} else if (!element.pinned && targetElement && targetElement.pinned) {
|
||||
// If the caller asks to move an unpinned element next to a pinned
|
||||
@@ -6145,7 +6283,7 @@
|
||||
@@ -6145,7 +6291,7 @@
|
||||
// move the tab group right before the first unpinned tab.
|
||||
// 4. Moving a tab group and the first unpinned tab is grouped:
|
||||
// move the tab group right before the first unpinned tab's tab group.
|
||||
@@ -647,7 +673,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
if (targetElement.group) {
|
||||
targetElement = targetElement.group;
|
||||
}
|
||||
@@ -6153,6 +6291,7 @@
|
||||
@@ -6153,6 +6299,7 @@
|
||||
}
|
||||
|
||||
let getContainer = () =>
|
||||
@@ -655,7 +681,16 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
element.pinned
|
||||
? this.tabContainer.pinnedTabsContainer
|
||||
: this.tabContainer;
|
||||
@@ -6210,7 +6349,7 @@
|
||||
@@ -6161,7 +6308,7 @@
|
||||
element,
|
||||
() => {
|
||||
if (moveBefore) {
|
||||
- getContainer().insertBefore(element, targetElement);
|
||||
+ targetElement.parentElement.insertBefore(element, targetElement);
|
||||
} else if (targetElement) {
|
||||
targetElement.after(element);
|
||||
} else {
|
||||
@@ -6210,7 +6357,7 @@
|
||||
if (!this.isTab(aTab)) {
|
||||
throw new Error("Can only move a tab into a tab group");
|
||||
}
|
||||
@@ -664,7 +699,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
return;
|
||||
}
|
||||
if (aTab.group && aTab.group.id === aGroup.id) {
|
||||
@@ -6304,6 +6443,10 @@
|
||||
@@ -6304,6 +6451,10 @@
|
||||
|
||||
moveActionCallback();
|
||||
|
||||
@@ -675,7 +710,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
// Clear tabs cache after moving nodes because the order of tabs may have
|
||||
// changed.
|
||||
this.tabContainer._invalidateCachedTabs();
|
||||
@@ -7198,7 +7341,7 @@
|
||||
@@ -7198,7 +7349,7 @@
|
||||
// preventDefault(). It will still raise the window if appropriate.
|
||||
break;
|
||||
}
|
||||
@@ -684,7 +719,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
window.focus();
|
||||
aEvent.preventDefault();
|
||||
break;
|
||||
@@ -8143,6 +8286,7 @@
|
||||
@@ -8143,6 +8294,7 @@
|
||||
aWebProgress.isTopLevel
|
||||
) {
|
||||
this.mTab.setAttribute("busy", "true");
|
||||
@@ -692,7 +727,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
gBrowser._tabAttrModified(this.mTab, ["busy"]);
|
||||
this.mTab._notselectedsinceload = !this.mTab.selected;
|
||||
}
|
||||
@@ -9108,7 +9252,7 @@ var TabContextMenu = {
|
||||
@@ -9108,7 +9260,7 @@ var TabContextMenu = {
|
||||
);
|
||||
contextUnpinSelectedTabs.hidden =
|
||||
!this.contextTab.pinned || !this.multiselected;
|
||||
@@ -701,7 +736,7 @@ index 96fd8acdc09cc4c9649d1ed7503c2a0bde536613..41f869c4841ab4055b706487611f022d
|
||||
// Move Tab items
|
||||
let contextMoveTabOptions = document.getElementById(
|
||||
"context_moveTabOptions"
|
||||
@@ -9384,6 +9528,7 @@ var TabContextMenu = {
|
||||
@@ -9384,6 +9536,7 @@ var TabContextMenu = {
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user