From 6213212d133037c150988bccf622b90800be220b Mon Sep 17 00:00:00 2001 From: citrons Date: Sat, 14 Jun 2025 01:03:31 -0500 Subject: read statuses on threads and forums --- apioforum/db.py | 9 +++++++++ apioforum/forum.py | 22 ++++++++++++++++++++++ apioforum/read.py | 12 ++++++++++++ apioforum/static/style.css | 12 ++++++++++++ apioforum/templates/view_forum.html | 4 ++-- apioforum/thread.py | 7 +++++++ 6 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 apioforum/read.py diff --git a/apioforum/db.py b/apioforum/db.py index 24146e2..2d06a13 100644 --- a/apioforum/db.py +++ b/apioforum/db.py @@ -233,6 +233,15 @@ CREATE VIEW public_posts AS JOIN forum_thread_of_post h ON p.id=h.p_id JOIN public_forums b ON b.id=h.f_id; """, +""" +CREATE TABLE read ( + user NOT NULL REFERENCES users(username), + forum REFERENCES forums(id), + thread REFERENCES threads(id), + time TIMESTAMP NOT NULL +); +ALTER TABLE forums ADD COLUMN updated TIMESTAMP; +""", ] diff --git a/apioforum/forum.py b/apioforum/forum.py index 988c9a5..289cc40 100644 --- a/apioforum/forum.py +++ b/apioforum/forum.py @@ -11,6 +11,7 @@ from .db import get_db from .mdrender import render from .roles import get_forum_roles,has_permission,is_bureaucrat,get_user_role, permissions as role_permissions from .permissions import is_admin +from . import read from sqlite3 import OperationalError import datetime import math @@ -89,6 +90,18 @@ def requires_bureaucrat(f): return f(forum, *args, **kwargs) return wrapper +def set_updated(forum_id): + db = get_db() + ancestors = db.execute(""" + WITH RECURSIVE fs AS + (SELECT * FROM forums WHERE id = ? + UNION ALL + SELECT forums.* FROM forums, fs WHERE fs.parent=forums.id) + SELECT * FROM fs; + """,(forum_id,)).fetchall() + for f in ancestors: + db.execute("UPDATE forums SET updated = current_timestamp WHERE id = ?;", (f['id'],)) + db.commit() @forum_route("",pagination=True) @requires_permission("p_view_forum", login_required=False) @@ -218,6 +231,13 @@ def view_forum(forum,page=1): WHERE role = 'bureaucrat' AND forum = ? """,(forum['id'],)).fetchall() bureaucrats = [b[0] for b in bureaucrats] + + + if g.user != None: + db.execute("DELETE FROM read WHERE user = ? AND forum = ?;", (g.user, forum['id'])) + db.execute("INSERT INTO read (user,forum,time) VALUES (?,?,current_timestamp);", (g.user, forum['id'])) + db.commit() + return render_template("view_forum.html", forum=forum, @@ -231,6 +251,7 @@ def view_forum(forum,page=1): page=page, current_sortby=sortby, tagfilter_tag=tagfilter_tag, + is_read=read.is_read, ) @forum_route("create_thread",methods=("GET","POST")) @@ -266,6 +287,7 @@ def create_thread(forum): (thread_id,g.user,content) ) db.commit() + set_updated(forum['id']) from . import webhooks thread = db.execute("select * from threads where id = ?",(thread_id,)).fetchone() diff --git a/apioforum/read.py b/apioforum/read.py new file mode 100644 index 0000000..289b40e --- /dev/null +++ b/apioforum/read.py @@ -0,0 +1,12 @@ +from flask import g +from .db import get_db + +def is_read(type, id): + if g.user == None: + return False + db = get_db() + read = db.execute("SELECT * FROM read WHERE user = ? AND " + type + " = ?;", (g.user, id)).fetchone() + if read == None: + return False + updated = db.execute("SELECT * FROM " + type + "s WHERE id = ?;", (id,)).fetchone()['updated'] + return updated == None or read['time'] >= updated diff --git a/apioforum/static/style.css b/apioforum/static/style.css index 3d6ec22..c77ec69 100644 --- a/apioforum/static/style.css +++ b/apioforum/static/style.css @@ -7,6 +7,7 @@ body { font-family: sans-serif; word-wrap: break-word; } --gray: darkgray; --light-colour: white; --username-colour: hsl(0, 0%, 25%); + --read-colour: hsl(0, 0%, 30%); --red: red; --yellow: yellow; --blue: blue; @@ -211,6 +212,16 @@ nav#pages .pageno { align-self: center; } flex-grow: 1; } +.listing-title a { + text-decoration: none; + color: var(--read-colour); +} + +.unread .listing-title a { + text-decoration: underline; + color: var(--dark-colour); +} + .thread-listing-tags { display: flex; align-items: center; @@ -359,6 +370,7 @@ textarea { --gray: lightgray; --light-colour: black; --username-colour: hsl(0, 0%, 80%); + --read-colour: hsl(0, 0%, 70%); --yellow: rgb(212, 173, 0); --blue: rgb(78, 89, 255); --visited: rgb(173, 110, 209); diff --git a/apioforum/templates/view_forum.html b/apioforum/templates/view_forum.html index b6b336f..d37a018 100644 --- a/apioforum/templates/view_forum.html +++ b/apioforum/templates/view_forum.html @@ -49,7 +49,7 @@
{% for subforum in subforums %}