From cef9e39b8ae5498ffe946020fa057839f521bd88 Mon Sep 17 00:00:00 2001 From: {{GIT_USER_NAME}} Date: Thu, 9 Oct 2025 03:08:06 -0500 Subject: [PATCH 1/4] Add Sort Tabs to tab context menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added context_zenSortTabs menu item to tab context menu - Positioned before "Reload Tab" for logical grouping - Added separator for better visual separation - Smart visibility based on sort feature and workspace state - Hides when multiple tabs selected (use button instead) - Uses existing cmd_zenSortTabs command for consistency - Updated initialization to check for tabContextMenu availability 💘 Generated with Crush Co-Authored-By: Crush <crush@charm.land> --- tab_sort_clear.uc.js | 90 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/tab_sort_clear.uc.js b/tab_sort_clear.uc.js index 2a82617..960e443 100644 --- a/tab_sort_clear.uc.js +++ b/tab_sort_clear.uc.js @@ -1,4 +1,4 @@ -// VERSION 4.11.0 (Added Mistral API support) +// VERSION 4.12.1 (Added Sort Tabs to tab context menu) (() => { // --- Configuration --- @@ -1496,6 +1496,85 @@ // --- Button Initialization & Workspace Handling --- + function addContextMenuItem() { + const tabContextMenu = document.getElementById('tabContextMenu'); + if (!tabContextMenu) { + console.error("BUTTONS: Could not find 'tabContextMenu'. Context menu item not added."); + return; + } + + // Check if our menu item already exists + if (tabContextMenu.querySelector('#context_zenSortTabs')) { + console.log("BUTTONS: Context menu item already exists."); + return; + } + + try { + const menuFragment = window.MozXULElement.parseXULToFragment( + ` + ` + ); + + // Insert before the "Reload Tab" menu item for logical grouping + const reloadTabItem = tabContextMenu.querySelector('#context_reloadTab'); + if (reloadTabItem) { + reloadTabItem.before(menuFragment); + } else { + // Fallback: append to the end + tabContextMenu.appendChild(menuFragment); + } + + console.log("BUTTONS: Sort Tabs context menu item added successfully."); + } catch (e) { + console.error("BUTTONS: Error adding context menu item:", e); + } + } + + function setupContextMenuListener() { + const tabContextMenu = document.getElementById('tabContextMenu'); + if (!tabContextMenu) { + console.error("BUTTONS: Could not find 'tabContextMenu' for listener setup."); + return; + } + + // Add popupshowing listener to control visibility + tabContextMenu.addEventListener('popupshowing', (event) => { + try { + const menuItem = document.getElementById('context_zenSortTabs'); + const separator = document.getElementById('context_zen-sort-tabs-separator'); + + if (!menuItem || !separator) return; + + // Check if sort feature is enabled + if (!CONFIG.featureConfig.sort) { + menuItem.setAttribute('hidden', 'true'); + separator.setAttribute('hidden', 'true'); + return; + } + + // Check if we're in the correct workspace + const currentWorkspaceId = window.gZenWorkspaces?.activeWorkspace; + const showMenuItem = currentWorkspaceId && + (!gBrowser?.selectedTabs || gBrowser.selectedTabs.length <= 1); // Hide when multiple tabs selected (use button instead) + + if (showMenuItem) { + menuItem.removeAttribute('hidden'); + separator.removeAttribute('hidden'); + } else { + menuItem.setAttribute('hidden', 'true'); + separator.setAttribute('hidden', 'true'); + } + } catch (e) { + console.error("BUTTONS: Error in context menu popupshowing listener:", e); + } + }); + + console.log("BUTTONS: Context menu listener setup complete."); + } + function ensureButtonsExist(container) { if (!container) return; @@ -1588,6 +1667,10 @@ console.error("BUTTONS INIT: Error adding command listener:", e); } } + + // Setup context menu items and listeners + addContextMenuItem(); + setupContextMenuListener(); } @@ -1657,10 +1740,11 @@ const separatorExists = !!document.querySelector(".pinned-tabs-container-separator"); const peripheryExists = !!document.querySelector('#tabbrowser-arrowscrollbox-periphery'); const commandSetExists = !!document.querySelector("commandset#zenCommandSet"); + const tabContextMenuExists = !!document.getElementById('tabContextMenu'); const gBrowserReady = typeof gBrowser !== 'undefined' && gBrowser.tabContainer; const gZenWorkspacesReady = typeof gZenWorkspaces !== 'undefined' && typeof gZenWorkspaces.activeWorkspace !== 'undefined'; - const ready = gBrowserReady && commandSetExists && (separatorExists || peripheryExists) && gZenWorkspacesReady; + const ready = gBrowserReady && commandSetExists && tabContextMenuExists && (separatorExists || peripheryExists) && gZenWorkspacesReady; if (ready) { console.log(`INIT: Required elements found after ${checkCount} checks. Initializing...`); @@ -1692,6 +1776,7 @@ console.error("INIT Status:", { gBrowserReady, commandSetExists, + tabContextMenuExists, separatorExists, peripheryExists, gZenWorkspacesReady @@ -1700,6 +1785,7 @@ if (!gZenWorkspacesReady) console.error(" -> gZenWorkspaces might not be fully initialized yet (activeWorkspace missing?). Ensure Zen Tab Organizer extension is loaded and enabled BEFORE this script runs."); if (!separatorExists && !peripheryExists) console.error(" -> Neither separator element '.pinned-tabs-container-separator' nor fallback periphery '#tabbrowser-arrowscrollbox-periphery' found in the DOM."); if (!commandSetExists) console.error(" -> Command set '#zenCommandSet' not found. Ensure Zen Tab Organizer extension is loaded and enabled."); + if (!tabContextMenuExists) console.error(" -> Tab context menu '#tabContextMenu' not found. Ensure Zen Browser tab context menu is loaded."); if (!gBrowserReady) console.error(" -> Global 'gBrowser' object not ready."); } }, checkInterval); From 870a9b81dde5acc4e547754d206c14b02f3be49c Mon Sep 17 00:00:00 2001 From: {{GIT_USER_NAME}} Date: Thu, 9 Oct 2025 03:08:38 -0500 Subject: [PATCH 2/4] Add CRUSH.md to .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 2833cd3..7d5d4a8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ api.txt -test.mjs \ No newline at end of file +test.mjsCRUSH.md From 6e8cc95027e262da831a315602a1b543e828cf59 Mon Sep 17 00:00:00 2001 From: {{GIT_USER_NAME}} Date: Thu, 9 Oct 2025 03:32:51 -0500 Subject: [PATCH 3/4] Add preference toggle for sort tabs context menu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added "Enable the sort tabs context menu item" toggle under Feature Toggles - New preference key: extensions.tabgroups.enable_context_menu - Context menu item now respects this toggle preference - Added CSS media query to hide menu item when disabled - Updated CONFIG.featureConfig to include contextMenu setting - Only sets up context menu when the feature is enabled 💘 Generated with Crush Co-Authored-By: Crush <crush@charm.land> --- preferences.json | 6 ++++++ tab_sort_clear.uc.js | 26 +++++++++++++++++++++----- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/preferences.json b/preferences.json index 314f50d..718b00e 100644 --- a/preferences.json +++ b/preferences.json @@ -16,6 +16,12 @@ "type": "checkbox", "defaultValue": true }, + { + "property": "extensions.tabgroups.enable_context_menu", + "label": "Enable the sort tabs context menu item.", + "type": "checkbox", + "defaultValue": true + }, { "property": "extensions.tabgroups.ai_model", "label": "Choose AI - Gemini, Ollama, or Mistral", diff --git a/tab_sort_clear.uc.js b/tab_sort_clear.uc.js index 960e443..c80d227 100644 --- a/tab_sort_clear.uc.js +++ b/tab_sort_clear.uc.js @@ -5,6 +5,7 @@ // Feature toggle preference keys const ENABLE_SORT_PREF = "extensions.tabgroups.enable_sort"; const ENABLE_CLEAR_PREF = "extensions.tabgroups.enable_clear"; + const ENABLE_CONTEXT_MENU_PREF = "extensions.tabgroups.enable_context_menu"; // Preference Key for AI Model Selection const AI_MODEL_PREF = "extensions.tabgroups.ai_model"; // '1' for Gemini, '2' for Ollama, '3' for Mistral // Preference Keys for AI Config @@ -38,6 +39,7 @@ // Read preference values const ENABLE_SORT_VALUE = getPref(ENABLE_SORT_PREF, true); const ENABLE_CLEAR_VALUE = getPref(ENABLE_CLEAR_PREF, true); + const ENABLE_CONTEXT_MENU_VALUE = getPref(ENABLE_CONTEXT_MENU_PREF, true); const AI_MODEL_VALUE = getPref(AI_MODEL_PREF, "1"); // Default to Gemini const OLLAMA_ENDPOINT_VALUE = getPref(OLLAMA_ENDPOINT_PREF, "http://localhost:11434/api/generate"); const OLLAMA_MODEL_VALUE = getPref(OLLAMA_MODEL_PREF, "llama3.2"); @@ -49,7 +51,8 @@ const CONFIG = { featureConfig: { sort: ENABLE_SORT_VALUE, - clear: ENABLE_CLEAR_VALUE + clear: ENABLE_CLEAR_VALUE, + contextMenu: ENABLE_CONTEXT_MENU_VALUE }, apiConfig: { ollama: { @@ -266,6 +269,17 @@ } } + @media not (-moz-bool-pref: "${ENABLE_CONTEXT_MENU_PREF}") { + + #context_zenSortTabs { + display: none; + } + + #context_zen-sort-tabs-separator { + display: none; + } + } + /*======== sort-button , clear-button ============*/ .pinned-tabs-container-separator{ height: 100% !important; @@ -1548,8 +1562,8 @@ if (!menuItem || !separator) return; - // Check if sort feature is enabled - if (!CONFIG.featureConfig.sort) { + // Check if sort feature and context menu are enabled + if (!CONFIG.featureConfig.sort || !CONFIG.featureConfig.contextMenu) { menuItem.setAttribute('hidden', 'true'); separator.setAttribute('hidden', 'true'); return; @@ -1669,8 +1683,10 @@ } // Setup context menu items and listeners - addContextMenuItem(); - setupContextMenuListener(); + if (CONFIG.featureConfig.contextMenu) { + addContextMenuItem(); + setupContextMenuListener(); + } } From 9e6c95f6f5e86dc1cccb2864f01da054602215ec Mon Sep 17 00:00:00 2001 From: {{GIT_USER_NAME}} Date: Thu, 9 Oct 2025 03:53:32 -0500 Subject: [PATCH 4/4] Add restart confirmation popup for context menu preference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added "restart": true to context menu preference - Sine will automatically show restart confirmation when toggling - Provides one-click restart functionality via toast notification - Improves user experience with clear feedback about required restart - Consistent with other Sine mod behavior 💘 Generated with Crush Co-Authored-By: Crush <crush@charm.land> --- preferences.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/preferences.json b/preferences.json index 718b00e..a9aa564 100644 --- a/preferences.json +++ b/preferences.json @@ -20,7 +20,8 @@ "property": "extensions.tabgroups.enable_context_menu", "label": "Enable the sort tabs context menu item.", "type": "checkbox", - "defaultValue": true + "defaultValue": true, + "restart": true }, { "property": "extensions.tabgroups.ai_model",