Refactor tab drag-and-drop functionality and enhance drag indicator styling

This commit is contained in:
mr. M
2025-01-31 23:02:13 +01:00
parent 00de303335
commit 7b41eb753d
4 changed files with 88 additions and 77 deletions

View File

@@ -285,7 +285,6 @@
padding: 0 !important; padding: 0 !important;
position: relative; position: relative;
border-radius: var(--border-radius-medium);
& .tab-background { & .tab-background {
overflow: hidden; overflow: hidden;
@@ -1072,21 +1071,32 @@
} }
} }
#vertical-pinned-tabs-container .tabbrowser-tab,
#tabbrowser-arrowscrollbox .tabbrowser-tab,
#zen-essentials-container .tabbrowser-tab {
transition: box-shadow 0.2s ease-in-out;
}
/* Vertical tabs reordering indicators */ /* Vertical tabs reordering indicators */
#vertical-pinned-tabs-container .tabbrowser-tab.drag-over-before, #zen-drag-indicator {
#tabbrowser-arrowscrollbox .tabbrowser-tab.drag-over-before { --zen-drag-indicator-height: 2px;
box-shadow: 0 3px 6px -2px var(--toolbarbutton-active-background, rgba(0, 0, 255, 0.2)); --zen-drag-indicator-bg: color-mix(in srgb, var(--zen-primary-color) 50%, light-dark(rgba(0, 0, 0, .85), rgba(255, 255, 255, .95)) 50%);
} width: calc(var(--indicator-width) - 2 * var(--zen-drag-indicator-height) - 4px);
height: var(--zen-drag-indicator-height);
position: fixed;
z-index: 1000;
background: var(--zen-drag-indicator-bg);
transition: top 0.1s ease;
pointer-events: none;
left: calc(var(--indicator-left) + 2 * var(--zen-drag-indicator-height) + 4px);
border-radius: 5px;
#vertical-pinned-tabs-container .tabbrowser-tab.drag-over-after, &::before {
#tabbrowser-arrowscrollbox .tabbrowser-tab.drag-over-after { content: "";
box-shadow: 0 -3px 6px -2px var(--toolbarbutton-active-background, rgba(0, 0, 255, 0.2)); position: absolute;
left: calc(-2 * var(--zen-drag-indicator-height));
top: 50%;
height: calc(2 * var(--zen-drag-indicator-height));
width: calc(2 * var(--zen-drag-indicator-height));
border: var(--zen-drag-indicator-height) solid var(--zen-drag-indicator-bg);
border-radius: 50%;
transform: translate(calc(-1 * var(--zen-drag-indicator-height)), -50%);
background: transparent;
}
} }
/* Horizontal tabs reordering indicators */ /* Horizontal tabs reordering indicators */

View File

