selfhostable, read-only reddit client
15
fork

Configure Feed

Select the types of activity you want to include in your feed.

Split `post-container` class Fixes `flex-*` issues in consolidated views.

+84 -78
+73 -69
src/mixins/post.pug
··· 6 6 - var sortQuery = query && query.sort ? query.sort + (query.t ? '&t=' + query.t : '') : 'hot' 7 7 article(class=`post`) 8 8 div.post-container(class=`${query.view} ${p.stickied?"sticky":""}`) 9 - div.post-text(class=`${query.view}`) 10 - div.title-container(class=`${query.view}`) 11 - a(class=`${query.view}`, href=`/comments/${p.id}?from=${from}&sort=${sortQuery}&view=${viewQuery}`) 12 - != p.title 13 - span.domain (#{p.domain}) 14 - div.info-container 15 - p 16 - | #{fmtnum(p.ups)} ↑ 17 - if p.gilded > 0 9 + div.post-info 10 + div.post-text(class=`${query.view}`) 11 + div.title-container(class=`${query.view}`) 12 + a(class=`${query.view}`, href=`/comments/${p.id}?from=${from}&sort=${sortQuery}&view=${viewQuery}`) 13 + != p.title 14 + span.domain (#{p.domain}) 15 + div.info-container 16 + p 17 + | #{fmtnum(p.ups)} ↑ 18 + if p.gilded > 0 19 + |  ·  20 + span.gilded 21 + | #{p.gilded} ☆ 22 + span.post-author 23 + |  ·  24 + | u/#{p.author} 18 25 |  ·  19 - span.gilded 20 - | #{p.gilded} ☆ 21 - span.post-author 26 + | #{timeDifference(Date.now(), p.created * 1000)} 27 + |  ·  28 + a(href=`/r/${p.subreddit}?sort=${sortQuery}&view=${viewQuery}`) r/#{p.subreddit} 22 29 |  ·  23 - | u/#{p.author} 24 - |  ·  25 - | #{timeDifference(Date.now(), p.created * 1000)} 26 - |  ·  27 - a(href=`/r/${p.subreddit}?sort=${sortQuery}&view=${viewQuery}`) r/#{p.subreddit} 28 - |  ·  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) 31 - div.self-text-overflow.card 32 - if p.spoiler || p.over_18 33 - div.spoiler(id=`spoiler_${p.id}`, onclick=`javascript:document.getElementById('spoiler_${p.id}').style.display = 'none';`) 34 - h2 35 - != p.over_18 ? 'nsfw' : 'spoiler' 36 - div.self-text.card 37 - != convertInlineImageLinks(p.selftext_html) 38 - if query.view != "card" 39 - div.media-preview 40 - - var onclick = `toggleDetails('${p.id}')` 30 + a(href=`/comments/${p.id}?from=${from}&sort=${sortQuery}&view=${viewQuery}`) #{fmtnum (p.num_comments)} ↩ 31 + if (query.view == "card" && !isPostGallery(p) && !isPostImage(p) && !isPostVideo(p) && p.selftext_html) 32 + div.self-text-overflow.card 33 + if p.spoiler || p.over_18 34 + div.spoiler(id=`spoiler_${p.id}`, onclick=`javascript:document.getElementById('spoiler_${p.id}').style.display = 'none';`) 35 + h2 36 + != p.over_18 ? 'nsfw' : 'spoiler' 37 + div.self-text.card 38 + != convertInlineImageLinks(p.selftext_html) 39 + if query.view != "card" 40 + div.media-preview 41 + - var onclick = `toggleDetails('${p.id}')` 42 + if isPostGallery(p) 43 + - var item = (p.over_18 ? `/nsfw.svg` : p.spoiler ? `/spoiler.svg` : postGalleryItems(p)[0].url) 44 + img(src=item onclick=onclick) 45 + else if isPostImage(p) 46 + - var url = postThumbnail(p) 47 + img(src=url onclick=onclick) 48 + else if isPostVideo(p) 49 + - var decodedVideos = decodePostVideoUrls(p) 50 + video(autoplay="" muted="" data-dashjs-player="" onclick=`toggleDetails('${p.id}')` poster=decodedVideos[4] width="100px" height="100px") 51 + // Scrubber 52 + source(src=decodedVideos[3]) 53 + else if isPostLink(p) 54 + a(href=p.url) 55 + | ↗ 56 + 57 + details(id=`${p.id}` open=(query.view == "card") class=`${query.view}`) 58 + summary.expand-post expand media 59 + div.image-viewer 60 + if query.view == "card" && (p.spoiler || p.over_18) && (isPostGallery(p) || isPostImage(p) || isPostVideo(p)) 61 + div.spoiler(id=`spoiler_${p.id}`, onclick=`javascript:document.getElementById('spoiler_${p.id}').style.display = 'none';`) 62 + h2 63 + != p.over_18 ? 'nsfw' : 'spoiler' 41 64 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) 65 + div.gallery 66 + each item in postGalleryItems(p) 67 + div.gallery-item 68 + a(href=`/media/${item.url}`) 69 + img(src=item.url loading="lazy") 70 + div.gallery-item-idx 71 + | #{`${item.idx}/${item.total}`} 44 72 else if isPostImage(p) 45 - - var url = postThumbnail(p) 46 - img(src=url onclick=onclick) 73 + a(href=`/media/${p.url}`) 74 + img(src=p.url loading="lazy") 47 75 else if isPostVideo(p) 48 76 - 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]) 77 + video(controls="" muted="" data-dashjs-player="" preload="metadata" playsinline="" poster=decodedVideos[4] objectfit="contain" loading="lazy") 78 + // HLS 79 + source(src=decodedVideos[0]) 80 + // Dash 81 + source(src=decodedVideos[1]) 82 + // Fallback 83 + source(src=decodedVideos[2]) 52 84 else if isPostLink(p) 53 85 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 59 - if query.view == "card" && (p.spoiler || p.over_18) && (isPostGallery(p) || isPostImage(p) || isPostVideo(p)) 60 - div.spoiler(id=`spoiler_${p.id}`, onclick=`javascript:document.getElementById('spoiler_${p.id}').style.display = 'none';`) 61 - h2 62 - != p.over_18 ? 'nsfw' : 'spoiler' 63 - if isPostGallery(p) 64 - div.gallery 65 - each item in postGalleryItems(p) 66 - div.gallery-item 67 - a(href=`/media/${item.url}`) 68 - img(src=item.url loading="lazy") 69 - div.gallery-item-idx 70 - | #{`${item.idx}/${item.total}`} 71 - else if isPostImage(p) 72 - a(href=`/media/${p.url}`) 73 - img(src=p.url loading="lazy") 74 - else if isPostVideo(p) 75 - - var decodedVideos = decodePostVideoUrls(p) 76 - video(controls="" muted="" data-dashjs-player="" preload="metadata" playsinline="" poster=decodedVideos[4] objectfit="contain" loading="lazy") 77 - // HLS 78 - source(src=decodedVideos[0]) 79 - // Dash 80 - source(src=decodedVideos[1]) 81 - // Fallback 82 - source(src=decodedVideos[2]) 83 - if (query.view == "compact") 84 - button(onclick=`toggleDetails('${p.id}')`) 85 - | close 86 + | #{p.domain} ↗ 87 + if (query.view == "compact") 88 + button(onclick=`toggleDetails('${p.id}')`) 89 + | close
+11 -9
src/public/styles.css
··· 302 302 object-fit: fill; 303 303 } 304 304 305 - .image-viewer a { 306 - font-size: 1.5rem; 307 - padding: unset; 308 - padding-left: 1rem; 309 - } 310 - 311 305 .image-viewer a:has(img) { 312 306 font-size: 0rem; 313 307 padding: unset; 314 308 } 315 309 316 - .media-preview a { 317 - font-size: 2rem; 310 + .media-preview a, 311 + .image-viewer a { 312 + font-size: 1.5rem; 318 313 text-decoration: none; 319 314 padding: 1rem; 320 315 } ··· 479 474 margin-top: 10px; 480 475 } 481 476 482 - .post-container { 477 + .post-info { 483 478 display: flex; 484 479 flex-direction: row; 485 480 align-items: center; ··· 616 611 details:not([open]) summary::before { 617 612 content: ""; 618 613 padding-right: 10px; 614 + } 615 + 616 + details.compact { 617 + /* 618 + display: flex; 619 + flex-basis: 100%; 620 + */ 619 621 } 620 622 621 623 .footer {