diff options
Diffstat (limited to 'html.c')
-rw-r--r-- | html.c | 212 |
1 files changed, 156 insertions, 56 deletions
@@ -113,9 +113,13 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, xs *name = actor_name(actor); /* get the avatar */ - if ((v = xs_dict_get(actor, "icon")) != NULL && - (v = xs_dict_get(v, "url")) != NULL) { - avatar = xs_dup(v); + if ((v = xs_dict_get(actor, "icon")) != NULL) { + /* if it's a list (Peertube), get the first one */ + if (xs_type(v) == XSTYPE_LIST) + v = xs_list_get(v, 0); + + if ((v = xs_dict_get(v, "url")) != NULL) + avatar = xs_dup(v); } if (avatar == NULL) @@ -245,7 +249,7 @@ xs_html *html_msg_icon(snac *user, char *actor_id, const xs_dict *msg) xs *actor = NULL; xs_html *actor_icon = NULL; - if (actor_id && valid_status(actor_get(actor_id, &actor))) { + if (actor_id && valid_status(actor_get_refresh(user, actor_id, &actor))) { char *date = NULL; char *udate = NULL; char *url = NULL; @@ -273,7 +277,8 @@ xs_html *html_note(snac *user, char *summary, char *edit_id, char *actor_id, xs_val *cw_yn, char *cw_text, xs_val *mnt_only, char *redir, - char *in_reply_to, int poll) + char *in_reply_to, int poll, + char *att_file, char *att_alt_text) { xs *action = xs_fmt("%s/admin/note", user->actor); @@ -359,19 +364,37 @@ xs_html *html_note(snac *user, char *summary, xs_html_attr("name", "edit_id"), xs_html_attr("value", edit_id))); + /* attachment controls */ + xs_html *att; + xs_html_add(form, xs_html_tag("p", NULL), - xs_html_tag("details", + att = xs_html_tag("details", xs_html_tag("summary", xs_html_text(L("Attachment..."))), - xs_html_tag("p", NULL), - xs_html_sctag("input", - xs_html_attr("type", "file"), - xs_html_attr("name", "attach")), - xs_html_sctag("input", - xs_html_attr("type", "text"), - xs_html_attr("name", "alt_text"), - xs_html_attr("placeholder", L("Attachment description"))))); + xs_html_tag("p", NULL))); + + if (att_file && *att_file) + xs_html_add(att, + xs_html_text(L("File:")), + xs_html_sctag("input", + xs_html_attr("type", "text"), + xs_html_attr("name", "attach_url"), + xs_html_attr("title", L("Clear this field to delete the attachment")), + xs_html_attr("value", att_file))); + else + xs_html_add(att, + xs_html_sctag("input", + xs_html_attr("type", "file"), + xs_html_attr("name", "attach"))); + + xs_html_add(att, + xs_html_text(" "), + xs_html_sctag("input", + xs_html_attr("type", "text"), + xs_html_attr("name", "alt_text"), + xs_html_attr("value", att_alt_text), + xs_html_attr("placeholder", L("Attachment description")))); /* add poll controls */ if (poll) { @@ -551,7 +574,7 @@ static xs_html *html_instance_body(char *tag) } -xs_html *html_user_head(snac *user, char *desc) +xs_html *html_user_head(snac *user, char *desc, char *url) { xs_html *head = html_base_head(); @@ -641,6 +664,13 @@ xs_html *html_user_head(snac *user, char *desc) xs_html_attr("title", "RSS"), xs_html_attr("href", rss_url))); + /* ActivityPub alternate link (actor id) */ + xs_html_add(head, + xs_html_sctag("link", + xs_html_attr("rel", "alternate"), + xs_html_attr("type", "application/activity+json"), + xs_html_attr("href", url ? url : user->actor))); + return head; } @@ -756,7 +786,7 @@ static xs_html *html_user_body(snac *user, int read_only) if (read_only) { xs *es1 = encode_html(xs_dict_get(user->config, "bio")); - xs *bio1 = not_really_markdown(es1, NULL); + xs *bio1 = not_really_markdown(es1, NULL, NULL); xs *tags = xs_list_new(); xs *bio2 = process_tags(user, bio1, &tags); @@ -774,7 +804,7 @@ static xs_html *html_user_body(snac *user, int read_only) xs_dict *val_links = user->links; if (xs_is_null(val_links)) - val_links = xs_stock_dict; + val_links = xs_stock(XSTYPE_DICT); xs_html *snac_metadata = xs_html_tag("div", xs_html_attr("class", "snac-metadata")); @@ -852,9 +882,9 @@ xs_html *html_top_controls(snac *snac) "new_post_div", "new_post_form", L("What's on your mind?"), "", NULL, NULL, - xs_stock_false, "", - xs_stock_false, NULL, - NULL, 1), + xs_stock(XSTYPE_FALSE), "", + xs_stock(XSTYPE_FALSE), NULL, + NULL, 1, "", ""), /** operations **/ xs_html_tag("details", @@ -1219,6 +1249,11 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const xs_html_add(form, html_button("like", L("Like"), L("Say you like this post"))); } + else { + /* not like it anymore */ + xs_html_add(form, + html_button("unlike", L("Unlike"), L("Nah don't like it that much"))); + } } else { if (is_pinned(snac, id)) @@ -1235,6 +1270,11 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const xs_html_add(form, html_button("boost", L("Boost"), L("Announce this post to your followers"))); } + else { + /* already boosted; add button to regret */ + xs_html_add(form, + html_button("unboost", L("Unboost"), L("I regret I boosted this"))); + } } if (strcmp(actor, snac->actor) != 0) { @@ -1278,6 +1318,20 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const xs *form_id = xs_fmt("%s_edit_form", md5); xs *redir = xs_fmt("%s_entry", md5); + char *att_file = ""; + char *att_alt_text = ""; + xs_list *att_list = xs_dict_get(msg, "attachment"); + + /* does it have an attachment? */ + if (xs_type(att_list) == XSTYPE_LIST && xs_list_len(att_list)) { + xs_dict *d = xs_list_get(att_list, 0); + + if (xs_type(d) == XSTYPE_DICT) { + att_file = xs_dict_get_def(d, "url", ""); + att_alt_text = xs_dict_get_def(d, "name", ""); + } + } + xs_html_add(controls, xs_html_tag("div", xs_html_tag("p", NULL), html_note(snac, L("Edit..."), @@ -1285,8 +1339,8 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const "", prev_src, id, NULL, xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), - xs_stock_false, redir, - NULL, 0)), + xs_stock(XSTYPE_FALSE), redir, + NULL, 0, att_file, att_alt_text)), xs_html_tag("p", NULL)); } @@ -1304,8 +1358,8 @@ xs_html *html_entry_controls(snac *snac, char *actor, const xs_dict *msg, const "", ct, NULL, NULL, xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), - xs_stock_false, redir, - id, 0)), + xs_stock(XSTYPE_FALSE), redir, + id, 0, "", "")), xs_html_tag("p", NULL)); } @@ -1858,6 +1912,9 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, xs_list *p = children; char *cmd5; + int cnt = 0; + int o_cnt = 0; + while (xs_list_iter(&p, &cmd5)) { xs *chd = NULL; @@ -1866,23 +1923,40 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, else object_get_by_md5(cmd5, &chd); - if (chd != NULL && xs_is_null(xs_dict_get(chd, "name"))) { - xs_html *che = html_entry(user, chd, read_only, level + 1, cmd5, hide_children); + if (chd != NULL) { + if (xs_is_null(xs_dict_get(chd, "name"))) { + xs_html *che = html_entry(user, chd, read_only, + level + 1, cmd5, hide_children); + + if (che != NULL) { + if (left > 3) { + xs_html_add(ch_older, + che); + + o_cnt++; + } + else + xs_html_add(ch_container, + che); - if (che != NULL) { - if (left > 3) - xs_html_add(ch_older, - che); - else - xs_html_add(ch_container, - che); + cnt++; + } } + + left--; } else srv_debug(2, xs_fmt("cannot read child %s", cmd5)); - - left--; } + + /* if no children were finally added, hide the details */ + if (cnt == 0) + xs_html_add(ch_details, + xs_html_attr("style", "display: none")); + + if (o_cnt == 0 && ch_older) + xs_html_add(ch_older, + xs_html_attr("style", "display: none")); } } @@ -1917,6 +1991,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, double t = ftime(); xs *desc = NULL; + xs *alternate = NULL; if (xs_list_len(list) == 1) { /* only one element? pick the description from the source */ @@ -1925,13 +2000,15 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, object_get_by_md5(id, &d); if (d && (v = xs_dict_get(d, "sourceContent")) != NULL) desc = xs_dup(v); + + alternate = xs_dup(xs_dict_get(d, "id")); } xs_html *head; xs_html *body; if (user) { - head = html_user_head(user, desc); + head = html_user_head(user, desc, alternate); body = html_user_body(user, read_only); } else { @@ -1977,9 +2054,16 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, if (user != NULL && !is_msg_public(msg)) { char *irt = xs_dict_get(msg, "inReplyTo"); + /* is it a reply to something not in the storage? */ if (!xs_is_null(irt) && !object_here(irt)) { - snac_debug(user, 1, xs_fmt("skipping non-public reply to an unknown post %s", v)); - continue; + /* is it for me? */ + xs_list *to = xs_dict_get_def(msg, "to", xs_stock(XSTYPE_LIST)); + xs_list *cc = xs_dict_get_def(msg, "cc", xs_stock(XSTYPE_LIST)); + + if (xs_list_in(to, user->actor) == -1 && xs_list_in(cc, user->actor) == -1) { + snac_debug(user, 1, xs_fmt("skipping non-public reply to an unknown post %s", v)); + continue; + } } } @@ -2077,9 +2161,7 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t) snac_posts = xs_html_tag("details", xs_html_attr("open", NULL), xs_html_tag("summary", - xs_html_text("...")), - xs_html_tag("div", - xs_html_attr("class", "snac-posts")))); + xs_html_text("...")))); xs_list *p = list; char *actor_id; @@ -2181,9 +2263,9 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t) dm_div_id, dm_form_id, "", "", NULL, actor_id, - xs_stock_false, "", - xs_stock_false, NULL, - NULL, 0), + xs_stock(XSTYPE_FALSE), "", + xs_stock(XSTYPE_FALSE), NULL, + NULL, 0, "", ""), xs_html_tag("p", NULL)); xs_html_add(snac_post, snac_controls); @@ -2202,10 +2284,12 @@ xs_str *html_people(snac *user) xs *wers = follower_list(user); xs_html *html = xs_html_tag("html", - html_user_head(user, NULL), + html_user_head(user, NULL, NULL), xs_html_add(html_user_body(user, 0), - html_people_list(user, wing, L("People you follow"), "i"), - html_people_list(user, wers, L("People that follow you"), "e"), + xs_html_tag("div", + xs_html_attr("class", "snac-posts"), + html_people_list(user, wing, L("People you follow"), "i"), + html_people_list(user, wers, L("People that follow you"), "e")), html_footer())); return xs_html_render_s(html, "<!DOCTYPE html>\n"); @@ -2220,7 +2304,7 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html *body = html_user_body(user, 0); xs_html *html = xs_html_tag("html", - html_user_head(user, NULL), + html_user_head(user, NULL, NULL), body); xs *clear_all_action = xs_fmt("%s/admin/clear-notifications", user->actor); @@ -2604,7 +2688,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, return 403; xs *elems = timeline_simple_list(&snac, "public", 0, 20); - xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL); + xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio"), NULL, NULL); xs *rss_title = xs_fmt("%s (@%s@%s)", xs_dict_get(snac.config, "name"), @@ -2802,7 +2886,7 @@ int html_post_handler(const xs_dict *req, const char *q_path, msg = msg_note(&snac, content_2, to, in_reply_to, attach_list, priv); if (sensitive != NULL) { - msg = xs_dict_set(msg, "sensitive", xs_stock_true); + msg = xs_dict_set(msg, "sensitive", xs_stock(XSTYPE_TRUE)); msg = xs_dict_set(msg, "summary", xs_is_null(summary) ? "..." : summary); } @@ -2881,6 +2965,22 @@ int html_post_handler(const xs_dict *req, const char *q_path, } } else + if (strcmp(action, L("Unlike")) == 0) { /** **/ + xs *msg = msg_repulsion(&snac, id, "Like"); + + if (msg != NULL) { + enqueue_message(&snac, msg); + } + } + else + if (strcmp(action, L("Unboost")) == 0) { /** **/ + xs *msg = msg_repulsion(&snac, id, "Announce"); + + if (msg != NULL) { + enqueue_message(&snac, msg); + } + } + else if (strcmp(action, L("MUTE")) == 0) { /** **/ mute(&snac, actor); } @@ -3036,17 +3136,17 @@ int html_post_handler(const xs_dict *req, const char *q_path, snac.config = xs_dict_set(snac.config, "purge_days", days); } if ((v = xs_dict_get(p_vars, "drop_dm_from_unknown")) != NULL && strcmp(v, "on") == 0) - snac.config = xs_dict_set(snac.config, "drop_dm_from_unknown", xs_stock_true); + snac.config = xs_dict_set(snac.config, "drop_dm_from_unknown", xs_stock(XSTYPE_TRUE)); else - snac.config = xs_dict_set(snac.config, "drop_dm_from_unknown", xs_stock_false); + snac.config = xs_dict_set(snac.config, "drop_dm_from_unknown", xs_stock(XSTYPE_FALSE)); if ((v = xs_dict_get(p_vars, "bot")) != NULL && strcmp(v, "on") == 0) - snac.config = xs_dict_set(snac.config, "bot", xs_stock_true); + snac.config = xs_dict_set(snac.config, "bot", xs_stock(XSTYPE_TRUE)); else - snac.config = xs_dict_set(snac.config, "bot", xs_stock_false); + snac.config = xs_dict_set(snac.config, "bot", xs_stock(XSTYPE_FALSE)); if ((v = xs_dict_get(p_vars, "private")) != NULL && strcmp(v, "on") == 0) - snac.config = xs_dict_set(snac.config, "private", xs_stock_true); + snac.config = xs_dict_set(snac.config, "private", xs_stock(XSTYPE_TRUE)); else - snac.config = xs_dict_set(snac.config, "private", xs_stock_false); + snac.config = xs_dict_set(snac.config, "private", xs_stock(XSTYPE_FALSE)); if ((v = xs_dict_get(p_vars, "metadata")) != NULL) { /* split the metadata and store it as a dict */ xs_dict *md = xs_dict_new(); |