Merge pull request #4282 from zen-browser/new-workspace-functionality

This commit is contained in:
mr. m
2025-01-11 17:37:41 +01:00
committed by GitHub
5 changed files with 94 additions and 71 deletions

View File

@@ -100,28 +100,6 @@
}
}
@keyframes zen-slide-in {
from {
transform: translateX(-150%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes zen-slide-in-reverse {
from {
transform: translateX(150%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes zen-deck-fadeIn {
0% {
transform: scale(0.9);

View File

@@ -242,23 +242,6 @@
& .tabbrowser-tab {
transition: scale 0.07s ease;
#tabbrowser-tabs &:not([zen-essential='true']) {
#tabbrowser-tabs[zen-workspace-animation='previous'] & {
animation: zen-slide-in;
}
#tabbrowser-tabs[zen-workspace-animation='next'] & {
animation: zen-slide-in-reverse;
}
#tabbrowser-tabs[zen-workspace-animation] & {
opacity: 0;
transform: translateX(-100%);
animation-delay: 0.2s;
animation-fill-mode: forwards;
animation-duration: 0.2s;
animation-timing-function: ease;
}
#tabbrowser-tabs[dont-animate-tabs] & {
opacity: 0;
}

View File

@@ -658,7 +658,7 @@
setTimeout(() => {
// Reactivate the transition after the animation
appWrapper.removeAttribute('post-animating');
});
}, 100);
}, 700);
});
}

View File

