From 13589cb7a024efaa51e9efbce5b4e8ad7475d448 Mon Sep 17 00:00:00 2001 From: Akshay Date: Sun, 3 Nov 2024 17:36:07 +0000 Subject: support expanding/collapsing comments fix pagination when sorting --- src/mixins/comment.pug | 49 +++++++++++++++++++---------- src/mixins/post.pug | 8 ++--- src/public/styles.css | 85 +++++++++++++++++++++++++++++++++++++++++--------- src/routes/index.js | 11 +++---- src/utils.pug | 8 ++++- src/views/comments.pug | 9 ++++++ src/views/index.pug | 36 +++++++++++++-------- 7 files changed, 151 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/mixins/comment.pug b/src/mixins/comment.pug index 2ec076f..3af1f53 100644 --- a/src/mixins/comment.pug +++ b/src/mixins/comment.pug @@ -1,24 +1,41 @@ include ../utils + +mixin infoContainer(data) + div.comment-info-container + div.info-item #{fmtnum(data.ups)} ↑ + div.info-item u/#{data.author} #{data.is_submitter ? '(OP)' : ''} + if data.collapsed_reason_code == "DELETED" + div.info-item + a(href=`https://undelete.pullpush.io${data.permalink}`) search on undelete + div.info-item #{timeDifference(Date.now(), data.created * 1000)} + +- + function hasReplies(data) { + return data.replies && data.replies.data && data.replies.data.children && data.replies.data.children.length > 0; + } + mixin comment(com, isfirst) - var data = com.data - var kind = com.kind + - var hasReplyData = hasReplies(data) + if kind == "more" - div(class=`${isfirst?'first':''}`) + div(class=`${isfirst ? 'first' : ''}`) div.more #{data.count} more comments else - div(class=`comment ${isfirst?'first':''}`) - div.comment-info-container - div.info-item #{fmtnum(data.ups)} ↑ - div.info-item u/#{data.author} #{data.is_submitter?'(OP)':''} - if data.collapsed_reason_code == "DELETED" - div.info-item - a(href=`https://undelete.pullpush.io${data.permalink}`) search on undelete - div.info-item #{timeDifference(Date.now(), data.created * 1000)} - div.comment-body - != data.body_html - div.replies - if data.replies - if data.replies.data - if data.replies.data.children + div(class=`comment ${isfirst ? 'first' : ''}`) + if hasReplyData + details(id=`${data.id}` open="") + summary.expand-comments + +infoContainer(data) + div.comment-body + != data.body_html + + div.replies each reply in data.replies.data.children - +comment(reply,false) + +comment(reply, false) + + else + +infoContainer(data) + div.comment-body + != data.body_html diff --git a/src/mixins/post.pug b/src/mixins/post.pug index 287c422..23eb19f 100644 --- a/src/mixins/post.pug +++ b/src/mixins/post.pug @@ -40,7 +40,7 @@ mixin post(p) if p.gallery_data if p.gallery_data.items details(id=`${p.id}`) - summary expand gallery + summary.expand-post expand gallery div.gallery - var total = p.gallery_data.items.length - var idx = 0 @@ -58,19 +58,19 @@ mixin post(p) button(onclick=`toggleDetails('${p.id}')`) close if p.post_hint == "image" && p.thumbnail && p.thumbnail != "self" && p.thumbnail != "default" details(id=`${p.id}`) - summary expand image + summary.expand-post expand image a(href=`/media/${p.url}`) img(src=p.url loading="lazy").post-media button(onclick=`toggleDetails('${p.id}')`) close else if p.post_hint == "hosted:video" details(id=`${p.id}`) - summary expand video + summary.expand-post expand video - var url = p.secure_media.reddit_video.dash_url video(src=url controls data-dashjs-player loading="lazy").post-media button(onclick=`toggleDetails('${p.id}')`) close else if !p.post_hint || (p.post_hint == "link" && p.thumbnail && p.thumbnail != "self" && p.thumbnail != "default") details(id=`${p.id}`) - summary expand link + summary.expand-post expand link a(href=`${p.url}`) | #{p.url} br diff --git a/src/public/styles.css b/src/public/styles.css index 4dc2740..76f70b5 100644 --- a/src/public/styles.css +++ b/src/public/styles.css @@ -1,4 +1,4 @@ -@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); +@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap'); :root { /* Light mode colors */ @@ -17,7 +17,7 @@ --bg-color-muted: #333; --text-color: white; --text-color-muted: #999; - --blockquote-color: green; + --blockquote-color: lightgreen; --link-color: lightblue; --link-visited-color: violet; } @@ -58,6 +58,27 @@ a:visited { justify-content: center; } +.sub-title { + display: flex; +} + +#button-container { + margin-left: 10px; + display: flex; + align-items: center; +} + +.sort-opts { + display: flex; + flex-direction: row; + flex-wrap: wrap; + justify-content: space-between; +} + +.sort-opts a { + margin: 10px; +} + .footer { display: flex; flex-direction: row; @@ -90,15 +111,22 @@ nav { .info-container, .comment-info-container, .more, +summary.expand-comments::before, hr { color: var(--text-color-muted) } -.info-container, .comment-info-container, .more { +.info-container, .more { font-size: 0.8rem; display: flex; } +.comment-info-container { + display: inline-flex; + align-items: center; + font-size: 0.8rem; +} + .domain { color: var(--text-color-muted); font-size: 0.8rem; @@ -124,6 +152,13 @@ hr { display: none } +.post-media { + display: block; + margin: 0 auto; + max-width: 95%; + padding: 5px; +} + @media (min-width: 768px) { .post, .comments-container, .hero, .header, .footer { flex: 1 1 90%; @@ -135,7 +170,8 @@ hr { .comments-container { font-size: 1.3rem; } - .info-container, .comment-info-container, .more { + .info-container, .comment-info-container, .more, summary.expand-comments::before + { font-size: 1rem; } .domain { @@ -150,6 +186,9 @@ hr { .post-author { display: inline } + .post-media { + max-width: 50%; + } } @media (min-width: 1080px) { @@ -163,7 +202,7 @@ hr { .comments-container { font-size: 1.3rem; } - .info-container, .comment-info-container, .more { + .info-container, .comment-info-container, .more, summary.expand-comments::before { font-size: 1rem; } .domain { @@ -178,6 +217,9 @@ hr { .post-author { display: inline } + .post-media { + max-width: 50%; + } } .comments-container, .self-text { @@ -229,15 +271,7 @@ hr { flex-direction: row; } -.post-media { - display: block; - margin: 0 auto; - max-width: 95%; - padding: 5px; -} - -.title-container, .comment-info-container { - flex: 1; +.title-container, .comment-info-container, summary.expand-comments::before { margin-top: 10px; margin-bottom: 10px; } @@ -296,10 +330,31 @@ p { text-align: left; } -summary { +summary.expand-post { display: none; } +summary.expand-comments { + list-style: none; + cursor: pointer; +} + +summary.expand-comments::before { + content: "[+] "; +} + +details[open] summary.expand-comments::before { + content: "[-] "; +} + +details:not([open]) summary.expand-comments::before { + content: "[+] "; +} + +.comment-body { + display: block; +} + .footer { padding-bottom: 40px; } diff --git a/src/routes/index.js b/src/routes/index.js index cef05da..f7a0425 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -11,18 +11,17 @@ router.get('/', async (req, res) => { }); // GET /r/:id -router.get('/r/:subreddit/:sort?', async (req, res) => { +router.get('/r/:subreddit', async (req, res) => { var subreddit = req.params.subreddit; - var query = req.query; - var sort = req.params.sort ? req.params.sort : 'hot'; - var options = req.query; + var query = req.query? req.query : {}; + var sort = query.sort? query.sort : 'hot'; - var postsReq = G.getSubmissions(sort, `${subreddit}`, options); + var postsReq = G.getSubmissions(sort, `${subreddit}`, query); var aboutReq = G.getSubreddit(`${subreddit}`); var [posts, about] = await Promise.all([postsReq, aboutReq]); - res.render('index', { subreddit, posts, about }); + res.render('index', { subreddit, posts, about, query }); }); // GET /comments/:id diff --git a/src/utils.pug b/src/utils.pug index 81cf3f7..17d1763 100644 --- a/src/utils.pug +++ b/src/utils.pug @@ -15,7 +15,7 @@ if (elapsed < msPerMinute) { return Math.round(elapsed/1000) + 's'; } else if (elapsed < msPerHour) { - return Math.round(elapsed/msPerMinute) + 'min'; + return Math.round(elapsed/msPerMinute) + 'm'; } else if (elapsed < msPerDay ) { return Math.round(elapsed/msPerHour ) + 'h'; } else if (elapsed < msPerMonth) { @@ -26,3 +26,9 @@ return Math.round(elapsed/msPerYear ) + 'y'; } } +- + function encodeQueryParams(obj) { + return Object.keys(obj) + .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key])) + .join('&'); + } diff --git a/src/views/comments.pug b/src/views/comments.pug index 8d5acf3..d9c96e9 100644 --- a/src/views/comments.pug +++ b/src/views/comments.pug @@ -1,5 +1,6 @@ include ../mixins/comment include ../mixins/header +include ../utils doctype html html @@ -9,6 +10,14 @@ html title reddit link(rel='stylesheet', href='/styles.css') script(src="https://cdn.dashjs.org/latest/dash.all.min.js") + script. + function toggleDetails(details_id) { + var detailsElement = document.getElementById(details_id); + if (detailsElement) { + detailsElement.open = !detailsElement.open; + } + } + body main#content +header() diff --git a/src/views/index.pug b/src/views/index.pug index 3f284f3..01b2941 100644 --- a/src/views/index.pug +++ b/src/views/index.pug @@ -1,6 +1,7 @@ include ../mixins/post include ../mixins/sub include ../mixins/header +include ../utils - var subs = [] doctype html html @@ -42,22 +43,31 @@ html +header() div.hero - a(href=`/r/${subreddit}`) - h1 r/#{subreddit} + div.sub-title + a(href=`/r/${subreddit}`) + h1 r/#{subreddit} + div#button-container if about p #{about.public_description} - div#button-container - ul - li - a(href=`/r/${subreddit}/hot`) hot - li - a(href=`/r/${subreddit}/top`) top - li - a(href=`/r/${subreddit}/top?t=all`) top all + details + summary sort by + div.sort-opts + a(href=`/r/${subreddit}?sort=hot`) hot + a(href=`/r/${subreddit}?sort=new`) new + a(href=`/r/${subreddit}?sort=rising`) rising + a(href=`/r/${subreddit}?sort=top`) top + a(href=`/r/${subreddit}?sort=top&t=day`) top day + a(href=`/r/${subreddit}?sort=top&t=week`) top week + a(href=`/r/${subreddit}?sort=top&t=month`) top month + a(href=`/r/${subreddit}?sort=top&t=year`) top year + a(href=`/r/${subreddit}?sort=top&t=all`) top all if posts each child in posts.posts +post(child.data) - div.footer - div.footer-item - a(href=`/r/${subreddit}?after=${posts.after}`) next → + + if posts.after + div.footer + div.footer-item + - var newQuery = {...query, after: posts.after} + a(href=`/r/${subreddit}?${encodeQueryParams(newQuery)}`) next → -- cgit v1.2.3