@@ -328,7 +328,7 @@
const actualPin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id')); const actualPin = this._pinsCache.find((pin) => pin.uuid === tab.getAttribute('zen-pin-id'));
if(!actualPin) { if (!actualPin) {
return; return;
} }
actualPin.position = tab.position; actualPin.position = tab.position;
@@ -646,9 +646,9 @@
} }
moveToAnotherTabContainerIfNecessary(event, draggedTab) { moveToAnotherTabContainerIfNecessary(event, draggedTab) {
const pinnedTabsTarget = event.target.closest("#vertical-pinned-tabs-container"); const pinnedTabsTarget = event.target.closest('#vertical-pinned-tabs-container');
const essentialTabsTarget = event.target.closest("#zen-essentials-container"); const essentialTabsTarget = event.target.closest('#zen-essentials-container');
const tabsTarget = event.target.closest("#tabbrowser-arrowscrollbox"); const tabsTarget = event.target.closest('#tabbrowser-arrowscrollbox');
let moved = false; let moved = false;
let isVertical = true; let isVertical = true;
@@ -658,7 +658,7 @@
if (!draggedTab.pinned) { if (!draggedTab.pinned) {
gBrowser.pinTab(draggedTab); gBrowser.pinTab(draggedTab);
moved = true; moved = true;
} else if (draggedTab.hasAttribute("zen-essential")) { } else if (draggedTab.hasAttribute('zen-essential')) {
this.removeEssentials(draggedTab); this.removeEssentials(draggedTab);
gBrowser.pinTab(draggedTab); gBrowser.pinTab(draggedTab);
moved = true; moved = true;
@@ -666,7 +666,7 @@
} }
// Check for essentials container // Check for essentials container
else if (essentialTabsTarget) { else if (essentialTabsTarget) {
if (!draggedTab.hasAttribute("zen-essential")) { if (!draggedTab.hasAttribute('zen-essential')) {
this.addToEssentials(draggedTab); this.addToEssentials(draggedTab);
moved = true; moved = true;
isVertical = false; isVertical = false;
@@ -674,11 +674,11 @@
} }
// Check for normal tabs container // Check for normal tabs container
else if (tabsTarget) { else if (tabsTarget) {
if (draggedTab.pinned && !draggedTab.hasAttribute("zen-essential")) { if (draggedTab.pinned && !draggedTab.hasAttribute('zen-essential')) {
gBrowser.unpinTab(draggedTab); gBrowser.unpinTab(draggedTab);
moved = true; moved = true;
isRegularTabs = true; isRegularTabs = true;
} else if (draggedTab.hasAttribute("zen-essential")) { } else if (draggedTab.hasAttribute('zen-essential')) {
this.removeEssentials(draggedTab); this.removeEssentials(draggedTab);
moved = true; moved = true;
isRegularTabs = true; isRegularTabs = true;
@@ -687,19 +687,18 @@
// If the tab was moved, adjust its position relative to the target tab // If the tab was moved, adjust its position relative to the target tab
if (moved) { if (moved) {
const targetTab = event.target.closest(".tabbrowser-tab"); const targetTab = event.target.closest('.tabbrowser-tab');
if (targetTab) { if (targetTab) {
const rect = targetTab.getBoundingClientRect(); const rect = targetTab.getBoundingClientRect();
let newIndex = targetTab._tPos; let newIndex = targetTab._tPos;
if (isVertical) { if (isVertical) {
const middleY = targetTab.screenY + rect.height / 2; const middleY = targetTab.screenY + rect.height / 2;
if(!isRegularTabs && event.screenY > middleY) { if (!isRegularTabs && event.screenY > middleY) {
newIndex++; newIndex++;
} else if(isRegularTabs && event.screenY < middleY) { } else if (isRegularTabs && event.screenY < middleY) {
newIndex--; newIndex--;
} }
} else { } else {
const middleX = targetTab.screenX + rect.width / 2; const middleX = targetTab.screenX + rect.width / 2;
if (event.screenX > middleX) { if (event.screenX > middleX) {
@@ -714,20 +713,24 @@
} }
removeTabContainersDragoverClass() { removeTabContainersDragoverClass() {
document this.dragIndicator.remove();
.querySelectorAll(".tabbrowser-tab.drag-over-before, .tabbrowser-tab.drag-over-after") this._dragIndicator = null;
.forEach(tab => { }
tab.classList.remove("drag-over-before", "drag-over-after");
}); get dragIndicator() {
if (!this._dragIndicator) {
this._dragIndicator = document.createElement('div');
this._dragIndicator.id = 'zen-drag-indicator';
document.body.appendChild(this._dragIndicator);
}
return this._dragIndicator;
} }
applyDragoverClass(event, draggedTab) { applyDragoverClass(event, draggedTab) {
this.removeTabContainersDragoverClass(); const pinnedTabsTarget = event.target.closest('#vertical-pinned-tabs-container');
const essentialTabsTarget = event.target.closest('#zen-essentials-container');
const pinnedTabsTarget = event.target.closest("#vertical-pinned-tabs-container"); const tabsTarget = event.target.closest('#tabbrowser-arrowscrollbox');
const essentialTabsTarget = event.target.closest("#zen-essentials-container"); const targetTab = event.target.closest('.tabbrowser-tab');
const tabsTarget = event.target.closest("#tabbrowser-arrowscrollbox");
const targetTab = event.target.closest(".tabbrowser-tab");
// If there's no valid target tab, nothing to do // If there's no valid target tab, nothing to do
if (!targetTab) { if (!targetTab) {
@@ -739,16 +742,16 @@
// Decide whether we should show a dragover class for the given target // Decide whether we should show a dragover class for the given target
if (pinnedTabsTarget) { if (pinnedTabsTarget) {
if (!draggedTab.pinned || draggedTab.hasAttribute("zen-essential")) { if (!draggedTab.pinned || draggedTab.hasAttribute('zen-essential')) {
shouldAddDragOverElement = true; shouldAddDragOverElement = true;
} }
} else if (essentialTabsTarget) { } else if (essentialTabsTarget) {
if (!draggedTab.hasAttribute("zen-essential")) { if (!draggedTab.hasAttribute('zen-essential')) {
shouldAddDragOverElement = true; shouldAddDragOverElement = true;
isVertical = false; isVertical = false;
} }
} else if (tabsTarget) { } else if (tabsTarget) {
if (draggedTab.pinned || draggedTab.hasAttribute("zen-essential")) { if (draggedTab.pinned || draggedTab.hasAttribute('zen-essential')) {
shouldAddDragOverElement = true; shouldAddDragOverElement = true;
} }
} }
@@ -761,19 +764,20 @@
const rect = targetTab.getBoundingClientRect(); const rect = targetTab.getBoundingClientRect();
if (isVertical) { if (isVertical) {
const separation = 8;
const middleY = targetTab.screenY + rect.height / 2; const middleY = targetTab.screenY + rect.height / 2;
const indicator = this.dragIndicator;
let top=0;
if (event.screenY > middleY) { if (event.screenY > middleY) {
targetTab.classList.add("drag-over-before"); top = rect.top + rect.height + 'px';
} else { } else {
targetTab.classList.add("drag-over-after"); top = rect.top + 'px';
} }
indicator.style.setProperty('--indicator-left', rect.left + (separation/2) + 'px');
indicator.style.setProperty('--indicator-width', rect.width - separation + 'px');
indicator.style.top = top;
} else { } else {
const middleX = targetTab.screenX + rect.width / 2; // SUPPORT FOR ESSENTIALS
if (event.screenX > middleX) {
targetTab.classList.add("drag-over-before");
} else {
targetTab.classList.add("drag-over-after");
}
} }
} }
} }

View File

@@ -1815,9 +1815,13 @@ var ZenWorkspaces = new (class extends ZenMultiWindowFeature {
if (matchingWorkspaces.length === 1) { if (matchingWorkspaces.length === 1) {
const workspace = matchingWorkspaces[0]; const workspace = matchingWorkspaces[0];
if (workspace.uuid !== this.getActiveWorkspaceFromCache().uuid) { if (workspace.uuid !== this.getActiveWorkspaceFromCache().uuid) {
window.addEventListener('TabSelected', (event) => { window.addEventListener(
this.changeWorkspace(workspace, { alwaysChange: true }); 'TabSelected',
}, { once: true }); (event) => {
this.changeWorkspace(workspace, { alwaysChange: true });
},
{ once: true }
);
return [userContextId, true, workspace.uuid]; return [userContextId, true, workspace.uuid];
} }
} }

View File

@@ -1,5 +1,5 @@
diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js diff --git a/browser/components/tabbrowser/content/tabs.js b/browser/components/tabbrowser/content/tabs.js
index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc790e25a5f1 100644 index 8aeb244ffca9f48661805f5b7d860b5896055562..35f5562d60d70ac4e117c7f098d96eccdd9bbbc4 100644
--- a/browser/components/tabbrowser/content/tabs.js --- a/browser/components/tabbrowser/content/tabs.js
+++ b/browser/components/tabbrowser/content/tabs.js +++ b/browser/components/tabbrowser/content/tabs.js
@@ -94,7 +94,7 @@ @@ -94,7 +94,7 @@
@@ -39,15 +39,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
if ( if (
(effects == "move" || effects == "copy") && (effects == "move" || effects == "copy") &&
this == draggedTab.container && this == draggedTab.container &&
@@ -955,6 +958,7 @@ @@ -972,6 +975,14 @@
// eslint-disable-next-line complexity
on_drop(event) {
+ gZenPinnedTabManager.removeTabContainersDragoverClass();
var dt = event.dataTransfer;
var dropEffect = dt.dropEffect;
var draggedTab;
@@ -972,6 +976,14 @@
this._tabDropIndicator.hidden = true; this._tabDropIndicator.hidden = true;
event.stopPropagation(); event.stopPropagation();
@@ -62,7 +54,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
if (draggedTab && dropEffect == "copy") { if (draggedTab && dropEffect == "copy") {
// copy the dropped tab (wherever it's from) // copy the dropped tab (wherever it's from)
let newIndex = this._getDropIndex(event); let newIndex = this._getDropIndex(event);
@@ -1010,7 +1022,7 @@ @@ -1010,7 +1021,7 @@
} }
} else { } else {
let pinned = draggedTab.pinned; let pinned = draggedTab.pinned;
@@ -71,7 +63,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
let tabs = this.visibleTabs.slice( let tabs = this.visibleTabs.slice(
pinned ? 0 : numPinned, pinned ? 0 : numPinned,
pinned ? numPinned : undefined pinned ? numPinned : undefined
@@ -1090,7 +1102,7 @@ @@ -1090,7 +1101,7 @@
let postTransitionCleanup = () => { let postTransitionCleanup = () => {
tab.removeAttribute("tabdrop-samewindow"); tab.removeAttribute("tabdrop-samewindow");
@@ -80,7 +72,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
if (dropIndex !== false) { if (dropIndex !== false) {
gBrowser.moveTabTo(tab, dropIndex); gBrowser.moveTabTo(tab, dropIndex);
if (!directionForward) { if (!directionForward) {
@@ -1100,7 +1112,7 @@ @@ -1100,7 +1111,7 @@
gBrowser.syncThrobberAnimations(tab); gBrowser.syncThrobberAnimations(tab);
}; };
@@ -89,7 +81,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
postTransitionCleanup(); postTransitionCleanup();
} else { } else {
let onTransitionEnd = transitionendEvent => { let onTransitionEnd = transitionendEvent => {
@@ -1263,7 +1275,8 @@ @@ -1263,7 +1274,8 @@
if ( if (
dt.mozUserCancelled || dt.mozUserCancelled ||
dt.dropEffect != "none" || dt.dropEffect != "none" ||
@@ -99,7 +91,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
) { ) {
delete draggedTab._dragData; delete draggedTab._dragData;
return; return;
@@ -1512,7 +1525,7 @@ @@ -1512,7 +1524,7 @@
} }
this.#allTabs = [ this.#allTabs = [
@@ -108,7 +100,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
...children, ...children,
]; ];
return this.#allTabs; return this.#allTabs;
@@ -1593,6 +1606,7 @@ @@ -1593,6 +1605,7 @@
} }
this.#focusableItems = [ this.#focusableItems = [
@@ -116,7 +108,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
...verticalPinnedTabsContainer.children, ...verticalPinnedTabsContainer.children,
...focusableItems, ...focusableItems,
]; ];
@@ -1617,8 +1631,8 @@ @@ -1617,8 +1630,8 @@
#isContainerVerticalPinnedExpanded(tab) { #isContainerVerticalPinnedExpanded(tab) {
return ( return (
this.verticalMode && this.verticalMode &&
@@ -127,7 +119,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
); );
} }
@@ -1816,7 +1830,7 @@ @@ -1816,7 +1829,7 @@
let rect = ele => { let rect = ele => {
return window.windowUtils.getBoundsWithoutFlushing(ele); return window.windowUtils.getBoundsWithoutFlushing(ele);
}; };
@@ -136,7 +128,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
if (tab && rect(tab).width <= this._tabClipWidth) { if (tab && rect(tab).width <= this._tabClipWidth) {
this.setAttribute("closebuttons", "activetab"); this.setAttribute("closebuttons", "activetab");
} else { } else {
@@ -1832,6 +1846,7 @@ @@ -1832,6 +1845,7 @@
this.arrowScrollbox.ensureElementIsVisible(selectedTab, aInstant); this.arrowScrollbox.ensureElementIsVisible(selectedTab, aInstant);
} }
@@ -144,7 +136,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
selectedTab._notselectedsinceload = false; selectedTab._notselectedsinceload = false;
} }
@@ -1879,7 +1894,7 @@ @@ -1879,7 +1893,7 @@
if (isEndTab && !this._hasTabTempMaxWidth) { if (isEndTab && !this._hasTabTempMaxWidth) {
return; return;
} }
@@ -153,7 +145,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
// Force tabs to stay the same width, unless we're closing the last tab, // Force tabs to stay the same width, unless we're closing the last tab,
// which case we need to let them expand just enough so that the overall // which case we need to let them expand just enough so that the overall
// tabbar width is the same. // tabbar width is the same.
@@ -1894,7 +1909,7 @@ @@ -1894,7 +1908,7 @@
let tabsToReset = []; let tabsToReset = [];
for (let i = numPinned; i < tabs.length; i++) { for (let i = numPinned; i < tabs.length; i++) {
let tab = tabs[i]; let tab = tabs[i];
@@ -162,7 +154,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
if (!isEndTab) { if (!isEndTab) {
// keep tabs the same width // keep tabs the same width
tab.style.transition = "none"; tab.style.transition = "none";
@@ -1963,13 +1978,13 @@ @@ -1963,13 +1977,13 @@
let verticalTabsContainer = document.getElementById( let verticalTabsContainer = document.getElementById(
"vertical-pinned-tabs-container" "vertical-pinned-tabs-container"
); );
@@ -179,7 +171,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
} }
} }
@@ -1993,7 +2008,7 @@ @@ -1993,7 +2007,7 @@
_positionPinnedTabs() { _positionPinnedTabs() {
let tabs = this.visibleTabs; let tabs = this.visibleTabs;
@@ -188,7 +180,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
let absPositionHorizontalTabs = let absPositionHorizontalTabs =
this.overflowing && tabs.length > numPinned && numPinned > 0; this.overflowing && tabs.length > numPinned && numPinned > 0;
@@ -2074,7 +2089,7 @@ @@ -2074,7 +2088,7 @@
return; return;
} }
@@ -197,7 +189,7 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
let directionX = screenX > dragData.animLastScreenX; let directionX = screenX > dragData.animLastScreenX;
let directionY = screenY > dragData.animLastScreenY; let directionY = screenY > dragData.animLastScreenY;
@@ -2257,9 +2272,9 @@ @@ -2257,9 +2271,9 @@
} }
let pinned = draggedTab.pinned; let pinned = draggedTab.pinned;
@@ -209,13 +201,14 @@ index 8aeb244ffca9f48661805f5b7d860b5896055562..aa672d49e5d3e8e0ce4747187becbc79
pinned ? numPinned : undefined pinned ? numPinned : undefined
); );
@@ -2502,8 +2517,8 @@ @@ -2502,8 +2516,9 @@
); );
} }
- _finishAnimateTabMove() { - _finishAnimateTabMove() {
- if (!this.hasAttribute("movingtab")) { - if (!this.hasAttribute("movingtab")) {
+ _finishAnimateTabMove(always = false) { + _finishAnimateTabMove(always = false) {
+ gZenPinnedTabManager.removeTabContainersDragoverClass();
+ if (!this.hasAttribute("movingtab") && !always) { + if (!this.hasAttribute("movingtab") && !always) {
return; return;
} }