aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mixins/comment.pug49
-rw-r--r--src/mixins/post.pug8
-rw-r--r--src/public/styles.css85
-rw-r--r--src/routes/index.js11
-rw-r--r--src/utils.pug8
-rw-r--r--src/views/comments.pug9
-rw-r--r--src/views/index.pug36
7 files changed, 151 insertions, 55 deletions
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 @@
1include ../utils 1include ../utils
2
3mixin infoContainer(data)
4 div.comment-info-container
5 div.info-item #{fmtnum(data.ups)} ↑
6 div.info-item u/#{data.author} #{data.is_submitter ? '(OP)' : ''}
7 if data.collapsed_reason_code == "DELETED"
8 div.info-item
9 a(href=`https://undelete.pullpush.io${data.permalink}`) search on undelete
10 div.info-item #{timeDifference(Date.now(), data.created * 1000)}
11
12-
13 function hasReplies(data) {
14 return data.replies && data.replies.data && data.replies.data.children && data.replies.data.children.length > 0;
15 }
16
2mixin comment(com, isfirst) 17mixin comment(com, isfirst)
3 - var data = com.data 18 - var data = com.data
4 - var kind = com.kind 19 - var kind = com.kind
20 - var hasReplyData = hasReplies(data)
21
5 if kind == "more" 22 if kind == "more"
6 div(class=`${isfirst?'first':''}`) 23 div(class=`${isfirst ? 'first' : ''}`)
7 div.more #{data.count} more comments 24 div.more #{data.count} more comments
8 else 25 else
9 div(class=`comment ${isfirst?'first':''}`) 26 div(class=`comment ${isfirst ? 'first' : ''}`)
10 div.comment-info-container 27 if hasReplyData
11 div.info-item #{fmtnum(data.ups)} ↑ 28 details(id=`${data.id}` open="")
12 div.info-item u/#{data.author} #{data.is_submitter?'(OP)':''} 29 summary.expand-comments
13 if data.collapsed_reason_code == "DELETED" 30 +infoContainer(data)
14 div.info-item 31 div.comment-body
15 a(href=`https://undelete.pullpush.io${data.permalink}`) search on undelete 32 != data.body_html
16 div.info-item #{timeDifference(Date.now(), data.created * 1000)} 33
17 div.comment-body 34 div.replies
18 != data.body_html
19 div.replies
20 if data.replies
21 if data.replies.data
22 if data.replies.data.children
23 each reply in data.replies.data.children 35 each reply in data.replies.data.children
24 +comment(reply,false) 36 +comment(reply, false)
37
38 else
39 +infoContainer(data)
40 div.comment-body
41 != 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)
40 if p.gallery_data 40 if p.gallery_data
41 if p.gallery_data.items 41 if p.gallery_data.items
42 details(id=`${p.id}`) 42 details(id=`${p.id}`)
43 summary expand gallery 43 summary.expand-post expand gallery
44 div.gallery 44 div.gallery
45 - var total = p.gallery_data.items.length 45 - var total = p.gallery_data.items.length
46 - var idx = 0 46 - var idx = 0
@@ -58,19 +58,19 @@ mixin post(p)
58 button(onclick=`toggleDetails('${p.id}')`) close 58 button(onclick=`toggleDetails('${p.id}')`) close
59 if p.post_hint == "image" && p.thumbnail && p.thumbnail != "self" && p.thumbnail != "default" 59 if p.post_hint == "image" && p.thumbnail && p.thumbnail != "self" && p.thumbnail != "default"
60 details(id=`${p.id}`) 60 details(id=`${p.id}`)
61 summary expand image 61 summary.expand-post expand image
62 a(href=`/media/${p.url}`) 62 a(href=`/media/${p.url}`)
63 img(src=p.url loading="lazy").post-media 63 img(src=p.url loading="lazy").post-media
64 button(onclick=`toggleDetails('${p.id}')`) close 64 button(onclick=`toggleDetails('${p.id}')`) close
65 else if p.post_hint == "hosted:video" 65 else if p.post_hint == "hosted:video"
66 details(id=`${p.id}`) 66 details(id=`${p.id}`)
67 summary expand video 67 summary.expand-post expand video
68 - var url = p.secure_media.reddit_video.dash_url 68 - var url = p.secure_media.reddit_video.dash_url
69 video(src=url controls data-dashjs-player loading="lazy").post-media 69 video(src=url controls data-dashjs-player loading="lazy").post-media
70 button(onclick=`toggleDetails('${p.id}')`) close 70 button(onclick=`toggleDetails('${p.id}')`) close
71 else if !p.post_hint || (p.post_hint == "link" && p.thumbnail && p.thumbnail != "self" && p.thumbnail != "default") 71 else if !p.post_hint || (p.post_hint == "link" && p.thumbnail && p.thumbnail != "self" && p.thumbnail != "default")
72 details(id=`${p.id}`) 72 details(id=`${p.id}`)
73 summary expand link 73 summary.expand-post expand link
74 a(href=`${p.url}`) 74 a(href=`${p.url}`)
75 | #{p.url} 75 | #{p.url}
76 br 76 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 @@
1@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); 1@import url('https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap');
2 2
3:root { 3:root {
4 /* Light mode colors */ 4 /* Light mode colors */
@@ -17,7 +17,7 @@
17 --bg-color-muted: #333; 17 --bg-color-muted: #333;
18 --text-color: white; 18 --text-color: white;
19 --text-color-muted: #999; 19 --text-color-muted: #999;
20 --blockquote-color: green; 20 --blockquote-color: lightgreen;
21 --link-color: lightblue; 21 --link-color: lightblue;
22 --link-visited-color: violet; 22 --link-visited-color: violet;
23 } 23 }
@@ -58,6 +58,27 @@ a:visited {
58 justify-content: center; 58 justify-content: center;
59} 59}
60 60
61.sub-title {
62 display: flex;
63}
64
65#button-container {
66 margin-left: 10px;
67 display: flex;
68 align-items: center;
69}
70
71.sort-opts {
72 display: flex;
73 flex-direction: row;
74 flex-wrap: wrap;
75 justify-content: space-between;
76}
77
78.sort-opts a {
79 margin: 10px;
80}
81
61.footer { 82.footer {
62 display: flex; 83 display: flex;
63 flex-direction: row; 84 flex-direction: row;
@@ -90,15 +111,22 @@ nav {
90.info-container, 111.info-container,
91.comment-info-container, 112.comment-info-container,
92.more, 113.more,
114summary.expand-comments::before,
93hr { 115hr {
94 color: var(--text-color-muted) 116 color: var(--text-color-muted)
95} 117}
96 118
97.info-container, .comment-info-container, .more { 119.info-container, .more {
98 font-size: 0.8rem; 120 font-size: 0.8rem;
99 display: flex; 121 display: flex;
100} 122}
101 123
124.comment-info-container {
125 display: inline-flex;
126 align-items: center;
127 font-size: 0.8rem;
128}
129
102.domain { 130.domain {
103 color: var(--text-color-muted); 131 color: var(--text-color-muted);
104 font-size: 0.8rem; 132 font-size: 0.8rem;
@@ -124,6 +152,13 @@ hr {
124 display: none 152 display: none
125} 153}
126 154
155.post-media {
156 display: block;
157 margin: 0 auto;
158 max-width: 95%;
159 padding: 5px;
160}
161
127@media (min-width: 768px) { 162@media (min-width: 768px) {
128 .post, .comments-container, .hero, .header, .footer { 163 .post, .comments-container, .hero, .header, .footer {
129 flex: 1 1 90%; 164 flex: 1 1 90%;
@@ -135,7 +170,8 @@ hr {
135 .comments-container { 170 .comments-container {
136 font-size: 1.3rem; 171 font-size: 1.3rem;
137 } 172 }
138 .info-container, .comment-info-container, .more { 173 .info-container, .comment-info-container, .more, summary.expand-comments::before
174 {
139 font-size: 1rem; 175 font-size: 1rem;
140 } 176 }
141 .domain { 177 .domain {
@@ -150,6 +186,9 @@ hr {
150 .post-author { 186 .post-author {
151 display: inline 187 display: inline
152 } 188 }
189 .post-media {
190 max-width: 50%;
191 }
153} 192}
154 193
155@media (min-width: 1080px) { 194@media (min-width: 1080px) {
@@ -163,7 +202,7 @@ hr {
163 .comments-container { 202 .comments-container {
164 font-size: 1.3rem; 203 font-size: 1.3rem;
165 } 204 }
166 .info-container, .comment-info-container, .more { 205 .info-container, .comment-info-container, .more, summary.expand-comments::before {
167 font-size: 1rem; 206 font-size: 1rem;
168 } 207 }
169 .domain { 208 .domain {
@@ -178,6 +217,9 @@ hr {
178 .post-author { 217 .post-author {
179 display: inline 218 display: inline
180 } 219 }
220 .post-media {
221 max-width: 50%;
222 }
181} 223}
182 224
183.comments-container, .self-text { 225.comments-container, .self-text {
@@ -229,15 +271,7 @@ hr {
229 flex-direction: row; 271 flex-direction: row;
230} 272}
231 273
232.post-media { 274.title-container, .comment-info-container, summary.expand-comments::before {
233 display: block;
234 margin: 0 auto;
235 max-width: 95%;
236 padding: 5px;
237}
238
239.title-container, .comment-info-container {
240 flex: 1;
241 margin-top: 10px; 275 margin-top: 10px;
242 margin-bottom: 10px; 276 margin-bottom: 10px;
243} 277}
@@ -296,10 +330,31 @@ p {
296 text-align: left; 330 text-align: left;
297} 331}
298 332
299summary { 333summary.expand-post {
300 display: none; 334 display: none;
301} 335}
302 336
337summary.expand-comments {
338 list-style: none;
339 cursor: pointer;
340}
341
342summary.expand-comments::before {
343 content: "[+] ";
344}
345
346details[open] summary.expand-comments::before {
347 content: "[-] ";
348}
349
350details:not([open]) summary.expand-comments::before {
351 content: "[+] ";
352}
353
354.comment-body {
355 display: block;
356}
357
303.footer { 358.footer {
304 padding-bottom: 40px; 359 padding-bottom: 40px;
305} 360}
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) => {
11}); 11});
12 12
13// GET /r/:id 13// GET /r/:id
14router.get('/r/:subreddit/:sort?', async (req, res) => { 14router.get('/r/:subreddit', async (req, res) => {
15 var subreddit = req.params.subreddit; 15 var subreddit = req.params.subreddit;
16 var query = req.query; 16 var query = req.query? req.query : {};
17 var sort = req.params.sort ? req.params.sort : 'hot'; 17 var sort = query.sort? query.sort : 'hot';
18 var options = req.query;
19 18
20 var postsReq = G.getSubmissions(sort, `${subreddit}`, options); 19 var postsReq = G.getSubmissions(sort, `${subreddit}`, query);
21 var aboutReq = G.getSubreddit(`${subreddit}`); 20 var aboutReq = G.getSubreddit(`${subreddit}`);
22 21
23 var [posts, about] = await Promise.all([postsReq, aboutReq]); 22 var [posts, about] = await Promise.all([postsReq, aboutReq]);
24 23
25 res.render('index', { subreddit, posts, about }); 24 res.render('index', { subreddit, posts, about, query });
26}); 25});
27 26
28// GET /comments/:id 27// 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 @@
15 if (elapsed < msPerMinute) { 15 if (elapsed < msPerMinute) {
16 return Math.round(elapsed/1000) + 's'; 16 return Math.round(elapsed/1000) + 's';
17 } else if (elapsed < msPerHour) { 17 } else if (elapsed < msPerHour) {
18 return Math.round(elapsed/msPerMinute) + 'min'; 18 return Math.round(elapsed/msPerMinute) + 'm';
19 } else if (elapsed < msPerDay ) { 19 } else if (elapsed < msPerDay ) {
20 return Math.round(elapsed/msPerHour ) + 'h'; 20 return Math.round(elapsed/msPerHour ) + 'h';
21 } else if (elapsed < msPerMonth) { 21 } else if (elapsed < msPerMonth) {
@@ -26,3 +26,9 @@
26 return Math.round(elapsed/msPerYear ) + 'y'; 26 return Math.round(elapsed/msPerYear ) + 'y';
27 } 27 }
28 } 28 }
29-
30 function encodeQueryParams(obj) {
31 return Object.keys(obj)
32 .map(key => encodeURIComponent(key) + '=' + encodeURIComponent(obj[key]))
33 .join('&');
34 }
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 @@
1include ../mixins/comment 1include ../mixins/comment
2include ../mixins/header 2include ../mixins/header
3include ../utils
3 4
4doctype html 5doctype html
5html 6html
@@ -9,6 +10,14 @@ html
9 title reddit 10 title reddit
10 link(rel='stylesheet', href='/styles.css') 11 link(rel='stylesheet', href='/styles.css')
11 script(src="https://cdn.dashjs.org/latest/dash.all.min.js") 12 script(src="https://cdn.dashjs.org/latest/dash.all.min.js")
13 script.
14 function toggleDetails(details_id) {
15 var detailsElement = document.getElementById(details_id);
16 if (detailsElement) {
17 detailsElement.open = !detailsElement.open;
18 }
19 }
20
12 body 21 body
13 main#content 22 main#content
14 +header() 23 +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 @@
1include ../mixins/post 1include ../mixins/post
2include ../mixins/sub 2include ../mixins/sub
3include ../mixins/header 3include ../mixins/header
4include ../utils
4- var subs = [] 5- var subs = []
5doctype html 6doctype html
6html 7html
@@ -42,22 +43,31 @@ html
42 +header() 43 +header()
43 44
44 div.hero 45 div.hero
45 a(href=`/r/${subreddit}`) 46 div.sub-title
46 h1 r/#{subreddit} 47 a(href=`/r/${subreddit}`)
48 h1 r/#{subreddit}
49 div#button-container
47 if about 50 if about
48 p #{about.public_description} 51 p #{about.public_description}
49 div#button-container 52 details
50 ul 53 summary sort by
51 li 54 div.sort-opts
52 a(href=`/r/${subreddit}/hot`) hot 55 a(href=`/r/${subreddit}?sort=hot`) hot
53 li 56 a(href=`/r/${subreddit}?sort=new`) new
54 a(href=`/r/${subreddit}/top`) top 57 a(href=`/r/${subreddit}?sort=rising`) rising
55 li 58 a(href=`/r/${subreddit}?sort=top`) top
56 a(href=`/r/${subreddit}/top?t=all`) top all 59 a(href=`/r/${subreddit}?sort=top&t=day`) top day
60 a(href=`/r/${subreddit}?sort=top&t=week`) top week
61 a(href=`/r/${subreddit}?sort=top&t=month`) top month
62 a(href=`/r/${subreddit}?sort=top&t=year`) top year
63 a(href=`/r/${subreddit}?sort=top&t=all`) top all
57 64
58 if posts 65 if posts
59 each child in posts.posts 66 each child in posts.posts
60 +post(child.data) 67 +post(child.data)
61 div.footer 68
62 div.footer-item 69 if posts.after
63 a(href=`/r/${subreddit}?after=${posts.after}`) next → 70 div.footer
71 div.footer-item
72 - var newQuery = {...query, after: posts.after}
73 a(href=`/r/${subreddit}?${encodeQueryParams(newQuery)}`) next →