fix: retire completed Today work across devices (#359)
CI / lint (pull_request) Successful in 40s
CI / build-release (pull_request) Successful in 5s
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-09 01:16:26 +00:00
1 parent 4610afd489
commit d940e0b37b
10 files changed
+117 -10

No files matched your search

+9 -1
View File
@@ -811,8 +811,16 @@
});
activeMyWork = partitioned.active;
laterMyWork = partitioned.later;
const authoritativeTodayReconciliation = liveMode && hasContextSnapshot &&
!lastContextSnapshot?.error &&
!Object.values(workPagination).some(page => page?.has_more);
todayMyWork = todayWork.reconcile(lastMyWork, {
pruneMissing: !Object.values(workPagination).some(page => page?.has_more),
pruneMissing: authoritativeTodayReconciliation,
onPrune: retiredIds => {
const queued = retiredIds.map(id => todaySync.enqueue('remove', id)).every(Boolean);
if (queued) todaySync.flush();
return queued;
},
});
const counts = countMyWork(activeMyWork);
counts.today = todayMyWork.length;
+1 -1
View File
@@ -1,6 +1,6 @@
const BASE = new URL('./', self.location.href).pathname;
importScripts(BASE + 'static/background-issue-sync.js');
const CACHE = 'stackchain-dashboard-shell-v45';
const CACHE = 'stackchain-dashboard-shell-v46';
const OUTAGE_STATUSES = new Set([500, 502, 503, 504]);
const NAVIGATION_TIMEOUT_MS = self.__STACKCHAIN_NAVIGATION_TIMEOUT_MS || 4000;
const SHELL = [
+6
View File
@@ -43,6 +43,12 @@ function createTodaySync({ storage, getLogin, fetchJson, onRemoteIds, onStatus,
function enqueue(action, itemId, direction = null) {
const operations = pending();
if (action === 'remove' && operations.some(operation =>
operation.action === 'remove' && operation.item_id === itemId
)) {
onStatus?.('pending');
return true;
}
operations.push({ operation_id: operationId(), action, item_id: itemId, direction });
const saved = save(operations);
onStatus?.(saved ? 'pending' : 'error');
+6 -2
View File
@@ -74,11 +74,15 @@ function createTodayWork({ storage, getLogin, limit = 5 }) {
return write(ids);
}
function reconcile(items, { pruneMissing = false } = {}) {
function reconcile(items, { pruneMissing = false, onPrune } = {}) {
const available = new Map((items || []).map(item => [identity(item), item]));
const ids = read();
const retained = pruneMissing ? ids.filter(id => available.has(id)) : ids;
if (retained.length !== ids.length) write(retained);
const retired = ids.filter(id => !retained.includes(id));
if (retired.length) {
const reported = onPrune?.(retired);
if (reported !== false) write(retained);
}
return retained.flatMap(id => available.has(id) ? [available.get(id)] : []);
}