tabctl 0.6.0-rc.11 → 0.6.0-rc.12
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/dist/extension/background.js +181 -36
- package/dist/extension/manifest.json +1 -1
- package/package.json +2 -2
|
@@ -783,7 +783,12 @@
|
|
|
783
783
|
var RECONNECT_ALARM = "tabctl-reconnect";
|
|
784
784
|
var KEEPALIVE_INTERVAL_MINUTES = 1;
|
|
785
785
|
var BROWSER_STATE_SYNC_DEBOUNCE_MS = 750;
|
|
786
|
-
var
|
|
786
|
+
var ACTIVE_PAGE_CACHE_LOADING_RETRY_MS = 100;
|
|
787
|
+
var ACTIVE_PAGE_CACHE_SETTLING_RETRY_MS = 150;
|
|
788
|
+
var ACTIVE_PAGE_CACHE_FIRST_QUIESCENT_TIMEOUT_MS = 750;
|
|
789
|
+
var ACTIVE_PAGE_CACHE_FIRST_QUIESCENT_SAMPLE_MS = 75;
|
|
790
|
+
var ACTIVE_PAGE_CACHE_FIRST_LOADING_MAX_ATTEMPTS = 300;
|
|
791
|
+
var ACTIVE_PAGE_CACHE_FIRST_SETTLING_MAX_ATTEMPTS = 200;
|
|
787
792
|
var ACTIVE_PAGE_CACHE_TIMEOUT_MS = 5e3;
|
|
788
793
|
var MAX_PAGE_HTML_CHARS = 10 * 1024 * 1024;
|
|
789
794
|
var ACTIVE_PAGE_CACHE_MAX_HTML_CHARS = MAX_PAGE_HTML_CHARS;
|
|
@@ -837,7 +842,15 @@
|
|
|
837
842
|
lastQuiescentCapturedKey: null,
|
|
838
843
|
lastQuiescentCapturedAt: 0,
|
|
839
844
|
statusRequests: /* @__PURE__ */ new Map(),
|
|
840
|
-
|
|
845
|
+
states: /* @__PURE__ */ new Map()
|
|
846
|
+
};
|
|
847
|
+
var ACTIVE_PAGE_CACHE_STATE_DETAILS = {
|
|
848
|
+
checking: "checking status",
|
|
849
|
+
loading: "page still loading",
|
|
850
|
+
settling: "waiting for page settle",
|
|
851
|
+
capturing: "capture pending",
|
|
852
|
+
cached: "page cache available",
|
|
853
|
+
error: "capture failed"
|
|
841
854
|
};
|
|
842
855
|
function log(...args) {
|
|
843
856
|
console.log("[tabctl]", ...args);
|
|
@@ -1040,20 +1053,40 @@
|
|
|
1040
1053
|
const key = activePageCacheKeyForTabId(tabId, url);
|
|
1041
1054
|
return activePageCache.inFlightKeys.has(key) || activePageCache.pending?.key === key || activePageCache.quiescentPending?.key === key;
|
|
1042
1055
|
}
|
|
1043
|
-
function
|
|
1044
|
-
activePageCache.
|
|
1056
|
+
function setActivePageCacheState(tabId, url, kind, detail = ACTIVE_PAGE_CACHE_STATE_DETAILS[kind]) {
|
|
1057
|
+
activePageCache.states.set(activePageCacheKeyForTabId(tabId, url), { kind, detail });
|
|
1058
|
+
}
|
|
1059
|
+
function activePageCacheState(tabId, url) {
|
|
1060
|
+
return activePageCache.states.get(activePageCacheKeyForTabId(tabId, url));
|
|
1045
1061
|
}
|
|
1046
|
-
function
|
|
1047
|
-
activePageCache.
|
|
1062
|
+
function clearActivePageCacheState(tabId, url) {
|
|
1063
|
+
activePageCache.states.delete(activePageCacheKeyForTabId(tabId, url));
|
|
1048
1064
|
}
|
|
1049
|
-
function
|
|
1065
|
+
function clearActivePageCacheStatesForTab(tabId) {
|
|
1050
1066
|
const prefix = `${tabId}:`;
|
|
1051
|
-
for (const key of activePageCache.
|
|
1067
|
+
for (const key of activePageCache.states.keys()) {
|
|
1052
1068
|
if (key.startsWith(prefix)) {
|
|
1053
|
-
activePageCache.
|
|
1069
|
+
activePageCache.states.delete(key);
|
|
1054
1070
|
}
|
|
1055
1071
|
}
|
|
1056
1072
|
}
|
|
1073
|
+
function clearPendingFirstActivePageCacheCapture(key) {
|
|
1074
|
+
if (activePageCache.pending?.key === key) {
|
|
1075
|
+
activePageCache.pending = null;
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
function failFirstActivePageCacheCapture(pending, tab, url, detail) {
|
|
1079
|
+
clearPendingFirstActivePageCacheCapture(pending.key);
|
|
1080
|
+
setActivePageCacheState(tab.id, url, "error", detail);
|
|
1081
|
+
void setCacheErrorIndicator(tab.id, url, detail);
|
|
1082
|
+
void requestPageCacheStatusForTab(tab.id, `first-capture:${detail.replace(/\s+/g, "-")}`);
|
|
1083
|
+
}
|
|
1084
|
+
function waitingDetailForActivePageCacheState(state2) {
|
|
1085
|
+
if (state2?.kind === "checking" || state2?.kind === "loading" || state2?.kind === "settling" || state2?.kind === "capturing") {
|
|
1086
|
+
return state2.detail;
|
|
1087
|
+
}
|
|
1088
|
+
return null;
|
|
1089
|
+
}
|
|
1057
1090
|
async function applyPageCacheStatus(tabId, expectedUrl, available) {
|
|
1058
1091
|
try {
|
|
1059
1092
|
const tab = await chrome.tabs.get(tabId);
|
|
@@ -1065,23 +1098,26 @@
|
|
|
1065
1098
|
return;
|
|
1066
1099
|
}
|
|
1067
1100
|
if (!available) {
|
|
1068
|
-
const
|
|
1069
|
-
|
|
1070
|
-
|
|
1101
|
+
const cacheState = activePageCacheState(tabId, expectedUrl);
|
|
1102
|
+
const waitingDetail = waitingDetailForActivePageCacheState(cacheState);
|
|
1103
|
+
if (waitingDetail) {
|
|
1104
|
+
await setCacheWaitingIndicator(tabId, expectedUrl, waitingDetail);
|
|
1071
1105
|
return;
|
|
1072
1106
|
}
|
|
1073
|
-
if (
|
|
1074
|
-
await setCacheErrorIndicator(tabId, expectedUrl,
|
|
1107
|
+
if (cacheState?.kind === "error") {
|
|
1108
|
+
await setCacheErrorIndicator(tabId, expectedUrl, cacheState.detail);
|
|
1075
1109
|
return;
|
|
1076
1110
|
}
|
|
1077
1111
|
if (hasPendingActivePageCacheWork(tabId, expectedUrl)) {
|
|
1078
|
-
|
|
1112
|
+
setActivePageCacheState(tabId, expectedUrl, "capturing");
|
|
1113
|
+
await setCacheWaitingIndicator(tabId, expectedUrl, ACTIVE_PAGE_CACHE_STATE_DETAILS.capturing);
|
|
1079
1114
|
return;
|
|
1080
1115
|
}
|
|
1116
|
+
clearActivePageCacheState(tabId, expectedUrl);
|
|
1081
1117
|
await clearCacheAvailableIndicator(tabId);
|
|
1082
1118
|
return;
|
|
1083
1119
|
}
|
|
1084
|
-
|
|
1120
|
+
setActivePageCacheState(tabId, expectedUrl, "cached");
|
|
1085
1121
|
await setCacheAvailableIndicator(tabId, expectedUrl);
|
|
1086
1122
|
} catch {
|
|
1087
1123
|
await clearCacheAvailableIndicator(tabId);
|
|
@@ -1115,6 +1151,7 @@
|
|
|
1115
1151
|
const port = state.port;
|
|
1116
1152
|
if (!port) {
|
|
1117
1153
|
connectNative();
|
|
1154
|
+
setActivePageCacheState(tab.id, url, "checking", "native host reconnecting");
|
|
1118
1155
|
void setCacheWaitingIndicator(tab.id, url, "native host reconnecting");
|
|
1119
1156
|
return;
|
|
1120
1157
|
}
|
|
@@ -1167,7 +1204,7 @@
|
|
|
1167
1204
|
}
|
|
1168
1205
|
function isEligibleActivePageCacheTab(tab) {
|
|
1169
1206
|
const url = activePageCacheUrl(tab);
|
|
1170
|
-
return typeof tab.id === "number" && Boolean(url) && tab.incognito !== true && !browserState.incognitoTabIds.has(tab.id) && (typeof tab.windowId !== "number" || !browserState.incognitoWindowIds.has(tab.windowId)) && tab.discarded !== true &&
|
|
1207
|
+
return typeof tab.id === "number" && Boolean(url) && tab.incognito !== true && !browserState.incognitoTabIds.has(tab.id) && (typeof tab.windowId !== "number" || !browserState.incognitoWindowIds.has(tab.windowId)) && tab.discarded !== true && isScriptableUrl(url);
|
|
1171
1208
|
}
|
|
1172
1209
|
function clearPendingActivePageCacheCapture() {
|
|
1173
1210
|
if (activePageCache.timer) {
|
|
@@ -1206,6 +1243,17 @@
|
|
|
1206
1243
|
}
|
|
1207
1244
|
}, ACTIVE_PAGE_CACHE_QUIESCENT_DELAY_MS);
|
|
1208
1245
|
}
|
|
1246
|
+
function scheduleFirstActivePageCacheRetry(pending, delayMs) {
|
|
1247
|
+
clearPendingActivePageCacheCapture();
|
|
1248
|
+
activePageCache.pending = pending;
|
|
1249
|
+
activePageCache.timer = setTimeout(() => {
|
|
1250
|
+
activePageCache.timer = null;
|
|
1251
|
+
const retry = activePageCache.pending;
|
|
1252
|
+
if (retry) {
|
|
1253
|
+
void captureFirstSettledActivePageCache(retry);
|
|
1254
|
+
}
|
|
1255
|
+
}, delayMs);
|
|
1256
|
+
}
|
|
1209
1257
|
function scheduleActivePageCacheCapture(tab, reason) {
|
|
1210
1258
|
if (!isEligibleActivePageCacheTab(tab)) {
|
|
1211
1259
|
if (typeof tab.id === "number") {
|
|
@@ -1217,23 +1265,25 @@
|
|
|
1217
1265
|
}
|
|
1218
1266
|
const url = activePageCacheUrl(tab);
|
|
1219
1267
|
const key = activePageCacheKey(tab, url);
|
|
1220
|
-
|
|
1221
|
-
|
|
1268
|
+
if (tab.status === "loading") {
|
|
1269
|
+
setActivePageCacheState(tab.id, url, "loading");
|
|
1270
|
+
void setCacheWaitingIndicator(tab.id, url, ACTIVE_PAGE_CACHE_STATE_DETAILS.loading);
|
|
1271
|
+
if (activePageCache.pending?.key !== key) {
|
|
1272
|
+
scheduleFirstActivePageCacheRetry({ tabId: tab.id, reason, key, attempts: 0 }, ACTIVE_PAGE_CACHE_LOADING_RETRY_MS);
|
|
1273
|
+
}
|
|
1274
|
+
return;
|
|
1275
|
+
}
|
|
1276
|
+
setActivePageCacheState(tab.id, url, "checking");
|
|
1277
|
+
void setCacheWaitingIndicator(tab.id, url, ACTIVE_PAGE_CACHE_STATE_DETAILS.checking);
|
|
1222
1278
|
requestPageCacheStatus(tab, reason);
|
|
1223
1279
|
scheduleQuiescentActivePageCacheCapture(tab, reason, key);
|
|
1224
1280
|
if (activePageCache.inFlightKeys.has(key) || activePageCache.lastCapturedKey === key) {
|
|
1225
1281
|
return;
|
|
1226
1282
|
}
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
const pending = activePageCache.pending;
|
|
1232
|
-
activePageCache.pending = null;
|
|
1233
|
-
if (pending) {
|
|
1234
|
-
void captureActivePageCache(pending.tab, pending.reason, pending.key);
|
|
1235
|
-
}
|
|
1236
|
-
}, ACTIVE_PAGE_CACHE_DEBOUNCE_MS);
|
|
1283
|
+
if (activePageCache.pending?.key === key) {
|
|
1284
|
+
return;
|
|
1285
|
+
}
|
|
1286
|
+
scheduleFirstActivePageCacheRetry({ tabId: tab.id, reason, key, attempts: 0 }, 0);
|
|
1237
1287
|
}
|
|
1238
1288
|
async function scheduleActivePageCacheCaptureForTab(tabId, reason) {
|
|
1239
1289
|
try {
|
|
@@ -1268,6 +1318,83 @@
|
|
|
1268
1318
|
return null;
|
|
1269
1319
|
}
|
|
1270
1320
|
}
|
|
1321
|
+
async function getPageCacheOpenTabs() {
|
|
1322
|
+
const tabs = await chrome.tabs.query({});
|
|
1323
|
+
return tabs.filter((tab) => typeof tab.id === "number").filter((tab) => tab.incognito !== true).map((tab) => ({ tabId: tab.id, url: activePageCacheUrl(tab) })).filter((tab) => tab.url.length > 0 && isScriptableUrl(tab.url));
|
|
1324
|
+
}
|
|
1325
|
+
async function captureFirstSettledActivePageCache(pending) {
|
|
1326
|
+
if (activePageCache.inFlightKeys.has(pending.key) || activePageCache.lastCapturedKey === pending.key) {
|
|
1327
|
+
if (activePageCache.pending?.key === pending.key) {
|
|
1328
|
+
activePageCache.pending = null;
|
|
1329
|
+
}
|
|
1330
|
+
return;
|
|
1331
|
+
}
|
|
1332
|
+
const tab = await currentActivePageCacheTab(pending.tabId, pending.key);
|
|
1333
|
+
if (!tab) {
|
|
1334
|
+
if (activePageCache.pending?.key === pending.key) {
|
|
1335
|
+
activePageCache.pending = null;
|
|
1336
|
+
}
|
|
1337
|
+
return;
|
|
1338
|
+
}
|
|
1339
|
+
const tabUrl = activePageCacheUrl(tab);
|
|
1340
|
+
if (tab.status === "loading") {
|
|
1341
|
+
setActivePageCacheState(tab.id, tabUrl, "loading");
|
|
1342
|
+
void setCacheWaitingIndicator(tab.id, tabUrl, ACTIVE_PAGE_CACHE_STATE_DETAILS.loading);
|
|
1343
|
+
if (pending.attempts < ACTIVE_PAGE_CACHE_FIRST_LOADING_MAX_ATTEMPTS) {
|
|
1344
|
+
scheduleFirstActivePageCacheRetry(
|
|
1345
|
+
{ ...pending, attempts: pending.attempts + 1 },
|
|
1346
|
+
ACTIVE_PAGE_CACHE_LOADING_RETRY_MS
|
|
1347
|
+
);
|
|
1348
|
+
} else {
|
|
1349
|
+
failFirstActivePageCacheCapture(pending, tab, tabUrl, "loading attempts exhausted");
|
|
1350
|
+
}
|
|
1351
|
+
return;
|
|
1352
|
+
}
|
|
1353
|
+
setActivePageCacheState(tab.id, tabUrl, "settling");
|
|
1354
|
+
void setCacheWaitingIndicator(tab.id, tabUrl, ACTIVE_PAGE_CACHE_STATE_DETAILS.settling);
|
|
1355
|
+
const probe = await content.probePageQuiescence(
|
|
1356
|
+
tab.id,
|
|
1357
|
+
ACTIVE_PAGE_CACHE_FIRST_QUIESCENT_TIMEOUT_MS,
|
|
1358
|
+
ACTIVE_PAGE_CACHE_FIRST_QUIESCENT_SAMPLE_MS
|
|
1359
|
+
);
|
|
1360
|
+
if (activePageCache.pending?.key !== pending.key) {
|
|
1361
|
+
return;
|
|
1362
|
+
}
|
|
1363
|
+
if (!probe.quiet) {
|
|
1364
|
+
if (probe.error || probe.documentReadyState === null) {
|
|
1365
|
+
failFirstActivePageCacheCapture(
|
|
1366
|
+
pending,
|
|
1367
|
+
tab,
|
|
1368
|
+
tabUrl,
|
|
1369
|
+
probe.reason || "page settle probe failed"
|
|
1370
|
+
);
|
|
1371
|
+
return;
|
|
1372
|
+
}
|
|
1373
|
+
const loading = probe.documentReadyState !== "interactive" && probe.documentReadyState !== "complete";
|
|
1374
|
+
setActivePageCacheState(tab.id, tabUrl, loading ? "loading" : "settling");
|
|
1375
|
+
void setCacheWaitingIndicator(
|
|
1376
|
+
tab.id,
|
|
1377
|
+
tabUrl,
|
|
1378
|
+
loading ? ACTIVE_PAGE_CACHE_STATE_DETAILS.loading : ACTIVE_PAGE_CACHE_STATE_DETAILS.settling
|
|
1379
|
+
);
|
|
1380
|
+
if (pending.attempts < ACTIVE_PAGE_CACHE_FIRST_SETTLING_MAX_ATTEMPTS) {
|
|
1381
|
+
scheduleFirstActivePageCacheRetry(
|
|
1382
|
+
{ ...pending, attempts: pending.attempts + 1 },
|
|
1383
|
+
loading ? ACTIVE_PAGE_CACHE_LOADING_RETRY_MS : ACTIVE_PAGE_CACHE_SETTLING_RETRY_MS
|
|
1384
|
+
);
|
|
1385
|
+
} else {
|
|
1386
|
+
failFirstActivePageCacheCapture(
|
|
1387
|
+
pending,
|
|
1388
|
+
tab,
|
|
1389
|
+
tabUrl,
|
|
1390
|
+
loading ? "loading attempts exhausted" : "settling attempts exhausted"
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1393
|
+
return;
|
|
1394
|
+
}
|
|
1395
|
+
clearPendingFirstActivePageCacheCapture(pending.key);
|
|
1396
|
+
await captureActivePageCache(tab, pending.reason, pending.key);
|
|
1397
|
+
}
|
|
1271
1398
|
async function rescheduleQuiescentActivePageCacheCapture(pending) {
|
|
1272
1399
|
if (pending.attempts >= 2 || isQuiescentCaptureCoolingDown(pending.key)) {
|
|
1273
1400
|
return;
|
|
@@ -1294,6 +1421,9 @@
|
|
|
1294
1421
|
if (!tab) {
|
|
1295
1422
|
return;
|
|
1296
1423
|
}
|
|
1424
|
+
const tabUrl = activePageCacheUrl(tab);
|
|
1425
|
+
setActivePageCacheState(tab.id, tabUrl, "settling");
|
|
1426
|
+
void setCacheWaitingIndicator(tab.id, tabUrl, ACTIVE_PAGE_CACHE_STATE_DETAILS.settling);
|
|
1297
1427
|
const probe = await content.probePageQuiescence(
|
|
1298
1428
|
tab.id,
|
|
1299
1429
|
ACTIVE_PAGE_CACHE_QUIESCENT_TIMEOUT_MS,
|
|
@@ -1314,7 +1444,7 @@
|
|
|
1314
1444
|
connectNative();
|
|
1315
1445
|
return false;
|
|
1316
1446
|
}
|
|
1317
|
-
if (!isEligibleActivePageCacheTab(tab) || activePageCache.inFlightKeys.has(key)) {
|
|
1447
|
+
if (!isEligibleActivePageCacheTab(tab) || tab.status === "loading" || activePageCache.inFlightKeys.has(key)) {
|
|
1318
1448
|
return false;
|
|
1319
1449
|
}
|
|
1320
1450
|
activePageCache.inFlightKeys.add(key);
|
|
@@ -1323,6 +1453,15 @@
|
|
|
1323
1453
|
if (!captureTab) {
|
|
1324
1454
|
return false;
|
|
1325
1455
|
}
|
|
1456
|
+
const captureUrl = activePageCacheUrl(captureTab);
|
|
1457
|
+
if (captureTab.status === "loading") {
|
|
1458
|
+
setActivePageCacheState(captureTab.id, captureUrl, "loading");
|
|
1459
|
+
void setCacheWaitingIndicator(captureTab.id, captureUrl, ACTIVE_PAGE_CACHE_STATE_DETAILS.loading);
|
|
1460
|
+
scheduleFirstActivePageCacheRetry({ tabId: captureTab.id, reason, key, attempts: 0 }, ACTIVE_PAGE_CACHE_LOADING_RETRY_MS);
|
|
1461
|
+
return false;
|
|
1462
|
+
}
|
|
1463
|
+
setActivePageCacheState(captureTab.id, captureUrl, "capturing");
|
|
1464
|
+
void setCacheWaitingIndicator(captureTab.id, captureUrl, ACTIVE_PAGE_CACHE_STATE_DETAILS.capturing);
|
|
1326
1465
|
const extraction = await content.extractPageHtml(captureTab.id, ACTIVE_PAGE_CACHE_TIMEOUT_MS, ACTIVE_PAGE_CACHE_MAX_HTML_CHARS);
|
|
1327
1466
|
if (extraction.status !== "READ" || typeof extraction.html !== "string" || extraction.html.length === 0) {
|
|
1328
1467
|
log("active page cache extraction not readable", {
|
|
@@ -1338,12 +1477,16 @@
|
|
|
1338
1477
|
});
|
|
1339
1478
|
if (extraction.status === "NOT_LOADED") {
|
|
1340
1479
|
const url = activePageCacheUrl(captureTab);
|
|
1341
|
-
|
|
1342
|
-
void setCacheWaitingIndicator(captureTab.id, url,
|
|
1480
|
+
setActivePageCacheState(captureTab.id, url, "loading");
|
|
1481
|
+
void setCacheWaitingIndicator(captureTab.id, url, ACTIVE_PAGE_CACHE_STATE_DETAILS.loading);
|
|
1482
|
+
scheduleFirstActivePageCacheRetry(
|
|
1483
|
+
{ tabId: captureTab.id, reason, key, attempts: 0 },
|
|
1484
|
+
ACTIVE_PAGE_CACHE_LOADING_RETRY_MS
|
|
1485
|
+
);
|
|
1343
1486
|
} else {
|
|
1344
1487
|
const detail = typeof extraction.status === "string" ? extraction.status.toLowerCase().replace(/_/g, " ") : "capture failed";
|
|
1345
1488
|
const url = activePageCacheUrl(captureTab);
|
|
1346
|
-
|
|
1489
|
+
setActivePageCacheState(captureTab.id, url, "error", detail);
|
|
1347
1490
|
void setCacheErrorIndicator(captureTab.id, url, detail);
|
|
1348
1491
|
}
|
|
1349
1492
|
void requestPageCacheStatusForTab(captureTab.id, `${reason}:capture-failed`);
|
|
@@ -1357,6 +1500,7 @@
|
|
|
1357
1500
|
if (!port) {
|
|
1358
1501
|
return false;
|
|
1359
1502
|
}
|
|
1503
|
+
const openTabs = await getPageCacheOpenTabs();
|
|
1360
1504
|
const id = nextActivePageCacheId();
|
|
1361
1505
|
trackPageCacheStatusRequest(id, verifiedTab.id, activePageCacheUrl(verifiedTab));
|
|
1362
1506
|
port.postMessage({
|
|
@@ -1366,6 +1510,7 @@
|
|
|
1366
1510
|
data: {
|
|
1367
1511
|
reason,
|
|
1368
1512
|
capturedAt: Date.now(),
|
|
1513
|
+
openTabs,
|
|
1369
1514
|
tab: {
|
|
1370
1515
|
tabId: verifiedTab.id,
|
|
1371
1516
|
windowId: verifiedTab.windowId,
|
|
@@ -1389,7 +1534,7 @@
|
|
|
1389
1534
|
} catch (error) {
|
|
1390
1535
|
log("active page cache capture failed", { tabId: tab.id, reason, error });
|
|
1391
1536
|
const url = activePageCacheUrl(tab);
|
|
1392
|
-
|
|
1537
|
+
setActivePageCacheState(tab.id, url, "error", "capture exception");
|
|
1393
1538
|
void setCacheErrorIndicator(tab.id, url, "capture exception");
|
|
1394
1539
|
void requestPageCacheStatusForTab(tab.id, `${reason}:capture-error`);
|
|
1395
1540
|
return false;
|
|
@@ -1514,7 +1659,7 @@
|
|
|
1514
1659
|
changeInfo
|
|
1515
1660
|
});
|
|
1516
1661
|
if ("url" in changeInfo || "status" in changeInfo || "discarded" in changeInfo) {
|
|
1517
|
-
|
|
1662
|
+
clearActivePageCacheStatesForTab(tabId);
|
|
1518
1663
|
void clearCacheAvailableIndicator(tabId);
|
|
1519
1664
|
}
|
|
1520
1665
|
if (tab.active && ("url" in changeInfo || "status" in changeInfo || "discarded" in changeInfo)) {
|
|
@@ -1554,7 +1699,7 @@
|
|
|
1554
1699
|
activePageCache.statusRequests.delete(requestId);
|
|
1555
1700
|
}
|
|
1556
1701
|
});
|
|
1557
|
-
|
|
1702
|
+
clearActivePageCacheStatesForTab(tabId);
|
|
1558
1703
|
void clearCacheAvailableIndicator(tabId);
|
|
1559
1704
|
});
|
|
1560
1705
|
chrome.tabs?.onActivated?.addListener((activeInfo) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tabctl",
|
|
3
|
-
"version": "0.6.0-rc.
|
|
3
|
+
"version": "0.6.0-rc.12",
|
|
4
4
|
"description": "CLI tool to manage and analyze browser tabs",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"typescript": "^5.4.5"
|
|
54
54
|
},
|
|
55
55
|
"optionalDependencies": {
|
|
56
|
-
"tabctl-win32-x64": "0.6.0-rc.
|
|
56
|
+
"tabctl-win32-x64": "0.6.0-rc.12"
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"normalize-url": "^8.1.1"
|