aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPortableProgrammer <[email protected]>2024-12-30 21:17:57 +0000
committerPortableProgrammer <[email protected]>2024-12-30 21:17:57 +0000
commiteae5094ea241cc69b38cce328b73e858e6ff63de (patch)
tree61c05c3ada6c7b18438405f9ad7fae3afc611499
parent6ada78b8b19e7618275c2f9491acc1b5e89cd59a (diff)
Feat: Card View
Initial Commit
-rw-r--r--src/mixins/header.pug12
-rw-r--r--src/mixins/post.pug105
-rw-r--r--src/mixins/postUtils.pug42
-rw-r--r--src/public/styles.css179
-rw-r--r--src/routes/index.js43
-rw-r--r--src/views/comments.pug6
-rw-r--r--src/views/index.pug33
-rw-r--r--src/views/post-search.pug4
-rw-r--r--src/views/search.pug6
-rw-r--r--src/views/sub-search.pug6
-rw-r--r--src/views/subs.pug4
11 files changed, 364 insertions, 76 deletions
diff --git a/src/mixins/header.pug b/src/mixins/header.pug
index 9cf1e1a..7d56ff5 100644
--- a/src/mixins/header.pug
+++ b/src/mixins/header.pug
@@ -1,16 +1,18 @@
1mixin header(user) 1mixin header(user)
2 - var viewQuery = 'view=' + (query && query.view ? query.view : 'compact')
3 - var sortQuery = 'sort=' + (query ? (query.sort ? query.sort + (query.t ? '&t=' + query.t : '') : 'hot') : 'hot')
2 div.header 4 div.header
3 div.header-item 5 div.header-item
4 a(href=`/`) home 6 a(href=`/?${sortQuery}&${viewQuery}`) home
5 div.header-item 7 div.header-item
6 a(href=`/r/all`) all 8 a(href=`/r/all?${sortQuery}&${viewQuery}`) all
7 div.header-item 9 div.header-item
8 a(href=`/search`) search 10 a(href=`/search?${sortQuery}&${viewQuery}`) search
9 div.header-item 11 div.header-item
10 a(href=`/subs`) subs 12 a(href=`/subs?${sortQuery}&${viewQuery}`) subs
11 if user 13 if user
12 div.header-item 14 div.header-item
13 a(href='/dashboard') #{user.username} 15 a(href=`/dashboard?${sortQuery}&${viewQuery}`) #{user.username}
14 |&nbsp; 16 |&nbsp;
15 a(href='/logout') (logout) 17 a(href='/logout') (logout)
16 else 18 else
diff --git a/src/mixins/post.pug b/src/mixins/post.pug
index 74a2b78..4022424 100644
--- a/src/mixins/post.pug
+++ b/src/mixins/post.pug
@@ -2,11 +2,13 @@ include ../utils
2include postUtils 2include postUtils
3mixin post(p, currentUrl) 3mixin post(p, currentUrl)
4 - var from = encodeURIComponent(currentUrl) 4 - var from = encodeURIComponent(currentUrl)
5 - var viewQuery = query && query.view ? query.view : 'compact'
6 - var sortQuery = query && query.sort ? query.sort + (query.t ? '&t=' + query.t : '') : 'hot'
5 article.post 7 article.post
6 div.post-container 8 div.post-container(class=`${query.view}`)
7 div.post-text 9 div.post-text(class=`${query.view}`)
8 div.title-container 10 div.title-container(class=`${query.view}`)
9 a(href=`/comments/${p.id}?from=${from}`) 11 a(class=`${query.view}`, href=`/comments/${p.id}?from=${from}&sort=${sortQuery}&view=${viewQuery}`)
10 != p.title 12 != p.title
11 span.domain (#{p.domain}) 13 span.domain (#{p.domain})
12 div.info-container 14 div.info-container
@@ -18,50 +20,73 @@ mixin post(p, currentUrl)
18 | &nbsp;·&nbsp; 20 | &nbsp;·&nbsp;
19 | #{timeDifference(Date.now(), p.created * 1000)} 21 | #{timeDifference(Date.now(), p.created * 1000)}
20 | &nbsp;·&nbsp; 22 | &nbsp;·&nbsp;
21 a(href=`/r/${p.subreddit}`) r/#{p.subreddit} 23 a(href=`/r/${p.subreddit}?sort=${sortQuery}&view=${viewQuery}`) r/#{p.subreddit}
22 | &nbsp;·&nbsp; 24 | &nbsp;·&nbsp;
23 a(href=`/comments/${p.id}?from=${from}`) #{fmtnum (p.num_comments)} ↩ 25 a(href=`/comments/${p.id}?from=${from}&sort=${sortQuery}&view=${viewQuery}`) #{fmtnum (p.num_comments)} ↩
24 div.media-preview 26 if (query.view == "card" && !isPostGallery(p) && !isPostImage(p) && !isPostVideo(p) && p.selftext_html)
27 div.self-text-overflow(class='card')
28 if query.view == "card" && (p.spoiler || p.over_18)
29 div.spoiler(id=`spoiler_${p.id}`, onclick=`javascript:document.getElementById('spoiler_${p.id}').style.display = 'none';`)
30 h2
31 != p.over_18 ? 'nsfw' : 'spoiler'
32 div.self-text(class='card')
33 != convertInlineImageLinks(p.selftext_html)
34 div.media-preview(class=`${query.view}`)
35 if query.view == "card" && (p.spoiler || p.over_18) && (isPostGallery(p) || isPostImage(p) || isPostVideo(p))
36 div.spoiler(id=`spoiler_${p.id}`, onclick=`javascript:document.getElementById('spoiler_${p.id}').style.display = 'none';`)
37 h2
38 != p.over_18 ? 'nsfw' : 'spoiler'
25 if isPostGallery(p) 39 if isPostGallery(p)
26 - var item = postGalleryItems(p)[0] 40 - var item = postGalleryItems(p)[0]
27 img(src=item.url onclick=`toggleDetails('${p.id}')`) 41 img(src=item.url onclick=`toggleDetails('${p.id}')`)
28 else if isPostImage(p) 42 else if isPostImage(p)
29 - var url = postThumbnail(p) 43 - var url = query.view == "card" ? p.url : postThumbnail(p)
30 img(src=url onclick=`toggleDetails('${p.id}')`) 44 img(src=url onclick=`toggleDetails('${p.id}')`)
31 else if isPostVideo(p) 45 else if isPostVideo(p)
32 - var url = p.secure_media.reddit_video.scrubber_media_url 46 - var decodedVideos = decodePostVideoUrls(p)
33 video(src=url data-dashjs-player width='100px' height='100px' onclick=`toggleDetails('${p.id}')`) 47 if query.view == "card"
48 video(controls="" muted="" data-dashjs-player="" preload="metadata" poster=decodedVideos[4])
49 // HLS
50 source(src=decodedVideos[0])
51 // Dash
52 source(src=decodedVideos[1])
53 // Fallback
54 source(src=decodedVideos[2])
55 else
56 video(autoplay="" muted="" data-dashjs-player="" onclick=`toggleDetails('${p.id}')` width="100px" height="100px")
57 // Scrubber
58 source(src=decodedVideos[3])
34 else if isPostLink(p) 59 else if isPostLink(p)
35 a(href=p.url) 60 a(href=p.url)
61 if (query.view == 'card')
62 | #{p.domain}
36 | ↗ 63 | ↗
37 64
38 if isPostGallery(p) 65 if (isPostGallery(p) || isPostImage(p) || isPostVideo(p))
39 details(id=`${p.id}`) 66 details(id=`${p.id}`,class=`${query.view}`)
40 summary.expand-post expand gallery 67 summary.expand-post expand media
41 div.gallery 68 div.image-viewer(class=`${query.view}`)
42 each item in postGalleryItems(p) 69 if isPostGallery(p)
43 div.gallery-item 70 div.gallery(class=`${query.view}`)
44 div.gallery-item-idx 71 each item in postGalleryItems(p)
45 | #{`${item.idx}/${item.total}`} 72 div.gallery-item(class=`${query.view}`)
46 a(href=`/media/${item.url}`) 73 div.gallery-item-idx(class=`${query.view}`)
47 img(src=item.url loading="lazy") 74 | #{`${item.idx}/${item.total}`}
48 button(onclick=`toggleDetails('${p.id}')`) close 75 a(href=`/media/${item.url}`)
49 else if isPostImage(p) 76 img(src=item.url loading="lazy")
50 details(id=`${p.id}`) 77 else if isPostImage(p)
51 summary.expand-post expand image 78 a(href=`/media/${p.url}`)
52 a(href=`/media/${p.url}`) 79 img(src=p.url loading="lazy").post-media
53 img(src=p.url loading="lazy").post-media 80 else if isPostVideo(p)
54 button(onclick=`toggleDetails('${p.id}')`) close 81 video(controls="" muted="" data-dashjs-player="" preload="metadata" playsinline="" poster=decodedVideos[4] objectfit="contain" loading="lazy").post-media
55 else if isPostVideo(p) 82 //HLS
56 details(id=`${p.id}`) 83 source(src=decodedVideos[0])
57 summary.expand-post expand video 84 // Dash
58 - var url = p.secure_media.reddit_video.dash_url 85 source(src=decodedVideos[1])
59 video(src=url controls data-dashjs-player loading="lazy").post-media 86 // Fallback
60 button(onclick=`toggleDetails('${p.id}')`) close 87 source(src=decodedVideos[2])
61 else if isPostLink(p) 88 button(onclick=`toggleDetails('${p.id}')`,class=`${query.view}`)
62 details(id=`${p.id}`) 89 if (query.view == 'card')
63 summary.expand-post expand link 90 | ╳
64 a(href=`${p.url}`) 91 else
65 | #{p.url} 92 | close
66 br
67 button(onclick=`toggleDetails('${p.id}')`) close
diff --git a/src/mixins/postUtils.pug b/src/mixins/postUtils.pug
index 816adf7..84add09 100644
--- a/src/mixins/postUtils.pug
+++ b/src/mixins/postUtils.pug
@@ -10,14 +10,14 @@
10 } 10 }
11- 11-
12 function postThumbnail(p) { 12 function postThumbnail(p) {
13 if (p.thumbnail == "image" || p.thumbnail == "") { 13 if (p.over_18) {
14 return p.url; 14 return "/nsfw.svg";
15 } else if (p.over_18) {
16 return "/nsfw.svg";
17 } else if (p.thumbnail == "spoiler") { 15 } else if (p.thumbnail == "spoiler") {
18 return "/spoiler.svg"; 16 return "/spoiler.svg";
17 } else if (p.thumbnail == "image" || p.thumbnail == "") {
18 return p.url;
19 } else { 19 } else {
20 return p.thumbnail; 20 return p.thumbnail;
21 } 21 }
22 } 22 }
23- 23-
@@ -51,3 +51,33 @@
51 return null; 51 return null;
52 } 52 }
53 } 53 }
54-
55 function convertInlineImageLinks(html) {
56 // Find all anchors that href to https://preview.redd.it
57 const expression = /<a href="https:\/\/preview\.redd\.it.*?">(.*?)<\/a>/g;
58 const matches = html.matchAll(expression);
59 var result = html;
60 matches.forEach((match) => {
61 // Replace each occurrence with an actual img tag
62 result = result.replace(match[0], '<a href="' + match[1] + '"><img src="' + match[1] + '"></a>');
63 })
64
65 return result;
66 }
67-
68 function decodePostVideoUrls(p) {
69 // Video URLs have querystring separators that are HTML-encoded, so replace them.
70 const expression = /&amp;/g;
71
72 var hls_url = p.secure_media && p.secure_media.reddit_video && p.secure_media.reddit_video.hls_url ? p.secure_media.reddit_video.hls_url.replace(expression, '&') : '';
73
74 var dash_url = p.secure_media && p.secure_media.reddit_video && p.secure_media.reddit_video.dash_url ? p.secure_media.reddit_video.dash_url.replace(expression, '&') : '';
75
76 var fallback_url = p.secure_media && p.secure_media.reddit_video && p.secure_media.reddit_video.fallback_url ? p.secure_media.reddit_video.fallback_url.replace(expression, '&') : '';
77
78 var scrubber_url = p.secure_media && p.secure_media.reddit_video && p.secure_media.reddit_video.scrubber_media_url ? p.secure_media.reddit_video.scrubber_media_url.replace(expression, '&') : '';
79
80 var poster_url = p.preview && p.preview.images ? p.preview.images[0].source.url.replace(expression, '&') : '';
81
82 return [hls_url, dash_url, fallback_url, scrubber_url, poster_url];
83 } \ No newline at end of file
diff --git a/src/public/styles.css b/src/public/styles.css
index 3db6790..edf0042 100644
--- a/src/public/styles.css
+++ b/src/public/styles.css
@@ -43,6 +43,10 @@ body {
43 color: var(--text-color); 43 color: var(--text-color);
44} 44}
45 45
46body:has(details.card[open]) {
47 overflow: hidden;
48}
49
46main { 50main {
47 display: flex; 51 display: flex;
48 flex-direction: column; 52 flex-direction: column;
@@ -127,6 +131,120 @@ nav {
127 font-size: 0.9rem; 131 font-size: 0.9rem;
128} 132}
129 133
134.post-container.card {
135 border: 1px solid var(--bg-color-muted);
136 border-radius: 16px;
137 display: block;
138}
139
140.post-text.card {
141 padding: 0.9rem;
142 padding-top: 0.3rem;
143}
144
145.self-text-overflow.card {
146 /* For spoiler positioning */
147 position: relative;
148 padding-top: 0.3rem;
149 max-height: 10vh;
150 overflow: hidden;
151 overflow-wrap: break-word;
152 display: block;
153}
154
155.self-text.card {
156 overflow: hidden;
157 display: -webkit-box;
158 /* Safari on iOS <= 17 */
159 -webkit-box-orient: vertical;
160 -webkit-line-clamp: 3;
161 line-clamp: 3;
162 text-overflow: ellipsis;
163}
164
165.media-preview.card {
166 position: relative;
167 padding: 0.3rem;
168 padding-bottom: 0.3rem;
169}
170
171.media-preview.card > img {
172 cursor: pointer;
173}
174
175.image-viewer.card {
176 /* Safari on iOS <= 17 */
177 -webkit-backdrop-filter: blur(2rem);
178 backdrop-filter: blur(2rem);
179 position: fixed;
180 inset: 0;
181 box-sizing: border-box;
182 display: flex;
183 height: 100%;
184 width: 100%;
185 justify-content: center;
186 align-items: center;
187 z-index: 100;
188}
189
190.image-viewer.card > button {
191 position: absolute;
192 top: 0;
193 right: 0;
194 margin: 1rem;
195 padding: initial;
196 height: 3rem;
197 width: 3rem;
198 font-size: 2rem;
199 border-radius: 100%;
200 cursor: pointer;
201}
202
203.image-viewer.card > a > img {
204 max-width: 100vw;
205 max-height: 100vh;
206 width: auto;
207 height: auto;
208}
209
210.gallery.card {
211 align-items: center;
212}
213
214.gallery-item.card > a > img {
215 max-width: 95vw;
216 max-height: 95vh;
217 width: auto;
218 height: auto;
219}
220
221.spoiler {
222 background-color: rbga(var(--bg-color-muted), 0.2);
223 /* Safari on iOS <= 17 */
224 -webkit-backdrop-filter: blur(3rem);
225 backdrop-filter: blur(3rem);
226 border-radius: 4px;
227
228 position: absolute;
229 top: 0;
230 left: 0;
231
232 box-sizing: border-box;
233 display: flex;
234 height: 100%;
235 width: 100%;
236
237 justify-content: center;
238 align-items: center;
239
240 cursor: pointer;
241}
242
243.gallery-item-idx.card,
244.spoiler > h2 {
245 text-shadow: 0.1rem 0.1rem 1rem var(--bg-color-muted);
246}
247
130.comments-container { 248.comments-container {
131 font-size: 0.9rem; 249 font-size: 0.9rem;
132} 250}
@@ -171,6 +289,29 @@ summary::before {
171 height: 4rem; 289 height: 4rem;
172} 290}
173 291
292.media-preview.card img,
293.media-preview.card video {
294 border-radius: 16px;
295
296 max-height: 40vh;
297 max-width: 100%;
298
299 display: block;
300 width: initial;
301 height: initial;
302 margin-left: auto;
303 margin-right: auto;
304 margin-bottom: 1rem;
305
306 object-fit: fill;
307}
308
309.media-preview.card a {
310 font-size: 1.5rem;
311 margin: 1rem;
312 padding: initial;
313}
314
174.media-preview a { 315.media-preview a {
175 font-size: 2rem; 316 font-size: 2rem;
176 text-decoration: none; 317 text-decoration: none;
@@ -225,6 +366,20 @@ form {
225 width: 5rem; 366 width: 5rem;
226 height: 5rem; 367 height: 5rem;
227 } 368 }
369 .media-preview.card img,
370 .media-preview.card video
371 {
372 max-height: 50vh;
373 }
374 .media-preview.card a {
375 font-size: 1rem;
376 margin: 0.7rem;
377 padding: initial;
378 }
379 .self-text.card {
380 -webkit-line-clamp: 4;
381 line-clamp: 4;
382 }
228 .post-author { 383 .post-author {
229 display: inline 384 display: inline
230 } 385 }
@@ -252,10 +407,24 @@ form {
252 width: 5rem; 407 width: 5rem;
253 height: 5rem; 408 height: 5rem;
254 } 409 }
410 .media-preview.card img,
411 .media-preview.card video
412 {
413 max-height: 30vh;
414 }
255 .media-preview a { 415 .media-preview a {
256 font-size: 2rem; 416 font-size: 2rem;
257 padding: 2rem; 417 padding: 2rem;
258 } 418 }
419 .media-preview.card a {
420 font-size: 1rem;
421 margin: 0.5rem;
422 padding: initial;
423 }
424 .self-text.card {
425 -webkit-line-clamp: 6;
426 line-clamp: 6;
427 }
259 .post-author { 428 .post-author {
260 display: inline 429 display: inline
261 } 430 }
@@ -277,6 +446,11 @@ form {
277 flex: 1 1 40%; 446 flex: 1 1 40%;
278 width: 40%; 447 width: 40%;
279 } 448 }
449 .media-preview.card img,
450 .media-preview.card video
451 {
452 max-height: 20vh;
453 }
280 .sort-opts { 454 .sort-opts {
281 grid-template-columns: repeat(9, 1fr); 455 grid-template-columns: repeat(9, 1fr);
282 grid-template-rows: repeat(1, 1fr); 456 grid-template-rows: repeat(1, 1fr);
@@ -345,6 +519,11 @@ form {
345 text-decoration: none; 519 text-decoration: none;
346} 520}
347 521
522.title-container.card > a {
523 font-size: 1.125rem;
524 font-weight: bold;
525}
526
348.title-container > a:hover { 527.title-container > a:hover {
349 text-decoration: underline; 528 text-decoration: underline;
350} 529}
diff --git a/src/routes/index.js b/src/routes/index.js
index 117b728..9415607 100644
--- a/src/routes/index.js
+++ b/src/routes/index.js
@@ -16,11 +16,14 @@ router.get("/", authenticateToken, async (req, res) => {
16 const subs = db 16 const subs = db
17 .query("SELECT * FROM subscriptions WHERE user_id = $id") 17 .query("SELECT * FROM subscriptions WHERE user_id = $id")
18 .all({ id: req.user.id }); 18 .all({ id: req.user.id });
19
20 const qs = req.query ? ('?' + new URLSearchParams(req.query).toString()) : '';
21
19 if (subs.length === 0) { 22 if (subs.length === 0) {
20 res.redirect("/r/all"); 23 res.redirect(`/r/all${qs}`);
21 } else { 24 } else {
22 const p = subs.map((s) => s.subreddit).join("+"); 25 const p = subs.map((s) => s.subreddit).join("+");
23 res.redirect(`/r/${p}`); 26 res.redirect(`/r/${p}${qs}`);
24 } 27 }
25}); 28});
26 29
@@ -32,6 +35,9 @@ router.get("/r/:subreddit", authenticateToken, async (req, res) => {
32 if (!query.sort) { 35 if (!query.sort) {
33 query.sort = "hot"; 36 query.sort = "hot";
34 } 37 }
38 if (!query.view) {
39 query.view = "compact";
40 }
35 41
36 let isSubbed = false; 42 let isSubbed = false;
37 if (!isMulti) { 43 if (!isMulti) {
@@ -47,6 +53,10 @@ router.get("/r/:subreddit", authenticateToken, async (req, res) => {
47 53
48 const [posts, about] = await Promise.all([postsReq, aboutReq]); 54 const [posts, about] = await Promise.all([postsReq, aboutReq]);
49 55
56 if (query.view == 'card' && posts && posts.posts) {
57 posts.posts.forEach(unescape_selftext);
58 }
59
50 res.render("index", { 60 res.render("index", {
51 subreddit, 61 subreddit,
52 posts, 62 posts,
@@ -71,6 +81,7 @@ router.get("/comments/:id", authenticateToken, async (req, res) => {
71 data: unescape_submission(response), 81 data: unescape_submission(response),
72 user: req.user, 82 user: req.user,
73 from: req.query.from, 83 from: req.query.from,
84 query: req.query,
74 }); 85 });
75}); 86});
76 87
@@ -104,12 +115,12 @@ router.get("/subs", authenticateToken, async (req, res) => {
104 ) 115 )
105 .all({ id: req.user.id }); 116 .all({ id: req.user.id });
106 117
107 res.render("subs", { subs, user: req.user }); 118 res.render("subs", { subs, user: req.user, query: req.query });
108}); 119});
109 120
110// GET /search 121// GET /search
111router.get("/search", authenticateToken, async (req, res) => { 122router.get("/search", authenticateToken, async (req, res) => {
112 res.render("search", { user: req.user }); 123 res.render("search", { user: req.user, query: req.query });
113}); 124});
114 125
115// GET /sub-search 126// GET /sub-search
@@ -133,6 +144,7 @@ router.get("/sub-search", authenticateToken, async (req, res) => {
133 message, 144 message,
134 user: req.user, 145 user: req.user,
135 original_query: req.query.q, 146 original_query: req.query.q,
147 query: req.query,
136 }); 148 });
137 } 149 }
138}); 150});
@@ -147,6 +159,11 @@ router.get("/post-search", authenticateToken, async (req, res) => {
147 items.length === 0 159 items.length === 0
148 ? "no results found" 160 ? "no results found"
149 : `showing ${items.length} results`; 161 : `showing ${items.length} results`;
162
163 if (req.query.view == 'card' && items) {
164 items.forEach(unescape_selftext);
165 }
166
150 res.render("post-search", { 167 res.render("post-search", {
151 items, 168 items,
152 after, 169 after,
@@ -154,6 +171,7 @@ router.get("/post-search", authenticateToken, async (req, res) => {
154 user: req.user, 171 user: req.user,
155 original_query: req.query.q, 172 original_query: req.query.q,
156 currentUrl: req.url, 173 currentUrl: req.url,
174 query: req.query,
157 }); 175 });
158 } 176 }
159}); 177});
@@ -176,7 +194,7 @@ router.get("/dashboard", authenticateToken, async (req, res) => {
176 usedAt: Date.parse(inv.usedAt), 194 usedAt: Date.parse(inv.usedAt),
177 })); 195 }));
178 } 196 }
179 res.render("dashboard", { invites, isAdmin, user: req.user }); 197 res.render("dashboard", { invites, isAdmin, user: req.user, query: req.query });
180}); 198});
181 199
182router.get("/create-invite", authenticateAdmin, async (req, res) => { 200router.get("/create-invite", authenticateAdmin, async (req, res) => {
@@ -359,14 +377,23 @@ function unescape_submission(response) {
359 const post = response.submission.data; 377 const post = response.submission.data;
360 const comments = response.comments; 378 const comments = response.comments;
361 379
362 if (post.selftext_html) { 380 unescape_selftext(post);
363 post.selftext_html = he.decode(post.selftext_html);
364 }
365 comments.forEach(unescape_comment); 381 comments.forEach(unescape_comment);
366 382
367 return { post, comments }; 383 return { post, comments };
368} 384}
369 385
386function unescape_selftext(post) {
387 // If called after getSubmissions
388 if (post.data && post.data.selftext_html) {
389 post.data.selftext_html = he.decode(post.data.selftext_html);
390 }
391 // If called after getSubmissionComments
392 if (post.selftext_html) {
393 post.selftext_html = he.decode(post.selftext_html);
394 }
395}
396
370function unescape_comment(comment) { 397function unescape_comment(comment) {
371 if (comment.data.body_html) { 398 if (comment.data.body_html) {
372 comment.data.body_html = he.decode(comment.data.body_html); 399 comment.data.body_html = he.decode(comment.data.body_html);
diff --git a/src/views/comments.pug b/src/views/comments.pug
index 17af45a..1caf65a 100644
--- a/src/views/comments.pug
+++ b/src/views/comments.pug
@@ -6,6 +6,8 @@ include ../utils
6 6
7- var post = data.post 7- var post = data.post
8- var comments = data.comments 8- var comments = data.comments
9- var viewQuery = 'view=' + (query && query.view ? query.view : 'compact')
10- var sortQuery = 'sort=' + (query && query.sort ? query.sort + (query.t ? '&t=' + query.t : '') : 'hot')
9doctype html 11doctype html
10html 12html
11 +head(post.title) 13 +head(post.title)
@@ -27,7 +29,7 @@ html
27 | &nbsp;&nbsp; 29 | &nbsp;&nbsp;
28 | · 30 | ·
29 | &nbsp;&nbsp; 31 | &nbsp;&nbsp;
30 a(href=`/r/${post.subreddit}`) r/#{post.subreddit} 32 a(href=`/r/${post.subreddit}?${sortQuery}&${viewQuery}`) r/#{post.subreddit}
31 33
32 div.info-container 34 div.info-container
33 - var domain = (new URL(post.url)).hostname 35 - var domain = (new URL(post.url)).hostname
@@ -65,7 +67,7 @@ html
65 67
66 if post.selftext_html 68 if post.selftext_html
67 div.self-text 69 div.self-text
68 != post.selftext_html 70 != convertInlineImageLinks(post.selftext_html)
69 71
70 hr 72 hr
71 73
diff --git a/src/views/index.pug b/src/views/index.pug
index 0f00efe..5c7d550 100644
--- a/src/views/index.pug
+++ b/src/views/index.pug
@@ -2,6 +2,8 @@ include ../mixins/post
2include ../mixins/header 2include ../mixins/header
3include ../mixins/head 3include ../mixins/head
4include ../utils 4include ../utils
5 - var viewQuery = query && query.view ? query.view : 'compact'
6 - var sortQuery = query && query.sort ? query.sort + (query.t ? '&t=' + query.t : '') : 'hot'
5doctype html 7doctype html
6html 8html
7 +head("home") 9 +head("home")
@@ -14,9 +16,9 @@ html
14 div.sub-title 16 div.sub-title
15 h1 17 h1
16 if isMulti 18 if isMulti
17 a(href=`/`) lurker 19 a(href=`/?${sortQuery}&${viewQuery}`) lurker
18 else 20 else
19 a(href=`/r/${subreddit}`) 21 a(href=`/r/${subreddit}?${sortQuery}&${viewQuery}`)
20 | r/#{subreddit} 22 | r/#{subreddit}
21 if !isMulti 23 if !isMulti
22 div#button-container 24 div#button-container
@@ -32,27 +34,32 @@ html
32 a(href="https://donate.stripe.com/dR62bTaZH1295Da4gg") oppiliappan 34 a(href="https://donate.stripe.com/dR62bTaZH1295Da4gg") oppiliappan
33 |, author of lurker 35 |, author of lurker
34 hr 36 hr
35 details 37 details.sort-details
36 summary.sorting sorting by #{query.sort + (query.t?' '+query.t:'')} 38 summary.sorting sorting by #{query.sort + (query.t?' '+query.t:'')}, #{viewQuery} view
37 div.sort-opts 39 div.sort-opts
38 div 40 div
39 a(href=`/r/${subreddit}?sort=hot`) hot 41 a(href=`/r/${subreddit}?sort=hot&view=${viewQuery}`) hot
40 div 42 div
41 a(href=`/r/${subreddit}?sort=new`) new 43 a(href=`/r/${subreddit}?sort=new&view=${viewQuery}`) new
42 div 44 div
43 a(href=`/r/${subreddit}?sort=rising`) rising 45 a(href=`/r/${subreddit}?sort=rising&view=${viewQuery}`) rising
44 div 46 div
45 a(href=`/r/${subreddit}?sort=top`) top 47 a(href=`/r/${subreddit}?sort=top&view=${viewQuery}`) top
46 div 48 div
47 a(href=`/r/${subreddit}?sort=top&t=day`) top day 49 a(href=`/r/${subreddit}?sort=top&t=day&view=${viewQuery}`) top day
48 div 50 div
49 a(href=`/r/${subreddit}?sort=top&t=week`) top week 51 a(href=`/r/${subreddit}?sort=top&t=week&view=${viewQuery}`) top week
50 div 52 div
51 a(href=`/r/${subreddit}?sort=top&t=month`) top month 53 a(href=`/r/${subreddit}?sort=top&t=month&view=${viewQuery}`) top month
52 div 54 div
53 a(href=`/r/${subreddit}?sort=top&t=year`) top year 55 a(href=`/r/${subreddit}?sort=top&t=year&view=${viewQuery}`) top year
54 div 56 div
55 a(href=`/r/${subreddit}?sort=top&t=all`) top all 57 a(href=`/r/${subreddit}?sort=top&t=all&view=${viewQuery}`) top all
58 div.sort-opts
59 div
60 a(href=`/r/${subreddit}?sort=${sortQuery}&view=compact`) compact
61 div
62 a(href=`/r/${subreddit}?sort=${sortQuery}&view=card`) card
56 63
57 if posts 64 if posts
58 each child in posts.posts 65 each child in posts.posts
diff --git a/src/views/post-search.pug b/src/views/post-search.pug
index b80f9f6..8f93798 100644
--- a/src/views/post-search.pug
+++ b/src/views/post-search.pug
@@ -2,6 +2,8 @@ include ../mixins/post
2include ../mixins/header 2include ../mixins/header
3include ../mixins/head 3include ../mixins/head
4 4
5- var viewQuery = query && query.view ? query.view : 'compact'
6- var sortQuery = query && query.sort ? query.sort + (query.t ? '&t=' + query.t : '') : 'hot'
5doctype html 7doctype html
6html 8html
7 +head("search posts") 9 +head("search posts")
@@ -14,6 +16,8 @@ html
14 form(action="/post-search" method="get").search-bar 16 form(action="/post-search" method="get").search-bar
15 - var prefill = original_query ?? ""; 17 - var prefill = original_query ?? "";
16 input(type="text" name="q" placeholder="type in a search term..." value=prefill required).search-input 18 input(type="text" name="q" placeholder="type in a search term..." value=prefill required).search-input
19 input(type="hidden" name="sort" value=sortQuery)
20 input(type="hidden" name="view" value=viewQuery)
17 button(type="submit").search-button go 21 button(type="submit").search-button go
18 if message 22 if message
19 div.search-message 23 div.search-message
diff --git a/src/views/search.pug b/src/views/search.pug
index ef9b53e..4dc5c0c 100644
--- a/src/views/search.pug
+++ b/src/views/search.pug
@@ -1,6 +1,8 @@
1include ../mixins/header 1include ../mixins/header
2include ../mixins/head 2include ../mixins/head
3 3
4- var viewQuery = query && query.view ? query.view : 'compact'
5- var sortQuery = query && query.sort ? query.sort + (query.t ? '&t=' + query.t : '') : 'hot'
4doctype html 6doctype html
5html 7html
6 +head("search subreddits") 8 +head("search subreddits")
@@ -14,6 +16,8 @@ html
14 form(action="/sub-search" method="get").search-bar 16 form(action="/sub-search" method="get").search-bar
15 - var prefill = original_query ?? ""; 17 - var prefill = original_query ?? "";
16 input(type="text" name="q" placeholder="type in a search term..." value=prefill required).search-input 18 input(type="text" name="q" placeholder="type in a search term..." value=prefill required).search-input
19 input(type="hidden" name="sort" value=sortQuery)
20 input(type="hidden" name="view" value=viewQuery)
17 button(type="submit").search-button go 21 button(type="submit").search-button go
18 22
19 hr 23 hr
@@ -23,6 +27,8 @@ html
23 form(action="/post-search" method="get").search-bar 27 form(action="/post-search" method="get").search-bar
24 - var prefill = original_query ?? ""; 28 - var prefill = original_query ?? "";
25 input(type="text" name="q" placeholder="type in a search term..." value=prefill required).search-input 29 input(type="text" name="q" placeholder="type in a search term..." value=prefill required).search-input
30 input(type="hidden" name="sort" value=sortQuery)
31 input(type="hidden" name="view" value=viewQuery)
26 button(type="submit").search-button go 32 button(type="submit").search-button go
27 p 33 p
28 | you can narrow search results using filters: 34 | you can narrow search results using filters:
diff --git a/src/views/sub-search.pug b/src/views/sub-search.pug
index f2402f7..cb8eeef 100644
--- a/src/views/sub-search.pug
+++ b/src/views/sub-search.pug
@@ -1,6 +1,8 @@
1include ../mixins/header 1include ../mixins/header
2include ../mixins/head 2include ../mixins/head
3 3
4- var viewQuery = (query && query.view) ? query.view : 'compact'
5- var sortQuery = (query && query.sort) ? query.sort + (query.t ? '&t=' + query.t : '') : 'hot'
4doctype html 6doctype html
5html 7html
6 +head("search subreddits") 8 +head("search subreddits")
@@ -13,6 +15,8 @@ html
13 form(action="/sub-search" method="get").search-bar 15 form(action="/sub-search" method="get").search-bar
14 - var prefill = original_query ?? ""; 16 - var prefill = original_query ?? "";
15 input(type="text" name="q" placeholder="type in a search term..." value=prefill required).search-input 17 input(type="text" name="q" placeholder="type in a search term..." value=prefill required).search-input
18 input(type="hidden" name="sort" value=sortQuery)
19 input(type="hidden" name="view" value=viewQuery)
16 button(type="submit").search-button go 20 button(type="submit").search-button go
17 if message 21 if message
18 div.search-message 22 div.search-message
@@ -25,7 +29,7 @@ html
25 - var isSubbed = subs.includes(subreddit) 29 - var isSubbed = subs.includes(subreddit)
26 div.sub-title 30 div.sub-title
27 h3 31 h3
28 a(href=`/r/${subreddit}`) 32 a(href=`/r/${subreddit}?sort=${sortQuery}&view=${viewQuery}`)
29 | r/#{subreddit} 33 | r/#{subreddit}
30 div#button-container 34 div#button-container
31 if isSubbed 35 if isSubbed
diff --git a/src/views/subs.pug b/src/views/subs.pug
index 8fca12d..aff8258 100644
--- a/src/views/subs.pug
+++ b/src/views/subs.pug
@@ -1,6 +1,8 @@
1include ../mixins/header 1include ../mixins/header
2include ../mixins/head 2include ../mixins/head
3 3
4- var viewQuery = query && query.view ? query.view : 'compact'
5- var sortQuery = query && query.sort ? query.sort + (query.t ? '&t=' + query.t : '') : 'hot'
4doctype html 6doctype html
5html 7html
6 +head("subscriptions") 8 +head("subscriptions")
@@ -16,7 +18,7 @@ html
16 - var isSubbed = true 18 - var isSubbed = true
17 div.sub-title 19 div.sub-title
18 h4 20 h4
19 a(href=`/r/${subreddit}`) 21 a(href=`/r/${subreddit}?sort=${sortQuery}&view=${viewQuery}`)
20 | r/#{subreddit} 22 | r/#{subreddit}
21 div#button-container 23 div#button-container
22 if isSubbed 24 if isSubbed