commit 93f82fa

Alexandre Oliva  ·  2025-12-30 12:12:46 +0000 UTC
parent b64bebd
Add posts by actor to people page

Select posts by the actor from the given timeline range.

Since posts by the actor may be very sparse in the timeline, add a
"More (x 10)" button to bump the show count, that controls how many
timeline posts we'll filter *from*.

We could conceivably keep searching the timeline until we find as many
posts as requested or reach the end, but that could take a very long
time.  Just filtering the given ranges is much simpler, and probably
sufficiently intuitive despite the potential initial surprise.
1 files changed,  +78, -7
M html.c
M html.c
+78, -7
  1@@ -3856,25 +3856,89 @@ xs_str *html_people(snac *user)
  2     return xs_html_render_s(html, "<!DOCTYPE html>\n");
  3 }
  4 
  5-xs_str *html_people_one(snac *user, const char *actor)
  6+/* Filter list to display only posts by actor.  We'll probably show
  7+   fewer than show posts.  Should we try harder to find some?  */
  8+xs_str *html_people_one(snac *user, const char *actor, const xs_list *list,
  9+                        int skip, int show, int show_more, const char *page)
 10 {
 11     const char *proxy = NULL;
 12+    xs_list *p = (xs_list *)list;
 13+    const char *v;
 14 
 15     if (xs_is_true(xs_dict_get(srv_config, "proxy_media")))
 16         proxy = user->actor;
 17 
 18+    xs_html *body = html_user_body(user, 0);
 19+
 20     xs_html *lists = xs_html_tag("div",
 21         xs_html_attr("class", "snac-posts"));
 22 
 23     xs *foll = xs_list_append(xs_list_new(), actor);
 24 
 25     xs_html_add(lists,
 26-        html_people_list(user, foll, L("People - single"), "p", proxy));
 27+        html_people_list(user, foll, L("Contact's posts"), "p", proxy));
 28+
 29+    xs_html_add(body, lists);
 30+
 31+    while (xs_list_iter(&p, &v)) {
 32+        xs *msg = NULL;
 33+        int status;
 34+
 35+        status = timeline_get_by_md5(user, v, &msg);
 36+
 37+        if (!valid_status(status))
 38+            continue;
 39+
 40+        const char *by = xs_dict_get(msg, "attributedTo");
 41+        if (!by || strcmp(actor, by) != 0)
 42+            continue;
 43+
 44+        xs_html *entry = html_entry(user, msg, 0, 0, v, 1);
 45+
 46+        if (entry != NULL)
 47+            xs_html_add(lists,
 48+                entry);
 49+    }
 50+
 51+    if (show_more) {
 52+        xs *m  = NULL;
 53+        xs *m10  = NULL;
 54+        xs *ss = xs_fmt("skip=%d&show=%d", skip + show, show);
 55+
 56+        xs *url = xs_dup(user == NULL ? srv_baseurl : user->actor);
 57+
 58+        if (page != NULL)
 59+            url = xs_str_cat(url, page);
 60+
 61+        if (xs_str_in(url, "?") != -1)
 62+            m = xs_fmt("%s&%s", url, ss);
 63+        else
 64+            m = xs_fmt("%s?%s", url, ss);
 65+            m10 = xs_fmt("%s0", m);
 66+
 67+        xs_html *more_links = xs_html_tag("p",
 68+            xs_html_tag("a",
 69+                xs_html_attr("href", url),
 70+                xs_html_attr("name", "snac-more"),
 71+                xs_html_text(L("Back to top"))),
 72+            xs_html_text(" - "),
 73+            xs_html_tag("a",
 74+                xs_html_attr("href", m),
 75+                xs_html_attr("name", "snac-more"),
 76+                xs_html_text(L("More..."))),
 77+            xs_html_text(" - "),
 78+            xs_html_tag("a",
 79+                xs_html_attr("href", m10),
 80+                xs_html_attr("name", "snac-more"),
 81+                xs_html_text(L("More (x 10)..."))));
 82+
 83+        xs_html_add(body,
 84+            more_links);
 85+    }
 86 
 87     xs_html *html = xs_html_tag("html",
 88         html_user_head(user, NULL, NULL),
 89-        xs_html_add(html_user_body(user, 0),
 90-            lists,
 91+        xs_html_add(body,
 92             html_footer(user)));
 93 
 94     return xs_html_render_s(html, "<!DOCTYPE html>\n");
 95@@ -4578,7 +4642,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
 96         }
 97     }
 98     else
 99-    if (xs_startswith(p_path, "people/")) { /** the list of people **/
100+    if (xs_startswith(p_path, "people/")) { /** a single actor **/
101         if (!login(&snac, req)) {
102             *body  = xs_dup(uid);
103             status = HTTP_STATUS_UNAUTHORIZED;
104@@ -4587,11 +4651,18 @@ int html_get_handler(const xs_dict *req, const char *q_path,
105             xs *actor_dict = NULL;
106             const char *actor_id = NULL;
107             xs *actor = NULL;
108+            xs_list *page_lst = xs_split_n(p_path, "?", 2);
109+            xs *page = xs_str_cat(xs_str_new("/"), xs_list_get(page_lst, 0));
110+            xs_list *l = xs_split_n(page, "/", 3);
111+            const char *actor_md5 = xs_list_get(l, 2);
112 
113-            if (valid_status(object_get_by_md5(p_path + strlen("people/"), &actor_dict)) &&
114+            if (valid_status(object_get_by_md5(actor_md5, &actor_dict)) &&
115                (actor_id = xs_dict_get(actor_dict, "id")) != NULL &&
116                valid_status(actor_get(actor_id, &actor))) {
117-                *body   = html_people_one(&snac, actor_id);
118+                int more = 0;
119+                xs *list = timeline_list(&snac, "private", skip, show, &more);
120+
121+                *body   = html_people_one(&snac, actor_id, list, skip, show, more, page);
122                 *b_size = strlen(*body);
123                 status  = HTTP_STATUS_OK;
124             }