feat: implement automatic tab grouping
This commit is contained in:
@@ -1383,6 +1383,9 @@
|
||||
});
|
||||
newTab.dispatchEvent(event);
|
||||
|
||||
// Notify observers for native tab grouping feature
|
||||
Services.obs.notifyObservers(newTab, "browser-tab-activated");
|
||||
|
||||
this._tabAttrModified(oldTab, ["selected"]);
|
||||
this._tabAttrModified(newTab, ["selected"]);
|
||||
|
||||
@@ -4037,6 +4040,9 @@
|
||||
detail: eventDetail || {},
|
||||
});
|
||||
tab.dispatchEvent(evt);
|
||||
|
||||
// Notify observers for native tab grouping feature
|
||||
Services.obs.notifyObservers(tab, "browser-tab-created");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -5013,6 +5019,8 @@
|
||||
}
|
||||
|
||||
_endRemoveTab(aTab) {
|
||||
// Notify observers for native tab grouping feature
|
||||
Services.obs.notifyObservers(aTab, "browser-tab-removed");
|
||||
if (!aTab || !aTab._endRemoveArgs) {
|
||||
return;
|
||||
}
|
||||
@@ -7220,6 +7228,10 @@
|
||||
// Intentional fallthrough
|
||||
case "deactivate":
|
||||
this.selectedTab.updateLastSeenActive();
|
||||
// Notify observers for native tab grouping feature
|
||||
if (aEvent.type === "activate") {
|
||||
Services.obs.notifyObservers(null, "browser-window-focus-changed");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,6 +271,7 @@
|
||||
@RESPATH@/browser/defaults/settings
|
||||
; Waterfox preference files
|
||||
@RESPATH@/browser/@PREF_DIR@/prefs-lepton.js
|
||||
@RESPATH@/browser/@PREF_DIR@/prefs-tabgroups.js
|
||||
|
||||
# channel-prefs.js has been removed on macOS.
|
||||
#ifndef XP_MACOSX
|
||||
|
||||
@@ -15,6 +15,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
PrivateTab: "resource:///modules/PrivateTab.sys.mjs",
|
||||
StatusBar: "resource:///modules/StatusBar.sys.mjs",
|
||||
TabFeatures: "resource:///modules/TabFeatures.sys.mjs",
|
||||
TabGrouping: "resource:///modules/TabGrouping.sys.mjs",
|
||||
setTimeout: "resource://gre/modules/Timer.sys.mjs",
|
||||
UICustomizations: "resource:///modules/UICustomizations.sys.mjs",
|
||||
});
|
||||
@@ -75,6 +76,9 @@ export const WaterfoxGlue = {
|
||||
this.addAddonListener();
|
||||
// Register about:cfg
|
||||
lazy.AboutPages.init();
|
||||
|
||||
// Initialize automatic tab grouping
|
||||
lazy.TabGrouping.init();
|
||||
},
|
||||
|
||||
async _setPrefObservers() {
|
||||
@@ -215,6 +219,9 @@ export const WaterfoxGlue = {
|
||||
this._beforeUIStartup();
|
||||
this._delayedTasks();
|
||||
break;
|
||||
case "quit-application-granted":
|
||||
this.shutdown();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -406,6 +413,11 @@ export const WaterfoxGlue = {
|
||||
}
|
||||
},
|
||||
|
||||
shutdown() {
|
||||
// Shutdown TabGrouping
|
||||
lazy.TabGrouping.shutdown();
|
||||
},
|
||||
|
||||
updateCustomStylesheets(addon) {
|
||||
if (addon.type === "theme") {
|
||||
// If any theme and WF on any theme, reload stylesheets for every theme enable.
|
||||
|
||||
@@ -14,6 +14,7 @@ DIRS += [
|
||||
"search",
|
||||
"statusbar",
|
||||
"tabfeatures",
|
||||
"tabgrouping",
|
||||
"uicustomizations",
|
||||
"utils",
|
||||
]
|
||||
|
||||
21
waterfox/browser/components/tabgrouping/LICENSE
Normal file
21
waterfox/browser/components/tabgrouping/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 David Demri
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the “Software”), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
58
waterfox/browser/components/tabgrouping/README.md
Normal file
58
waterfox/browser/components/tabgrouping/README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# Automatic Tab Grouping Feature
|
||||
|
||||
This feature is inspired by the Firefox WebExtension "New Tab Same Group" by onlybets.
|
||||
(Source: https://github.com/onlybets/firefox-addon-new-tab-same-group/blob/main/README.md)
|
||||
|
||||
This module implements automatic tab grouping functionality, which automatically adds new tabs to the same group as the currently active tab.
|
||||
|
||||
## Features
|
||||
|
||||
- **Automatic Grouping**: When enabled, new tabs are automatically added to the same group as the source tab (the tab that was active when the new tab was created).
|
||||
|
||||
- **Configurable Placement**: Users can choose where new tabs appear within the group:
|
||||
- After the source tab (default)
|
||||
- At the beginning of the group
|
||||
- At the end of the group
|
||||
|
||||
- **Optional Delay**: Users can enable a 1-second delay before grouping occurs, allowing them to cancel the operation if desired.
|
||||
|
||||
- **Keyboard Shortcut**: When delay is enabled, users can press a keyboard shortcut (default: Ctrl+` on Windows/Linux, Alt+` on macOS) to cancel pending grouping operations.
|
||||
|
||||
- **Bypass Shortcut**: Press Alt+Shift+T to open a new tab in the standard way (no grouping). This can be configured via preferences.
|
||||
|
||||
- **Smart Tab Tracking**: The feature maintains a history of active tabs to handle edge cases where the source tab might not be immediately available.
|
||||
|
||||
## Implementation
|
||||
|
||||
The feature consists of:
|
||||
|
||||
1. **TabGrouping.sys.mjs**: Core module that handles all the grouping logic
|
||||
2. **Preferences**: User-configurable settings with defaults
|
||||
3. **UI Overlays**: Integration with the preferences UI
|
||||
4. **Localization**: User-facing strings in tabgrouping.ftl
|
||||
|
||||
## Preferences
|
||||
|
||||
- `browser.tabs.autoGroupNewTabs`: Enable/disable the feature (default: true)
|
||||
- `browser.tabs.autoGroupNewTabs.placement`: Tab placement mode (default: "after")
|
||||
- `browser.tabs.autoGroupNewTabs.delayEnabled`: Enable grouping delay (default: false)
|
||||
- `browser.tabs.autoGroupNewTabs.delayMs`: Delay duration in milliseconds (default: 1000)
|
||||
- `browser.tabs.autoGroupNewTabs.cancelShortcut`: Keyboard shortcut to cancel (platform-specific default)
|
||||
- `browser.tabs.autoGroupNewTabs.bypassShortcut`: Keyboard shortcut to open a standard new tab without grouping (default: "Alt+Shift+T")
|
||||
|
||||
## Architecture
|
||||
|
||||
The module:
|
||||
- Listens for tab creation events via observer notifications
|
||||
- Tracks active tab history to determine the appropriate source tab
|
||||
- Manages pending grouping operations with timers
|
||||
- Handles keyboard shortcuts dynamically when delay is enabled
|
||||
- Integrates with the existing tab group infrastructure in tabbrowser.js
|
||||
|
||||
## Usage
|
||||
|
||||
The feature is automatically initialized when the browser starts via WaterfoxGlue.sys.mjs.
|
||||
|
||||
This project contains code under two licenses:
|
||||
- Original implementation: MIT License (see LICENSE)
|
||||
- Rewritten portions: Mozilla Public License 2.0
|
||||
1045
waterfox/browser/components/tabgrouping/TabGrouping.sys.mjs
Normal file
1045
waterfox/browser/components/tabgrouping/TabGrouping.sys.mjs
Normal file
File diff suppressed because it is too large
Load Diff
13
waterfox/browser/components/tabgrouping/moz.build
Normal file
13
waterfox/browser/components/tabgrouping/moz.build
Normal file
@@ -0,0 +1,13 @@
|
||||
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
"TabGrouping.sys.mjs",
|
||||
]
|
||||
|
||||
JS_PREFERENCE_PP_FILES += [
|
||||
"prefs-tabgroups.js",
|
||||
]
|
||||
40
waterfox/browser/components/tabgrouping/prefs-tabgroups.js
Normal file
40
waterfox/browser/components/tabgrouping/prefs-tabgroups.js
Normal file
@@ -0,0 +1,40 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
// Default preferences for automatic tab grouping feature
|
||||
|
||||
// Enable automatic tab grouping
|
||||
pref("browser.tabs.autoGroupNewTabs", false);
|
||||
|
||||
// Placement mode for new tabs in groups
|
||||
// Options: "after" (after source tab), "first" (beginning of group), "last" (end of group)
|
||||
pref("browser.tabs.autoGroupNewTabs.placement", "after");
|
||||
|
||||
// Enable delay before grouping (allows user to cancel)
|
||||
pref("browser.tabs.autoGroupNewTabs.delayEnabled", false);
|
||||
|
||||
// Delay in milliseconds before grouping occurs
|
||||
pref("browser.tabs.autoGroupNewTabs.delayMs", 1000);
|
||||
|
||||
// Keyboard shortcut to cancel pending grouping
|
||||
// Default: Ctrl+` on Windows/Linux, Option+` on macOS
|
||||
#ifdef XP_MACOSX
|
||||
pref("browser.tabs.autoGroupNewTabs.cancelShortcut", "Option+`");
|
||||
#else
|
||||
pref("browser.tabs.autoGroupNewTabs.cancelShortcut", "Ctrl+`");
|
||||
#endif
|
||||
|
||||
// Keyboard shortcut to open a standard new tab (bypass grouping)
|
||||
// Default: Alt+Shift+T (Windows/Linux), Option+Shift+T (macOS)
|
||||
#ifdef XP_MACOSX
|
||||
pref("browser.tabs.autoGroupNewTabs.bypassShortcut", "Option+Shift+T");
|
||||
#else
|
||||
pref("browser.tabs.autoGroupNewTabs.bypassShortcut", "Alt+Shift+T");
|
||||
#endif
|
||||
|
||||
// Enable verbose debug logging for TabGrouping
|
||||
pref("browser.tabs.autoGroupNewTabs.debugLog", false);
|
||||
|
||||
// Grace period after session restore before resuming auto-grouping (ms)
|
||||
pref("browser.tabs.autoGroupNewTabs.resumeGraceMs", 1000);
|
||||
Reference in New Issue
Block a user