aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPortableProgrammer <[email protected]>2025-01-10 20:37:49 +0000
committerPortableProgrammer <[email protected]>2025-01-10 20:37:49 +0000
commit83ab88264880b13e2d0826ee0af8a6f17b18c33e (patch)
tree925f2c2991605527acc1e3282bc8e9fa9602ded1
parentf983c1313cd17fc5acf5f703638ec53e15c831bf (diff)
Feat: Consolidate/port Card and Compact media viewers
-rw-r--r--src/mixins/post.pug93
-rw-r--r--src/public/styles.css70
2 files changed, 69 insertions, 94 deletions
diff --git a/src/mixins/post.pug b/src/mixins/post.pug
index c4f3bc5..30310a8 100644
--- a/src/mixins/post.pug
+++ b/src/mixins/post.pug
@@ -28,77 +28,58 @@ mixin post(p, currentUrl)
28 | &nbsp;·&nbsp; 28 | &nbsp;·&nbsp;
29 a(href=`/comments/${p.id}?from=${from}&sort=${sortQuery}&view=${viewQuery}`) #{fmtnum (p.num_comments)} ↩ 29 a(href=`/comments/${p.id}?from=${from}&sort=${sortQuery}&view=${viewQuery}`) #{fmtnum (p.num_comments)} ↩
30 if (query.view == "card" && !isPostGallery(p) && !isPostImage(p) && !isPostVideo(p) && p.selftext_html) 30 if (query.view == "card" && !isPostGallery(p) && !isPostImage(p) && !isPostVideo(p) && p.selftext_html)
31 div.self-text-overflow(class='card') 31 div.self-text-overflow.card
32 if query.view == "card" && (p.spoiler || p.over_18) 32 if p.spoiler || p.over_18
33 div.spoiler(id=`spoiler_${p.id}`, onclick=`javascript:document.getElementById('spoiler_${p.id}').style.display = 'none';`) 33 div.spoiler(id=`spoiler_${p.id}`, onclick=`javascript:document.getElementById('spoiler_${p.id}').style.display = 'none';`)
34 h2 34 h2
35 != p.over_18 ? 'nsfw' : 'spoiler' 35 != p.over_18 ? 'nsfw' : 'spoiler'
36 div.self-text(class='card') 36 div.self-text.card
37 != convertInlineImageLinks(p.selftext_html) 37 != convertInlineImageLinks(p.selftext_html)
38 div.media-preview(class=`${query.view}`) 38 if query.view != "card"
39 - var onclick = query.view != "card" ? `toggleDetails('${p.id}')` : `` 39 div.media-preview
40 - var onclick = `toggleDetails('${p.id}')`
41 if isPostGallery(p)
42 - var item = (p.over_18 ? `/nsfw.svg` : p.spoiler ? `/spoiler.svg` : postGalleryItems(p)[0].url)
43 img(src=item onclick=onclick)
44 else if isPostImage(p)
45 - var url = postThumbnail(p)
46 img(src=url onclick=onclick)
47 else if isPostVideo(p)
48 - var decodedVideos = decodePostVideoUrls(p)
49 video(autoplay="" muted="" data-dashjs-player="" onclick=`toggleDetails('${p.id}')` poster=decodedVideos[4] width="100px" height="100px")
50 // Scrubber
51 source(src=decodedVideos[3])
52 else if isPostLink(p)
53 a(href=p.url)
54 | ↗
55
56 details(id=`${p.id}` open=(query.view == "card" && (isPostGallery(p) || isPostImage(p) || isPostVideo(p))))
57 summary.expand-post expand media
58 div.image-viewer
40 if query.view == "card" && (p.spoiler || p.over_18) && (isPostGallery(p) || isPostImage(p) || isPostVideo(p)) 59 if query.view == "card" && (p.spoiler || p.over_18) && (isPostGallery(p) || isPostImage(p) || isPostVideo(p))
41 div.spoiler(id=`spoiler_${p.id}`, onclick=`javascript:document.getElementById('spoiler_${p.id}').style.display = 'none';`) 60 div.spoiler(id=`spoiler_${p.id}`, onclick=`javascript:document.getElementById('spoiler_${p.id}').style.display = 'none';`)
42 h2 61 h2
43 != p.over_18 ? 'nsfw' : 'spoiler' 62 != p.over_18 ? 'nsfw' : 'spoiler'
44 if isPostGallery(p) 63 if isPostGallery(p)
45 - var item = postGalleryItems(p)[0] 64 div.gallery
46 if query.view == "card" 65 each item in postGalleryItems(p)
47 div.gallery(class=`${query.view}`) 66 div.gallery-item
48 each item in postGalleryItems(p) 67 a(href=`/media/${item.url}`)
49 div.gallery-item(class=`${query.view}`) 68 img(src=item.url loading="lazy")
50 a(href=`/media/${item.url}`) 69 div.gallery-item-idx
51 img(src=item.url loading="lazy") 70 | #{`${item.idx}/${item.total}`}
52 div.gallery-item-idx(class=`${query.view}`)
53 | #{`${item.idx}/${item.total}`}
54 else
55 img(src=item.url onclick=onclick)
56 else if isPostImage(p) 71 else if isPostImage(p)
57 - var url = query.view == "card" ? p.url : postThumbnail(p) 72 a(href=`/media/${p.url}`)
58 #{query.view == "card" ? "a href=/media/" + url : span} 73 img(src=p.url loading="lazy")
59 img(src=url onclick=onclick)
60 else if isPostVideo(p) 74 else if isPostVideo(p)
61 - var decodedVideos = decodePostVideoUrls(p) 75 - var decodedVideos = decodePostVideoUrls(p)
62 if query.view == "card" 76 video(controls="" muted="" data-dashjs-player="" preload="metadata" playsinline="" poster=decodedVideos[4] objectfit="contain" loading="lazy")
63 video(controls="" muted="" data-dashjs-player="" preload="metadata" poster=decodedVideos[4])
64 // HLS 77 // HLS
65 source(src=decodedVideos[0]) 78 source(src=decodedVideos[0])
66 // Dash 79 // Dash
67 source(src=decodedVideos[1]) 80 source(src=decodedVideos[1])
68 // Fallback 81 // Fallback
69 source(src=decodedVideos[2]) 82 source(src=decodedVideos[2])
70 else 83 if (query.view == "compact")
71 video(autoplay="" muted="" data-dashjs-player="" onclick=`toggleDetails('${p.id}')` width="100px" height="100px") 84 button(onclick=`toggleDetails('${p.id}')`)
72 // Scrubber 85 | close
73 source(src=decodedVideos[3])
74 else if isPostLink(p)
75 a(href=p.url)
76 if (query.view == 'card')
77 | #{p.domain}
78 | ↗
79
80 if query.view == "compact" && (isPostGallery(p) || isPostImage(p) || isPostVideo(p))
81 details(id=`${p.id}`)
82 summary.expand-post expand media
83 div.image-viewer
84 if isPostGallery(p)
85 div.gallery
86 each item in postGalleryItems(p)
87 div.gallery-item
88 div.gallery-item-idx
89 | #{`${item.idx}/${item.total}`}
90 a(href=`/media/${item.url}`)
91 img(src=item.url loading="lazy")
92 else if isPostImage(p)
93 a(href=`/media/${p.url}`)
94 img(src=p.url loading="lazy").post-media
95 else if isPostVideo(p)
96 video(controls="" muted="" data-dashjs-player="" preload="metadata" playsinline="" poster=decodedVideos[4] objectfit="contain" loading="lazy").post-media
97 //HLS
98 source(src=decodedVideos[0])
99 // Dash
100 source(src=decodedVideos[1])
101 // Fallback
102 source(src=decodedVideos[2])
103 button(onclick=`toggleDetails('${p.id}')`)
104 | close
diff --git a/src/public/styles.css b/src/public/styles.css
index d9f6a40..8bfdc72 100644
--- a/src/public/styles.css
+++ b/src/public/styles.css
@@ -11,6 +11,9 @@
11 --link-visited-color: #999; 11 --link-visited-color: #999;
12 --accent: var(--link-color); 12 --accent: var(--link-color);
13 --error-text-color: red; 13 --error-text-color: red;
14 --border-radius-card: 8px;
15 --border-radius-media: 6px;
16 --border-radius-preview: 4px;
14 17
15 font-family: Inter, sans-serif; 18 font-family: Inter, sans-serif;
16 font-feature-settings: 'ss01' 1, 'kern' 1, 'liga' 1, 'cv05' 1, 'dlig' 1, 'ss01' 1, 'ss07' 1, 'ss08' 1; 19 font-feature-settings: 'ss01' 1, 'kern' 1, 'liga' 1, 'cv05' 1, 'dlig' 1, 'ss01' 1, 'ss07' 1, 'ss08' 1;
@@ -47,10 +50,6 @@ body {
47 color: var(--text-color); 50 color: var(--text-color);
48} 51}
49 52
50body:has(details.card[open]) {
51 overflow: hidden;
52}
53
54body.media-maximized { 53body.media-maximized {
55 /* Fix for Safari User Agent stylesheet */ 54 /* Fix for Safari User Agent stylesheet */
56 margin: 0; 55 margin: 0;
@@ -169,7 +168,7 @@ nav {
169 168
170.post-container.card { 169.post-container.card {
171 border: 1px solid var(--bg-color-muted); 170 border: 1px solid var(--bg-color-muted);
172 border-radius: 8px; 171 border-radius: var(--border-radius-card);
173 display: block; 172 display: block;
174} 173}
175 174
@@ -198,37 +197,22 @@ nav {
198 text-overflow: ellipsis; 197 text-overflow: ellipsis;
199} 198}
200 199
201.media-preview.card { 200.image-viewer {
202 position: relative; 201 position: relative;
203 padding: 0.3rem; 202 padding: 0.3rem;
204 padding-bottom: 0.3rem; 203 padding-bottom: 0.3rem;
205} 204}
206 205
207.media-preview.card > img { 206.image-viewer > img {
208 cursor: pointer; 207 cursor: pointer;
209} 208}
210 209
211.gallery.card {
212 align-items: center;
213 scroll-snap-type: both mandatory;
214}
215
216.gallery-item.card {
217 max-width: 100%;
218 width: 100%;
219 scroll-snap-align: center;
220}
221
222.gallery-item-idx.card {
223 text-align: center;
224}
225
226.spoiler { 210.spoiler {
227 background-color: rbga(var(--bg-color-muted), 0.2); 211 background-color: rbga(var(--bg-color-muted), 0.2);
228 /* Safari on iOS <= 17 */ 212 /* Safari on iOS <= 17 */
229 -webkit-backdrop-filter: blur(3rem); 213 -webkit-backdrop-filter: blur(3rem);
230 backdrop-filter: blur(3rem); 214 backdrop-filter: blur(3rem);
231 border-radius: 4px; 215 border-radius: var(--border-radius-preview);
232 216
233 position: absolute; 217 position: absolute;
234 top: 0; 218 top: 0;
@@ -247,7 +231,7 @@ nav {
247 z-index: 10; 231 z-index: 10;
248} 232}
249 233
250.gallery-item-idx.card, 234.gallery-item-idx,
251.spoiler > h2 { 235.spoiler > h2 {
252 text-shadow: 0.1rem 0.1rem 1rem var(--bg-color-muted); 236 text-shadow: 0.1rem 0.1rem 1rem var(--bg-color-muted);
253} 237}
@@ -294,15 +278,16 @@ summary::before {
294 object-fit: cover; 278 object-fit: cover;
295 width: 4rem; 279 width: 4rem;
296 height: 4rem; 280 height: 4rem;
281 border-radius: var(--border-radius-preview);
297} 282}
298 283
299.media-preview.card { 284.image-viewer {
300 padding: unset; 285 padding: unset;
301} 286}
302 287
303.media-preview.card img, 288.image-viewer img,
304.media-preview.card video { 289.image-viewer video {
305 border-radius: 6px; 290 border-radius: var(--border-radius-media);
306 291
307 max-height: 40vh; 292 max-height: 40vh;
308 max-width: 95%; 293 max-width: 95%;
@@ -317,13 +302,13 @@ summary::before {
317 object-fit: fill; 302 object-fit: fill;
318} 303}
319 304
320.media-preview.card a { 305.image-viewer a {
321 font-size: 1.5rem; 306 font-size: 1.5rem;
322 padding: unset; 307 padding: unset;
323 padding-left: 1rem; 308 padding-left: 1rem;
324} 309}
325 310
326.media-preview.card a:has(img) { 311.image-viewer a:has(img) {
327 font-size: 0rem; 312 font-size: 0rem;
328 padding: unset; 313 padding: unset;
329} 314}
@@ -382,12 +367,12 @@ form {
382 width: 5rem; 367 width: 5rem;
383 height: 5rem; 368 height: 5rem;
384 } 369 }
385 .media-preview.card img, 370 .image-viewer img,
386 .media-preview.card video 371 .image-viewer video
387 { 372 {
388 max-height: 50vh; 373 max-height: 50vh;
389 } 374 }
390 .media-preview.card a { 375 .image-viewer a {
391 font-size: 1rem; 376 font-size: 1rem;
392 margin: 0.7rem; 377 margin: 0.7rem;
393 padding: initial; 378 padding: initial;
@@ -424,8 +409,8 @@ form {
424 width: 5rem; 409 width: 5rem;
425 height: 5rem; 410 height: 5rem;
426 } 411 }
427 .media-preview.card img, 412 .image-viewer img,
428 .media-preview.card video 413 .image-viewer video
429 { 414 {
430 max-height: 30vh; 415 max-height: 30vh;
431 } 416 }
@@ -433,7 +418,7 @@ form {
433 font-size: 2rem; 418 font-size: 2rem;
434 padding: 2rem; 419 padding: 2rem;
435 } 420 }
436 .media-preview.card a { 421 .image-viewer a {
437 font-size: 1rem; 422 font-size: 1rem;
438 margin: 0.5rem; 423 margin: 0.5rem;
439 padding: initial; 424 padding: initial;
@@ -464,8 +449,8 @@ form {
464 flex: 1 1 40%; 449 flex: 1 1 40%;
465 width: 40%; 450 width: 40%;
466 } 451 }
467 .media-preview.card img, 452 .image-viewer img,
468 .media-preview.card video 453 .image-viewer video
469 { 454 {
470 max-height: 20vh; 455 max-height: 20vh;
471 } 456 }
@@ -648,11 +633,20 @@ a {
648 overflow-x: auto; 633 overflow-x: auto;
649 position: relative; 634 position: relative;
650 padding: 5px; 635 padding: 5px;
636 align-items: center;
637 scroll-snap-type: both mandatory;
651} 638}
652 639
653.gallery-item { 640.gallery-item {
654 flex: 0 0 auto; 641 flex: 0 0 auto;
655 margin-right: 10px; 642 margin-right: 10px;
643 max-width: 100%;
644 width: 100%;
645 scroll-snap-align: center;
646}
647
648.gallery-item-idx {
649 text-align: center;
656} 650}
657 651
658.gallery img { 652.gallery img {