Fix reordering for KDE, and dragging to the end

Fixes #2705 -

The drag-drop API does not work on this extension under KDE.
Switching over to mouse events retains this ability, and works under KDE.
Note: I have note tested outside KDE.

Fixes #2665 -

In addition, this also fixes the issue of moving to the end.
This commit is contained in:
Arnab Bose 2025-03-10 15:33:41 +05:30
parent a60f5bb1be
commit 1b5ba22305
2 changed files with 43 additions and 43 deletions

28
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "testpilot-containers", "name": "testpilot-containers",
"version": "8.1.3", "version": "8.2.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "testpilot-containers", "name": "testpilot-containers",
"version": "8.1.1", "version": "8.2.0",
"license": "MPL-2.0", "license": "MPL-2.0",
"devDependencies": { "devDependencies": {
"addons-linter": "^5.28.0", "addons-linter": "^5.28.0",
@ -15032,8 +15032,7 @@
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true, "dev": true
"requires": {}
}, },
"acorn-walk": { "acorn-walk": {
"version": "7.2.0", "version": "7.2.0",
@ -17246,15 +17245,13 @@
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.2.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.2.tgz",
"integrity": "sha512-Pry0S9YmHoz8NCEMRQh7N0Yexh2MYCNPIlrV52hTmS7qXnTghWsjXouF08bgsrrZqaW9tt1ZiK3j5NEmPE+EjQ==", "integrity": "sha512-Pry0S9YmHoz8NCEMRQh7N0Yexh2MYCNPIlrV52hTmS7qXnTghWsjXouF08bgsrrZqaW9tt1ZiK3j5NEmPE+EjQ==",
"dev": true, "dev": true
"requires": {}
}, },
"eslint-plugin-promise": { "eslint-plugin-promise": {
"version": "5.2.0", "version": "5.2.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz",
"integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==", "integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==",
"dev": true, "dev": true
"requires": {}
}, },
"eslint-scope": { "eslint-scope": {
"version": "5.1.1", "version": "5.1.1",
@ -19763,8 +19760,7 @@
"version": "7.5.9", "version": "7.5.9",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
"dev": true, "dev": true
"requires": {}
} }
} }
}, },
@ -21971,8 +21967,7 @@
"version": "0.36.2", "version": "0.36.2",
"resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz",
"integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==", "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==",
"dev": true, "dev": true
"requires": {}
}, },
"postcss-value-parser": { "postcss-value-parser": {
"version": "4.2.0", "version": "4.2.0",
@ -22826,8 +22821,7 @@
"version": "3.7.0", "version": "3.7.0",
"resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz",
"integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==",
"dev": true, "dev": true
"requires": {}
}, },
"slash": { "slash": {
"version": "3.0.0", "version": "3.0.0",
@ -23571,8 +23565,7 @@
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-3.0.0.tgz", "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-3.0.0.tgz",
"integrity": "sha512-F6yTRuc06xr1h5Qw/ykb2LuFynJ2IxkKfCMf+1xqPffkxh0S09Zc902XCffcsw/XMFq/OzQ1w54fLIDtmRNHnQ==", "integrity": "sha512-F6yTRuc06xr1h5Qw/ykb2LuFynJ2IxkKfCMf+1xqPffkxh0S09Zc902XCffcsw/XMFq/OzQ1w54fLIDtmRNHnQ==",
"dev": true, "dev": true
"requires": {}
}, },
"stylelint-config-standard": { "stylelint-config-standard": {
"version": "20.0.0", "version": "20.0.0",
@ -24946,8 +24939,7 @@
"version": "8.12.0", "version": "8.12.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz",
"integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==",
"dev": true, "dev": true
"requires": {}
}, },
"xdg-basedir": { "xdg-basedir": {
"version": "5.1.0", "version": "5.1.0",

View file

@ -10,7 +10,6 @@ const DEFAULT_ICON = "circle";
const NEW_CONTAINER_ID = "new"; const NEW_CONTAINER_ID = "new";
const ONBOARDING_STORAGE_KEY = "onboarding-stage"; const ONBOARDING_STORAGE_KEY = "onboarding-stage";
const CONTAINER_DRAG_DATA_TYPE = "firefox-container";
// List of panels // List of panels
const P_ONBOARDING_1 = "onboarding1"; const P_ONBOARDING_1 = "onboarding1";
@ -129,7 +128,7 @@ const Logic = {
notificationCards.forEach(notificationCard => { notificationCards.forEach(notificationCard => {
notificationCard.textContent = text; notificationCard.textContent = text;
notificationCard.classList.add("is-shown"); notificationCard.classList.add("is-shown");
setTimeout(() => { setTimeout(() => {
notificationCard.classList.remove("is-shown"); notificationCard.classList.remove("is-shown");
}, 2000); }, 2000);
@ -1198,6 +1197,8 @@ Logic.registerPanel(MANAGE_CONTAINERS_PICKER, {
const identities = Logic.identities(); const identities = Logic.identities();
let dataBeingDragged = null;
for (const identity of identities) { for (const identity of identities) {
const tr = document.createElement("tr"); const tr = document.createElement("tr");
tr.classList.add("menu-item", "hover-highlight", "keyboard-nav"); tr.classList.add("menu-item", "hover-highlight", "keyboard-nav");
@ -1226,42 +1227,49 @@ Logic.registerPanel(MANAGE_CONTAINERS_PICKER, {
tr.appendChild(td); tr.appendChild(td);
tr.draggable = true;
tr.dataset.containerId = identity.cookieStoreId; tr.dataset.containerId = identity.cookieStoreId;
tr.addEventListener("dragstart", (e) => { // Note: The draggable API does not appear to work with this extension on KDE.
e.dataTransfer.setData(CONTAINER_DRAG_DATA_TYPE, identity.cookieStoreId); // Thus we use mouse events instead of drag events.
}); tr.addEventListener("mousedown", (e) => {
tr.addEventListener("dragover", (e) => { if (e.target.closest(".move-button")) {
if (e.dataTransfer.types.includes(CONTAINER_DRAG_DATA_TYPE)) { dataBeingDragged = identity.cookieStoreId;
tr.classList.add("drag-over");
e.preventDefault();
} }
}); });
tr.addEventListener("dragenter", (e) => { tr.addEventListener("mouseover", () => {
if (e.dataTransfer.types.includes(CONTAINER_DRAG_DATA_TYPE)) { if (dataBeingDragged !== null) tr.classList.add("drag-over");
e.preventDefault();
tr.classList.add("drag-over");
}
}); });
tr.addEventListener("dragleave", (e) => { tr.addEventListener("mouseleave", () => {
if (e.dataTransfer.types.includes(CONTAINER_DRAG_DATA_TYPE)) { if (dataBeingDragged !== null) tr.classList.remove("drag-over");
e.preventDefault();
tr.classList.remove("drag-over");
}
}); });
tr.addEventListener("drop", async (e) => { tr.addEventListener("mouseup", async () => {
e.preventDefault(); if (dataBeingDragged === null) return;
const parent = tr.parentNode; const parent = tr.parentNode;
const containerId = e.dataTransfer.getData(CONTAINER_DRAG_DATA_TYPE); const containerId = dataBeingDragged;
dataBeingDragged = null;
let droppedElement; let droppedElement;
let dropAfter = false;
parent.childNodes.forEach((node) => { parent.childNodes.forEach((node) => {
if (node === tr && droppedElement !== undefined) {
// If the element being dropped was before this tr, drop after this tr.
dropAfter = true;
}
if (node.dataset.containerId === containerId) { if (node.dataset.containerId === containerId) {
droppedElement = node; droppedElement = node;
} }
}); });
if (droppedElement && droppedElement !== tr) { if (droppedElement && droppedElement !== tr) {
tr.classList.remove("drag-over"); tr.classList.remove("drag-over");
parent.insertBefore(droppedElement, tr); if (dropAfter) {
// Drop it after this tr.
const nextSibling = tr.nextSibling;
if (nextSibling) {
parent.insertBefore(droppedElement, nextSibling);
} else {
parent.appendChild(droppedElement);
}
} else {
parent.insertBefore(droppedElement, tr);
}
await Logic.saveContainerOrder(parent.childNodes); await Logic.saveContainerOrder(parent.childNodes);
await Logic.refreshIdentities(); await Logic.refreshIdentities();
} }
@ -2319,7 +2327,7 @@ Logic.registerPanel(P_CLEAR_CONTAINER_STORAGE, {
// This method is called when the panel is shown. // This method is called when the panel is shown.
prepare() { prepare() {
const identity = Logic.currentIdentity(); const identity = Logic.currentIdentity();
// Populating the panel: name, icon, and warning message // Populating the panel: name, icon, and warning message
document.getElementById("container-clear-storage-title").textContent = identity.name; document.getElementById("container-clear-storage-title").textContent = identity.name;
return Promise.resolve(null); return Promise.resolve(null);