commit 2e4a9a9

grunfink  ·  2026-09-01 13:01:08 +0000 UTC
parent c38ad28
More text browser friendly stuff.
3 files changed,  +49, -29
M html.c
M snac.h
M html.c
+45, -26
  1@@ -2081,7 +2081,7 @@ xs_str *build_mentions(snac *user, const xs_dict *msg)
  2 
  3 
  4 xs_html *html_entry_controls(snac *user, const char *actor,
  5-                            const xs_dict *msg, const char *md5)
  6+                            const xs_dict *msg, const char *md5, int tb_friendly)
  7 {
  8     const char *id    = xs_dict_get(msg, "id");
  9     const char *group = xs_dict_get(msg, "audience");
 10@@ -2193,6 +2193,21 @@ xs_html *html_entry_controls(snac *user, const char *actor,
 11     xs_html_add(form,
 12         html_button("hide",   L("Hide"), L("Hide this post and its children")));
 13 
 14+    if (tb_friendly) {
 15+        /* generate a link a More... text pointing to the one-post-only timeline */
 16+        xs *url = xs_fmt("%s/admin/p/%s#%s_entry", user->actor, md5, md5);
 17+
 18+        xs_html_add(controls,
 19+            xs_html_tag("p", NULL),
 20+            xs_html_tag("a",
 21+                xs_html_attr("href", url),
 22+                xs_html_text(L("More..."))));
 23+
 24+        /* and DONE */
 25+
 26+        return controls;
 27+    }
 28+
 29     const char *prev_src = xs_dict_get(msg, "sourceContent");
 30 
 31     if (!xs_is_null(prev_src) && strcmp(actor, user->actor) == 0) { /** edit **/
 32@@ -2309,7 +2324,7 @@ static const xs_str* words_in_content(const xs_list *words, const xs_val *conten
 33 
 34 
 35 xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
 36-                   int level, const char *md5, int hide_children)
 37+                   int level, const char *md5, int hide_children, int tb_friendly)
 38 {
 39     const char *id    = xs_dict_get(msg, "id");
 40     const char *type  = xs_dict_get(msg, "type");
 41@@ -2872,7 +2887,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
 42                 xs_html_add(snac_content,
 43                     xs_html_tag("blockquote",
 44                         xs_html_attr("class", "snac-quoted-post"),
 45-                        html_entry(user, quoted_post, 1, level + 1, md5, 1)));
 46+                        html_entry(user, quoted_post, 1, level + 1, md5, 1, tb_friendly)));
 47             }
 48             else
 49             if (user)
 50@@ -3320,7 +3335,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
 51 
 52     if (!read_only && user) {
 53         xs_html_add(entry,
 54-            html_entry_controls(user, actor, msg, md5));
 55+            html_entry_controls(user, actor, msg, md5, tb_friendly));
 56     }
 57 
 58     /** children **/
 59@@ -3382,7 +3397,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
 60                        so that it appears unindented just before the parent
 61                        like a fucking Twitter-like thread */
 62                     xs_html_add(fch_container,
 63-                        html_entry(user, f_chd, read_only, level + 1, cmd5, hide_children));
 64+                        html_entry(user, f_chd, read_only, level + 1, cmd5, hide_children, tb_friendly));
 65 
 66                     cnt++;
 67                     f_cnt++;
 68@@ -3403,7 +3418,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only,
 69                 if (chd != NULL) {
 70                     if (xs_is_null(xs_dict_get(chd, "name"))) {
 71                         xs_html *che = html_entry(user, chd, read_only,
 72-                            level + 1, cmd5, hide_children);
 73+                            level + 1, cmd5, hide_children, tb_friendly);
 74 
 75                         if (che != NULL) {
 76                             if (left > 3) {
 77@@ -3470,7 +3485,7 @@ xs_html *html_footer(const snac *user)
 78 xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
 79                       int skip, int show, int show_more,
 80                       const char *title, const char *page,
 81-                      int utl, const char *error, int terse)
 82+                      int utl, const char *error, int terse, int tb_friendly)
 83 /* returns the HTML for the timeline */
 84 {
 85     const char *v;
 86@@ -3537,10 +3552,9 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
 87 
 88         xs *lists = list_maint(user, NULL, OP_LIST); /* get list of lists */
 89 
 90-        int ct = 0;
 91         const char *v;
 92 
 93-        while (xs_list_next(lists, &v, &ct)) {
 94+        xs_list_foreach(lists, v) {
 95             const char *lname = xs_list_get(v, 1);
 96             xs *url = xs_fmt("%s/list/%s", user->actor, xs_list_get(v, 0));
 97             xs *ttl = xs_fmt(L("Timeline for list '%s'"), lname);
 98@@ -3664,6 +3678,11 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
 99 
100     int show_unlisted = user ? xs_is_true(xs_dict_get(user->config, "show_unlisted")) : 0;
101 
102+    /* disable text-browser friendliness if it's just one post,
103+       to force the details/summary controls to appear */
104+    if (xs_list_len(list) == 1)
105+        tb_friendly = 0;
106+
107     xs_list_foreach(list, v) {
108         xs *msg = NULL;
109         int status;
110@@ -3730,7 +3749,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
111                 continue;
112         }
113 
114-        xs_html *entry = html_entry(user, msg, read_only, 0, v, (user && !hide_children) ? 0 : 1);
115+        xs_html *entry = html_entry(user, msg, read_only, 0, v, (user && !hide_children) ? 0 : 1, tb_friendly);
116 
117         if (entry != NULL)
118             xs_html_add(posts,
119@@ -4182,7 +4201,7 @@ xs_str *html_people_one(snac *user, const char *actor, const xs_list *list,
120               xs_list_in((reacts = object_get_emoji_reacts(id)), actor_md5) == -1)))
121             continue;
122 
123-        xs_html *entry = html_entry(user, msg, 0, 0, v, 1);
124+        xs_html *entry = html_entry(user, msg, 0, 0, v, 1, 0);
125 
126         if (entry != NULL)
127             xs_html_add(lists,
128@@ -4554,7 +4573,7 @@ xs_str *html_notifications(snac *user, int skip, int show)
129             xs *md5 = xs_md5_hex(id, strlen(id));
130             xs *ctxt = xs_fmt("%s/admin/p/%s#%s_entry", user->actor, md5, md5);
131 
132-            xs_html *h = html_entry(user, obj, 0, 0, md5, 1);
133+            xs_html *h = html_entry(user, obj, 0, 0, md5, 1, 0);
134 
135             if (h != NULL) {
136                 xs_html_add(entry,
137@@ -4822,7 +4841,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
138 
139         if (xs_type(xs_dict_get(snac.config, "private")) == XSTYPE_TRUE) {
140             /** empty public timeline for private users **/
141-            *body = html_timeline(&snac, NULL, 1, 0, 0, 0, NULL, "", 1, error, terse);
142+            *body = html_timeline(&snac, NULL, 1, 0, 0, 0, NULL, "", 1, error, terse, tb_friendly);
143             *b_size = strlen(*body);
144             status  = HTTP_STATUS_OK;
145         }
146@@ -4845,7 +4864,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
147             xs *pins = pinned_list(&snac);
148             pins = xs_list_cat(pins, list);
149 
150-            *body = html_timeline(&snac, pins, 1, skip, show, more, NULL, "", 1, error, terse);
151+            *body = html_timeline(&snac, pins, 1, skip, show, more, NULL, "", 1, error, terse, tb_friendly);
152 
153             *b_size = strlen(*body);
154             status  = HTTP_STATUS_OK;
155@@ -4973,7 +4992,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
156                     xs *title = xs_fmt(xs_list_len(tl) ?
157                         L("Search results for tag %s") : L("Nothing found for tag %s"), q);
158 
159-                    *body = html_timeline(&snac, tl, 0, skip, show, more, title, page, 0, error, terse);
160+                    *body = html_timeline(&snac, tl, 0, skip, show, more, title, page, 0, error, terse, tb_friendly);
161                     *b_size = strlen(*body);
162                     status  = HTTP_STATUS_OK;
163                 }
164@@ -4998,7 +5017,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
165                         title = xs_fmt(L("Nothing found for '%s'"), q);
166 
167                     *body   = html_timeline(&snac, tl, 0, skip, tl_len, to || tl_len == show,
168-                                            title, page, 0, error, terse);
169+                                            title, page, 0, error, terse, tb_friendly);
170                     *b_size = strlen(*body);
171                     status  = HTTP_STATUS_OK;
172                 }
173@@ -5025,7 +5044,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
174                     xs *list = timeline_list(&snac, "private", skip, show, &more);
175 
176                     *body = html_timeline(&snac, list, 0, skip, show,
177-                            more, NULL, "/admin", 1, error, terse);
178+                            more, NULL, "/admin", 1, error, terse, tb_friendly);
179 
180                     *b_size = strlen(*body);
181                     status  = HTTP_STATUS_OK;
182@@ -5052,7 +5071,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
183                 xs *list0 = xs_list_append(xs_list_new(), md5);
184                 xs *list  = timeline_top_level(&snac, list0);
185 
186-                *body   = html_timeline(&snac, list, 0, 0, 0, 0, NULL, "/admin", 1, error, terse);
187+                *body   = html_timeline(&snac, list, 0, 0, 0, 0, NULL, "/admin", 1, error, terse, tb_friendly);
188                 *b_size = strlen(*body);
189                 status  = HTTP_STATUS_OK;
190             }
191@@ -5124,7 +5143,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
192             xs *next = timeline_instance_list(skip + show, 1);
193 
194             *body = html_timeline(&snac, list, 0, skip, show,
195-                xs_list_len(next), L("Showing instance timeline"), "/instance", 0, error, terse);
196+                xs_list_len(next), L("Showing instance timeline"), "/instance", 0, error, terse, tb_friendly);
197             *b_size = strlen(*body);
198             status  = HTTP_STATUS_OK;
199         }
200@@ -5139,7 +5158,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
201             xs *list = pinned_list(&snac);
202 
203             *body = html_timeline(&snac, list, 0, skip, show,
204-                0, L("Pinned posts"), "", 0, error, terse);
205+                0, L("Pinned posts"), "", 0, error, terse, tb_friendly);
206             *b_size = strlen(*body);
207             status  = HTTP_STATUS_OK;
208         }
209@@ -5155,7 +5174,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
210             xs *list = timeline_list(&snac, "admire", skip, show, &more);
211 
212             *body = html_timeline(&snac, list, 0, skip, show,
213-                more, L("Liked, boosted or reacted posts"), "/admirations", 0, error, terse);
214+                more, L("Liked, boosted or reacted posts"), "/admirations", 0, error, terse, tb_friendly);
215             *b_size = strlen(*body);
216             status  = HTTP_STATUS_OK;
217         }
218@@ -5170,7 +5189,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
219             xs *list = bookmark_list(&snac);
220 
221             *body = html_timeline(&snac, list, 0, skip, show,
222-                0, L("Bookmarked posts"), "", 0, error, terse);
223+                0, L("Bookmarked posts"), "", 0, error, terse, tb_friendly);
224             *b_size = strlen(*body);
225             status  = HTTP_STATUS_OK;
226         }
227@@ -5185,7 +5204,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
228             xs *list = draft_list(&snac);
229 
230             *body = html_timeline(&snac, list, 0, skip, show,
231-                0, L("Post drafts"), "", 0, error, terse);
232+                0, L("Post drafts"), "", 0, error, terse, tb_friendly);
233             *b_size = strlen(*body);
234             status  = HTTP_STATUS_OK;
235         }
236@@ -5200,7 +5219,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
237             xs *list = scheduled_list(&snac);
238 
239             *body = html_timeline(&snac, list, 0, skip, show,
240-                0, L("Scheduled posts"), "", 0, error, terse);
241+                0, L("Scheduled posts"), "", 0, error, terse, tb_friendly);
242             *b_size = strlen(*body);
243             status  = HTTP_STATUS_OK;
244         }
245@@ -5226,7 +5245,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
246                 xs *title = xs_fmt(L("Showing timeline for list '%s'"), name);
247 
248                 *body = html_timeline(&snac, ttl, 0, skip, show,
249-                    xs_list_len(next), title, base, 1, error, terse);
250+                    xs_list_len(next), title, base, 1, error, terse, tb_friendly);
251                 *b_size = strlen(*body);
252                 status  = HTTP_STATUS_OK;
253             }
254@@ -5246,7 +5265,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
255 
256             list = xs_list_append(list, md5);
257 
258-            *body   = html_timeline(&snac, list, 1, 0, 0, 0, NULL, "", 1, error, terse);
259+            *body   = html_timeline(&snac, list, 1, 0, 0, 0, NULL, "", 1, error, terse, tb_friendly);
260             *b_size = strlen(*body);
261             status  = HTTP_STATUS_OK;
262         }
+2, -2
 1@@ -258,7 +258,7 @@ int server_get_handler(xs_dict *req, const char *q_path,
 2             else {
 3                 xs *page = xs_fmt("?t=%s", t);
 4                 xs *title = xs_fmt(L("Search results for tag #%s"), t);
 5-                *body = html_timeline(NULL, tl, 0, skip, show, more, title, page, 0, NULL, 0);
 6+                *body = html_timeline(NULL, tl, 0, skip, show, more, title, page, 0, NULL, 0, 0);
 7             }
 8         }
 9         else
10@@ -266,7 +266,7 @@ int server_get_handler(xs_dict *req, const char *q_path,
11             /** instance timeline **/
12             xs *tl = timeline_instance_list(0, 30);
13             *body = html_timeline(NULL, tl, 0, 0, 0, 0,
14-                L("Recent posts by users in this instance"), NULL, 0, NULL, 0);
15+                L("Recent posts by users in this instance"), NULL, 0, NULL, 0, 0);
16         }
17         else
18             *body = greeting_html();
M snac.h
+2, -1
 1@@ -438,7 +438,8 @@ xs_str *encode_html(const char *str);
 2 
 3 xs_str *html_timeline(snac *user, const xs_list *list, int read_only,
 4                       int skip, int show, int show_more,
 5-                      const char *title, const char *page, int utl, const char *error, int terse);
 6+                      const char *title, const char *page,
 7+                      int utl, const char *error, int terse, int tb_friendly);
 8 
 9 int html_get_handler(const xs_dict *req, const char *q_path,
10                      char **body, int *b_size, char **ctype,