selfhostable, read-only reddit client
16
fork

Configure Feed

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

add search page

Akshay d9c9da7c a0ed8623

+146 -49
+1 -1
src/geddit.js
··· 263 263 264 264 const params = { 265 265 limit: 25, 266 - include_over_18: true, 266 + include_over_18: false, 267 267 }; 268 268 269 269 return await fetch(
+2 -2
src/mixins/header.pug
··· 5 5 div.header-item 6 6 a(href=`/r/all`) all 7 7 div.header-item 8 - a(href=`/r/popular`) popular 8 + a(href=`/search`) search 9 9 div.header-item 10 - a(href=`/subs`) subscriptions 10 + a(href=`/subs`) subs 11 11 if user 12 12 div.header-item 13 13 a(href='/dashboard') #{user.username}
+49
src/mixins/subUtils.pug
··· 1 + - 2 + script(defer). 3 + async function toggleSub(sub) { 4 + let thinger = document.getElementById(`thinger_${sub}`); 5 + if (thinger.innerText === 'unsubscribe') { 6 + await doThing(sub, 'unsubscribe'); 7 + } else { 8 + await doThing(sub, 'subscribe'); 9 + } 10 + } 11 + 12 + function getCookie(name) { 13 + const value = `; ${document.cookie}`; 14 + const parts = value.split(`; ${name}=`); 15 + if (parts.length === 2) return parts.pop().split(";").shift(); 16 + } 17 + 18 + async function doThing(sub, thing) { 19 + const jwtToken = getCookie("auth_token"); 20 + const response = await fetch(`/${thing}`, { 21 + method: 'POST', 22 + headers: { 23 + 'Authorization': `Bearer ${jwtToken}`, 24 + 'Content-Type': 'application/json', 25 + }, 26 + body: JSON.stringify({ subreddit: sub }), 27 + }); 28 + 29 + let thinger = document.getElementById(`thinger_${sub}`); 30 + if (thing === 'subscribe') { 31 + thinger.innerText = 'unsubscribe'; 32 + } else { 33 + thinger.innerText = 'subscribe'; 34 + } 35 + 36 + if (!response.ok) { 37 + console.error(response); 38 + console.error(`Failed to do ${thing}`); 39 + } 40 + } 41 + 42 + function toggleDetails(details_id) { 43 + var detailsElement = document.getElementById(details_id); 44 + if (detailsElement) { 45 + detailsElement.open = !detailsElement.open; 46 + } 47 + } 48 + 49 +
+23
src/public/styles.css
··· 542 542 .invite-link { 543 543 font-family: monospace; 544 544 } 545 + 546 + .search-bar { 547 + display: flex; 548 + flex-direction: row; 549 + justify-content: space-evenly; 550 + width: 100%; 551 + gap: 10px; 552 + } 553 + 554 + .search-input { 555 + flex: 9; 556 + } 557 + 558 + .search-button { 559 + flex: 1; 560 + padding: 10px; 561 + } 562 + 563 + .search-results { 564 + display: flex; 565 + flex-direction: column; 566 + gap: 20px; 567 + }
+32
src/routes/index.js
··· 103 103 res.render("subs", { subs, user: req.user }); 104 104 }); 105 105 106 + // GET /search-subreddits 107 + router.get("/search", authenticateToken, async (req, res) => { 108 + if (!req.query || !req.query.q) { 109 + res.render("sub-search", {}); 110 + } else { 111 + const { q, options } = req.query.q.split(/\s+/).reduce( 112 + (acc, word) => { 113 + if (word.startsWith("+")) { 114 + acc.options.push(word.slice(1)); 115 + } else { 116 + acc.q += `${word} `; 117 + } 118 + return acc; 119 + }, 120 + { options: [], q: "" }, 121 + ); 122 + 123 + const { items, after } = await G.searchSubreddits(q, { 124 + include_over_18: options.includes("nsfw"), 125 + }); 126 + const subs = db 127 + .query("SELECT subreddit FROM subscriptions WHERE user_id = $id") 128 + .all({ id: req.user.id }) 129 + .map((res) => res.subreddit); 130 + const message = 131 + items.length === 0 132 + ? "no results found" 133 + : `showing ${items.length} results`; 134 + res.render("sub-search", { items, subs, after, message }); 135 + } 136 + }); 137 + 106 138 // GET /dashboard 107 139 router.get("/dashboard", authenticateToken, async (req, res) => { 108 140 let invites = null;
+3 -46
src/views/index.pug
··· 5 5 doctype html 6 6 html 7 7 +head("home") 8 - script(defer). 9 - async function subscribe(sub) { 10 - await doThing(sub, 'subscribe'); 11 - } 12 - 13 - async function unsubscribe(sub) { 14 - await doThing(sub, 'unsubscribe'); 15 - } 16 - 17 - function getCookie(name) { 18 - const value = `; ${document.cookie}`; 19 - const parts = value.split(`; ${name}=`); 20 - if (parts.length === 2) return parts.pop().split(";").shift(); 21 - } 22 - 23 - async function doThing(sub, thing) { 24 - const jwtToken = getCookie("auth_token"); 25 - const response = await fetch(`/${thing}`, { 26 - method: 'POST', 27 - headers: { 28 - 'Authorization': `Bearer ${jwtToken}`, 29 - 'Content-Type': 'application/json', 30 - }, 31 - body: JSON.stringify({ subreddit: sub }), 32 - }); 33 - 34 - let thinger = document.getElementById('thinger'); 35 - if (thing == 'subscribe') { 36 - thinger.innerText = 'unsubscribe'; 37 - } else { 38 - thinger.innerText = 'subscribe'; 39 - } 40 - 41 - if (!response.ok) { 42 - console.error(`Failed to do ${thing}`); 43 - } 44 - } 45 - 46 - function toggleDetails(details_id) { 47 - var detailsElement = document.getElementById(details_id); 48 - if (detailsElement) { 49 - detailsElement.open = !detailsElement.open; 50 - } 51 - } 8 + include ../mixins/subUtils 52 9 53 10 body 54 11 main#content ··· 64 21 if !isMulti 65 22 div#button-container 66 23 if isSubbed 67 - button(onclick=`unsubscribe('${subreddit}')`)#thinger unsubscribe 24 + button(onclick=`toggleSub('${subreddit}')` id=`thinger_${subreddit}`) unsubscribe 68 25 else 69 - button(onclick=`subscribe('${subreddit}')`)#thinger subscribe 26 + button(onclick=`toggleSub('${subreddit}')` id=`thinger_${subreddit}`) subscribe 70 27 if about && !isMulti 71 28 p #{about.public_description} 72 29 else
+36
src/views/sub-search.pug
··· 1 + include ../mixins/header 2 + include ../mixins/head 3 + 4 + doctype html 5 + html 6 + +head("search subreddits") 7 + include ../mixins/subUtils 8 + body 9 + main#content 10 + +header(user) 11 + div.hero 12 + h1 search subreddits 13 + form(action="/search" method="get").search-bar 14 + input(type="text" name="q" placeholder="search subreddits (add +nsfw to include over-18 results)" required).search-input 15 + button(type="submit").search-button go 16 + if message 17 + div.search-message 18 + | #{message} 19 + if items 20 + div.search-results 21 + each i in items 22 + div.search-result 23 + - var subreddit = i.data.display_name 24 + - var isSubbed = subs.includes(subreddit) 25 + div.sub-title 26 + h3 27 + a(href=`/r/${subreddit}`) 28 + | r/#{subreddit} 29 + div#button-container 30 + if isSubbed 31 + button(onclick=`toggleSub('${subreddit}')` id=`thinger_${subreddit}`) unsubscribe 32 + else 33 + button(onclick=`toggleSub('${subreddit}')` id=`thinger_${subreddit}`) subscribe 34 + 35 + if i.data.public_description 36 + p #{i.data.public_description}