diff --git a/public/s/js/f0ck.js b/public/s/js/f0ck.js index 5d66b85..36c25ed 100644 --- a/public/s/js/f0ck.js +++ b/public/s/js/f0ck.js @@ -1010,6 +1010,28 @@ class NotificationSystem { this.markAllReadUI(); }); } + + // Handle individual notification clicks + if (this.list) { + this.list.addEventListener('click', async (e) => { + const item = e.target.closest('.notif-item'); + if (!item) return; + + e.preventDefault(); + const id = item.dataset.id; + const href = item.getAttribute('href'); + + // Mark as read + if (item.classList.contains('unread')) { + try { + await fetch(`/api/notifications/${id}/read`, { method: 'POST' }); + } catch (err) { console.error(err); } + } + + // Navigate + window.location.href = href; + }); + } } async poll() { @@ -1043,12 +1065,15 @@ class NotificationSystem { } renderItem(n) { - const typeText = n.type === 'comment_reply' ? 'replied to your comment' : 'Start'; + let typeText = 'Start'; + if (n.type === 'comment_reply') typeText = 'replied to you'; + else if (n.type === 'subscription') typeText = 'commented in a thread you follow'; + const cid = n.comment_id || n.reference_id; const link = `/${n.item_id}#c${cid}`; return ` - +
${n.from_user} ${typeText}
@@ -1057,6 +1082,7 @@ class NotificationSystem { `; } + markAllReadUI() { this.countBadge.style.display = 'none'; this.list.querySelectorAll('.notif-item.unread').forEach(el => el.classList.remove('unread')); diff --git a/src/inc/routes/comments.mjs b/src/inc/routes/comments.mjs index 41fe03d..f9cd5cc 100644 --- a/src/inc/routes/comments.mjs +++ b/src/inc/routes/comments.mjs @@ -110,23 +110,38 @@ export default (router, tpl) => { parentAuthor = await db`SELECT user_id FROM comments WHERE id = ${parent_id}`; } - // 3. Collect unique recipients - const recipients = new Set(); - subscribers.forEach(s => recipients.add(s.user_id)); - parentAuthor.forEach(p => recipients.add(p.user_id)); + // 3. Prepare notifications + const notificationsToAdd = []; - // Remove self - recipients.delete(req.session.id); + // Parent author gets 'comment_reply' + if (parentAuthor.length > 0) { + const pid = parentAuthor[0].user_id; + if (pid !== req.session.id) { + notificationsToAdd.push({ + user_id: pid, + type: 'comment_reply', + item_id: item_id, + reference_id: commentId + }); + } + } + + // Subscribers get 'subscription' (unless they already got comment_reply) + const parentUserId = parentAuthor.length > 0 ? parentAuthor[0].user_id : -1; + + subscribers.forEach(s => { + if (s.user_id !== req.session.id && s.user_id !== parentUserId) { + notificationsToAdd.push({ + user_id: s.user_id, + type: 'subscription', + item_id: item_id, + reference_id: commentId + }); + } + }); // 4. Batch insert - if (recipients.size > 0) { - const notificationsToAdd = Array.from(recipients).map(uid => ({ - user_id: uid, - type: 'comment_reply', - item_id: item_id, - reference_id: commentId - })); - + if (notificationsToAdd.length > 0) { await db`INSERT INTO notifications ${db(notificationsToAdd)}`; }