diff options
| -rw-r--r-- | jakob/utils/comments.scm | 31 | ||||
| -rw-r--r-- | static/css/style.css | 43 | ||||
| -rw-r--r-- | static/js/dynamic-comment-form.js | 51 |
3 files changed, 114 insertions, 11 deletions
diff --git a/jakob/utils/comments.scm b/jakob/utils/comments.scm index f9228bd..15824b1 100644 --- a/jakob/utils/comments.scm +++ b/jakob/utils/comments.scm @@ -114,17 +114,25 @@ (if (webmention? comment) '() (internal-comment-reactions comment))) + (define (comment-subject comment) + (if (webmention? comment) + #f + (internal-comment-subject comment))) `(article (@ ,@(if (not (webmention? comment)) `((id ,(format #f "comment-~a" (internal-comment-id comment)))) '()) - (class "comment-block")) + ,(if reply? + '(class "comment-block reply") + '(class "comment-block"))) (header (@ (class "comment-meta")) (img (@ (class "comment-avatar") (src ,(comment-photo comment)) (alt "User Icon"))) (div (@ (class "comment-info")) (strong ,(comment-name comment)) - ;; (span (@ (class "subject"))) + ,@(if (comment-subject comment) + `((span (@ (class "subject")) ,(comment-subject comment)(span (@ (class "subject"))))) + '()) (br) ,@(if (and (comment-url comment) (not (string= "" (comment-url comment))) @@ -139,11 +147,20 @@ ,(date->string (comment-publish-time comment) "~B ~e, ~Y at ~H:~M")))) (div (@ (class "comment-body")) ,@(comment-content comment)) - (footer (@ (class "comment-reactions")) - ,@(map (match-lambda - ((emote . count) - `(span (@ (class "reaction")) ,(format #f "~a ~a" emote count)))) - (comment-reactions comment))) + ,@(if (not (webmention? comment)) + `((footer (@ (class "comment-reactions")) + (button (@ (class "reply-button") (hidden #t) + (aria-label "Reply to comment") + (data-target ,(format #f "comment-~a" (internal-comment-id comment))) + (data-reply-to-id ,(internal-comment-id comment))) + "Reply") + ,@(map (match-lambda + ((emote . count) + `(span (@ (class "reaction")) ,(format #f "~a ~a" emote count)))) + (comment-reactions comment)) + (button (@ (class "add-reaction") (hidden #t) + (aria-label "Add reaction")) "+"))) + '()) ,@(if (and (not reply?) (internal-comment? comment) (positive? (length (internal-comment-replies comment)))) diff --git a/static/css/style.css b/static/css/style.css index 442af67..2fee7bf 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -368,6 +368,25 @@ hr { font-size: 8px } +.reply-button { + background: #eee; + border: 1px solid #ccc; + color: #666; + cursor: pointer; + font-size: 8px; + padding: 2px 6px; + border-radius: 3px; + text-transform: uppercase; + font-family: inherit; + margin-right: 5px +} + +.reply-button:hover { + background: #e0e0e0; + color: #333; + border-color: #999 +} + .reaction { background: #eee; border: 1px solid #ccc; @@ -468,6 +487,30 @@ hr { color: #999 } +#reply-preview-area { + padding: 10px; + background: #fcfcfc; + border: 1px dashed #ccc; + margin-bottom: 15px; +} + +#reply-preview-area .comment-block { + margin-bottom: 0; + border-right: 1px solid #eee; /* Visual hint it's a preview */ +} + +#cancel-reply { + background: #333; + color: #fff; + border: none; + padding: 2px 5px; + text-transform: uppercase; +} + +#cancel-reply:hover { + background: #cc0000; +} + .legacy-warning { background: linear-gradient(to bottom,#fff3e0 0,#ffe0b2 100%); border: 1px dotted #fb8c00; diff --git a/static/js/dynamic-comment-form.js b/static/js/dynamic-comment-form.js index 809a755..75e2fb6 100644 --- a/static/js/dynamic-comment-form.js +++ b/static/js/dynamic-comment-form.js @@ -81,12 +81,55 @@ window.addEventListener("load", () => { }); window.addEventListener("load", () => { - // Unhide additional comment actions if Javascript is enabled. - let additionalActionsRows = document.querySelectorAll(".comment-additional-actions"); - for (let row of additionalActionsRows) { - row.removeAttribute("hidden"); + const replyToField = document.getElementById("reply-to"); + const commentFormModule = document.querySelector('.comment-form-module'); + + // Create a "Replying To" preview container dynamically + const previewContainer = document.createElement('div'); + previewContainer.id = 'reply-preview-area'; + previewContainer.style.display = 'none'; + commentFormModule.prepend(previewContainer); + + const replyButtons = document.querySelectorAll(".reply-button"); + for (const button of replyButtons) { + button.removeAttribute("hidden"); + button.addEventListener('click', (e) => { + replyTo.value = button.getAttribute("data-reply-to-id"); + const targetId = button.getAttribute('data-target'); + const originalComment = document.getElementById(targetId); + + if (originalComment) { + const clone = originalComment.cloneNode(true); + const nestedReplies = clone.querySelectorAll('.reply'); + nestedReplies.forEach(reply => reply.remove()); + const actionButtons = clone.querySelector('.comment-reactions'); + if (actionButtons) actionButtons.remove(); + previewContainer.innerHTML = ` +<div> + <strong>You are replying to this comment:</strong> + <button id="cancel-reply" style="margin-left: auto; cursor: pointer; font-size: 8px;">Cancel Reply</button> +</div> +<div class="reply-preview-content" style="opacity: 0.8; scale: 0.95; origin: top left;"> + ${clone.outerHTML} +</div> +`; + previewContainer.style.display = 'block'; + commentFormModule.scrollIntoView({ behavior: 'smooth', block: 'center' }); + document.getElementById('cancel-reply').addEventListener('click', () => { + replyTo.value = ""; + previewContainer.style.display = 'none'; + previewContainer.innerHTML = ''; + }); + } + }) } + document.addEventListener('click', (e) => { + if (e.target.classList.contains('reply-button')) { + + } + }); + let header = document.getElementById("comment-form-header"); let replyTo = document.getElementById("reply-to"); let buttons = document.querySelectorAll(".comment-reply-button"); |