function createCommentActions({ fetchJson, getLogin, confirmDelete = () => false }) { const encodedRepository = repository => String(repository || '').split('/') .map(encodeURIComponent).join('/'); function pathFor(context, commentId) { const item = context?.item || {}; if (context?.kind === 'update') { return 'api/v1/notifications/' + encodeURIComponent(item.notification_id) + '/comments/' + encodeURIComponent(commentId); } if (!['issue', 'pull'].includes(context?.kind)) throw new Error('Comment conversation is unavailable.'); return 'api/v1/repos/' + encodedRepository(item.repository) + '/' + (context.kind === 'pull' ? 'pulls/' : 'issues/') + encodeURIComponent(item.number) + '/comments/' + encodeURIComponent(commentId); } const controller = { isOwned(comment) { const login = String(getLogin() || '').trim(); return Boolean(login && comment && comment.author === login); }, async edit(context, pager, commentId, body) { const draft = String(body || '').trim(); if (!draft) throw new Error('Comment must not be blank.'); const comment = await fetchJson(pathFor(context, commentId), { method: 'PATCH', headers: { Accept: 'application/json', 'Content-Type': 'application/json' }, body: JSON.stringify({ body: draft }), }); pager.replace(comment); return pager.snapshot(); }, async remove(context, pager, commentId) { if (!confirmDelete('Delete this comment permanently?')) return null; const result = await fetchJson(pathFor(context, commentId), { method: 'DELETE', headers: { Accept: 'application/json' }, }); if (!result?.deleted || Number(result.id) !== Number(commentId)) { throw new Error('Comment deletion was not confirmed.'); } pager.remove(commentId); return pager.snapshot(); }, actionHtml(comment) { return controller.isOwned(comment) ? '
' + '' + '
' : ''; }, wire({ root, getSurface, isOffline, escapeHtml }) { root.addEventListener('click', async event => { const button = event.target.closest('[data-comment-action]'); if (!button) return; const card = button.closest('.issue-comment'); const commentId = Number(card?.dataset.commentId); const surface = getSurface(); const comment = surface.pager?.snapshot().comments.find(item => item.id === commentId); if (!comment || !controller.isOwned(comment)) return; if (isOffline()) { surface.status.textContent = 'Reconnect to edit or delete this comment.'; return; } if (button.dataset.commentAction === 'delete') { try { const state = await controller.remove(surface.context, surface.pager, commentId); if (state) { surface.render(state); surface.status.textContent = 'Comment deleted.'; } } catch (error) { surface.status.textContent = error.message || 'Comment deletion failed. Retry or open it in Gitea.'; } return; } card.innerHTML = '
Editing your comment
' + '' + '
' + '
'; const textarea = card.querySelector('.comment-edit-textarea'); textarea.focus(); card.querySelector('[data-comment-edit-cancel]').addEventListener('click', () => surface.render(surface.pager.snapshot())); card.querySelector('[data-comment-edit-save]').addEventListener('click', async saveEvent => { const save = saveEvent.currentTarget; save.disabled = true; surface.status.textContent = 'Saving comment…'; try { const state = await controller.edit(surface.context, surface.pager, commentId, textarea.value); surface.render(state); surface.status.textContent = 'Comment updated.'; } catch (error) { save.disabled = false; surface.status.textContent = error.message || 'Comment update failed. Your edit is safe; retry or open it in Gitea.'; textarea.focus(); } }); }); }, }; return controller; } if (typeof module !== 'undefined' && module.exports) module.exports = createCommentActions;