@@ -391,7 +391,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
activeWorkspace = workspaces.workspaces[0];
this.activeWorkspace = activeWorkspace?.uuid;
}
await this.changeWorkspace(activeWorkspace, true);
await this.changeWorkspace(activeWorkspace, { onInit: true });
}
try {
if (activeWorkspace) {
@@ -415,6 +415,10 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
indicator.addEventListener('click', th);
}
shouldCloseWindow() {
return !window.toolbar.visible || Services.prefs.getBoolPref('browser.tabs.closeWindowWithLastTab');
}
handleTabBeforeClose(tab) {
if (!this.workspaceEnabled || this.__contextIsDelete) {
return null;
@@ -425,17 +429,33 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
return null;
}
const shouldOpenNewTabIfLastUnpinnedTabIsClosed = this.shouldOpenNewTabIfLastUnpinnedTabIsClosed;
let tabs = gBrowser.tabs.filter(
(t) =>
t.getAttribute('zen-workspace-id') === workspaceID &&
(!shouldOpenNewTabIfLastUnpinnedTabIsClosed || !t.pinned || t.getAttribute('pending') !== 'true')
);
let tabs = gBrowser.visibleTabs;
let tabsPinned = tabs.filter((t) => !this.shouldOpenNewTabIfLastUnpinnedTabIsClosed || !t.pinned);
const shouldCloseWindow = this.shouldCloseWindow();
if (tabs.length === 1 && tabs[0] === tab) {
let newTab = this._createNewTabForWorkspace({ uuid: workspaceID });
return newTab;
if (shouldCloseWindow) {
// We've already called beforeunload on all the relevant tabs if we get here,
// so avoid calling it again:
window.skipNextCanClose = true;
// Closing the tab and replacing it with a blank one is notably slower
// than closing the window right away. If the caller opts in, take
// the fast path.
if (!gBrowser._removingTabs.size) {
// This call actually closes the window, unless the user
// cancels the operation. We are finished here in both cases.
this._isClosingWindow = true;
// Inside a setTimeout to avoid reentrancy issues.
setTimeout(() => {
document.getElementById('cmd_closeWindow').doCommand();
}, 100);
return this._createNewTabForWorkspace({ uuid: workspaceID });
}
return null;
}
} else if (tabsPinned.length === 1 && tabsPinned[0] === tab) {
return this._createNewTabForWorkspace({ uuid: workspaceID });
}
return null;
@@ -1247,7 +1267,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
this._changeListeners.push(func);
}
async changeWorkspace(window, onInit = false) {
async changeWorkspace(window, ...args) {
if (!this.workspaceEnabled || this._inChangingWorkspace) {
return;
}
@@ -1255,14 +1275,14 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
await SessionStore.promiseInitialized;
this._inChangingWorkspace = true;
try {
await this._performWorkspaceChange(window, onInit);
await this._performWorkspaceChange(window, ...args);
} finally {
this._inChangingWorkspace = false;
this.tabContainer.removeAttribute('dont-animate-tabs');
}
}
async _performWorkspaceChange(window, onInit) {
async _performWorkspaceChange(window, { onInit = false, explicitAnimationDirection = undefined } = {}) {
const previousWorkspace = await this.getActiveWorkspace();
this.activeWorkspace = window.uuid;
@@ -1272,6 +1292,21 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
// Refresh tab cache
this.tabContainer._invalidateCachedTabs();
let animationDirection;
if (previousWorkspace && !onInit && !this._animatingChange) {
animationDirection =
explicitAnimationDirection ??
(workspaces.workspaces.findIndex((w) => w.uuid === previousWorkspace.uuid) <
workspaces.workspaces.findIndex((w) => w.uuid === window.uuid)
? 'right'
: 'left');
}
if (animationDirection) {
// Animate tabs out of view before changing workspace, therefor we
// need to animate in the opposite direction
await this._animateTabs(animationDirection === 'left' ? 'right' : 'left', true);
}
// First pass: Handle tab visibility and workspace ID assignment
const visibleTabs = this._processTabVisibility(window.uuid, containerId, workspaces);
@@ -1281,23 +1316,42 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
// Update UI and state
await this._updateWorkspaceState(window, onInit);
// Animate acordingly
if (previousWorkspace && !this._animatingChange) {
// we want to know if we are moving forward or backward in sense of animation
let isNextWorkspace =
onInit ||
workspaces.workspaces.findIndex((w) => w.uuid === previousWorkspace.uuid) <
workspaces.workspaces.findIndex((w) => w.uuid === window.uuid);
gBrowser.tabContainer.setAttribute('zen-workspace-animation', isNextWorkspace ? 'next' : 'previous');
this.tabContainer.removeAttribute('dont-animate-tabs');
this._animatingChange = true;
setTimeout(() => {
this._animatingChange = false;
gBrowser.tabContainer.removeAttribute('zen-workspace-animation');
}, 600);
if (animationDirection) {
await this._animateTabs(animationDirection);
}
}
async _animateTabs(direction, out = false) {
const tabs = gBrowser.visibleTabs.filter((tab) => !tab.hasAttribute('zen-essential'));
return new Promise((resolve) => {
let count = 0;
const onAnimationEnd = () => {
count++;
if (count >= tabs.length) {
resolve();
}
};
this.tabContainer.removeAttribute('dont-animate-tabs');
if (out) {
for (let tab of tabs) {
tab.animate([{ transform: 'translateX(0)' }, { transform: `translateX(${direction === 'left' ? '-' : ''}100%)` }], {
duration: 150,
easing: 'ease',
fill: 'both',
}).onfinish = onAnimationEnd;
}
return;
}
for (let tab of tabs) {
tab.animate([{ transform: `translateX(${direction === 'left' ? '-' : ''}100%)` }, { transform: 'translateX(0)' }], {
duration: 150,
easing: 'ease',
fill: 'both',
}).onfinish = onAnimationEnd;
}
});
}
_processTabVisibility(workspaceUuid, containerId, workspaces) {
const visibleTabs = new Set();
const lastSelectedTab = this._lastSelectedWorkspaceTabs[workspaceUuid];
@@ -1524,7 +1578,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
}
async onLocationChange(browser) {
if (!this.workspaceEnabled || this._inChangingWorkspace) {
if (!this.workspaceEnabled || this._inChangingWorkspace || this._isClosingWindow) {
return;
}
@@ -1663,7 +1717,7 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
}
let nextWorkspace = workspaces.workspaces[targetIndex];
await this.changeWorkspace(nextWorkspace);
await this.changeWorkspace(nextWorkspace, { explicitAnimationDirection: offset > 0 ? 'right' : 'left' });
}
_initializeWorkspaceTabContextMenus() {

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tabbrowser.js b/browser/components/tabbrowser/content/tabbrowser.js
index ce68c339f35416574b7bc7ebf8c93378f653242b..46d25e4381eaae71f3aec1025788684c593a60c7 100644
index ce68c339f35416574b7bc7ebf8c93378f653242b..07e3f7fcdb3e219c523201929cf07b6878d4d394 100644
--- a/browser/components/tabbrowser/content/tabbrowser.js
+++ b/browser/components/tabbrowser/content/tabbrowser.js
@@ -409,11 +409,39 @@
@@ -237,7 +237,7 @@ index ce68c339f35416574b7bc7ebf8c93378f653242b..46d25e4381eaae71f3aec1025788684c
if (
!this._beginRemoveTab(aTab, {
closeWindowFastpath: true,
@@ -4556,7 +4657,7 @@
@@ -4556,14 +4657,14 @@
!!this.tabsInCollapsedTabGroups.length;
if (
aTab.visible &&
@@ -246,6 +246,14 @@ index ce68c339f35416574b7bc7ebf8c93378f653242b..46d25e4381eaae71f3aec1025788684c
!anyRemainingTabsInCollapsedTabGroups
) {
closeWindow =
closeWindowWithLastTab != null
? closeWindowWithLastTab
: !window.toolbar.visible ||
- Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
+ Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab") && !ZenWorkspaces._isClosingWindow;
if (closeWindow) {
// We've already called beforeunload on all the relevant tabs if we get here,
@@ -5411,10 +5512,10 @@
SessionStore.deleteCustomTabValue(aTab, "hiddenBy");
}