diff --git a/internal/util/util.go b/internal/util/util.go
index abf4272..1aa42e1 100644
--- a/internal/util/util.go
+++ b/internal/util/util.go
@@ -1,19 +1,35 @@
package util
import (
+ "fmt"
"html/template"
"strings"
)
func EnrichPost(body string) string {
- lines := strings.Split(body, "\n")
- for i, line := range lines {
- if strings.HasPrefix(line, ">") {
- escaped := template.HTMLEscapeString(line)
- lines[i] = `` + escaped + ``
- } else {
- lines[i] = template.HTMLEscapeString(line)
+ var b strings.Builder
+ for _, raw := range strings.Split(body, "\n") {
+ var out string
+ switch {
+ case strings.HasPrefix(raw, ">>"):
+ postId := strings.TrimPrefix(raw, ">>")
+ esc := template.HTMLEscapeString(raw)
+ out = fmt.Sprintf(
+ `%s`,
+ postId, esc,
+ )
+ case strings.HasPrefix(raw, ">"):
+ esc := template.HTMLEscapeString(raw)
+ out = `` + esc + ``
+ default:
+ out = template.HTMLEscapeString(raw)
}
+
+ b.WriteString(out)
+ b.WriteString("
")
}
- return strings.Join(lines, "
")
+ return b.String()
}
diff --git a/web/static/index.css b/web/static/index.css
index 06ab7bb..75f84dd 100644
--- a/web/static/index.css
+++ b/web/static/index.css
@@ -111,6 +111,11 @@ body {
margin-left: auto;
}
+#newPostBody {
+ width: 270px;
+ height: 100px;
+}
+
.new-post-container {
width: max-content;
margin: auto;
@@ -145,6 +150,23 @@ body {
margin-right: 5px;
}
+.post-op {
+ margin-bottom: 10px;
+}
+
+.post {
+ display: inline-block;
+ margin: 5x;
+ padding: 10px;
+ background-color: #D6DAF0;
+ border: 1px solid #282a2e;
+ margin-bottom: 10px;
+}
+
+.post-highlighted {
+ background: #D6BAD0;
+}
+
.post-header {
display: flex;
margin-bottom: 10px;
@@ -174,23 +196,21 @@ body {
line-height: 1.3;
}
-.op-post {
- margin-bottom: 10px;
-}
-
-.post {
- display: inline-block;
- margin: 5x;
- padding: 10px;
- background-color: #D6DAF0;
- border: 1px solid #282a2e;
- margin-bottom: 10px;
+.post-num:hover {
+ cursor: pointer;
+ color: #ff0000;
}
.greentext {
color: #789922
}
+.reply-link {
+ color: #D00;
+ text-decoration: underline;
+ cursor: pointer;
+}
+
/* GENERAL LAYOUT */
.container {
diff --git a/web/static/index.js b/web/static/index.js
index 915304f..4a6d449 100644
--- a/web/static/index.js
+++ b/web/static/index.js
@@ -1 +1,57 @@
const $ = (id) => document.getElementById(id);
+
+function isOffScreen(el) {
+ const rect = el.getBoundingClientRect();
+ const vh = window.innerHeight || document.documentElement.clientHeight;
+ const vw = window.innerWidth || document.documentElement.clientWidth;
+
+ return (
+ rect.bottom < 0 ||
+ rect.top > vh ||
+ rect.right < 0 ||
+ rect.left > vw
+ );
+}
+
+function insertAfter(referenceNode, newNode) {
+ referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
+}
+
+function onReplyLinkClick(e) {
+ const hoveringPost = document.getElementById("hoveringPost");
+ hoveringPost?.remove();
+}
+
+function highlightPost(postId, e, status = true) {
+ const posts = Array.from(document.querySelectorAll("article"));
+ const postToHighlight = posts.find(p => +p.id.split("-")[1] === +postId);
+ if (!postToHighlight) return;
+
+ const isOp = postToHighlight.id === posts[0]?.id;
+ if (isOffScreen(postToHighlight) || isOp) {
+ if (e.type === "mouseleave") {
+ const hoveringPost = document.querySelector("#hoveringPost")
+ hoveringPost.remove();
+ }
+ else {
+ const postCopy = postToHighlight.cloneNode(true);
+ postCopy.style.position = "absolute";
+ postCopy.id = "hoveringPost";
+
+ if (isOp) {
+ postCopy.classList.remove("post-op");
+ postCopy.classList.add("post");
+ }
+
+ insertAfter(e.target, postCopy);
+ }
+ }
+ else {
+ if (status) {
+ postToHighlight.classList.add("post-highlighted");
+ }
+ else {
+ postToHighlight.classList.remove("post-highlighted");
+ }
+ }
+}
diff --git a/web/views/shared/layout.templ b/web/views/shared/layout.templ
index e142551..2ac6698 100644
--- a/web/views/shared/layout.templ
+++ b/web/views/shared/layout.templ
@@ -8,6 +8,7 @@ templ Layout() {
Comfychan
+
diff --git a/web/views/thread.templ b/web/views/thread.templ
index e29cb5c..b56d968 100644
--- a/web/views/thread.templ
+++ b/web/views/thread.templ
@@ -8,24 +8,44 @@ import (
"strconv"
)
+func getPostClass(isOp bool) string {
+ if isOp {
+ return "post-op"
+ }
+ return "post"
+}
+
+templ ThreadPost(post database.Post, thread *database.Thread) {
+ {{ isOp := thread != nil }}
+
+ if post.MediaPath != "" {
+
+

+
+ }
+
+
+ @templ.Raw(util.EnrichPost(post.Body))
+
+
+}
+
templ ThreadPosts(posts []database.Post) {
for _, post := range (posts) {
-
- if post.MediaPath != "" {
-
-

-
- }
-
-
- @templ.Raw(util.EnrichPost(post.Body))
-
-
+ @ThreadPost(post, nil)
}
}
@@ -61,23 +81,7 @@ templ Thread(board database.Board, thread database.Thread, posts []database.Post
-
- if posts[0].MediaPath != "" {
-
-

-
- }
-
-
- @templ.Raw(util.EnrichPost(posts[0].Body))
-
-
+ @ThreadPost(posts[0], &thread)
@ThreadPosts(posts[1:])
diff --git a/web/views/threads.templ b/web/views/threads.templ
index 812f6d7..2245f2c 100644
--- a/web/views/threads.templ
+++ b/web/views/threads.templ
@@ -14,10 +14,10 @@ templ ThreadsCatalog(previews []CatalogThreadPreview) {
for _, preview := range previews {
-
+
-
+
@templ.Raw(util.EnrichPost(preview.Body))