feat: continue offline checklist progress (Closes #909)
CI / lint (pull_request) Failing after 1m57s
CI / build-release (pull_request) Has been skipped
CI / browser-journey (pull_request) Has been skipped
CI / release-candidate (pull_request) Has been skipped

This commit is contained in:
timmy committed 2026-08-15 18:26:34 +00:00
1 parent 475739328c
commit 5c370cbe33
6 files changed
+138 -2

No files matched your search

+17 -1
View File
@@ -61,6 +61,21 @@ function createAuthoredOutbox({ storage, fetchJson, coordinator, backgroundSync,
throw new Error('A review for this saved head is already queued. Open Drafts to inspect or discard it first.');
}
}
if (message.kind === 'issue-content') {
const queuedContent = items.find(item => item.kind === 'issue-content' && item.status === 'queued' &&
item.ownerLogin === ownerLogin && item.repository === String(message.repository || '') &&
item.number === Number(message.number || 0));
if (queuedContent) {
const replacement = {
...queuedContent,
operationId: String(requestedOperationId || makeId()).slice(0, 128),
title: String(message.title || ''),
body: String(message.body || ''),
};
write(items.map(item => item.id === queuedContent.id ? replacement : item), mirror);
return replacement;
}
}
if (items.length >= maxItems) throw new Error('Message outbox is full. Send or discard a queued message first.');
const id = String(requestedOperationId || makeId()).slice(0, 128);
const item = {
@@ -107,6 +122,7 @@ function createAuthoredOutbox({ storage, fetchJson, coordinator, backgroundSync,
}
async function enqueueDurably(message) {
const previousItems = read();
const item = enqueue(message, false);
if (message.attachment && ['update-reply', 'update-reply-read'].includes(message.kind) &&
(!backgroundSync?.reconcile || !backgroundSync?.requestSync)) {
@@ -128,7 +144,7 @@ function createAuthoredOutbox({ storage, fetchJson, coordinator, backgroundSync,
try {
await backgroundSync.reconcile(durableItems, 'authored');
} catch (error) {
write(read().filter(candidate => candidate.id !== item.id), false);
write(previousItems, false);
throw error;
}
try {
+5
View File
@@ -105,6 +105,11 @@ function createIssueSyncStore({
};
incoming.set(current.id, replacement);
}
if (current.kind === 'issue-content' && replacement.kind === 'issue-content' &&
current.operationId !== replacement.operationId && current.status === 'sending' &&
Number(current.claimUntil) > Number(now())) {
throw new Error('Checklist sync is already delivering. Retry this change.');
}
if ((current.status === 'sending' && Number(current.claimUntil) > Number(now())) ||
(['attention', 'authorization'].includes(current.status) &&
replacement.status === current.status) ||
+1 -1
View File
@@ -200,7 +200,7 @@ function createIssueSheet({ fetchJson, storage, renderMarkdown = globalThis.rend
container.classList.toggle('checklist-pending', detail.checklist_pending === true);
container.innerHTML = renderMarkdown(
detail.body || 'No description provided.', {
interactiveTasks: Boolean(interactive) && detail.checklist_pending !== true,
interactiveTasks: Boolean(interactive),
}
);
},