-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackground.js
More file actions
129 lines (111 loc) · 4.37 KB
/
Copy pathbackground.js
File metadata and controls
129 lines (111 loc) · 4.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/**
* Auto Tab Group - background service worker
*
* When a new tab is opened from an existing tab (openerTabId is set),
* automatically place the new tab into the same group as the opener.
* If the opener is not in any group, create a new group for both.
*/
const UNGROUPED = chrome.tabGroups.TAB_GROUP_ID_NONE; // -1
// Default settings
const DEFAULT_SETTINGS = {
enabled: true,
groupOpenerToo: true, // whether to also pull opener into a new group when it's ungrouped
captureNewTab: false, // whether to group tabs opened as a new tab (e.g. middle-click, Cmd+click)
dissolveOnSingle: false, // whether to ungroup a group when only one tab remains
};
async function getSettings() {
return new Promise((resolve) => {
chrome.storage.sync.get(DEFAULT_SETTINGS, resolve);
});
}
chrome.tabs.onCreated.addListener(async (newTab) => {
const { id: newTabId, openerTabId, pinned, pendingUrl, url } = newTab;
// Pinned tabs cannot be grouped
if (pinned) return;
// No opener means it was opened manually (address bar, new tab page, etc.)
if (!openerTabId) return;
const settings = await getSettings();
if (!settings.enabled) return;
// A "new tab" is one that opens without a destination URL (e.g. Cmd+T, middle-click on
// a tab bar area, or an explicit window.open() with no URL). Skip these unless the user
// has opted in via captureNewTab.
const tabUrl = pendingUrl || url || "";
const isBlankNewTab = tabUrl === "" || tabUrl === "chrome://newtab/";
if (isBlankNewTab && !settings.captureNewTab) return;
try {
const openerTab = await chrome.tabs.get(openerTabId);
// Opener is pinned — can't group with it
if (openerTab.pinned) return;
if (openerTab.groupId !== UNGROUPED) {
// ── Opener is already in a group → add the new tab to the same group ──
await chrome.tabs.group({
tabIds: newTabId,
groupId: openerTab.groupId,
});
} else {
// ── Opener is not grouped ──
if (settings.groupOpenerToo) {
// Create a new group for both opener + new tab
await chrome.tabs.group({
tabIds: [openerTabId, newTabId],
});
} else {
// Create a solo group just for the new tab
await chrome.tabs.group({
tabIds: newTabId,
});
}
}
} catch (err) {
// Opener tab may have been closed before we could act — this is fine
console.debug("[AutoTabGroup] skipped grouping:", err.message);
}
});
// ── Dissolve single-tab groups ──────────────────────────────────────────────
async function dissolveIfSingle(groupId) {
if (groupId === UNGROUPED) return;
const settings = await getSettings();
if (!settings.dissolveOnSingle) return;
try {
const tabs = await chrome.tabs.query({ groupId });
if (tabs.length === 1) {
await chrome.tabs.ungroup([tabs[0].id]);
}
} catch (err) {
console.debug("[AutoTabGroup] skipped dissolve:", err.message);
}
}
// Tab closed — check the group it belonged to
chrome.tabs.onRemoved.addListener(async (tabId, { isWindowClosing }) => {
if (isWindowClosing) return;
// At this point the tab is already gone; query remaining tabs in each group.
// We don't know which group it was in, so we scan all single-tab groups.
const settings = await getSettings();
if (!settings.dissolveOnSingle) return;
try {
const groups = await chrome.tabGroups.query({});
for (const group of groups) {
await dissolveIfSingle(group.id);
}
} catch (err) {
console.debug("[AutoTabGroup] skipped dissolve scan:", err.message);
}
});
// Tab dragged out of a group — onUpdated fires with the new groupId;
// we check the group the tab just left.
chrome.tabs.onUpdated.addListener(async (tabId, changeInfo) => {
// changeInfo.groupId is set when a tab moves between groups (or is ungrouped)
if (changeInfo.groupId === undefined) return;
// The tab has already moved; find its previous group by looking at what
// single-tab groups remain across the window.
const settings = await getSettings();
if (!settings.dissolveOnSingle) return;
try {
const groups = await chrome.tabGroups.query({});
for (const group of groups) {
await dissolveIfSingle(group.id);
}
} catch (err) {
console.debug("[AutoTabGroup] skipped dissolve scan:", err.message);
}
});