diff options
| author | 2025-09-14 00:30:00 +0200 | |
|---|---|---|
| committer | 2025-09-20 17:16:54 +0200 | |
| commit | dcf5acaf538924aab532ea95bb311e4b80538856 (patch) | |
| tree | 47ae5f679eab641c1a0fe28edbe834fce242c68e /html.c | |
| parent | Don't use # anchors in the reply paging, as Misskey seems to dislike them. (diff) | |
| download | penes-snac2-dcf5acaf538924aab532ea95bb311e4b80538856.tar.gz penes-snac2-dcf5acaf538924aab532ea95bb311e4b80538856.tar.xz penes-snac2-dcf5acaf538924aab532ea95bb311e4b80538856.zip | |
implementing visibility scopes
Diffstat (limited to 'html.c')
| -rw-r--r-- | html.c | 144 |
1 files changed, 112 insertions, 32 deletions
| @@ -165,7 +165,7 @@ xs_str *format_text_with_emoji(snac *user, const char *text, int ems, const char | |||
| 165 | 165 | ||
| 166 | 166 | ||
| 167 | xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, | 167 | xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, |
| 168 | const char *udate, const char *url, int priv, | 168 | const char *udate, const char *url, int scope, |
| 169 | int in_people, const char *proxy, const char *lang, | 169 | int in_people, const char *proxy, const char *lang, |
| 170 | const char *md5) | 170 | const char *md5) |
| 171 | { | 171 | { |
| @@ -249,12 +249,35 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, | |||
| 249 | xs_html_raw("🤝"))); | 249 | xs_html_raw("🤝"))); |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | if (priv) { | 252 | if (scope != -1) { |
| 253 | xs_html_add(actor_icon, | 253 | if (scope == SCOPE_FOLLOWERS) { |
| 254 | xs_html_text(" "), | 254 | xs_html_add(actor_icon, |
| 255 | xs_html_tag("span", | 255 | xs_html_text(" "), |
| 256 | xs_html_attr("title", "private"), | 256 | xs_html_tag("span", |
| 257 | xs_html_raw("🔒"))); | 257 | xs_html_attr("title", "followers"), |
| 258 | xs_html_raw("🔒"))); // emoji of a lock | ||
| 259 | } | ||
| 260 | else if (scope == SCOPE_PUBLIC) { | ||
| 261 | xs_html_add(actor_icon, | ||
| 262 | xs_html_text(" "), | ||
| 263 | xs_html_tag("span", | ||
| 264 | xs_html_attr("title", "public"), | ||
| 265 | xs_html_raw("🌐"))); // emoji of a globe | ||
| 266 | } | ||
| 267 | else if (scope == SCOPE_UNLISTED) { | ||
| 268 | xs_html_add(actor_icon, | ||
| 269 | xs_html_text(" "), | ||
| 270 | xs_html_tag("span", | ||
| 271 | xs_html_attr("title", "unlisted"), | ||
| 272 | xs_html_raw("🔓"))); // emoji of an unlocked lock | ||
| 273 | } | ||
| 274 | else if (scope == SCOPE_MENTIONED) { | ||
| 275 | xs_html_add(actor_icon, | ||
| 276 | xs_html_text(" "), | ||
| 277 | xs_html_tag("span", | ||
| 278 | xs_html_attr("title", "mentioned"), | ||
| 279 | xs_html_raw("✉️"))); // emoji of a mail | ||
| 280 | } | ||
| 258 | } | 281 | } |
| 259 | 282 | ||
| 260 | if (xs_is_null(date)) { | 283 | if (xs_is_null(date)) { |
| @@ -342,18 +365,17 @@ xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, | |||
| 342 | const char *date = NULL; | 365 | const char *date = NULL; |
| 343 | const char *udate = NULL; | 366 | const char *udate = NULL; |
| 344 | const char *url = NULL; | 367 | const char *url = NULL; |
| 345 | int priv = 0; | ||
| 346 | const char *type = xs_dict_get(msg, "type"); | 368 | const char *type = xs_dict_get(msg, "type"); |
| 369 | const int scope = get_msg_visibility(msg); | ||
| 347 | 370 | ||
| 348 | if (xs_match(type, POSTLIKE_OBJECT_TYPE)) | 371 | if (xs_match(type, POSTLIKE_OBJECT_TYPE)) |
| 349 | url = xs_dict_get(msg, "id"); | 372 | url = xs_dict_get(msg, "id"); |
| 350 | 373 | ||
| 351 | priv = !is_msg_public(msg); | ||
| 352 | 374 | ||
| 353 | date = xs_dict_get(msg, "published"); | 375 | date = xs_dict_get(msg, "published"); |
| 354 | udate = xs_dict_get(msg, "updated"); | 376 | udate = xs_dict_get(msg, "updated"); |
| 355 | 377 | ||
| 356 | actor_icon = html_actor_icon(user, actor, date, udate, url, priv, 0, proxy, lang, md5); | 378 | actor_icon = html_actor_icon(user, actor, date, udate, url, scope, 0, proxy, lang, md5); |
| 357 | } | 379 | } |
| 358 | 380 | ||
| 359 | return actor_icon; | 381 | return actor_icon; |
| @@ -365,7 +387,7 @@ xs_html *html_note(snac *user, const char *summary, | |||
| 365 | const char *ta_plh, const char *ta_content, | 387 | const char *ta_plh, const char *ta_content, |
| 366 | const char *edit_id, const char *actor_id, | 388 | const char *edit_id, const char *actor_id, |
| 367 | const xs_val *cw_yn, const char *cw_text, | 389 | const xs_val *cw_yn, const char *cw_text, |
| 368 | const xs_val *mnt_only, const char *redir, | 390 | const int scope, const char *redir, |
| 369 | const char *in_reply_to, int poll, | 391 | const char *in_reply_to, int poll, |
| 370 | const xs_list *att_files, const xs_list *att_alt_texts, | 392 | const xs_list *att_files, const xs_list *att_alt_texts, |
| 371 | int is_draft, const char *published, | 393 | int is_draft, const char *published, |
| @@ -417,14 +439,44 @@ xs_html *html_note(snac *user, const char *summary, | |||
| 417 | xs_html_attr("name", "to"), | 439 | xs_html_attr("name", "to"), |
| 418 | xs_html_attr("value", actor_id))); | 440 | xs_html_attr("value", actor_id))); |
| 419 | else { | 441 | else { |
| 420 | /* no actor_id; ask for mentioned_only */ | ||
| 421 | xs_html_add(form, | 442 | xs_html_add(form, |
| 422 | xs_html_tag("p", NULL), | 443 | xs_html_tag("p", |
| 423 | xs_html_text(L("Only for mentioned people: ")), | 444 | xs_html_text(L("Visibility: ")), |
| 424 | xs_html_sctag("input", | 445 | xs_html_tag("label", |
| 425 | xs_html_attr("type", "checkbox"), | 446 | xs_html_sctag("input", |
| 426 | xs_html_attr("name", "mentioned_only"), | 447 | xs_html_attr("type", "radio"), |
| 427 | xs_html_attr(xs_type(mnt_only) == XSTYPE_TRUE ? "checked" : "", NULL))); | 448 | xs_html_attr("name", "visibility"), |
| 449 | xs_html_attr("value", "public"), | ||
| 450 | xs_html_attr(scope == SCOPE_PUBLIC ? "checked" : "", NULL)), | ||
| 451 | xs_html_text(" "), | ||
| 452 | xs_html_text(L("Public"))), | ||
| 453 | xs_html_text(" "), | ||
| 454 | xs_html_tag("label", | ||
| 455 | xs_html_sctag("input", | ||
| 456 | xs_html_attr("type", "radio"), | ||
| 457 | xs_html_attr("name", "visibility"), | ||
| 458 | xs_html_attr("value", "unlisted"), | ||
| 459 | xs_html_attr(scope == SCOPE_UNLISTED ? "checked" : "", NULL)), | ||
| 460 | xs_html_text(" "), | ||
| 461 | xs_html_text(L("Unlisted"))), | ||
| 462 | xs_html_text(" "), | ||
| 463 | xs_html_tag("label", | ||
| 464 | xs_html_sctag("input", | ||
| 465 | xs_html_attr("type", "radio"), | ||
| 466 | xs_html_attr("name", "visibility"), | ||
| 467 | xs_html_attr("value", "followers"), | ||
| 468 | xs_html_attr(scope == SCOPE_FOLLOWERS ? "checked" : "", NULL)), | ||
| 469 | xs_html_text(" "), | ||
| 470 | xs_html_text(L("Followers-only"))), | ||
| 471 | xs_html_text(" "), | ||
| 472 | xs_html_tag("label", | ||
| 473 | xs_html_sctag("input", | ||
| 474 | xs_html_attr("type", "radio"), | ||
| 475 | xs_html_attr("name", "visibility"), | ||
| 476 | xs_html_attr("value", "mentioned"), | ||
| 477 | xs_html_attr(scope == SCOPE_MENTIONED ? "checked" : "", NULL)), | ||
| 478 | xs_html_text(" "), | ||
| 479 | xs_html_text(L("Direct Message"))))); | ||
| 428 | } | 480 | } |
| 429 | 481 | ||
| 430 | if (redir) | 482 | if (redir) |
| @@ -1236,7 +1288,7 @@ xs_html *html_top_controls(snac *user) | |||
| 1236 | L("What's on your mind?"), "", | 1288 | L("What's on your mind?"), "", |
| 1237 | NULL, NULL, | 1289 | NULL, NULL, |
| 1238 | xs_stock(XSTYPE_FALSE), "", | 1290 | xs_stock(XSTYPE_FALSE), "", |
| 1239 | xs_stock(XSTYPE_FALSE), NULL, | 1291 | SCOPE_PUBLIC, NULL, |
| 1240 | NULL, 1, NULL, NULL, 0, NULL, NULL), | 1292 | NULL, 1, NULL, NULL, 0, NULL, NULL), |
| 1241 | 1293 | ||
| 1242 | /** operations **/ | 1294 | /** operations **/ |
| @@ -1942,6 +1994,8 @@ xs_html *html_entry_controls(snac *user, const char *actor, | |||
| 1942 | xs_dict_next(cmap, ¬e_lang, &dummy, &c); | 1994 | xs_dict_next(cmap, ¬e_lang, &dummy, &c); |
| 1943 | } | 1995 | } |
| 1944 | 1996 | ||
| 1997 | const int edit_scope = get_msg_visibility(msg); | ||
| 1998 | |||
| 1945 | xs_html_add(controls, xs_html_tag("div", | 1999 | xs_html_add(controls, xs_html_tag("div", |
| 1946 | xs_html_tag("p", NULL), | 2000 | xs_html_tag("p", NULL), |
| 1947 | html_note(user, L("Edit..."), | 2001 | html_note(user, L("Edit..."), |
| @@ -1949,7 +2003,7 @@ xs_html *html_entry_controls(snac *user, const char *actor, | |||
| 1949 | "", prev_src, | 2003 | "", prev_src, |
| 1950 | id, NULL, | 2004 | id, NULL, |
| 1951 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), | 2005 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), |
| 1952 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, | 2006 | edit_scope, redir, |
| 1953 | NULL, 0, att_files, att_alt_texts, is_draft(user, id), | 2007 | NULL, 0, att_files, att_alt_texts, is_draft(user, id), |
| 1954 | xs_dict_get(msg, "published"), note_lang)), | 2008 | xs_dict_get(msg, "published"), note_lang)), |
| 1955 | xs_html_tag("p", NULL)); | 2009 | xs_html_tag("p", NULL)); |
| @@ -1962,6 +2016,8 @@ xs_html *html_entry_controls(snac *user, const char *actor, | |||
| 1962 | xs *form_id = xs_fmt("%s_reply_form", md5); | 2016 | xs *form_id = xs_fmt("%s_reply_form", md5); |
| 1963 | xs *redir = xs_fmt("%s_entry", md5); | 2017 | xs *redir = xs_fmt("%s_entry", md5); |
| 1964 | 2018 | ||
| 2019 | const int scope = get_msg_visibility(msg); | ||
| 2020 | |||
| 1965 | xs_html_add(controls, xs_html_tag("div", | 2021 | xs_html_add(controls, xs_html_tag("div", |
| 1966 | xs_html_tag("p", NULL), | 2022 | xs_html_tag("p", NULL), |
| 1967 | html_note(user, L("Reply..."), | 2023 | html_note(user, L("Reply..."), |
| @@ -1969,7 +2025,7 @@ xs_html *html_entry_controls(snac *user, const char *actor, | |||
| 1969 | "", ct, | 2025 | "", ct, |
| 1970 | NULL, NULL, | 2026 | NULL, NULL, |
| 1971 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), | 2027 | xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), |
| 1972 | xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, | 2028 | scope, redir, |
| 1973 | id, 0, NULL, NULL, 0, NULL, NULL)), | 2029 | id, 0, NULL, NULL, 0, NULL, NULL)), |
| 1974 | xs_html_tag("p", NULL)); | 2030 | xs_html_tag("p", NULL)); |
| 1975 | } | 2031 | } |
| @@ -2061,6 +2117,12 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 2061 | xs_html_attr("name", s1))); | 2117 | xs_html_attr("name", s1))); |
| 2062 | } | 2118 | } |
| 2063 | 2119 | ||
| 2120 | /* don't show followers-only notes from not followed users */ | ||
| 2121 | if (user && get_msg_visibility(msg) == SCOPE_FOLLOWERS && | ||
| 2122 | strcmp(user->actor, actor) != 0 && following_check(user, actor) == 0) { | ||
| 2123 | return NULL; | ||
| 2124 | } | ||
| 2125 | |||
| 2064 | if ((user == NULL || strcmp(actor, user->actor) != 0) | 2126 | if ((user == NULL || strcmp(actor, user->actor) != 0) |
| 2065 | && !valid_status(actor_get(actor, NULL))) { | 2127 | && !valid_status(actor_get(actor, NULL))) { |
| 2066 | 2128 | ||
| @@ -2275,7 +2337,6 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, | |||
| 2275 | 2337 | ||
| 2276 | has_title = 1; | 2338 | has_title = 1; |
| 2277 | } | 2339 | } |
| 2278 | |||
| 2279 | snac_content = xs_html_tag("div", NULL); | 2340 | snac_content = xs_html_tag("div", NULL); |
| 2280 | } | 2341 | } |
| 2281 | 2342 | ||
| @@ -3089,8 +3150,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, | |||
| 3089 | xs_html_text(title))); | 3150 | xs_html_text(title))); |
| 3090 | } | 3151 | } |
| 3091 | 3152 | ||
| 3092 | xs_html_add(body, | 3153 | xs_html_add(body, posts); |
| 3093 | posts); | ||
| 3094 | 3154 | ||
| 3095 | int mark_shown = 0; | 3155 | int mark_shown = 0; |
| 3096 | 3156 | ||
| @@ -3130,8 +3190,9 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, | |||
| 3130 | if (user == NULL && is_msg_from_private_user(msg)) | 3190 | if (user == NULL && is_msg_from_private_user(msg)) |
| 3131 | continue; | 3191 | continue; |
| 3132 | 3192 | ||
| 3133 | /* is this message a non-public reply? */ | 3193 | const int scope = get_msg_visibility(msg); |
| 3134 | if (user != NULL && !is_msg_public(msg)) { | 3194 | if (user != NULL && scope != SCOPE_PUBLIC){ |
| 3195 | /* is this message a non-public reply? */ | ||
| 3135 | const char *irt = get_in_reply_to(msg); | 3196 | const char *irt = get_in_reply_to(msg); |
| 3136 | 3197 | ||
| 3137 | /* is it a reply to something not in the storage? */ | 3198 | /* is it a reply to something not in the storage? */ |
| @@ -3146,6 +3207,14 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, | |||
| 3146 | } | 3207 | } |
| 3147 | } | 3208 | } |
| 3148 | } | 3209 | } |
| 3210 | /* hide non-public posts from /instance view */ | ||
| 3211 | if (page != NULL && strcmp(page, "/instance") == 0 && scope != SCOPE_PUBLIC){ | ||
| 3212 | continue; | ||
| 3213 | } | ||
| 3214 | /* hide non-public posts viewed from outside */ | ||
| 3215 | if (read_only && scope != SCOPE_PUBLIC){ | ||
| 3216 | continue; | ||
| 3217 | } | ||
| 3149 | 3218 | ||
| 3150 | xs_html *entry = html_entry(user, msg, read_only, 0, v, (user && !hide_children) ? 0 : 1); | 3219 | xs_html *entry = html_entry(user, msg, read_only, 0, v, (user && !hide_children) ? 0 : 1); |
| 3151 | 3220 | ||
| @@ -3256,7 +3325,7 @@ xs_html *html_people_list(snac *user, xs_list *list, const char *header, const c | |||
| 3256 | xs_html_tag("div", | 3325 | xs_html_tag("div", |
| 3257 | xs_html_attr("class", "snac-post-header"), | 3326 | xs_html_attr("class", "snac-post-header"), |
| 3258 | html_actor_icon(user, actor, xs_dict_get(actor, "published"), | 3327 | html_actor_icon(user, actor, xs_dict_get(actor, "published"), |
| 3259 | NULL, NULL, 0, 1, proxy, NULL, NULL))); | 3328 | NULL, NULL, -1, 1, proxy, NULL, NULL))); |
| 3260 | 3329 | ||
| 3261 | /* content (user bio) */ | 3330 | /* content (user bio) */ |
| 3262 | const char *c = xs_dict_get(actor, "summary"); | 3331 | const char *c = xs_dict_get(actor, "summary"); |
| @@ -3357,7 +3426,7 @@ xs_html *html_people_list(snac *user, xs_list *list, const char *header, const c | |||
| 3357 | "", "", | 3426 | "", "", |
| 3358 | NULL, actor_id, | 3427 | NULL, actor_id, |
| 3359 | xs_stock(XSTYPE_FALSE), "", | 3428 | xs_stock(XSTYPE_FALSE), "", |
| 3360 | xs_stock(XSTYPE_FALSE), NULL, | 3429 | SCOPE_MENTIONED, NULL, |
| 3361 | NULL, 0, NULL, NULL, 0, NULL, NULL), | 3430 | NULL, 0, NULL, NULL, 0, NULL, NULL), |
| 3362 | xs_html_tag("p", NULL)); | 3431 | xs_html_tag("p", NULL)); |
| 3363 | 3432 | ||
| @@ -3564,7 +3633,7 @@ xs_str *html_notifications(snac *user, int skip, int show) | |||
| 3564 | xs_html_add(entry, | 3633 | xs_html_add(entry, |
| 3565 | xs_html_tag("div", | 3634 | xs_html_tag("div", |
| 3566 | xs_html_attr("class", "snac-post"), | 3635 | xs_html_attr("class", "snac-post"), |
| 3567 | html_actor_icon(user, actor, NULL, NULL, NULL, 0, 0, proxy, NULL, NULL))); | 3636 | html_actor_icon(user, actor, NULL, NULL, NULL, -1, 0, proxy, NULL, NULL))); |
| 3568 | } | 3637 | } |
| 3569 | else | 3638 | else |
| 3570 | if (strcmp(type, "Move") == 0) { | 3639 | if (strcmp(type, "Move") == 0) { |
| @@ -3578,7 +3647,7 @@ xs_str *html_notifications(snac *user, int skip, int show) | |||
| 3578 | xs_html_add(entry, | 3647 | xs_html_add(entry, |
| 3579 | xs_html_tag("div", | 3648 | xs_html_tag("div", |
| 3580 | xs_html_attr("class", "snac-post"), | 3649 | xs_html_attr("class", "snac-post"), |
| 3581 | html_actor_icon(user, old_actor, NULL, NULL, NULL, 0, 0, proxy, NULL, NULL))); | 3650 | html_actor_icon(user, old_actor, NULL, NULL, NULL, -1, 0, proxy, NULL, NULL))); |
| 3582 | } | 3651 | } |
| 3583 | } | 3652 | } |
| 3584 | } | 3653 | } |
| @@ -4445,7 +4514,18 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4445 | const char *post_date = xs_dict_get_def(p_vars, "post_date", ""); | 4514 | const char *post_date = xs_dict_get_def(p_vars, "post_date", ""); |
| 4446 | const char *post_time = xs_dict_get_def(p_vars, "post_time", ""); | 4515 | const char *post_time = xs_dict_get_def(p_vars, "post_time", ""); |
| 4447 | const char *post_lang = xs_dict_get(p_vars, "post_lang"); | 4516 | const char *post_lang = xs_dict_get(p_vars, "post_lang"); |
| 4448 | int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only")); | 4517 | const char *visibility = xs_dict_get(p_vars, "visibility"); |
| 4518 | int scope = SCOPE_PUBLIC; /* default to public */ | ||
| 4519 | if (!xs_is_null(visibility)) { | ||
| 4520 | if (strcmp(visibility, "unlisted") == 0) | ||
| 4521 | scope = SCOPE_UNLISTED; | ||
| 4522 | else | ||
| 4523 | if (strcmp(visibility, "followers") == 0) | ||
| 4524 | scope = SCOPE_FOLLOWERS; | ||
| 4525 | else | ||
| 4526 | if (strcmp(visibility, "mentioned") == 0) | ||
| 4527 | scope = SCOPE_MENTIONED; | ||
| 4528 | } | ||
| 4449 | int store_as_draft = !xs_is_null(xs_dict_get(p_vars, "is_draft")); | 4529 | int store_as_draft = !xs_is_null(xs_dict_get(p_vars, "is_draft")); |
| 4450 | xs *attach_list = xs_list_new(); | 4530 | xs *attach_list = xs_list_new(); |
| 4451 | 4531 | ||
| @@ -4528,7 +4608,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, | |||
| 4528 | enqueue_close_question(&snac, xs_dict_get(msg, "id"), end_secs); | 4608 | enqueue_close_question(&snac, xs_dict_get(msg, "id"), end_secs); |
| 4529 | } | 4609 | } |
| 4530 | else | 4610 | else |
| 4531 | msg = msg_note(&snac, content_2, to, in_reply_to, attach_list, priv, post_lang, NULL); | 4611 | msg = msg_note(&snac, content_2, to, in_reply_to, attach_list, scope, post_lang, NULL); |
| 4532 | 4612 | ||
| 4533 | if (sensitive != NULL) { | 4613 | if (sensitive != NULL) { |
| 4534 | msg = xs_dict_set(msg, "sensitive", xs_stock(XSTYPE_TRUE)); | 4614 | msg = xs_dict_set(msg, "sensitive", xs_stock(XSTYPE_TRUE)); |