selfhostable, read-only reddit client
16
fork

Configure Feed

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

add dark mode, add time for comments and posts

Akshay 0d0cfdd2 bd78cbc3

+128 -27
+1
src/mixins/comment.pug
··· 13 13 if data.collapsed_reason_code == "DELETED" 14 14 div.info-item 15 15 a(href=`https://undelete.pullpush.io${data.permalink}`) search on undelete 16 + div.info-item #{timeDifference(Date.now(), data.created * 1000)} 16 17 div.comment-body 17 18 != data.body_html 18 19 div.replies
+15 -5
src/mixins/post.pug
··· 14 14 |  ·  15 15 by u/#{p.author} 16 16 |  ·  17 + | #{timeDifference(Date.now(), p.created * 1000)} 18 + |  ·  17 19 a(href=`/r/${p.subreddit}`) r/#{p.subreddit} 18 20 |  ·  19 21 a(href=`/comments/${p.id}`) #{fmtnum (p.num_comments)} ↩ ··· 28 30 if p.thumbnail && p.thumbnail != "self" || p.thumbnail != "default" 29 31 img(src=p.thumbnail onclick=`toggleDetails('${p.id}')`) 30 32 else if p.post_hint == "hosted:video" 31 - - var url = p.secure_media.reddit_video.dash_url 33 + - var url = p.secure_media.reddit_video.scrubber_media_url 32 34 video(src=url data-dashjs-player width='100px' height='100px' onclick=`toggleDetails('${p.id}')`) 33 35 34 36 if p.is_gallery && p.is_gallery == true ··· 37 39 details(id=`${p.id}`) 38 40 summary expand gallery 39 41 div.gallery 42 + - var total = p.gallery_data.items.length 43 + - var idx = 0 44 + - var metadata = p.media_metadata 45 + - var img_ext = (id) => stripPrefix(metadata[id].m, "image/") 40 46 each item in p.gallery_data.items 41 - - var url = `https://i.redd.it/${item.media_id}.jpg` 47 + - var id = item.media_id 48 + - var ext = img_ext(item.media_id) 49 + - var url = `https://i.redd.it/${id}.${ext}` 42 50 div.gallery-item 43 51 a(href=`/media/${url}`) 44 - img(src=url) 52 + img(src=url loading="lazy") 53 + div.gallery-item-idx 54 + | #{`${++idx}/${total}`} 45 55 button(onclick=`toggleDetails('${p.id}')`) close 46 56 if p.post_hint == "image" && p.thumbnail && p.thumbnail != "self" && p.thumbnail != "default" 47 57 details(id=`${p.id}`) 48 58 summary expand image 49 59 a(href=`/media/${p.url}`) 50 - img(src=p.url).post-media 60 + img(src=p.url loading="lazy").post-media 51 61 button(onclick=`toggleDetails('${p.id}')`) close 52 62 else if p.post_hint == "hosted:video" 53 63 details(id=`${p.id}`) 54 64 summary expand video 55 65 - var url = p.secure_media.reddit_video.dash_url 56 - video(src=url controls data-dashjs-player).post-media 66 + video(src=url controls data-dashjs-player loading="lazy").post-media 57 67 button(onclick=`toggleDetails('${p.id}')`) close 58 68 else if p.post_hint == "link" && p.thumbnail && p.thumbnail != "self" && p.thumbnail != "default" 59 69 details(id=`${p.id}`)
+71 -17
src/public/styles.css
··· 1 1 @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); 2 2 3 + :root { 4 + /* Light mode colors */ 5 + --bg-color: white; 6 + --text-color: black; 7 + --text-color-muted: #999; 8 + --blockquote-color: green; 9 + --link-color: blue; 10 + --link-visited-color: purple; 11 + } 12 + 13 + @media (prefers-color-scheme: dark) { 14 + :root { 15 + --bg-color: black; 16 + --text-color: white; 17 + --text-color-muted: #999; 18 + --blockquote-color: green; 19 + --link-color: lightblue; 20 + --link-visited-color: violet; 21 + } 22 + } 23 + 24 + 3 25 body { 4 26 font-family: 'Inter', sans-serif; 5 27 overflow-x: hidden; 28 + background-color: var(--bg-color); 29 + color: var(--text-color); 6 30 } 7 31 8 32 main { ··· 12 36 align-items: center; 13 37 } 14 38 39 + a { 40 + color: var(--link-color); 41 + text-decoration: none; 42 + } 43 + 44 + a:hover { 45 + color: var(--link-color); 46 + text-decoration: underline; 47 + } 48 + 49 + a:visited { 50 + color: var(--link-visited-color); 51 + } 52 + 15 53 .header { 16 54 display: flex; 17 55 flex-direction: row; ··· 38 76 width: 100%; 39 77 } 40 78 41 - .post { 79 + .post, .hero { 42 80 font-size: 1rem; 43 81 } 44 82 ··· 46 84 font-size: 1rem; 47 85 } 48 86 87 + .info-container a, 88 + .info-container, 89 + .comment-info-container, 90 + .more, 91 + hr { 92 + color: var(--text-color-muted) 93 + } 94 + 49 95 .info-container, .comment-info-container, .more { 50 - color: #777; 51 96 font-size: 0.8rem; 52 97 display: flex; 53 98 } 54 99 55 100 .domain { 56 - color: #777; 101 + color: var(--text-color-muted); 57 102 font-size: 0.8rem; 58 103 } 59 104 ··· 62 107 } 63 108 64 109 65 - .media-preview img { 110 + .media-preview img, 111 + .media-preview video { 66 112 object-fit: cover; 67 113 } 68 114 ··· 81 127 flex: 1 1 90%; 82 128 width: 90%; 83 129 } 84 - .post { 130 + .post, .hero { 85 131 font-size: 1.3rem; 86 132 } 87 133 .comments-container { 88 - font-size: 1.1rem; 134 + font-size: 1.3rem; 89 135 } 90 136 .info-container, .comment-info-container, .more { 91 137 font-size: 1rem; ··· 106 152 107 153 @media (min-width: 1080px) { 108 154 .post, .comments-container, .hero, .header, .footer { 109 - flex: 1 1 50%; 110 - width: 50%; 155 + flex: 1 1 60%; 156 + width: 60%; 111 157 } 112 - .post { 158 + .post, .hero { 113 159 font-size: 1.3rem; 114 160 } 115 161 .comments-container { 116 - font-size: 1.1rem; 162 + font-size: 1.3rem; 117 163 } 118 164 .info-container, .comment-info-container, .more { 119 165 font-size: 1rem; ··· 138 184 139 185 .comment, .more { 140 186 width: 100%; 141 - border-left: 1px dashed; 187 + border-left: 1px dashed var(--text-color-muted); 142 188 padding: 10px 0px 0px 24px; 143 189 box-sizing: border-box; 144 190 } ··· 149 195 150 196 .more { 151 197 margin-bottom: 0px; 152 - color: #777; 153 198 } 154 199 155 200 .first { ··· 189 234 padding: 5px; 190 235 } 191 236 192 - .title-container,.info-container, .comment-info-container { 237 + .title-container, .comment-info-container { 193 238 flex: 1; 194 239 margin-top: 10px; 195 240 margin-bottom: 10px; 196 241 } 197 242 243 + .info-container { 244 + flex: 1; 245 + } 246 + 198 247 .title-container > a { 199 - color: black; 248 + color: var(--text-color); 200 249 text-decoration: none; 201 250 } 202 251 203 252 .title-container > a:visited { 204 - color: #999; 253 + color: var(--text-color-muted) 254 + } 255 + 256 + .header a { 257 + color: var(--text-color); 205 258 } 206 259 207 260 hr { ··· 211 264 blockquote { 212 265 margin: 0px; 213 266 padding-left: 10px; 214 - border-left: 4px solid green; 215 - color: green; 267 + border-left: 4px solid var(--blockquote-color); 268 + color: var(--blockquote-color); 216 269 } 217 270 218 271 pre, code { ··· 254 307 .gallery { 255 308 display: flex; 256 309 overflow-x: auto; 310 + position: relative; 257 311 scroll-snap-type: x mandatory; 258 312 padding: 5px; 259 313 }
+26 -1
src/utils.pug
··· 1 1 - var fmtnum = (n)=>n>=1000?(n/1000).toFixed(1)+'k':n; 2 2 - var fmttxt = (n,t)=>`${t}${n==1?'':'s'}` 3 - 3 + - var stripPrefix = (s, p) => s.startsWith(p) ? s.slice(p.length) : s; 4 + - 5 + function timeDifference(current, previous) { 6 + if (!current || !previous) { 7 + return ''; 8 + } 9 + var msPerMinute = 60 * 1000; 10 + var msPerHour = msPerMinute * 60; 11 + var msPerDay = msPerHour * 24; 12 + var msPerMonth = msPerDay * 30; 13 + var msPerYear = msPerDay * 365; 14 + var elapsed = current - previous; 15 + if (elapsed < msPerMinute) { 16 + return Math.round(elapsed/1000) + 's'; 17 + } else if (elapsed < msPerHour) { 18 + return Math.round(elapsed/msPerMinute) + 'min'; 19 + } else if (elapsed < msPerDay ) { 20 + return Math.round(elapsed/msPerHour ) + 'h'; 21 + } else if (elapsed < msPerMonth) { 22 + return Math.round(elapsed/msPerDay) + 'd'; 23 + } else if (elapsed < msPerYear) { 24 + return Math.round(elapsed/msPerMonth) + 'mo'; 25 + } else { 26 + return Math.round(elapsed/msPerYear ) + 'y'; 27 + } 28 + }
+15 -4
src/views/comments.pug
··· 21 21 if post.is_gallery && post.is_gallery == true 22 22 if post.gallery_data 23 23 if post.gallery_data.items 24 - each item in post.gallery_data.items 25 - - var url = `https://i.redd.it/${item.media_id}.jpg` 26 - img(src=url).post-media 27 - if (post.post_hint == "image" || post.post_hint == "link") && post.thumbnail && post.thumbnail != "self" && post.thumbnail != "default" 24 + div.gallery 25 + - var total = post.gallery_data.items.length 26 + - var idx = 0 27 + each item in post.gallery_data.items 28 + - var url = `https://i.redd.it/${item.media_id}.jpg` 29 + div.gallery-item 30 + a(href=`/media/${url}`) 31 + img(src=url loading="lazy") 32 + div.gallery-item-idx 33 + | #{`${++idx}/${total}`} 34 + else if post.post_hint == "image" && post.thumbnail && post.thumbnail != "self" && post.thumbnail != "default" 28 35 img(src=post.url).post-media 29 36 else if post.post_hint == 'hosted:video' 30 37 - var url = post.secure_media.reddit_video.dash_url 31 38 video(controls data-dashjs-player src=`${url}`).post-media 39 + else if post.post_hint == "link" && post.thumbnail && post.thumbnail != "self" && post.thumbnail != "default" 40 + a(href=`${post.url}`) 41 + | #{post.url} 32 42 33 43 if post.selftext_html 34 44 p.self-text !{post.selftext_html} 45 + 35 46 div.info-container 36 47 p 37 48 | #{fmtnum(post.ups)} ↑