-
Notifications
You must be signed in to change notification settings - Fork 2
/
autoGroup.js
333 lines (282 loc) · 12.3 KB
/
autoGroup.js
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
/*
Filename: options.js
Purpose: This script manages the automatic grouping feature in the Tab Manager Chrome extension. It allows users to create and manage tab groups based on specified patterns and enables or disables the auto-grouping functionality through a user-friendly interface.
Key Functions:
- autoGroup: Initializes the auto-grouping feature, loads saved settings, and manages the user interface for adding and deleting tab groups.
- loadSavedGroups: Displays the user's saved tab groups in the UI, allowing for easy management.
- deleteGroup: Removes a tab group from storage and ungroups any associated tabs in the Chrome browser.
- updatePatternList: Updates the displayed list of patterns for the current group.
- clearForm: Resets the input fields and selected colors in the form used for creating new groups.
- extractDomain: Extracts the domain (excluding subdomains) from a given URL.
- extractSubdomain: Extracts the full hostname (including subdomains) from a given URL.
Event Listeners:
- Checkbox for enabling/disabling auto-grouping.
- Button for adding a new pattern.
- Button for saving a new group.
- Button for clearing the form.
- Buttons for retrieving the domain, subdomain, and exact URL of the active tab.
Dependencies:
- Utilizes Chrome storage API methods (chrome.storage.local.get and chrome.storage.local.set) for persisting user settings.
- Assumes the existence of specific HTML elements with IDs that correspond to the settings being manipulated (e.g., 'activateAutoGroupingCheckbox', 'formContainer').
Storage Variables:
- autoGroupingEnabled
- tabGroups
HTML Element IDs:
- activateAutoGroupingCheckbox
- formContainer
- saveGroupBtn
- addPatternBtn
- clearFormBtn
- groupPattern
- patternList
- groupName
- savedGroupsList
- getDomainBtn
- getSubdomainBtn
- getExactUrlBtn
Initialization:
- The autoGroup function is called to set up the auto-grouping interface, loading saved settings and establishing event listeners for user interactions.
*/
const autoGroup = async () => {
const autoGroupCheckbox = document.getElementById('activateAutoGroupingCheckbox');
const formContainer = document.getElementById('formContainer');
const saveGroupBtn = document.getElementById('saveGroupBtn');
const addPatternBtn = document.getElementById('addPatternBtn');
const clearFormBtn = document.getElementById('clearFormBtn');
const patternInput = document.getElementById('groupPattern');
const patternList = document.getElementById('patternList');
const groupNameInput = document.getElementById('groupName');
const colorPickerCircles = document.querySelectorAll('.color-circle');
const savedGroupsList = document.getElementById('savedGroupsList');
const getDomainBtn = document.getElementById('getDomainBtn');
const getSubdomainBtn = document.getElementById('getSubdomainBtn');
const getExactUrlBtn = document.getElementById('getExactUrlBtn');
let selectedColor = 'grey'; // Default color
let patterns = []; // Array to hold patterns
// Load saved settings
const settings = await chrome.storage.local.get(['autoGroupingEnabled', 'tabGroups']);
autoGroupCheckbox.checked = settings.autoGroupingEnabled || false;
let tabGroups = settings.tabGroups || [];
formContainer.classList.toggle('disabled', !autoGroupCheckbox.checked);
// Enable or disable form based on checkbox state
autoGroupCheckbox.addEventListener('change', async () => {
formContainer.classList.toggle('disabled', !autoGroupCheckbox.checked);
await chrome.storage.local.set({ autoGroupingEnabled: autoGroupCheckbox.checked });
});
// Handle color selection
colorPickerCircles.forEach(circle => {
circle.addEventListener('click', () => {
selectedColor = circle.dataset.color;
colorPickerCircles.forEach(c => c.classList.remove('selected'));
circle.classList.add('selected');
});
});
// Add pattern to the list
addPatternBtn.addEventListener('click', () => {
const patternValue = patternInput.value.trim();
if (patternValue && !patterns.includes(patternValue)) {
patterns.push(patternValue);
updatePatternList();
patternInput.value = ''; // Clear input after adding
}
});
// Save group
saveGroupBtn.addEventListener('click', async () => {
const groupName = groupNameInput.value.trim();
if (!groupName || patterns.length === 0) {
alert('Please provide a group name and at least one pattern.');
return;
}
const newGroup = {
id: Date.now().toString(),
idInChrome: null,
title: groupName,
color: selectedColor,
patterns: [...patterns]
};
const updatedTabGroups = [newGroup, ...tabGroups];
await chrome.storage.local.set({ tabGroups: updatedTabGroups });
clearForm();
tabGroups = updatedTabGroups;
loadSavedGroups(tabGroups);
});
// Clear form
clearFormBtn.addEventListener('click', clearForm);
// Load saved groups into the UI
function loadSavedGroups(groups) {
savedGroupsList.innerHTML = ''; // Clear existing items
if (groups.length === 0) {
// If there are no saved groups, show a message
const noGroupsMessage = document.createElement('p');
noGroupsMessage.textContent = 'No groups saved yet.';
noGroupsMessage.classList.add('no-groups-message'); // Optional: Add a class for styling
savedGroupsList.appendChild(noGroupsMessage);
return; // Exit the function if there are no groups to display
}
groups.forEach(group => {
const listItem = document.createElement('li');
// Create a div to wrap color circle and title
const colorAndTitleDiv = document.createElement('div');
colorAndTitleDiv.classList.add('color-title-wrapper'); // Apply CSS class for styling
// Create color circle
const colorCircle = document.createElement('span');
colorCircle.classList.add('group-color-circle'); // Apply CSS class for styling
colorCircle.style.backgroundColor = group.color; // Set the background color to the group's color
// Create the title text
const titleText = document.createElement('span');
titleText.classList.add('group-title');
titleText.textContent = group.title;
// Add the color circle and group title to the colorAndTitleDiv
colorAndTitleDiv.appendChild(colorCircle);
colorAndTitleDiv.appendChild(titleText);
// Create another div to hold color/title div and delete button
const groupInfoDiv = document.createElement('div');
groupInfoDiv.classList.add('group-info-wrapper'); // Apply CSS class for styling
// Append colorAndTitleDiv to groupInfoDiv
groupInfoDiv.appendChild(colorAndTitleDiv);
// Create delete button
const deleteBtn = document.createElement('button');
deleteBtn.classList.add('delete-button');
deleteBtn.textContent = 'Delete';
deleteBtn.addEventListener('click', () => deleteGroup(group.id));
// Add the delete button to groupInfoDiv
groupInfoDiv.appendChild(deleteBtn);
// Add the groupInfoDiv to the listItem
listItem.appendChild(groupInfoDiv);
// Create patterns list
const patternsList = document.createElement('ul');
patternsList.classList.add('patterns-list'); // Apply CSS class for styling
group.patterns.forEach(pattern => {
const patternItem = document.createElement('li');
patternItem.textContent = pattern;
patternsList.appendChild(patternItem);
});
// Add the patterns list to the list item
listItem.appendChild(patternsList);
// Add listItem to the savedGroupsList
savedGroupsList.appendChild(listItem);
});
}
// Delete group
async function deleteGroup(groupId) {
try {
// Retrieve the latest tab groups from storage
const storedData = await chrome.storage.local.get('tabGroups');
tabGroups = storedData.tabGroups || []; // Update tabGroups with stored data
// Find the group to delete
const groupToDelete = tabGroups.find(g => g.id === groupId);
if (!groupToDelete) {
console.warn(`Group with ID: ${groupId} not found.`);
return; // Exit if the group doesn't exist
}
const groupIdInChrome = groupToDelete.idInChrome;
// Fetch all tabs in the current group
const tabsInGroup = await chrome.tabs.query({ groupId: groupIdInChrome });
// Ungroup each tab in the group
for (const tab of tabsInGroup) {
await new Promise((resolve, reject) => {
chrome.tabs.ungroup(tab.id, () => {
if (chrome.runtime.lastError) {
reject(chrome.runtime.lastError);
} else {
resolve();
}
}); // Ungroup the tab
});
console.log(`Ungrouped tab with ID: ${tab.id} from group ID: ${groupIdInChrome}`);
}
// Now delete the group from local storage
const updatedTabGroups = tabGroups.filter(g => g.id !== groupId);
await chrome.storage.local.set({ tabGroups: updatedTabGroups });
tabGroups = updatedTabGroups;
loadSavedGroups(tabGroups);
console.log(`Deleted group with ID: ${groupId}`);
} catch (error) {
console.error('Error deleting group:', error);
}
}
// Update pattern list in the UI
function updatePatternList() {
patternList.innerHTML = '';
patterns.forEach(pattern => {
const listItem = document.createElement('li');
listItem.textContent = pattern;
const removeBtn = document.createElement('button');
removeBtn.textContent = 'Remove';
removeBtn.classList.add('clear-btn');
removeBtn.addEventListener('click', () => {
patterns = patterns.filter(p => p !== pattern);
updatePatternList();
});
listItem.appendChild(removeBtn);
patternList.appendChild(listItem);
});
}
// Clear form inputs
function clearForm() {
groupNameInput.value = '';
patternInput.value = '';
patterns = [];
updatePatternList();
selectedColor = 'grey';
colorPickerCircles.forEach(c => c.classList.remove('selected'));
// Find the gray circle and add 'selected' class to it
const grayCircle = Array.from(colorPickerCircles).find(c => c.dataset.color === 'grey');
if (grayCircle) {
grayCircle.classList.add('selected');
}
}
// Function to extract the domain (without subdomain)
function extractDomain(url) {
try {
const hostname = new URL(url).hostname;
const parts = hostname.split('.');
// Get the last two parts (e.g., "example.com" from "sub.example.com")
return parts.slice(-2).join('.');
} catch (error) {
console.error('Invalid URL:', error);
return null;
}
}
// Function to extract the domain with subdomain
function extractSubdomain(url) {
try {
const hostname = new URL(url).hostname;
return hostname; // Return the full hostname including subdomain
} catch (error) {
console.error('Invalid URL:', error);
return null;
}
}
// Get the domain of the active tab
getDomainBtn.addEventListener('click', () => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (tabs.length > 0) {
const activeTab = tabs[0];
const domain = extractDomain(activeTab.url);
patternInput.value = domain; // Set the pattern input value
}
});
});
// Get the subdomain of the active tab
getSubdomainBtn.addEventListener('click', () => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (tabs.length > 0) {
const activeTab = tabs[0];
const subdomain = extractSubdomain(activeTab.url);
patternInput.value = subdomain; // Set the pattern input value
}
});
});
// Get the exact URL of the active tab
getExactUrlBtn.addEventListener('click', () => {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
if (tabs.length > 0) {
const activeTab = tabs[0];
patternInput.value = activeTab.url; // Set the pattern input value to the exact URL
}
});
});
// Load saved groups initially
loadSavedGroups(tabGroups);
}