From de5f66648ae2f76b666dd987c6c38bb472bec4d5 Mon Sep 17 00:00:00 2001 From: "mr. M" Date: Sun, 3 Nov 2024 10:21:53 +0100 Subject: [PATCH] Refactor code to improve performance --- src/ZenEssentialsToolbar.mjs | 831 ----------------------------------- 1 file changed, 831 deletions(-) delete mode 100644 src/ZenEssentialsToolbar.mjs diff --git a/src/ZenEssentialsToolbar.mjs b/src/ZenEssentialsToolbar.mjs deleted file mode 100644 index 0701875..0000000 --- a/src/ZenEssentialsToolbar.mjs +++ /dev/null @@ -1,831 +0,0 @@ - -class ZenEssentialsToolbar extends PlacesViewBase { - constructor(placesUrl) { - ZenEssentialsToolbar._initInitialLayout(); - - // We'll initialize the places URL after ensuring the folder exists - super(null, document.getElementById("EssentialsToolbarItems"), document.getElementById("EssentialsToolbar")); - // Do initialization of properties that don't depend on Places - this._init(); - this._initPlacesFolder(); - } - - get _accordionHeader() { - return document.getElementById("essentials-accordion-header"); - } - - async _initPlacesFolder() { - try { - const ESSENTIALS_GUID = "pfgqteRgY-Wr"; // Fixed GUID for the folder - - // First try to fetch by GUID since it's more efficient - let folder = await PlacesUtils.bookmarks.fetch(ESSENTIALS_GUID ); - - if (!folder) { - // If not found by GUID, try creating with our specific GUID - // try { - folder = await PlacesUtils.bookmarks.insert({ - type: PlacesUtils.bookmarks.TYPE_FOLDER, - guid: ESSENTIALS_GUID, - title: "Zen Essentials", - parentGuid: PlacesUtils.bookmarks.menuGuid - }); - } - - // Ensure the folder is in the right place with the right title - if (folder.parentGuid !== PlacesUtils.bookmarks.menuGuid || - folder.title !== "Zen Essentials") { - await PlacesUtils.bookmarks.update({ - guid: folder.guid, - title: "Zen Essentials", - parentGuid: PlacesUtils.bookmarks.menuGuid, - index: folder.index - }); - } - - if(!folder) { - console.error("Failed to initialize ZenEssentials folder"); - return; - } - - // Now that we have the folder, set up the places URL - this.place = `place:parent=${folder.guid}`; - - // Initialize view event listeners and setup - this._setupEventListeners(); - - } catch (ex) { - console.error("Failed to initialize ZenEssentials folder:", ex); - } - } - - _updateEssentialsVisibility() { - // Get current preference value - this.isEssentialsEnabled = Services.prefs.getBoolPref("zen.essentials.enabled", false); - - // Update visibility - if (this._rootElt) { - this._rootElt.hidden = !this.isEssentialsEnabled; - } - - if (this._accordionHeader) { - this._accordionHeader.style.display = this.isEssentialsEnabled ? "flex" : "none"; - } - } - - // Called by PlacesViewBase during initialization - _init() { - this._prefObserver = (() => { - this._updateEssentialsVisibility(); - }).bind(this); - - // Get initial preference value and set up observer - Services.prefs.addObserver("zen.essentials.enabled", this._prefObserver); - - // Initialize visibility based on current pref value - this.isEssentialsEnabled = Services.prefs.getBoolPref("zen.essentials.enabled", false); - this._updateEssentialsVisibility(); - this._overFolder = { - elt: null, - openTimer: null, - hoverTime: 350, - closeTimer: null, - }; - - let thisView = this; - [ - ["_dropIndicator", "EssentialsToolbarDropIndicator"], - ].forEach(function (elementGlobal) { - let [name, id] = elementGlobal; - thisView.__defineGetter__(name, function () { - let element = document.getElementById(id); - if (!element) { - return null; - } - delete thisView[name]; - return (thisView[name] = element); - }); - }); - - // Initialize base properties - this._viewElt._placesView = this; - this._dragRoot = this._viewElt; - } - - _setupEventListeners() { - // Add standard event listeners - this._addEventListeners(this._dragRoot, this._cbEvents, false); - this._addEventListeners(this._rootElt, ["popupshowing", "popuphidden"], true); - this._addEventListeners(window, ["unload"], false); - } - - static _initInitialLayout() { - const fragment = window.MozXULElement.parseXULToFragment(` - - - - - - - `); - - document.getElementById("vertical-pinned-tabs-container").before(fragment); - } - - _cbEvents = [ - "dragstart", - "dragover", - "dragleave", - "dragend", - "drop", - "mousemove", - "mouseover", - "mouseout", - "mousedown", - ]; - - QueryInterface = ChromeUtils.generateQI([ - "nsINamed", - "nsITimerCallback", - ...PlacesViewBase.interfaces, - ]); - - uninit() { - if (this._prefObserver) { - Services.prefs.removeObserver("zen.essentials.enabled", this._prefObserver); - this._prefObserver = null; - } - if (this._dragRoot) { - this._removeEventListeners(this._dragRoot, this._cbEvents, false); - } - this._removeEventListeners( - this._rootElt, - ["popupshowing", "popuphidden"], - true - ); - this._removeEventListeners(window, ["unload"], false); - - super.uninit(); - } - - _allowPopupShowing = true; - - - - get _isAlive() { - return this._resultNode && this._rootElt; - } - - async _rebuild() { - if (this._overFolder.elt) { - this._clearOverFolder(); - } - - while (this._rootElt.hasChildNodes()) { - this._rootElt.firstChild.remove(); - } - - let cc = this._resultNode.childCount; - if (cc > 0) { - for (let i = 0; i < cc; i++) { - this._insertNewItem(this._resultNode.getChild(i), this._rootElt); - } - } - } - - _insertNewItem(aChild, aInsertionNode, aBefore = null) { - this._domNodes.delete(aChild); - - let type = aChild.type; - let button; - if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) { - button = document.createXULElement("toolbarseparator"); - } else { - button = document.createXULElement("toolbarbutton"); - button.className = "bookmark-item"; - button.setAttribute("label", aChild.title || ""); - - if (PlacesUtils.containerTypes.includes(type)) { - button.setAttribute("type", "menu"); - button.setAttribute("container", "true"); - - if (PlacesUtils.nodeIsQuery(aChild)) { - button.setAttribute("query", "true"); - if (PlacesUtils.nodeIsTagQuery(aChild)) { - button.setAttribute("tagContainer", "true"); - } - } - - let popup = document.createXULElement("menupopup", { - is: "places-popup", - }); - popup.setAttribute("placespopup", "true"); - popup.classList.add("toolbar-menupopup"); - button.appendChild(popup); - popup._placesNode = PlacesUtils.asContainer(aChild); - popup.setAttribute("context", "placesContext"); - - this._domNodes.set(aChild, popup); - } else if (PlacesUtils.nodeIsURI(aChild)) { - button.setAttribute( - "scheme", - PlacesUIUtils.guessUrlSchemeForUI(aChild.uri) - ); - button.hidden = ZenWorkspaces.isBookmarkInAnotherWorkspace(aChild); - button.addEventListener("command", gZenGlanceManager.openGlanceForBookmark.bind(gZenGlanceManager)); - } - } - - button._placesNode = aChild; - let { icon } = button._placesNode; - if (icon) { - button.setAttribute("image", icon); - } - if (!this._domNodes.has(aChild)) { - this._domNodes.set(aChild, button); - } - - if (aBefore) { - aInsertionNode.insertBefore(button, aBefore); - } else { - aInsertionNode.appendChild(button); - } - return button; - } - - handleEvent(aEvent) { - switch (aEvent.type) { - case "unload": - this.uninit(); - break; - case "dragstart": - this._onDragStart(aEvent); - break; - case "dragover": - this._onDragOver(aEvent); - break; - case "dragleave": - this._onDragLeave(aEvent); - break; - case "dragend": - this._onDragEnd(aEvent); - break; - case "drop": - this._onDrop(aEvent); - break; - case "mouseover": - this._onMouseOver(aEvent); - break; - case "mousemove": - this._onMouseMove(aEvent); - break; - case "mouseout": - this._onMouseOut(aEvent); - break; - case "mousedown": - this._onMouseDown(aEvent); - break; - case "popupshowing": - this._onPopupShowing(aEvent); - break; - case "popuphidden": - this._onPopupHidden(aEvent); - break; - default: - throw new Error("Trying to handle unexpected event."); - } - } - - - - nodeInserted(aParentPlacesNode, aPlacesNode, aIndex) { - let parentElt = this._getDOMNodeForPlacesNode(aParentPlacesNode); - if (parentElt == this._rootElt) { - let children = this._rootElt.children; - if (aIndex > children.length) { - return; - } - - this._insertNewItem( - aPlacesNode, - this._rootElt, - children[aIndex] || null - ); - return; - } - - super.nodeInserted(aParentPlacesNode, aPlacesNode, aIndex); - } - - nodeRemoved(aParentPlacesNode, aPlacesNode, aIndex) { - let parentElt = this._getDOMNodeForPlacesNode(aParentPlacesNode); - if (parentElt == this._rootElt) { - let elt = this._getDOMNodeForPlacesNode(aPlacesNode, true); - if (!elt) { - return; - } - - if (elt.localName == "menupopup") { - elt = elt.parentNode; - } - - this._removeChild(elt); - if (this._resultNode.childCount > this._rootElt.children.length) { - this._insertNewItem( - this._resultNode.getChild(this._rootElt.children.length), - this._rootElt - ); - } - return; - } - - super.nodeRemoved(aParentPlacesNode, aPlacesNode, aIndex); - } - - nodeMoved(aPlacesNode, aOldParentPlacesNode, aOldIndex, aNewParentPlacesNode, aNewIndex) { - let parentElt = this._getDOMNodeForPlacesNode(aNewParentPlacesNode); - if (parentElt == this._rootElt) { - let elt = this._getDOMNodeForPlacesNode(aPlacesNode, true); - if (elt) { - if (elt.localName == "menupopup") { - elt = elt.parentNode; - } - this._removeChild(elt); - } - - this._insertNewItem( - aPlacesNode, - this._rootElt, - this._rootElt.children[aNewIndex] - ); - return; - } - - super.nodeMoved( - aPlacesNode, - aOldParentPlacesNode, - aOldIndex, - aNewParentPlacesNode, - aNewIndex - ); - } - - nodeTitleChanged(aPlacesNode, aNewTitle) { - let elt = this._getDOMNodeForPlacesNode(aPlacesNode, true); - if (!elt || elt == this._rootElt) { - return; - } - - super.nodeTitleChanged(aPlacesNode, aNewTitle); - - if (elt.localName == "menupopup") { - elt = elt.parentNode; - } - } - - invalidateContainer(aPlacesNode) { - let elt = this._getDOMNodeForPlacesNode(aPlacesNode, true); - // Nothing to do if it's a never-visible node. - if (!elt) { - return; - } - - if (elt == this._rootElt) { - // Container is the toolbar itself. - let instance = (this._rebuildingInstance = {}); - if (!this._rebuilding) { - this._rebuilding = Promise.withResolvers(); - } - this._rebuild() - .catch(console.error) - .finally(() => { - if (instance == this._rebuildingInstance) { - this._rebuilding.resolve(); - this._rebuilding = null; - } - }); - return; - } - - super.invalidateContainer(aPlacesNode); - } - - _clearOverFolder() { - // The mouse is no longer dragging over the stored menubutton. - // Close the menubutton, clear out drag styles, and clear all - // timers for opening/closing it. - if (this._overFolder.elt && this._overFolder.elt.menupopup) { - if (!this._overFolder.elt.menupopup.hasAttribute("dragover")) { - this._overFolder.elt.menupopup.hidePopup(); - } - this._overFolder.elt.removeAttribute("dragover"); - this._overFolder.elt = null; - } - if (this._overFolder.openTimer) { - this._overFolder.openTimer.cancel(); - this._overFolder.openTimer = null; - } - if (this._overFolder.closeTimer) { - this._overFolder.closeTimer.cancel(); - this._overFolder.closeTimer = null; - } - } - - /** - * Determines the drop target while dragging over the vertical toolbar. - * - * @param {object} aEvent - * The drag event. - * @returns {object} - * - ip: The insertion point for the bookmarks service. - * - beforeIndex: Child index to drop before, for the drop indicator. - * - folderElt: The folder to drop into, if applicable. - */ - _getDropPoint(aEvent) { - if (!PlacesUtils.nodeIsFolderOrShortcut(this._resultNode)) { - return null; - } - - let dropPoint = { ip: null, beforeIndex: null, folderElt: null }; - let elt = aEvent.target; - - // If we're not dragging over a child element, handle dropping at the end - if (!elt._placesNode || elt == this._rootElt || elt.localName == "menupopup") { - dropPoint.ip = new PlacesInsertionPoint({ - parentGuid: PlacesUtils.getConcreteItemGuid(this._resultNode), - orientation: Ci.nsITreeView.DROP_BEFORE - }); - dropPoint.beforeIndex = -1; - - // Find the closest child based on vertical position - for (let i = 0; i < this._rootElt.children.length; i++) { - let childRect = this._rootElt.children[i].getBoundingClientRect(); - if (aEvent.clientY <= childRect.top) { - dropPoint.beforeIndex = i; - dropPoint.ip.index = i; - break; - } - } - return dropPoint; - } - - // Get target element's position info - let eltRect = elt.getBoundingClientRect(); - let eltIndex = Array.prototype.indexOf.call(this._rootElt.children, elt); - - // Handle dropping on folders - if (PlacesUtils.nodeIsFolderOrShortcut(elt._placesNode) && - !PlacesUIUtils.isFolderReadOnly(elt._placesNode)) { - - // Define drop zones: top 25%, middle 50%, bottom 25% - let topThreshold = eltRect.top + (eltRect.height * 0.25); - let bottomThreshold = eltRect.bottom - (eltRect.height * 0.25); - - if (aEvent.clientY < topThreshold) { - // Drop before folder - dropPoint.ip = new PlacesInsertionPoint({ - parentGuid: PlacesUtils.getConcreteItemGuid(this._resultNode), - index: eltIndex, - orientation: Ci.nsITreeView.DROP_BEFORE - }); - dropPoint.beforeIndex = eltIndex; - } else if (aEvent.clientY > bottomThreshold) { - // Drop after folder - let beforeIndex = eltIndex == this._rootElt.children.length - 1 ? -1 : eltIndex + 1; - dropPoint.ip = new PlacesInsertionPoint({ - parentGuid: PlacesUtils.getConcreteItemGuid(this._resultNode), - index: beforeIndex, - orientation: Ci.nsITreeView.DROP_BEFORE - }); - dropPoint.beforeIndex = beforeIndex; - } else { - // Drop inside folder - let tagName = PlacesUtils.nodeIsTagQuery(elt._placesNode) - ? elt._placesNode.title - : null; - dropPoint.ip = new PlacesInsertionPoint({ - parentGuid: PlacesUtils.getConcreteItemGuid(elt._placesNode), - tagName - }); - dropPoint.beforeIndex = eltIndex; - dropPoint.folderElt = elt; - } - } else { - // Handle dropping around non-folder items - let midPoint = eltRect.top + (eltRect.height / 2); - - if (aEvent.clientY < midPoint) { - // Drop before item - dropPoint.ip = new PlacesInsertionPoint({ - parentGuid: PlacesUtils.getConcreteItemGuid(this._resultNode), - index: eltIndex, - orientation: Ci.nsITreeView.DROP_BEFORE - }); - dropPoint.beforeIndex = eltIndex; - } else { - // Drop after item - let beforeIndex = eltIndex == this._rootElt.children.length - 1 ? -1 : eltIndex + 1; - dropPoint.ip = new PlacesInsertionPoint({ - parentGuid: PlacesUtils.getConcreteItemGuid(this._resultNode), - index: beforeIndex, - orientation: Ci.nsITreeView.DROP_BEFORE - }); - dropPoint.beforeIndex = beforeIndex; - } - } - - return dropPoint; - } - - _setTimer(aTime) { - let timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - timer.initWithCallback(this, aTime, timer.TYPE_ONE_SHOT); - return timer; - } - - get name() { - return "ZenEssentialsToolbar"; - } - - notify(aTimer) { - if (aTimer == this._overFolder.openTimer) { - this._overFolder.elt.menupopup.setAttribute("autoopened", "true"); - this._overFolder.elt.open = true; - this._overFolder.openTimer = null; - } else if (aTimer == this._overFolder.closeTimer) { - let currentPlacesNode = PlacesControllerDragHelper.currentDropTarget; - let inHierarchy = false; - while (currentPlacesNode) { - if (currentPlacesNode == this._rootElt) { - inHierarchy = true; - break; - } - currentPlacesNode = currentPlacesNode.parentNode; - } - if (inHierarchy) { - this._overFolder.elt = null; - } - this._clearOverFolder(); - } - } - - _onMouseOver(aEvent) { - let button = aEvent.target; - if ( - button.parentNode == this._rootElt && - button._placesNode && - PlacesUtils.nodeIsURI(button._placesNode) - ) { - window.XULBrowserWindow.setOverLink(aEvent.target._placesNode.uri); - } - } - - _onMouseOut() { - window.XULBrowserWindow.setOverLink(""); - } - - _onMouseDown(aEvent) { - let target = aEvent.target; - if ( - aEvent.button == 0 && - target.localName == "toolbarbutton" && - target.getAttribute("type") == "menu" - ) { - - - let modifKey = aEvent.shiftKey || aEvent.getModifierState("Accel"); - if (modifKey) { - // Do not open the popup since BEH_onClick is about to - // open all child uri nodes in tabs. - this._allowPopupShowing = false; - } - } - PlacesUIUtils.maybeSpeculativeConnectOnMouseDown(aEvent); - } - - _cleanupDragDetails() { - // Called on dragend and drop. - PlacesControllerDragHelper.currentDropTarget = null; - this._draggedElt = null; - this._dropIndicator.collapsed = true; - } - - _onDragStart(aEvent) { - // Sub menus have their own d&d handlers. - let draggedElt = aEvent.target; - if (draggedElt.parentNode != this._rootElt || !draggedElt._placesNode) { - return; - } - - if ( - draggedElt.localName == "toolbarbutton" && - draggedElt.getAttribute("type") == "menu" - ) { - // If the drag gesture on a container is toward down we open instead - // of dragging. - let translateY = this._cachedMouseMoveEvent.clientY - aEvent.clientY; - let translateX = this._cachedMouseMoveEvent.clientX - aEvent.clientX; - if (translateY >= Math.abs(translateX / 2)) { - // Don't start the drag. - aEvent.preventDefault(); - // Open the menu. - draggedElt.open = true; - return; - } - - // If the menu is open, close it. - if (draggedElt.open) { - draggedElt.menupopup.hidePopup(); - draggedElt.open = false; - } - } - - // Activate the view and cache the dragged element. - this._draggedElt = draggedElt._placesNode; - this._rootElt.focus(); - - this._controller.setDataTransfer(aEvent); - aEvent.stopPropagation(); - } - - _onDragOver(aEvent) { - // Cache the dataTransfer - PlacesControllerDragHelper.currentDropTarget = aEvent.target; - let dt = aEvent.dataTransfer; - - let dropPoint = this._getDropPoint(aEvent); - if ( - !dropPoint || - !dropPoint.ip || - !PlacesControllerDragHelper.canDrop(dropPoint.ip, dt) - ) { - this._dropIndicator.collapsed = true; - aEvent.stopPropagation(); - return; - } - - if (dropPoint.folderElt) { - let overElt = dropPoint.folderElt; - if (this._overFolder.elt != overElt) { - this._clearOverFolder(); - this._overFolder.elt = overElt; - this._overFolder.openTimer = this._setTimer(this._overFolder.hoverTime); - } - if (!this._overFolder.elt.hasAttribute("dragover")) { - this._overFolder.elt.setAttribute("dragover", "true"); - } - - this._dropIndicator.collapsed = true; - } else { - // Dragging over a normal toolbarbutton, - // show indicator bar and move it to the appropriate drop point. - let ind = this._dropIndicator; - ind.parentNode.collapsed = false; - let halfInd = ind.clientWidth / 2; - let translateX; - if (this.isRTL) { - halfInd = Math.ceil(halfInd); - translateX = 0 - this._rootElt.getBoundingClientRect().right - halfInd; - if (this._rootElt.firstElementChild) { - if (dropPoint.beforeIndex == -1) { - translateX += - this._rootElt.lastElementChild.getBoundingClientRect().left; - } else { - translateX += - this._rootElt.children[ - dropPoint.beforeIndex - ].getBoundingClientRect().right; - } - } - } else { - halfInd = Math.floor(halfInd); - translateX = 0 - this._rootElt.getBoundingClientRect().left + halfInd; - if (this._rootElt.firstElementChild) { - if (dropPoint.beforeIndex == -1) { - translateX += - this._rootElt.lastElementChild.getBoundingClientRect().right; - } else { - translateX += - this._rootElt.children[ - dropPoint.beforeIndex - ].getBoundingClientRect().left; - } - } - } - - ind.style.transform = "translate(" + Math.round(translateX) + "px)"; - ind.style.marginInlineStart = -ind.clientWidth + "px"; - ind.collapsed = false; - - // Clear out old folder information. - this._clearOverFolder(); - } - - aEvent.preventDefault(); - aEvent.stopPropagation(); - } - - _onDrop(aEvent) { - PlacesControllerDragHelper.currentDropTarget = aEvent.target; - - let dropPoint = this._getDropPoint(aEvent); - if (dropPoint && dropPoint.ip) { - PlacesControllerDragHelper.onDrop( - dropPoint.ip, - aEvent.dataTransfer - ).catch(console.error); - aEvent.preventDefault(); - } - - this._cleanupDragDetails(); - aEvent.stopPropagation(); - } - - _onDragLeave() { - PlacesControllerDragHelper.currentDropTarget = null; - - this._dropIndicator.collapsed = true; - - // If we hovered over a folder, close it now. - if (this._overFolder.elt) { - this._overFolder.closeTimer = this._setTimer(this._overFolder.hoverTime); - } - } - - _onDragEnd() { - this._cleanupDragDetails(); - } - - _onPopupShowing(aEvent) { - if (!this._allowPopupShowing) { - this._allowPopupShowing = true; - aEvent.preventDefault(); - return; - } - - let parent = aEvent.target.parentNode; - if (parent.localName == "toolbarbutton") { - this._openedMenuButton = parent; - } - - super._onPopupShowing(aEvent); - } - - _onPopupHidden(aEvent) { - let popup = aEvent.target; - let placesNode = popup._placesNode; - // Avoid handling popuphidden of inner views - if ( - placesNode && - PlacesUIUtils.getViewForNode(popup) == this && - // UI performance: folder queries are cheap, keep the resultnode open - // so we don't rebuild its contents whenever the popup is reopened. - !PlacesUtils.nodeIsFolderOrShortcut(placesNode) - ) { - placesNode.containerOpen = false; - } - - let parent = popup.parentNode; - if (parent.localName == "toolbarbutton") { - this._openedMenuButton = null; - // Clear the dragover attribute if present, if we are dragging into a - // folder in the hierachy of current opened popup we don't clear - // this attribute on clearOverFolder. See Notify for closeTimer. - if (parent.hasAttribute("dragover")) { - parent.removeAttribute("dragover"); - } - } - } - - _onMouseMove(aEvent) { - // Used in dragStart to prevent dragging folders when dragging down. - this._cachedMouseMoveEvent = aEvent; - - if ( - this._openedMenuButton == null || - PlacesControllerDragHelper.getSession() - ) { - return; - } - - let target = aEvent.originalTarget; - if ( - this._openedMenuButton != target && - target.localName == "toolbarbutton" && - target.type == "menu" - ) { - this._openedMenuButton.open = false; - target.open = true; - } - } -} \ No newline at end of file