mirror of
https://github.com/zen-browser/desktop.git
synced 2026-07-09 10:29:32 +00:00
gh-13870: Fix essentials overlap and fix two space wrap-around (gh-14476)
This commit is contained in:
@@ -449,7 +449,7 @@ class nsZenWorkspaces {
|
||||
container = 0;
|
||||
}
|
||||
let essentialsContainer = document.querySelector(
|
||||
`.zen-essentials-container[container="${container}"]:not([cloned])`
|
||||
`.zen-essentials-container[container="${container}"]`
|
||||
);
|
||||
if (!essentialsContainer) {
|
||||
essentialsContainer = document.createXULElement("hbox");
|
||||
@@ -1864,6 +1864,11 @@ class nsZenWorkspaces {
|
||||
}
|
||||
const newTransform = diff * 100;
|
||||
element.style.transform = `translateX(${newTransform + offsetPixels / 2}%)`;
|
||||
// A special case for two spaces
|
||||
if (spaceLen === 2 && diff !== 0) {
|
||||
const side = offsetPixels > 0 ? -100 : 100;
|
||||
element.style.transform = `translateX(${side + offsetPixels / 2}%)`;
|
||||
}
|
||||
}
|
||||
// Hide other essentials with different containerTabId
|
||||
for (const container of otherContainersEssentials) {
|
||||
@@ -2017,28 +2022,20 @@ class nsZenWorkspaces {
|
||||
diff += spaceLen;
|
||||
}
|
||||
const isGoingLeft = diff < 0;
|
||||
const clonedEssentials = [];
|
||||
const essentialsAnimData = [];
|
||||
if (shouldAnimate && this.shouldAnimateEssentials && previousWorkspace) {
|
||||
const containerIds = new Map();
|
||||
for (const workspace of workspaces) {
|
||||
const essentialsContainer = this.getEssentialsSection(
|
||||
workspace.containerTabId
|
||||
);
|
||||
let lastCloned = clonedEssentials[clonedEssentials.length - 1];
|
||||
if (lastCloned && lastCloned.contextId == workspace.containerTabId) {
|
||||
lastCloned.repeat++;
|
||||
lastCloned.workspaces.push(workspace);
|
||||
continue;
|
||||
const containerId = workspace.containerTabId;
|
||||
if (!containerIds.has(containerId)) {
|
||||
containerIds.set(containerId, []);
|
||||
}
|
||||
essentialsContainer.setAttribute("hidden", "true");
|
||||
const essentialsClone = essentialsContainer.cloneNode(true);
|
||||
essentialsClone.removeAttribute("hidden");
|
||||
essentialsClone.setAttribute("cloned", "true");
|
||||
clonedEssentials.push({
|
||||
container: essentialsClone,
|
||||
workspaces: [workspace],
|
||||
contextId: workspace.containerTabId,
|
||||
originalContainer: essentialsContainer,
|
||||
repeat: 0,
|
||||
containerIds.get(containerId).push(workspace);
|
||||
}
|
||||
for (const [containerId, spaces] of containerIds) {
|
||||
essentialsAnimData.push({
|
||||
element: this.getEssentialsSection(containerId),
|
||||
workspaces: spaces,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2102,6 +2099,12 @@ class nsZenWorkspaces {
|
||||
offset += spaceLen;
|
||||
}
|
||||
offset = offset * 100;
|
||||
// A special case for two spaces
|
||||
if (spaceLen === 2 && offset !== 0) {
|
||||
const currentTransform =
|
||||
parseFloat(element.style.transform.split("(")[1]) || 0;
|
||||
offset = currentTransform >= 0 ? 100 : -100;
|
||||
}
|
||||
const newTransform = `translateX(${offset}%)`;
|
||||
// Only animate the workspace that is coming in, to avoid having multiple workspaces
|
||||
// animating off-screen at the same time which can cause performance issues. With an off
|
||||
@@ -2145,190 +2148,59 @@ class nsZenWorkspaces {
|
||||
}
|
||||
}
|
||||
if (this.shouldAnimateEssentials && previousWorkspace) {
|
||||
// Animate essentials
|
||||
const newWorkspaceEssentialsContainer = clonedEssentials.find(cloned =>
|
||||
cloned.workspaces.some(w => w.uuid === newWorkspace.uuid)
|
||||
);
|
||||
// Get a list of essentials containers that are in between the first and last workspace
|
||||
const essentialsContainersInBetween = clonedEssentials.filter(cloned => {
|
||||
const essentialsWorkspaces = cloned.workspaces;
|
||||
const firstIndex = workspaces.findIndex(
|
||||
w => w.uuid === essentialsWorkspaces[0].uuid
|
||||
for (const data of essentialsAnimData) {
|
||||
const container = data.element;
|
||||
const essentialsWorkspaces = data.workspaces;
|
||||
|
||||
const containsPrev = essentialsWorkspaces.some(
|
||||
w => w.uuid === previousWorkspace.uuid
|
||||
);
|
||||
const lastIndex = workspaces.findIndex(
|
||||
w =>
|
||||
w.uuid ===
|
||||
essentialsWorkspaces[essentialsWorkspaces.length - 1].uuid
|
||||
const containsNew = essentialsWorkspaces.some(
|
||||
w => w.uuid === newWorkspace.uuid
|
||||
);
|
||||
|
||||
const [start, end] = [
|
||||
Math.min(previousWorkspaceIndex, newWorkspaceIndex),
|
||||
Math.max(previousWorkspaceIndex, newWorkspaceIndex),
|
||||
];
|
||||
|
||||
// Check if any part of the container overlaps with the movement range
|
||||
return firstIndex <= end && lastIndex >= start;
|
||||
});
|
||||
for (const cloned of clonedEssentials) {
|
||||
const container = cloned.container;
|
||||
const essentialsWorkspaces = cloned.workspaces;
|
||||
const repeats = cloned.repeat;
|
||||
// Animate like the workspaces above expect essentials are a bit more
|
||||
// complicated because they are not based on workspaces but on containers
|
||||
// So, if we have the following arangement:
|
||||
// | [workspace1] [workspace2] [workspace3] [workspace4]
|
||||
// | [container1] [container1] [container2] [container1]
|
||||
// And if we are changing from workspace 1 to workspace 4,
|
||||
// we should be doing the following:
|
||||
// First container (repeat 2 times) will stay in place until
|
||||
// we reach container 3, then animate to the left and container 2
|
||||
// also move to the left after that while container 1 in workspace 4
|
||||
// will slide in from the right
|
||||
|
||||
// Get the index from first and last workspace
|
||||
const firstWorkspaceIndex = workspaces.findIndex(
|
||||
w => w.uuid === essentialsWorkspaces[0].uuid
|
||||
);
|
||||
const lastWorkspaceIndex = workspaces.findIndex(
|
||||
w =>
|
||||
w.uuid ===
|
||||
essentialsWorkspaces[essentialsWorkspaces.length - 1].uuid
|
||||
);
|
||||
cloned.originalContainer.style.removeProperty("transform");
|
||||
// Check if the container is even going to appear on the screen, to save on animation
|
||||
if (
|
||||
// We also need to check if the container is even going to appear on the screen.
|
||||
// In order to do this, we need to check if the container is between the first and last workspace.
|
||||
// Note that essential containers can have multiple workspaces,
|
||||
// so we need to check if any of the workspaces in the container are between the
|
||||
// first and last workspace.
|
||||
!essentialsContainersInBetween.find(
|
||||
ce =>
|
||||
ce.workspaces.some(
|
||||
w => w.uuid === essentialsWorkspaces[0].uuid
|
||||
) &&
|
||||
ce.workspaces.some(
|
||||
w =>
|
||||
w.uuid ===
|
||||
essentialsWorkspaces[essentialsWorkspaces.length - 1].uuid
|
||||
)
|
||||
)
|
||||
) {
|
||||
if (!containsPrev && !containsNew) {
|
||||
container.setAttribute("hidden", "true");
|
||||
continue;
|
||||
}
|
||||
cloned.originalContainer.parentNode.appendChild(container);
|
||||
let stepsInBetween =
|
||||
Math.abs(
|
||||
newWorkspaceIndex -
|
||||
(isGoingLeft ? firstWorkspaceIndex : lastWorkspaceIndex)
|
||||
) + 1;
|
||||
const usingSameContainer =
|
||||
newWorkspaceEssentialsContainer?.workspaces.some(
|
||||
w => w.uuid === newWorkspace.uuid
|
||||
) &&
|
||||
newWorkspaceEssentialsContainer?.workspaces.some(
|
||||
w => w.uuid === previousWorkspace.uuid
|
||||
);
|
||||
let newOffset =
|
||||
-(
|
||||
newWorkspaceIndex -
|
||||
(isGoingLeft ? firstWorkspaceIndex : lastWorkspaceIndex) +
|
||||
(!isGoingLeft ? repeats - 1 : -repeats + 1)
|
||||
) * 100;
|
||||
|
||||
let existingOffset =
|
||||
-(
|
||||
newWorkspaceIndex -
|
||||
(isGoingLeft ? lastWorkspaceIndex : firstWorkspaceIndex) +
|
||||
(isGoingLeft ? repeats - 1 : -repeats + 1)
|
||||
) * 100;
|
||||
container.removeAttribute("hidden");
|
||||
|
||||
// If we are on the same container and both new and old workspace are in the same "essentialsWorkspaces"
|
||||
// we can simply not animate the essentials
|
||||
if (
|
||||
usingSameContainer &&
|
||||
essentialsWorkspaces.some(w => w.uuid === newWorkspace.uuid) &&
|
||||
essentialsWorkspaces.some(w => w.uuid === previousWorkspace.uuid)
|
||||
) {
|
||||
newOffset = 0;
|
||||
existingOffset = 0;
|
||||
if (containsPrev && containsNew) {
|
||||
container.style.transform = "translateX(0%)";
|
||||
continue;
|
||||
}
|
||||
|
||||
const needsOffsetAdjustment =
|
||||
stepsInBetween > essentialsWorkspaces.length || usingSameContainer;
|
||||
let existingOffset, newOffset;
|
||||
const currentTransform =
|
||||
parseFloat(container.style.transform.split("(")[1]) || 0;
|
||||
if (containsPrev && !containsNew) {
|
||||
existingOffset = currentTransform;
|
||||
newOffset = isGoingLeft ? 100 : -100;
|
||||
} else {
|
||||
existingOffset = currentTransform || (isGoingLeft ? -100 : 100);
|
||||
newOffset = 0;
|
||||
}
|
||||
|
||||
if (repeats > 0 && needsOffsetAdjustment) {
|
||||
if (!isGoingLeft) {
|
||||
if (existingOffset !== 0) {
|
||||
existingOffset += 100;
|
||||
}
|
||||
if (newOffset !== 0) {
|
||||
newOffset += 100;
|
||||
}
|
||||
if (spaceLen === 2) {
|
||||
if (containsPrev && !containsNew) {
|
||||
existingOffset = currentTransform;
|
||||
newOffset = currentTransform >= 0 ? 100 : -100;
|
||||
} else {
|
||||
if (existingOffset !== 0) {
|
||||
existingOffset -= 100;
|
||||
}
|
||||
if (newOffset !== 0) {
|
||||
newOffset -= 100;
|
||||
}
|
||||
existingOffset = currentTransform >= 0 ? 100 : -100;
|
||||
newOffset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Special case: going forward from single reused container to a new one
|
||||
if (
|
||||
!usingSameContainer &&
|
||||
!isGoingLeft &&
|
||||
lastWorkspaceIndex === newWorkspaceIndex - 1
|
||||
) {
|
||||
existingOffset = 0;
|
||||
newOffset = -100;
|
||||
stepsInBetween = 1;
|
||||
}
|
||||
if (
|
||||
!usingSameContainer &&
|
||||
isGoingLeft &&
|
||||
firstWorkspaceIndex === newWorkspaceIndex + 1
|
||||
) {
|
||||
existingOffset = 0;
|
||||
newOffset = 100;
|
||||
stepsInBetween = 1;
|
||||
}
|
||||
if (
|
||||
!usingSameContainer &&
|
||||
isGoingLeft &&
|
||||
(firstWorkspaceIndex === newWorkspaceIndex - 1 ||
|
||||
firstWorkspaceIndex === newWorkspaceIndex)
|
||||
) {
|
||||
existingOffset = -100;
|
||||
newOffset = 0;
|
||||
stepsInBetween = 1;
|
||||
}
|
||||
if (
|
||||
!usingSameContainer &&
|
||||
!isGoingLeft &&
|
||||
firstWorkspaceIndex === newWorkspaceIndex
|
||||
) {
|
||||
existingOffset = 100;
|
||||
newOffset = 0;
|
||||
stepsInBetween = 1;
|
||||
}
|
||||
|
||||
const newTransform = `translateX(${newOffset}%)`;
|
||||
let existingTransform = `translateX(${existingOffset}%)`;
|
||||
if (container.style.transform && container.style.transform !== "none") {
|
||||
existingTransform = container.style.transform;
|
||||
}
|
||||
if (shouldAnimate) {
|
||||
container.style.transform = existingTransform;
|
||||
animations.push(
|
||||
gZenUIManager.motion.animate(
|
||||
container,
|
||||
{
|
||||
transform: [
|
||||
existingTransform,
|
||||
new Array(stepsInBetween).fill(newTransform).join(","),
|
||||
],
|
||||
transform: [existingTransform, newTransform],
|
||||
},
|
||||
{
|
||||
type: "spring",
|
||||
@@ -2357,17 +2229,12 @@ class nsZenWorkspaces {
|
||||
this.#currentSpaceSwitchContext.animations = [];
|
||||
document.documentElement.removeAttribute("animating-background");
|
||||
if (shouldAnimate) {
|
||||
for (const cloned of clonedEssentials) {
|
||||
cloned.container.remove();
|
||||
for (const data of essentialsAnimData) {
|
||||
data.element.style.removeProperty("transform");
|
||||
}
|
||||
this._alwaysAnimatePaddingTop = true;
|
||||
this.updateTabsContainers();
|
||||
}
|
||||
const essentialsContainer = this.getEssentialsSection(
|
||||
newWorkspace.containerTabId
|
||||
);
|
||||
essentialsContainer.removeAttribute("hidden");
|
||||
essentialsContainer.style.transform = "none";
|
||||
gBrowser.tabContainer._invalidateCachedTabs();
|
||||
gZenUIManager.tabsWrapper.style.removeProperty("scrollbar-width");
|
||||
this._animatingChange = false;
|
||||
@@ -3242,9 +3109,6 @@ class nsZenWorkspaces {
|
||||
...normalContainers,
|
||||
];
|
||||
for (const container of containers) {
|
||||
if (container.hasAttribute("cloned")) {
|
||||
continue;
|
||||
}
|
||||
for (const tab of container.children) {
|
||||
if (gBrowser.isTab(tab)) {
|
||||
tabs.push(tab);
|
||||
|
||||
@@ -1156,10 +1156,6 @@
|
||||
pointer-events: none;
|
||||
position: fixed; /* Fix position to prevent scrolling */
|
||||
}
|
||||
|
||||
&[cloned] {
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
.tabbrowser-tab[zen-essential="true"],
|
||||
|
||||
Reference in New Issue
Block a user