stackchain-dashboard/frontend/update-reply-read-next.js
timmy 31f6097afc
All checks were successful
CI / lint (pull_request) Successful in 1m13s
CI / build-release (pull_request) Successful in 5s
CI / release-candidate (pull_request) Has been skipped
feat: attach screenshots to update replies (Closes #527)
2026-08-11 01:04:18 +00:00

65 lines
2.3 KiB
JavaScript

function createUpdateReplyReadNext({
post, markRead, queue, canQueue, deliver, accept = () => undefined, next = () => undefined,
}) {
let inFlight = null;
async function admit(item, body, operationId, replyConfirmed) {
const admission = await queue({
kind: 'update-reply-read',
notificationId: item.notification_id,
body,
operationId,
replyConfirmed,
});
if (!admission || (!admission.item && admission.durable !== true)) {
throw new Error('Reply and acknowledgement were not saved for delivery.');
}
accept(item);
return {
accepted: true,
delivery: admission.background ? 'queued' : 'saved',
next: await next(item),
};
}
function submit(item, body, operationId, attachment = null) {
if (inFlight) return inFlight;
inFlight = (async () => {
let replyConfirmed = false;
try {
if (attachment) {
const admission = await queue({
kind:'update-reply-read', notificationId:item.notification_id, body,
operationId, replyConfirmed:false, attachment,
});
if (!admission?.item) throw new Error('Reply and screenshot were not saved for delivery.');
const outcome = deliver ? await deliver(admission.item) : null;
const remaining = outcome?.remaining?.find(candidate => candidate.id === admission.item.id);
if (remaining?.status === 'attention') {
throw new Error(remaining.error || 'Reply and screenshot need attention.');
}
accept(item);
return { accepted:true, delivery:outcome?.confirmed?.length ? 'posted' : 'queued', next:await next(item) };
}
try {
await post(item, body, operationId);
replyConfirmed = true;
await markRead(item.notification_id);
} catch (error) {
if (!canQueue(error)) throw error;
return await admit(item, body, operationId, replyConfirmed);
}
accept(item);
return { accepted: true, delivery: 'posted', next: await next(item) };
} finally {
inFlight = null;
}
})();
return inFlight;
}
return { submit, busy: () => Boolean(inFlight) };
}
if (typeof module !== 'undefined' && module.exports) module.exports = createUpdateReplyReadNext;