-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbackground.js
More file actions
231 lines (195 loc) · 6.22 KB
/
background.js
File metadata and controls
231 lines (195 loc) · 6.22 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
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
// Keep track of the currently open popup window.
let currentPopupWindowId = null;
// Creates a new popup window.
async function createPopupWindow() {
const currentWindow = await browser.windows.getCurrent();
const {width, height, top, left} = await calculatePopupDimensions(currentWindow);
const popup = await browser.windows.create({
url: browser.runtime.getURL("popup.html"),
type: "popup",
width: width,
height: height,
top: top,
left: left
});
currentPopupWindowId = popup.id;
}
//Calculate dimensions for the popup window.
async function calculatePopupDimensions(currentWindow) {
const currentWidth = currentWindow.width ?? 800;
const currentHeight = currentWindow.height ?? 600;
const maxHeight = currentHeight * 0.8;
const currentLeft = currentWindow.left ?? 0;
const currentTop = currentWindow.top ?? 0;
let left = currentLeft + currentWidth / 4;
let top = currentTop + 160;
const tabs = await browser.tabs.query({});
const tabsCount = tabs.length;
// Scale the window height depending on the number of tabs.
let height = Math.min((127 + 34 * tabsCount), maxHeight);
let width = currentWidth/2;
// Convert to integers, rounding to the nearest whole number.
width = Math.round(width);
height = Math.round(height);
top = Math.round(top);
left = Math.round(left);
return { width, height, top, left };
}
// Listen for the command to open the popup. Close the current one if it's open.
browser.commands.onCommand.addListener(async (command) => {
if (command === "open-popup") {
if (currentPopupWindowId !== null) {
try {
await browser.windows.remove(currentPopupWindowId);
} catch (err) {
console.warn("Tried to close an old window, but it may already be closed:", err);
}
currentPopupWindowId = null;
}
createPopupWindow();
}
});
// Callback to clear the current popup window ID when it's closed.
browser.windows.onRemoved.addListener((removedWindowId) => {
if (removedWindowId === currentPopupWindowId) {
currentPopupWindowId = null;
}
});
// Listen for focus changes and close the popup if it loses focus.
browser.windows.onFocusChanged.addListener(async (windowId) => {
if (currentPopupWindowId !== null) {
if (windowId !== currentPopupWindowId) {
try {
await browser.windows.remove(currentPopupWindowId);
} catch (error) {
console.warn("Failed to close popup window:", error);
} finally {
currentPopupWindowId = null;
}
}
}
// If this focus change to another app, skip the timestamp logic.
if (windowId === browser.windows.WINDOW_ID_NONE) {
return;
}
// Update the timestamp for the active tab if focusing a new window and not the popup.
try {
const winInfo = await browser.windows.get(windowId, { populate: true });
if (winInfo.type === "popup") {
return;
}
const activeTab = winInfo.tabs.find((tab) => tab.active);
if (activeTab) {
const tabId = activeTab.id;
tabLastVisitMap[tabId] = Date.now();
const existingIndex = visitedTabs.indexOf(tabId);
if (existingIndex !== -1) {
visitedTabs.splice(existingIndex, 1);
}
visitedTabs.unshift(tabId);
try {
await browser.storage.local.set({
visitedTabs,
tabLastVisitMap
});
} catch (err) {
console.error("Error saving to storage:", err);
}
}
} catch (err) {
console.error("Failed to get or update window info:", err);
}
});
// Visited tabs array
let visitedTabs = [];
// Map of tabId to last visit time stamps.
let tabLastVisitMap = {};
// Load the visitedTabs and tabLastVisitMap from storage.
(async function loadFromStorage() {
try {
// Load the visitedTabs and tabLastVisitMap from storage.
// If the key is not found, the default value is used.
const {
visitedTabs: storedVisitedTabs = [],
tabLastVisitMap: storedTabLastVisitMap = {}
} = await browser.storage.local.get({
visitedTabs: [],
tabLastVisitMap: {}
});
visitedTabs = storedVisitedTabs;
tabLastVisitMap = storedTabLastVisitMap;
} catch (err) {
console.error("Error loading from storage:", err);
visitedTabs = [];
tabLastVisitMap = {};
}
})();
/**
* Listens for tab activation (when user switches to a tab).
* Moving tab ID to the front of the `recentTabs`.
*/
browser.tabs.onActivated.addListener(async (activeInfo) => {
const { tabId } = activeInfo;
const currentWindow = await browser.windows.get(activeInfo.windowId);
if (currentWindow.type === "popup") {
return;
}
tabLastVisitMap[tabId] = Date.now();
const existingIndex = visitedTabs.indexOf(tabId);
if (existingIndex !== -1) {
visitedTabs.splice(existingIndex, 1);
}
visitedTabs.unshift(tabId);
try {
await browser.storage.local.set({
visitedTabs,
tabLastVisitMap
});
} catch (err) {
console.error("Error saving to storage:", err);
}
});
/**
* Gets the current visitedTabs and timestamps
* so the popup can build the list with "time since used."
*/
async function getVisitedData() {
const mRUTabs = await getTabsInMRUOrder();
return {
tabs: mRUTabs,
timestamps: tabLastVisitMap
};
}
/**
* Gets all tabs in MRU order:
* 1. The tabs found in `visitedTabs` (most recent first).
* 2. Then, any other tabs in default order (as returned by query).
*/
async function getTabsInMRUOrder() {
const allTabs = await browser.tabs.query({ currentWindow: false });
const sortedTabs = [];
// 1) For each tabId in `visitedTabs`, if it's still open, push its tab info.
for (const tabId of visitedTabs) {
const t = allTabs.find((tab) => tab.id === tabId);
if (t) {
sortedTabs.push(t);
}
}
// 2) For each tab from `allTabs`,
// if we haven’t added it yet: append it in the default order.
for (const t of allTabs) {
const alreadyIncluded = sortedTabs.some((st) => st.id === t.id);
if (!alreadyIncluded) {
sortedTabs.push(t);
}
}
return sortedTabs;
}
/**
* Listen for messages requesting the visited tabs data.
*/
browser.runtime.onMessage.addListener(async (message) => {
if (message.command === "getVisitedTabs") {
return Promise.resolve({ visitedData: await getVisitedData() });
}
});