Bubble [main]

Dashboard: Subgrouping of notifications based on posts

=> 82955491aed1a4a121f6e91e7444d4f1c59117d7

diff --git a/model.py b/model.py
index 88a03e4..0b3881f 100644
--- a/model.py
+++ b/model.py
@@ -100,7 +100,8 @@ class Notification:
 
     def __init__(self, id, type, dst, src, post, subspace, comment, is_sent, ts,
                  src_name=None, post_title=None, post_issueid=None, post_summary=None,
-                 post_subname=None, post_subowner=None, subname=None, reaction=None):
+                 post_subname=None, post_subowner=None, subname=None, reaction=None,
+                 post_subid=None):
         self.id = id
         self.type = type
         self.dst = dst
@@ -114,6 +115,7 @@ class Notification:
         self.post_title = post_title
         self.post_issueid = post_issueid
         self.post_summary = post_summary
+        self.post_subid = post_subid
         self.post_subname = post_subname
         self.post_subowner = post_subowner
         self.subname = subname
@@ -128,6 +130,11 @@ class Notification:
     def age(self):
         return ago_text(self.ts)
 
+    def title_text(self):
+        return shorten_text(self.post_title, 50) if self.post_title \
+            else shorten_text(strip_links(clean_title(self.post_summary)), 50) if self.post_summary \
+            else None
+
     def entry(self, show_age=True, with_time=False, with_title=True, tz=None) -> tuple:
         """Returns (link, label) to use in the notification list."""
 
@@ -195,9 +202,7 @@ class Notification:
             event = f"reported the {kind}"
 
         if with_title:
-            vis_title = shorten_text(self.post_title, 50) if self.post_title \
-                else shorten_text(strip_links(clean_title(self.post_summary)), 50) if self.post_summary \
-                else None
+            vis_title = self.title_text()
             if vis_title:
                 if self.type == Notification.MENTION:
                     event += ' in'
@@ -383,8 +388,6 @@ class Post:
             return self.title
         elif self.parent:
             text = f'Comment on {"u" if self.sub_owner else "s"}/{self.sub_name}/{self.parent}'
-            #if self.summary:
-            #    text += f': "{shorten_text(self.summary(30))}"'
             return text
         else:
             return '(untitled issue)' if self.issueid else '(untitled post)'
@@ -2387,7 +2390,7 @@ class Database:
                 n.id, n.type, n.dst, n.src, n.post, n.subspace, n.comment, n.is_sent, UNIX_TIMESTAMP(n.ts),
                 u.name,
                 p.title, p.issueid, p.summary,
-                s.name, s.owner,
+                s.id, s.name, s.owner,
                 s2.name,
                 r.reaction
             FROM notifs n
@@ -2405,10 +2408,11 @@ class Database:
         """, tuple(values))
         notifs = []
         for (id, type, dst, src, post, subspace, comment, is_sent, ts, src_name, post_title, post_issueid,
-             post_summary, post_subname, post_subowner, subname, reaction) in cur:
+             post_summary, post_subid, post_subname, post_subowner, subname, reaction) in cur:
             notifs.append(Notification(id, type, dst, src, post, subspace, comment, is_sent, ts,
                                        src_name, post_title, post_issueid, post_summary,
-                                       post_subname, post_subowner, subname, reaction))
+                                       post_subname, post_subowner, subname, reaction,
+                                       post_subid=post_subid))
 
         notifs = self.resolve_notifications(notifs)
         notifs.sort(key=lambda n: n.ts, reverse=sort_desc)
diff --git a/user.py b/user.py
index 3213ba5..6665705 100644
--- a/user.py
+++ b/user.py
@@ -244,6 +244,38 @@ def user_actions(session):
         return 42, 'Invalid notification'
 
 
+class Subgrouping:
+    """Sorts notifications by related post ID and descending time."""
+
+    def __init__(self, user, notifs):
+        self.user = user
+        self.by_post = {}
+        ordered = sorted(notifs, key=lambda n: -n.ts)
+        for notif in ordered:
+            if not notif.post in self.by_post:
+                self.by_post[notif.post] = []
+            self.by_post[notif.post].append(notif)
+
+    def render(self):
+        src = []
+        top_head = False
+        for post_id, notifs in self.by_post.items():
+            if top_head:
+                # Separate subgroups.
+                src.append('')
+            top_head = post_id and len(notifs) > 1
+            if top_head:
+                n = notifs[0]
+                if n.post_subname and n.post_subowner != self.user.id:
+                    sub_text = f" in {'u/' if n.post_subowner else 's/'}{n.post_subname}"
+                else:
+                    sub_text = ''
+                src.append(f'"{n.title_text()}"{sub_text}:')
+            for notif in notifs:
+                src.append('=> %s %s' % notif.entry(with_title=not top_head))
+        return '\n'.join(src) + '\n'
+
+
 def make_dashboard_page(session):
     if not session.user:
         return 60, "Login required"
@@ -263,6 +295,7 @@ def make_dashboard_page(session):
     if n:
         # Group in two: @user and Followed.
         yours = []
+        moderated = []
         followed = []
         for notif in notifs:
             if not notif.type in Notification.PRIORITY or \
@@ -270,19 +303,22 @@ def make_dashboard_page(session):
                 Notification.PRIORITY[notif.type] >= 10:
                 yours.append(notif)
             else:
-                followed.append(notif)
+                if notif.post_subid in user.moderated_subspace_ids:
+                    moderated.append(notif)
+                else:
+                    followed.append(notif)
 
         if yours:
             page += f'\n### @{session.user.name}\n'
-            for notif in sorted(yours, key=lambda n: -n.ts):
-                link, label = notif.entry()
-                page += f'=> {link} {label}\n'
+            page += Subgrouping(user, yours).render()
+
+        if moderated:
+            page += f'\n### Moderated\n'
+            page += Subgrouping(user, moderated).render()
 
         if followed:
             page += f'\n### Followed\n'
-            for notif in sorted(followed, key=lambda n: -n.ts):
-                link, label = notif.entry()
-                page += f'=> {link} {label}\n'
+            page += Subgrouping(user, followed).render()
 
         page += '\n=> /notif/clear 🧹 Clear all\n'
     page += '=> /notif/feed Notifications feed\nSubscribe to this Gemini feed to view your unread notifications in a feed reader.\n'
Proxy Information
Original URL
gemini://git.skyjake.fi/bubble/main/cdiff/82955491aed1a4a121f6e91e7444d4f1c59117d7
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
29.248101 milliseconds
Gemini-to-HTML Time
0.424104 milliseconds

This content has been proxied by September (3851b).