-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathmain.js
139 lines (121 loc) · 4.45 KB
/
main.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
'use strict';
// See https://github.com/tfoxy/chrome-promise
chrome.promise = new ChromePromise();
const stashNamePlaceholder = 'Untitled stash';
const getRandomString = function(length) {
let text = '';
const possible =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < length; i++) {
text += possible.charAt(Math.floor(Math.random() * possible.length));
}
return text;
};
/** Converts Chrome API's array of tabs to a serializable representation. */
const transformTabsForStorage = (tabs) => tabs.map(
tab => ({title: tab.title, url: tab.url, favIconUrl: tab.favIconUrl}));
/** Used to store stash names in local storage. */
const getStashNameStorageKey = windowId => 'stashName_' + windowId;
/** Used to store data on stashes in sync storage. */
const getStashStorageKey = stashId => 'stash_' + stashId;
/** Used to store a tab in the stash in sync storage. */
const getTabStorageKey = (stashId, tabIndex) =>
'tab_' + stashId + '_' + tabIndex;
const getStashes = async function() {
const items = await chrome.promise.storage.sync.get(null);
const stashes = {};
for (let key in items) {
const stashMatches = key.match(/^stash_(.*)/);
if (stashMatches) {
_.merge(stashes, {[stashMatches[1]]: items[key]});
}
const tabMatches = key.match(/^tab_(.*)_(\d*)/);
if (tabMatches) {
_.set(
stashes, [tabMatches[1], 'tabs', parseInt(tabMatches[2], 10)],
items[key]);
}
}
return stashes;
};
const getMessages = async function() {
const items = await chrome.promise.storage.sync.get('messages');
return items['messages'] || {};
};
const setStashes = async function(stashes) {
// We have to store tabs as individual items because of size limits of sync
// API for a single item.
const itemsToStore = {}, itemsToRemove = [];
for (let stashId in stashes) {
const stash = stashes[stashId];
itemsToStore[getStashStorageKey(stashId)] = _.omit(stash, 'tabs');
stash.tabs.forEach((tab, tabIndex) => {
itemsToStore[getTabStorageKey(stashId, tabIndex)] = tab;
});
}
const currentItems = await chrome.promise.storage.sync.get(null);
for (let key in currentItems) {
if (key.startsWith('stash_') || key.startsWith('tab_')) {
if (!(key in itemsToStore)) {
itemsToRemove.push(key);
} else if (_.isEqual(currentItems[key], itemsToStore[key])) {
delete itemsToStore[key];
}
}
}
let removePromise, setPromise;
if (itemsToRemove) {
removePromise = chrome.promise.storage.sync.remove(itemsToRemove);
}
if (!_.isEmpty(itemsToStore)) {
setPromise = chrome.promise.storage.sync.set(itemsToStore);
}
await Promise.all([removePromise, setPromise]);
};
const setMessageRead = async function(name) {
const messages = await getMessages();
messages[name] = true;
await chrome.promise.storage.sync.set({messages: messages});
};
const saveStash = async function(name, tabs, activeTabIndex) {
const stashes = await getStashes();
stashes[getRandomString(10)] = {
name: name.trim(),
timestamp: (new Date()).toISOString(),
tabs: transformTabsForStorage(tabs),
activeTabIndex: activeTabIndex
};
await setStashes(stashes);
await chrome.promise.tabs.remove(tabs.map(tab => tab.id));
};
const openStash = async function(stash) {
const window = await chrome.promise.windows.create(
{url: stash.tabs.map(tab => tab.url)});
const activeTabIndex = ('activeTabIndex' in stash) ? stash.activeTabIndex :
(window.tabs.length - 1);
await chrome.promise.tabs.update(
window.tabs[activeTabIndex].id, {active: true});
return window;
};
const deleteStash = async function(stashId) {
const stashes = await getStashes();
delete stashes[stashId];
await setStashes(stashes);
};
const topUp = async function(stashId, tabs) {
const stashes = await getStashes();
if (!(stashId in stashes)) {
return;
};
stashes[stashId].tabs =
stashes[stashId].tabs.concat(transformTabsForStorage(tabs));
stashes[stashId].timestamp = (new Date()).toISOString();
await setStashes(stashes);
await chrome.promise.tabs.remove(tabs.map(tab => tab.id));
};
const getOriginalStashName = async function() {
const currentWindow = await chrome.promise.windows.getCurrent();
const stashNameStorageKey = getStashNameStorageKey(currentWindow.id);
const items = await chrome.promise.storage.local.get(stashNameStorageKey);
return items[stashNameStorageKey];
};