commit 2e4a9a9
grunfink
·
2026-09-01 13:01:08 +0000 UTC
parent c38ad28
More text browser friendly stuff.
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 }
M
httpd.c
+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,