aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/geddit.js2
-rw-r--r--src/mixins/header.pug4
-rw-r--r--src/mixins/subUtils.pug49
-rw-r--r--src/public/styles.css23
-rw-r--r--src/routes/index.js32
-rw-r--r--src/views/index.pug49
-rw-r--r--src/views/sub-search.pug36
7 files changed, 146 insertions, 49 deletions
diff --git a/src/geddit.js b/src/geddit.js
index aee7703..d81cedf 100644
--- a/src/geddit.js
+++ b/src/geddit.js
@@ -263,7 +263,7 @@ class Geddit {
263 263
264 const params = { 264 const params = {
265 limit: 25, 265 limit: 25,
266 include_over_18: true, 266 include_over_18: false,
267 }; 267 };
268 268
269 return await fetch( 269 return await fetch(
diff --git a/src/mixins/header.pug b/src/mixins/header.pug
index 4bec1f8..9cf1e1a 100644
--- a/src/mixins/header.pug
+++ b/src/mixins/header.pug
@@ -5,9 +5,9 @@ mixin header(user)
5 div.header-item 5 div.header-item
6 a(href=`/r/all`) all 6 a(href=`/r/all`) all
7 div.header-item 7 div.header-item
8 a(href=`/r/popular`) popular 8 a(href=`/search`) search
9 div.header-item 9 div.header-item
10 a(href=`/subs`) subscriptions 10 a(href=`/subs`) subs
11 if user 11 if user
12 div.header-item 12 div.header-item
13 a(href='/dashboard') #{user.username} 13 a(href='/dashboard') #{user.username}
diff --git a/src/mixins/subUtils.pug b/src/mixins/subUtils.pug
new file mode 100644
index 0000000..7f40bf4
--- /dev/null
+++ b/src/mixins/subUtils.pug
@@ -0,0 +1,49 @@
1-
2script(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
diff --git a/src/public/styles.css b/src/public/styles.css
index ba2940d..3b3e80d 100644
--- a/src/public/styles.css
+++ b/src/public/styles.css
@@ -542,3 +542,26 @@ form input[type="submit"]:hover {
542.invite-link { 542.invite-link {
543 font-family: monospace; 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}
diff --git a/src/routes/index.js b/src/routes/index.js
index e585d3d..c56b73e 100644
--- a/src/routes/index.js
+++ b/src/routes/index.js
@@ -103,6 +103,38 @@ router.get("/subs", authenticateToken, async (req, res) => {
103 res.render("subs", { subs, user: req.user }); 103 res.render("subs", { subs, user: req.user });
104}); 104});
105 105
106// GET /search-subreddits
107router.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// GET /dashboard 138// GET /dashboard
107router.get("/dashboard", authenticateToken, async (req, res) => { 139router.get("/dashboard", authenticateToken, async (req, res) => {
108 let invites = null; 140 let invites = null;
diff --git a/src/views/index.pug b/src/views/index.pug
index 140cd57..636f9ac 100644
--- a/src/views/index.pug
+++ b/src/views/index.pug
@@ -5,50 +5,7 @@ include ../utils
5doctype html 5doctype html
6html 6html
7 +head("home") 7 +head("home")
8 script(defer). 8 include ../mixins/subUtils
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 }
52 9
53 body 10 body
54 main#content 11 main#content
@@ -64,9 +21,9 @@ html
64 if !isMulti 21 if !isMulti
65 div#button-container 22 div#button-container
66 if isSubbed 23 if isSubbed
67 button(onclick=`unsubscribe('${subreddit}')`)#thinger unsubscribe 24 button(onclick=`toggleSub('${subreddit}')` id=`thinger_${subreddit}`) unsubscribe
68 else 25 else
69 button(onclick=`subscribe('${subreddit}')`)#thinger subscribe 26 button(onclick=`toggleSub('${subreddit}')` id=`thinger_${subreddit}`) subscribe
70 if about && !isMulti 27 if about && !isMulti
71 p #{about.public_description} 28 p #{about.public_description}
72 else 29 else
diff --git a/src/views/sub-search.pug b/src/views/sub-search.pug
new file mode 100644
index 0000000..4fa707e
--- /dev/null
+++ b/src/views/sub-search.pug
@@ -0,0 +1,36 @@
1include ../mixins/header
2include ../mixins/head
3
4doctype html
5html
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}