function createUpdateOwnership({ claim, addToday, onClaimed, onState }) { let detail = null; let update = null; let claimedItem = null; let request = null; function state(value) { onState?.(value); } function open(nextDetail, nextUpdate) { detail = nextDetail; update = nextUpdate; claimedItem = null; request = null; state({ action: nextDetail?.issue?.claimable ? 'claim' : 'hidden', busy: false, message: '', }); } function act() { if (request) return request; if (claimedItem) { const result = addToday(claimedItem); const messages = { added: 'Added to Today.', exists: 'This issue is already in Today.', full: 'Today is limited to 5 items. Remove one before adding more.', unavailable: 'Could not save Today on this device.', }; state({ action: 'today', busy: false, message: messages[result] || messages.unavailable }); return Promise.resolve(result); } if (!detail?.issue?.claimable) return Promise.resolve('hidden'); state({ action: 'claim', busy: true, message: 'Assigning…' }); request = Promise.resolve(claim({ repository: detail.repository, number: detail.issue.number, })).then(result => { claimedItem = { ...result, repository: detail.repository, kind: 'issue', notification_id: update?.notification_id, updated_at: update?.updated_at || result.updated_at, has_update: true, }; detail.issue.claimable = false; onClaimed?.(claimedItem); state({ action: 'today', busy: false, message: 'Assigned to you. The update is still unread.' }); return claimedItem; }).catch(error => { if (error?.status === 409) { detail.issue.claimable = false; state({ action: 'hidden', busy: false, message: 'Someone else claimed or closed this issue. The update is still unread.', }); return 'conflict'; } state({ action: 'claim', busy: false, message: (error?.message || 'The issue could not be assigned.') + ' The update and your reply draft are safe; retry.', }); return 'retry'; }).finally(() => { request = null; }); return request; } return { open, act }; } if (typeof module !== 'undefined' && module.exports) module.exports = createUpdateOwnership;