tabctl 0.5.3 → 0.6.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +135 -35
- package/dist/extension/background.js +179 -3155
- package/dist/extension/lib/content.js +0 -115
- package/dist/extension/lib/screenshot.js +0 -93
- package/dist/extension/manifest.json +2 -2
- package/package.json +13 -5
- package/dist/cli/lib/args.js +0 -141
- package/dist/cli/lib/client.js +0 -83
- package/dist/cli/lib/commands/doctor.js +0 -134
- package/dist/cli/lib/commands/index.js +0 -51
- package/dist/cli/lib/commands/list.js +0 -159
- package/dist/cli/lib/commands/meta.js +0 -229
- package/dist/cli/lib/commands/params-groups.js +0 -48
- package/dist/cli/lib/commands/params-move.js +0 -44
- package/dist/cli/lib/commands/params.js +0 -314
- package/dist/cli/lib/commands/profile.js +0 -91
- package/dist/cli/lib/commands/setup.js +0 -294
- package/dist/cli/lib/constants.js +0 -30
- package/dist/cli/lib/help.js +0 -205
- package/dist/cli/lib/options-commands.js +0 -274
- package/dist/cli/lib/options-groups.js +0 -41
- package/dist/cli/lib/options.js +0 -125
- package/dist/cli/lib/output.js +0 -147
- package/dist/cli/lib/pagination.js +0 -55
- package/dist/cli/lib/policy-filter.js +0 -202
- package/dist/cli/lib/policy.js +0 -91
- package/dist/cli/lib/report.js +0 -61
- package/dist/cli/lib/response.js +0 -235
- package/dist/cli/lib/scope.js +0 -250
- package/dist/cli/lib/snapshot.js +0 -216
- package/dist/cli/lib/types.js +0 -2
- package/dist/cli/tabctl.js +0 -475
- package/dist/extension/lib/archive.js +0 -444
- package/dist/extension/lib/deps.js +0 -4
- package/dist/extension/lib/groups.js +0 -529
- package/dist/extension/lib/inspect.js +0 -252
- package/dist/extension/lib/move.js +0 -342
- package/dist/extension/lib/tabs.js +0 -456
- package/dist/extension/lib/undo-handlers.js +0 -447
- package/dist/host/host.bundle.js +0 -670
- package/dist/host/host.js +0 -143
- package/dist/host/host.sh +0 -5
- package/dist/host/launcher/go.mod +0 -3
- package/dist/host/launcher/main.go +0 -109
- package/dist/host/lib/handlers.js +0 -327
- package/dist/host/lib/undo.js +0 -60
- package/dist/shared/config.js +0 -134
- package/dist/shared/extension-sync.js +0 -170
- package/dist/shared/profiles.js +0 -78
- package/dist/shared/version.js +0 -8
- package/dist/shared/wrapper-health.js +0 -132
|
@@ -1,447 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Undo transaction handlers — extracted from background.ts (pure structural refactor).
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.undoGroupUpdate = undoGroupUpdate;
|
|
5
|
-
exports.undoGroupUngroup = undoGroupUngroup;
|
|
6
|
-
exports.undoGroupAssign = undoGroupAssign;
|
|
7
|
-
exports.undoGroupGather = undoGroupGather;
|
|
8
|
-
exports.undoMoveTab = undoMoveTab;
|
|
9
|
-
exports.undoMoveGroup = undoMoveGroup;
|
|
10
|
-
exports.undoMergeWindow = undoMergeWindow;
|
|
11
|
-
exports.undoArchive = undoArchive;
|
|
12
|
-
exports.undoClose = undoClose;
|
|
13
|
-
exports.undoTransaction = undoTransaction;
|
|
14
|
-
async function ensureWindow(windowId) {
|
|
15
|
-
if (windowId) {
|
|
16
|
-
try {
|
|
17
|
-
const existing = await chrome.windows.get(windowId);
|
|
18
|
-
if (existing) {
|
|
19
|
-
return windowId;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
// fall through to create
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
const created = await chrome.windows.create({ focused: false });
|
|
27
|
-
return created.id;
|
|
28
|
-
}
|
|
29
|
-
async function restoreTabsFromUndo(entries, deps) {
|
|
30
|
-
const skipped = [];
|
|
31
|
-
const restored = [];
|
|
32
|
-
const windowMap = new Map();
|
|
33
|
-
for (const entry of entries) {
|
|
34
|
-
const tabId = Number(entry.tabId);
|
|
35
|
-
if (!Number.isFinite(tabId)) {
|
|
36
|
-
skipped.push({ tabId: entry.tabId, reason: "missing_tab" });
|
|
37
|
-
continue;
|
|
38
|
-
}
|
|
39
|
-
const sourceWindowId = Number(entry.windowId);
|
|
40
|
-
if (!Number.isFinite(sourceWindowId)) {
|
|
41
|
-
skipped.push({ tabId, reason: "missing_window" });
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
let targetWindowId = windowMap.get(sourceWindowId);
|
|
45
|
-
if (!targetWindowId) {
|
|
46
|
-
targetWindowId = await ensureWindow(sourceWindowId);
|
|
47
|
-
windowMap.set(sourceWindowId, targetWindowId);
|
|
48
|
-
}
|
|
49
|
-
try {
|
|
50
|
-
await chrome.tabs.move(tabId, { windowId: targetWindowId, index: -1 });
|
|
51
|
-
restored.push({ tabId, entry, targetWindowId });
|
|
52
|
-
}
|
|
53
|
-
catch {
|
|
54
|
-
skipped.push({ tabId, reason: "move_failed" });
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
const groupsByWindow = new Map();
|
|
58
|
-
for (const item of restored) {
|
|
59
|
-
const entry = item.entry;
|
|
60
|
-
const rawGroupId = typeof entry.groupId === "number" ? entry.groupId : null;
|
|
61
|
-
const groupId = rawGroupId != null && rawGroupId !== -1 ? rawGroupId : null;
|
|
62
|
-
const groupTitle = typeof entry.groupTitle === "string" ? entry.groupTitle : null;
|
|
63
|
-
if (!groupId && !groupTitle) {
|
|
64
|
-
continue;
|
|
65
|
-
}
|
|
66
|
-
const groupKey = groupId != null ? `id:${groupId}` : `title:${groupTitle}`;
|
|
67
|
-
const key = `${item.targetWindowId}:${groupKey}`;
|
|
68
|
-
if (!groupsByWindow.has(key)) {
|
|
69
|
-
groupsByWindow.set(key, {
|
|
70
|
-
windowId: item.targetWindowId,
|
|
71
|
-
groupId,
|
|
72
|
-
groupTitle,
|
|
73
|
-
groupColor: typeof entry.groupColor === "string" ? entry.groupColor : null,
|
|
74
|
-
groupCollapsed: typeof entry.groupCollapsed === "boolean" ? entry.groupCollapsed : null,
|
|
75
|
-
tabIds: [],
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
groupsByWindow.get(key)?.tabIds.push(item.tabId);
|
|
79
|
-
}
|
|
80
|
-
for (const group of groupsByWindow.values()) {
|
|
81
|
-
if (group.tabIds.length === 0) {
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
let targetGroupId = null;
|
|
85
|
-
if (group.groupId != null) {
|
|
86
|
-
try {
|
|
87
|
-
targetGroupId = await chrome.tabs.group({ groupId: group.groupId, tabIds: group.tabIds });
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
targetGroupId = null;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
if (targetGroupId == null) {
|
|
94
|
-
try {
|
|
95
|
-
targetGroupId = await chrome.tabs.group({
|
|
96
|
-
tabIds: group.tabIds,
|
|
97
|
-
createProperties: { windowId: group.windowId },
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
catch (error) {
|
|
101
|
-
deps.log("Failed to regroup tabs", error);
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
const update = {};
|
|
106
|
-
if (typeof group.groupTitle === "string") {
|
|
107
|
-
update.title = group.groupTitle;
|
|
108
|
-
}
|
|
109
|
-
if (typeof group.groupColor === "string" && group.groupColor) {
|
|
110
|
-
update.color = group.groupColor;
|
|
111
|
-
}
|
|
112
|
-
if (typeof group.groupCollapsed === "boolean") {
|
|
113
|
-
update.collapsed = group.groupCollapsed;
|
|
114
|
-
}
|
|
115
|
-
if (Object.keys(update).length > 0) {
|
|
116
|
-
try {
|
|
117
|
-
await chrome.tabGroups.update(targetGroupId, update);
|
|
118
|
-
}
|
|
119
|
-
catch (error) {
|
|
120
|
-
deps.log("Failed to update restored group", error);
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
const orderByWindow = new Map();
|
|
125
|
-
for (const item of restored) {
|
|
126
|
-
const index = Number(item.entry.index);
|
|
127
|
-
if (!Number.isFinite(index)) {
|
|
128
|
-
continue;
|
|
129
|
-
}
|
|
130
|
-
if (!orderByWindow.has(item.targetWindowId)) {
|
|
131
|
-
orderByWindow.set(item.targetWindowId, []);
|
|
132
|
-
}
|
|
133
|
-
orderByWindow.get(item.targetWindowId)?.push({ tabId: item.tabId, index });
|
|
134
|
-
}
|
|
135
|
-
for (const [targetWindowId, items] of orderByWindow.entries()) {
|
|
136
|
-
const ordered = [...items].sort((a, b) => a.index - b.index);
|
|
137
|
-
for (const item of ordered) {
|
|
138
|
-
try {
|
|
139
|
-
await chrome.tabs.move(item.tabId, { windowId: targetWindowId, index: item.index });
|
|
140
|
-
}
|
|
141
|
-
catch {
|
|
142
|
-
// ignore ordering failures
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
return {
|
|
147
|
-
summary: {
|
|
148
|
-
restoredTabs: restored.length,
|
|
149
|
-
skippedTabs: skipped.length,
|
|
150
|
-
},
|
|
151
|
-
skipped,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
async function undoGroupUpdate(undo) {
|
|
155
|
-
const groupId = Number(undo.groupId);
|
|
156
|
-
if (!Number.isFinite(groupId)) {
|
|
157
|
-
return {
|
|
158
|
-
summary: { restoredGroups: 0, skippedGroups: 1 },
|
|
159
|
-
skipped: [{ groupId: undo.groupId, reason: "missing_group" }],
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
const previous = undo.previous || {};
|
|
163
|
-
const update = {};
|
|
164
|
-
if (typeof previous.title === "string") {
|
|
165
|
-
update.title = previous.title;
|
|
166
|
-
}
|
|
167
|
-
if (typeof previous.color === "string" && previous.color) {
|
|
168
|
-
update.color = previous.color;
|
|
169
|
-
}
|
|
170
|
-
if (typeof previous.collapsed === "boolean") {
|
|
171
|
-
update.collapsed = previous.collapsed;
|
|
172
|
-
}
|
|
173
|
-
if (!Object.keys(update).length) {
|
|
174
|
-
return {
|
|
175
|
-
summary: { restoredGroups: 0, skippedGroups: 1 },
|
|
176
|
-
skipped: [{ groupId, reason: "missing_values" }],
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
try {
|
|
180
|
-
await chrome.tabGroups.update(groupId, update);
|
|
181
|
-
return {
|
|
182
|
-
summary: { restoredGroups: 1, skippedGroups: 0 },
|
|
183
|
-
skipped: [],
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
catch {
|
|
187
|
-
return {
|
|
188
|
-
summary: { restoredGroups: 0, skippedGroups: 1 },
|
|
189
|
-
skipped: [{ groupId, reason: "update_failed" }],
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
async function undoGroupUngroup(undo, deps) {
|
|
194
|
-
const tabs = undo.tabs || [];
|
|
195
|
-
return await restoreTabsFromUndo(tabs, deps);
|
|
196
|
-
}
|
|
197
|
-
async function undoGroupAssign(undo, deps) {
|
|
198
|
-
const tabs = undo.tabs || [];
|
|
199
|
-
return await restoreTabsFromUndo(tabs, deps);
|
|
200
|
-
}
|
|
201
|
-
async function undoGroupGather(undo, deps) {
|
|
202
|
-
const tabs = undo.tabs || [];
|
|
203
|
-
return await restoreTabsFromUndo(tabs, deps);
|
|
204
|
-
}
|
|
205
|
-
async function undoMoveTab(undo, deps) {
|
|
206
|
-
const from = undo.from || {};
|
|
207
|
-
const entry = {
|
|
208
|
-
tabId: undo.tabId,
|
|
209
|
-
windowId: from.windowId,
|
|
210
|
-
index: from.index,
|
|
211
|
-
groupId: from.groupId,
|
|
212
|
-
groupTitle: from.groupTitle,
|
|
213
|
-
groupColor: from.groupColor,
|
|
214
|
-
groupCollapsed: from.groupCollapsed,
|
|
215
|
-
};
|
|
216
|
-
return await restoreTabsFromUndo([entry], deps);
|
|
217
|
-
}
|
|
218
|
-
async function undoMoveGroup(undo, deps) {
|
|
219
|
-
const tabs = undo.tabs || [];
|
|
220
|
-
return await restoreTabsFromUndo(tabs, deps);
|
|
221
|
-
}
|
|
222
|
-
async function undoMergeWindow(undo, deps) {
|
|
223
|
-
const tabs = undo.tabs || [];
|
|
224
|
-
return await restoreTabsFromUndo(tabs, deps);
|
|
225
|
-
}
|
|
226
|
-
async function undoArchive(undo, deps) {
|
|
227
|
-
const tabs = undo.tabs || [];
|
|
228
|
-
const restored = [];
|
|
229
|
-
const skipped = [];
|
|
230
|
-
const windowMap = new Map();
|
|
231
|
-
for (const entry of tabs) {
|
|
232
|
-
if (!entry.tabId) {
|
|
233
|
-
skipped.push({ tabId: entry.tabId, reason: "missing_tab" });
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
let targetWindowId = windowMap.get(entry.from.windowId);
|
|
237
|
-
if (!targetWindowId) {
|
|
238
|
-
targetWindowId = await ensureWindow(entry.from.windowId);
|
|
239
|
-
windowMap.set(entry.from.windowId, targetWindowId);
|
|
240
|
-
}
|
|
241
|
-
try {
|
|
242
|
-
await chrome.tabs.move(entry.tabId, { windowId: targetWindowId, index: -1 });
|
|
243
|
-
restored.push({ tabId: entry.tabId, targetWindowId });
|
|
244
|
-
}
|
|
245
|
-
catch {
|
|
246
|
-
skipped.push({ tabId: entry.tabId, reason: "move_failed" });
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
const restoredSet = new Set(restored.map((item) => item.tabId));
|
|
250
|
-
const groupsByWindow = new Map();
|
|
251
|
-
for (const entry of tabs) {
|
|
252
|
-
if (!restoredSet.has(entry.tabId)) {
|
|
253
|
-
continue;
|
|
254
|
-
}
|
|
255
|
-
const targetWindowId = windowMap.get(entry.from.windowId) || entry.from.windowId;
|
|
256
|
-
const hasGroupId = entry.from.groupId != null && entry.from.groupId !== -1;
|
|
257
|
-
const hasGroupTitle = entry.from.groupTitle != null;
|
|
258
|
-
if (!hasGroupId && !hasGroupTitle) {
|
|
259
|
-
continue;
|
|
260
|
-
}
|
|
261
|
-
const groupKey = hasGroupId ? entry.from.groupId : entry.from.groupTitle;
|
|
262
|
-
const key = `${targetWindowId}:${groupKey}`;
|
|
263
|
-
if (!groupsByWindow.has(key)) {
|
|
264
|
-
groupsByWindow.set(key, []);
|
|
265
|
-
}
|
|
266
|
-
groupsByWindow.get(key)?.push(entry);
|
|
267
|
-
}
|
|
268
|
-
for (const [key, groupTabs] of groupsByWindow.entries()) {
|
|
269
|
-
const [windowIdPart] = key.split(":");
|
|
270
|
-
const targetWindowId = Number(windowIdPart);
|
|
271
|
-
const tabIds = groupTabs.map((entry) => entry.tabId).filter(Boolean);
|
|
272
|
-
if (!tabIds.length) {
|
|
273
|
-
continue;
|
|
274
|
-
}
|
|
275
|
-
try {
|
|
276
|
-
const groupId = await chrome.tabs.group({ tabIds, createProperties: { windowId: targetWindowId } });
|
|
277
|
-
await chrome.tabGroups.update(groupId, {
|
|
278
|
-
title: groupTabs[0].from.groupTitle || "",
|
|
279
|
-
color: groupTabs[0].from.groupColor || "grey",
|
|
280
|
-
collapsed: groupTabs[0].from.groupCollapsed || false,
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
catch (error) {
|
|
284
|
-
deps.log("Failed to recreate group", error);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
for (const [originalWindowId, targetWindowId] of windowMap.entries()) {
|
|
288
|
-
const windowTabs = tabs
|
|
289
|
-
.filter((entry) => entry.from.windowId === originalWindowId && restoredSet.has(entry.tabId))
|
|
290
|
-
.sort((a, b) => a.from.index - b.from.index);
|
|
291
|
-
for (const entry of windowTabs) {
|
|
292
|
-
if (!entry.tabId) {
|
|
293
|
-
continue;
|
|
294
|
-
}
|
|
295
|
-
try {
|
|
296
|
-
await chrome.tabs.move(entry.tabId, { windowId: targetWindowId, index: entry.from.index });
|
|
297
|
-
}
|
|
298
|
-
catch {
|
|
299
|
-
// ignore ordering failures
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
const activeTab = windowTabs.find((entry) => entry.active);
|
|
303
|
-
if (activeTab && activeTab.tabId) {
|
|
304
|
-
try {
|
|
305
|
-
await chrome.tabs.update(activeTab.tabId, { active: true });
|
|
306
|
-
}
|
|
307
|
-
catch {
|
|
308
|
-
// ignore
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
return {
|
|
313
|
-
summary: {
|
|
314
|
-
restoredTabs: restored.length,
|
|
315
|
-
skippedTabs: skipped.length,
|
|
316
|
-
},
|
|
317
|
-
skipped,
|
|
318
|
-
};
|
|
319
|
-
}
|
|
320
|
-
async function undoClose(undo, deps) {
|
|
321
|
-
const tabs = undo.tabs || [];
|
|
322
|
-
const restored = [];
|
|
323
|
-
const skipped = [];
|
|
324
|
-
const windowMap = new Map();
|
|
325
|
-
for (const entry of tabs) {
|
|
326
|
-
if (!entry.url) {
|
|
327
|
-
skipped.push({ url: entry.url, reason: "missing_url" });
|
|
328
|
-
continue;
|
|
329
|
-
}
|
|
330
|
-
let targetWindowId = windowMap.get(entry.from.windowId);
|
|
331
|
-
if (!targetWindowId) {
|
|
332
|
-
targetWindowId = await ensureWindow(entry.from.windowId);
|
|
333
|
-
windowMap.set(entry.from.windowId, targetWindowId);
|
|
334
|
-
}
|
|
335
|
-
try {
|
|
336
|
-
const created = await chrome.tabs.create({
|
|
337
|
-
windowId: targetWindowId,
|
|
338
|
-
url: entry.url,
|
|
339
|
-
active: false,
|
|
340
|
-
pinned: entry.pinned,
|
|
341
|
-
});
|
|
342
|
-
restored.push({ tabId: created.id, entry });
|
|
343
|
-
}
|
|
344
|
-
catch {
|
|
345
|
-
skipped.push({ url: entry.url, reason: "create_failed" });
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
|
-
const groupsByWindow = new Map();
|
|
349
|
-
for (const item of restored) {
|
|
350
|
-
const entry = item.entry;
|
|
351
|
-
const targetWindowId = windowMap.get(entry.from.windowId) || entry.from.windowId;
|
|
352
|
-
const hasGroupId = entry.from.groupId != null && entry.from.groupId !== -1;
|
|
353
|
-
const hasGroupTitle = entry.from.groupTitle != null;
|
|
354
|
-
if (!hasGroupId && !hasGroupTitle) {
|
|
355
|
-
continue;
|
|
356
|
-
}
|
|
357
|
-
const groupKey = hasGroupId ? entry.from.groupId : entry.from.groupTitle;
|
|
358
|
-
const key = `${targetWindowId}:${groupKey}`;
|
|
359
|
-
if (!groupsByWindow.has(key)) {
|
|
360
|
-
groupsByWindow.set(key, []);
|
|
361
|
-
}
|
|
362
|
-
groupsByWindow.get(key)?.push({ tabId: item.tabId, entry });
|
|
363
|
-
}
|
|
364
|
-
for (const [key, groupTabs] of groupsByWindow.entries()) {
|
|
365
|
-
const [windowIdPart] = key.split(":");
|
|
366
|
-
const targetWindowId = Number(windowIdPart);
|
|
367
|
-
const tabIds = groupTabs.map((item) => item.tabId).filter(Boolean);
|
|
368
|
-
if (!tabIds.length) {
|
|
369
|
-
continue;
|
|
370
|
-
}
|
|
371
|
-
try {
|
|
372
|
-
const groupId = await chrome.tabs.group({ tabIds, createProperties: { windowId: targetWindowId } });
|
|
373
|
-
await chrome.tabGroups.update(groupId, {
|
|
374
|
-
title: groupTabs[0].entry.from.groupTitle || "",
|
|
375
|
-
color: groupTabs[0].entry.from.groupColor || "grey",
|
|
376
|
-
collapsed: groupTabs[0].entry.from.groupCollapsed || false,
|
|
377
|
-
});
|
|
378
|
-
}
|
|
379
|
-
catch (error) {
|
|
380
|
-
deps.log("Failed to recreate group", error);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
for (const [originalWindowId, targetWindowId] of windowMap.entries()) {
|
|
384
|
-
const windowTabs = restored
|
|
385
|
-
.map((item) => ({ tabId: item.tabId, entry: item.entry }))
|
|
386
|
-
.filter((item) => item.entry.from.windowId === originalWindowId)
|
|
387
|
-
.sort((a, b) => a.entry.from.index - b.entry.from.index);
|
|
388
|
-
for (const item of windowTabs) {
|
|
389
|
-
try {
|
|
390
|
-
await chrome.tabs.move(item.tabId, { windowId: targetWindowId, index: item.entry.from.index });
|
|
391
|
-
}
|
|
392
|
-
catch {
|
|
393
|
-
// ignore ordering failures
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
const activeTab = windowTabs.find((item) => item.entry.active);
|
|
397
|
-
if (activeTab) {
|
|
398
|
-
try {
|
|
399
|
-
await chrome.tabs.update(activeTab.tabId, { active: true });
|
|
400
|
-
}
|
|
401
|
-
catch {
|
|
402
|
-
// ignore
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
return {
|
|
407
|
-
summary: {
|
|
408
|
-
restoredTabs: restored.length,
|
|
409
|
-
skippedTabs: skipped.length,
|
|
410
|
-
},
|
|
411
|
-
skipped,
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
async function undoTransaction(params, deps) {
|
|
415
|
-
if (!params.record || !params.record.undo) {
|
|
416
|
-
throw new Error("Undo record missing");
|
|
417
|
-
}
|
|
418
|
-
const undo = params.record.undo;
|
|
419
|
-
if (undo.action === "archive") {
|
|
420
|
-
return await undoArchive(undo, deps);
|
|
421
|
-
}
|
|
422
|
-
if (undo.action === "close") {
|
|
423
|
-
return await undoClose(undo, deps);
|
|
424
|
-
}
|
|
425
|
-
if (undo.action === "group-update") {
|
|
426
|
-
return await undoGroupUpdate(undo);
|
|
427
|
-
}
|
|
428
|
-
if (undo.action === "group-ungroup") {
|
|
429
|
-
return await undoGroupUngroup(undo, deps);
|
|
430
|
-
}
|
|
431
|
-
if (undo.action === "group-assign") {
|
|
432
|
-
return await undoGroupAssign(undo, deps);
|
|
433
|
-
}
|
|
434
|
-
if (undo.action === "group-gather") {
|
|
435
|
-
return await undoGroupGather(undo, deps);
|
|
436
|
-
}
|
|
437
|
-
if (undo.action === "move-tab") {
|
|
438
|
-
return await undoMoveTab(undo, deps);
|
|
439
|
-
}
|
|
440
|
-
if (undo.action === "move-group") {
|
|
441
|
-
return await undoMoveGroup(undo, deps);
|
|
442
|
-
}
|
|
443
|
-
if (undo.action === "merge-window") {
|
|
444
|
-
return await undoMergeWindow(undo, deps);
|
|
445
|
-
}
|
|
446
|
-
throw new Error(`Unknown undo action: ${undo.action}`);
|
|
447
|
-
}
|