From 3b818f557ae3c1073f1464fe0a7319a0e025ba86 Mon Sep 17 00:00:00 2001 From: Eirik Oeverby Date: Mon, 6 Jan 2025 20:03:00 +0100 Subject: Add short_description_raw option --- html.c | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index e8803ab..b54556d 100644 --- a/html.c +++ b/html.c @@ -537,10 +537,11 @@ xs_html *html_instance_head(void) static xs_html *html_instance_body(void) { - const char *host = xs_dict_get(srv_config, "host"); - const char *sdesc = xs_dict_get(srv_config, "short_description"); - const char *email = xs_dict_get(srv_config, "admin_email"); - const char *acct = xs_dict_get(srv_config, "admin_account"); + const char *host = xs_dict_get(srv_config, "host"); + const char *sdesc = xs_dict_get(srv_config, "short_description"); + const char *sdescraw = xs_dict_get(srv_config, "short_description_raw"); + const char *email = xs_dict_get(srv_config, "admin_email"); + const char *acct = xs_dict_get(srv_config, "admin_account"); xs *blurb = xs_replace(snac_blurb, "%host%", host); @@ -553,12 +554,21 @@ static xs_html *html_instance_body(void) dl = xs_html_tag("dl", NULL))); if (sdesc && *sdesc) { - xs_html_add(dl, - xs_html_tag("di", - xs_html_tag("dt", - xs_html_text(L("Site description"))), - xs_html_tag("dd", - xs_html_text(sdesc)))); + if (!xs_is_null(sdescraw) && xs_type(sdescraw) == XSTYPE_TRUE) { + xs_html_add(dl, + xs_html_tag("di", + xs_html_tag("dt", + xs_html_text(L("Site description"))), + xs_html_tag("dd", + xs_html_raw(sdesc)))); + } else { + xs_html_add(dl, + xs_html_tag("di", + xs_html_tag("dt", + xs_html_text(L("Site description"))), + xs_html_tag("dd", + xs_html_text(sdesc)))); + } } if (email && *email) { xs *mailto = xs_fmt("mailto:%s", email); -- cgit v1.2.3 From 5c303d539b48cdec5cc9cca77472faaa7c5c8d71 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 24 Jan 2025 14:54:55 +0100 Subject: Improved notification messages. --- html.c | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 3fd1e4b..e1f21bb 100644 --- a/html.c +++ b/html.c @@ -2967,8 +2967,8 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_attr("class", "snac-posts")); xs_html_add(body, posts); - xs_set rep; - xs_set_init(&rep); + /* dict to store previous notification labels */ + xs *admiration_labels = xs_dict_new(); const xs_str *v; @@ -2995,8 +2995,8 @@ xs_str *html_notifications(snac *user, int skip, int show) const char *msg_id = NULL; - if (xs_is_dict(obj) && (msg_id = xs_dict_get(obj, "id")) && xs_set_add(&rep, msg_id) != 1) - continue; + if (xs_is_dict(obj)) + msg_id = xs_dict_get(obj, "id"); const char *actor_id = xs_dict_get(noti, "actor"); xs *actor = NULL; @@ -3030,9 +3030,7 @@ xs_str *html_notifications(snac *user, int skip, int show) xs *s_date = xs_crop_i(xs_dup(date), 0, 10); - xs_html *entry = xs_html_tag("div", - xs_html_attr("class", "snac-post-with-desc"), - xs_html_tag("p", + xs_html *this_html_label = xs_html_container( xs_html_tag("b", xs_html_text(label), xs_html_text(" by "), @@ -3043,7 +3041,37 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_tag("time", xs_html_attr("class", "dt-published snac-pubdate"), xs_html_attr("title", date), - xs_html_text(s_date)))); + xs_html_text(s_date))); + + xs_html *html_label = NULL; + + if (xs_is_string(msg_id)) { + const xs_val *prev_label = xs_dict_get(admiration_labels, msg_id); + + if (xs_type(prev_label) == XSTYPE_DATA) { + /* there is a previous list of admiration labels! */ + xs_data_get(&html_label, prev_label); + + xs_html_add(html_label, + xs_html_sctag("br", NULL), + this_html_label); + + continue; + } + } + + xs_html *entry = NULL; + + html_label = xs_html_tag("p", + this_html_label); + + /* store in the admiration labels dict */ + xs *pl = xs_data_new(&html_label, sizeof(html_label)); + admiration_labels = xs_dict_set(admiration_labels, msg_id, pl); + + entry = xs_html_tag("div", + xs_html_attr("class", "snac-post-with-desc"), + html_label); if (strcmp(type, "Follow") == 0 || strcmp(utype, "Follow") == 0 || strcmp(type, "Block") == 0) { xs_html_add(entry, @@ -3111,8 +3139,6 @@ xs_str *html_notifications(snac *user, int skip, int show) } } - xs_set_free(&rep); - if (noti_new == NULL && noti_seen == NULL) xs_html_add(body, xs_html_tag("h2", -- cgit v1.2.3 From 896a36837c8da070d85abe92d62d12c4009fca1c Mon Sep 17 00:00:00 2001 From: default Date: Sat, 25 Jan 2025 21:45:14 +0100 Subject: Another tweak to fix repeated notifications. --- html.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index e1f21bb..31d8d97 100644 --- a/html.c +++ b/html.c @@ -2967,6 +2967,9 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_attr("class", "snac-posts")); xs_html_add(body, posts); + xs_set rep; + xs_set_init(&rep); + /* dict to store previous notification labels */ xs *admiration_labels = xs_dict_new(); @@ -2983,6 +2986,7 @@ xs_str *html_notifications(snac *user, int skip, int show) const char *utype = xs_dict_get(noti, "utype"); const char *id = xs_dict_get(noti, "objid"); const char *date = xs_dict_get(noti, "date"); + const char *id2 = xs_dict_get_path(noti, "msg.id"); xs *wrk = NULL; if (xs_is_null(id)) @@ -2991,6 +2995,9 @@ xs_str *html_notifications(snac *user, int skip, int show) if (is_hidden(user, id)) continue; + if (xs_is_string(id2) && xs_set_add(&rep, id2) != 1) + continue; + object_get(id, &obj); const char *msg_id = NULL; @@ -3158,6 +3165,8 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_text(L("More..."))))); } + xs_set_free(&rep); + xs_html_add(body, html_footer()); -- cgit v1.2.3 From 5d267968cb0d2670f8a4bd7587e505f812dfa3bc Mon Sep 17 00:00:00 2001 From: default Date: Sat, 25 Jan 2025 23:13:59 +0100 Subject: Fixed crash in the notification area after deleting a post. --- html.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 31d8d97..3b63cfc 100644 --- a/html.c +++ b/html.c @@ -3074,7 +3074,9 @@ xs_str *html_notifications(snac *user, int skip, int show) /* store in the admiration labels dict */ xs *pl = xs_data_new(&html_label, sizeof(html_label)); - admiration_labels = xs_dict_set(admiration_labels, msg_id, pl); + + if (xs_is_string(msg_id)) + admiration_labels = xs_dict_set(admiration_labels, msg_id, pl); entry = xs_html_tag("div", xs_html_attr("class", "snac-post-with-desc"), -- cgit v1.2.3 From 82bcc4b465f73a5d1f2eebcf3813452bc1c37fbd Mon Sep 17 00:00:00 2001 From: default Date: Mon, 27 Jan 2025 16:59:08 +0100 Subject: Minor optimization in timeline retrieving. Functions now receive an optional int *more, set to 1 if there are more than the 'show' requested. --- html.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 3b63cfc..bd94e9f 100644 --- a/html.c +++ b/html.c @@ -3314,21 +3314,17 @@ int html_get_handler(const xs_dict *req, const char *q_path, } else { xs *list = NULL; - xs *next = NULL; + int more = 0; - if (xs_is_true(xs_dict_get(srv_config, "strict_public_timelines"))) { - list = timeline_simple_list(&snac, "public", skip, show); - next = timeline_simple_list(&snac, "public", skip + show, 1); - } - else { - list = timeline_list(&snac, "public", skip, show); - next = timeline_list(&snac, "public", skip + show, 1); - } + if (xs_is_true(xs_dict_get(srv_config, "strict_public_timelines"))) + list = timeline_simple_list(&snac, "public", skip, show, &more); + else + list = timeline_list(&snac, "public", skip, show, &more); xs *pins = pinned_list(&snac); pins = xs_list_cat(pins, list); - *body = html_timeline(&snac, pins, 1, skip, show, xs_list_len(next), NULL, "", 1, error); + *body = html_timeline(&snac, pins, 1, skip, show, more, NULL, "", 1, error); *b_size = strlen(*body); status = HTTP_STATUS_OK; @@ -3490,13 +3486,14 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs_dict_get(req, "if-none-match"), etag); } else { + int more = 0; + snac_debug(&snac, 1, xs_fmt("building timeline")); - xs *list = timeline_list(&snac, "private", skip, show); - xs *next = timeline_list(&snac, "private", skip + show, 1); + xs *list = timeline_list(&snac, "private", skip, show, &more); *body = html_timeline(&snac, list, 0, skip, show, - xs_list_len(next), NULL, "/admin", 1, error); + more, NULL, "/admin", 1, error); *b_size = strlen(*body); status = HTTP_STATUS_OK; @@ -3702,7 +3699,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, int cnt = xs_number_get(xs_dict_get_def(srv_config, "max_public_entries", "20")); - xs *elems = timeline_simple_list(&snac, "public", 0, cnt); + xs *elems = timeline_simple_list(&snac, "public", 0, cnt, NULL); xs *bio = xs_dup(xs_dict_get(snac.config, "bio")); xs *rss_title = xs_fmt("%s (@%s@%s)", -- cgit v1.2.3 From 1766d6bf92eb433841c03ccb096c636a4c5dc968 Mon Sep 17 00:00:00 2001 From: default Date: Mon, 27 Jan 2025 20:20:40 +0100 Subject: Added a 'No more unseen posts' mark. --- html.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index bd94e9f..771d2af 100644 --- a/html.c +++ b/html.c @@ -2648,10 +2648,31 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_add(body, posts); + int mark_shown = 0; + while (xs_list_iter(&p, &v)) { xs *msg = NULL; int status; + /* "already seen" mark? */ + if (strcmp(v, MD5_ALREADY_SEEN_MARK) == 0) { + if (skip == 0 && !mark_shown) { + xs *s = xs_fmt("%s/admin#top", user->actor); + + xs_html_add(posts, + xs_html_text(L("No more unseen posts")), + xs_html_text(" - "), + xs_html_tag("a", + xs_html_attr("href", s), + xs_html_text(L("Back to top"))), + xs_html_sctag("hr", NULL)); + } + + mark_shown = 1; + + continue; + } + if (utl && user && !is_pinned_by_md5(user, v)) status = timeline_get_by_md5(user, v, &msg); else @@ -3473,6 +3494,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, } } else { + /** the private timeline **/ double t = history_mtime(&snac, "timeline.html_"); /* if enabled by admin, return a cached page if its timestamp is: @@ -3492,6 +3514,8 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list = timeline_list(&snac, "private", skip, show, &more); + timeline_add_mark(&snac); + *body = html_timeline(&snac, list, 0, skip, show, more, NULL, "/admin", 1, error); -- cgit v1.2.3 From d9d2dedbc053b35aee02ba7f408e056ab03368c0 Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 07:48:31 +0100 Subject: Set the CSS class snac-no-more-unseen-posts. --- html.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 771d2af..c27ab99 100644 --- a/html.c +++ b/html.c @@ -2660,12 +2660,13 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs *s = xs_fmt("%s/admin#top", user->actor); xs_html_add(posts, - xs_html_text(L("No more unseen posts")), - xs_html_text(" - "), - xs_html_tag("a", - xs_html_attr("href", s), - xs_html_text(L("Back to top"))), - xs_html_sctag("hr", NULL)); + xs_html_tag("div", + xs_html_attr("class", "snac-no-more-unseen-posts"), + xs_html_text(L("No more unseen posts")), + xs_html_text(" - "), + xs_html_tag("a", + xs_html_attr("href", s), + xs_html_text(L("Back to top"))))); } mark_shown = 1; -- cgit v1.2.3 From 06ba1174ca7084a3d691aa8c2b552b708d04b8db Mon Sep 17 00:00:00 2001 From: default Date: Tue, 28 Jan 2025 10:04:23 +0100 Subject: Some tweaks to the already seen mark code. --- html.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index c27ab99..8f8b524 100644 --- a/html.c +++ b/html.c @@ -2657,7 +2657,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, /* "already seen" mark? */ if (strcmp(v, MD5_ALREADY_SEEN_MARK) == 0) { if (skip == 0 && !mark_shown) { - xs *s = xs_fmt("%s/admin#top", user->actor); + xs *s = xs_fmt("%s/admin", user->actor); xs_html_add(posts, xs_html_tag("div", @@ -2665,7 +2665,7 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_text(L("No more unseen posts")), xs_html_text(" - "), xs_html_tag("a", - xs_html_attr("href", s), + xs_html_attr("href", s), xs_html_text(L("Back to top"))))); } -- cgit v1.2.3 From 4acb3f65db21b1be6c16cf017aae890bb6dd4eea Mon Sep 17 00:00:00 2001 From: default Date: Wed, 29 Jan 2025 09:24:09 +0100 Subject: Call timeline_add_mark() after history_add() for better timestamp checks. --- html.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 8f8b524..6365afb 100644 --- a/html.c +++ b/html.c @@ -3515,8 +3515,6 @@ int html_get_handler(const xs_dict *req, const char *q_path, xs *list = timeline_list(&snac, "private", skip, show, &more); - timeline_add_mark(&snac); - *body = html_timeline(&snac, list, 0, skip, show, more, NULL, "/admin", 1, error); @@ -3525,6 +3523,8 @@ int html_get_handler(const xs_dict *req, const char *q_path, if (save) history_add(&snac, "timeline.html_", *body, *b_size, etag); + + timeline_add_mark(&snac); } } } -- cgit v1.2.3 From 1d37e33e405975ce740be89fc02968cc7ec09b0f Mon Sep 17 00:00:00 2001 From: default Date: Wed, 5 Feb 2025 10:14:42 +0100 Subject: Added a 'Context' link to each notification. --- html.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 6365afb..500272b 100644 --- a/html.c +++ b/html.c @@ -3129,11 +3129,16 @@ xs_str *html_notifications(snac *user, int skip, int show) else if (obj != NULL) { xs *md5 = xs_md5_hex(id, strlen(id)); + xs *ctxt = xs_fmt("%s/admin/p/%s#%s_entry", user->actor, md5, md5); xs_html *h = html_entry(user, obj, 0, 0, md5, 1); if (h != NULL) { xs_html_add(entry, + xs_html_tag("p", + xs_html_tag("a", + xs_html_attr("href", ctxt), + xs_html_text(L("Context")))), h); } } @@ -3540,7 +3545,8 @@ int html_get_handler(const xs_dict *req, const char *q_path, const char *md5 = xs_list_get(l, -1); if (md5 && *md5 && timeline_here(&snac, md5)) { - xs *list = xs_list_append(xs_list_new(), md5); + xs *list0 = xs_list_append(xs_list_new(), md5); + xs *list = timeline_top_level(&snac, list0); *body = html_timeline(&snac, list, 0, 0, 0, 0, NULL, "/admin", 1, error); *b_size = strlen(*body); -- cgit v1.2.3 From a5aea195c2676a5c17a66f6c98f5654ce79a3794 Mon Sep 17 00:00:00 2001 From: default Date: Wed, 5 Feb 2025 12:58:10 +0100 Subject: Minor HTML tweak. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 5f1cd6c..b3a18d9 100644 --- a/html.c +++ b/html.c @@ -3145,7 +3145,7 @@ xs_str *html_notifications(snac *user, int skip, int show) if (h != NULL) { xs_html_add(entry, - xs_html_tag("p", + xs_html_tag("div", xs_html_tag("a", xs_html_attr("href", ctxt), xs_html_text(L("Context")))), -- cgit v1.2.3 From de8fd8305396abd1e7e7208f443be4a4891219cd Mon Sep 17 00:00:00 2001 From: default Date: Wed, 5 Feb 2025 13:11:14 +0100 Subject: More HTML tweaks. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index b3a18d9..5f1cd6c 100644 --- a/html.c +++ b/html.c @@ -3145,7 +3145,7 @@ xs_str *html_notifications(snac *user, int skip, int show) if (h != NULL) { xs_html_add(entry, - xs_html_tag("div", + xs_html_tag("p", xs_html_tag("a", xs_html_attr("href", ctxt), xs_html_text(L("Context")))), -- cgit v1.2.3 From 8e1a2c5ff92d01789e02980f2e36c8808c8ea033 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Thu, 6 Feb 2025 09:04:36 +0100 Subject: Merged 53ad5cdf0371fc068fa03bf287fc94be. --- html.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 5f1cd6c..82d2e55 100644 --- a/html.c +++ b/html.c @@ -3306,7 +3306,7 @@ int html_get_handler(const xs_dict *req, const char *q_path, cache = 0; int skip = 0; - int def_show = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries")); + int def_show = xs_number_get(xs_dict_get_def(srv_config, "def_timeline_entries", "50")); int show = def_show; if ((v = xs_dict_get(q_vars, "skip")) != NULL) -- cgit v1.2.3 From f9796044c6c1fda786bd608987c1f41d5244e528 Mon Sep 17 00:00:00 2001 From: Alexandre Oliva Date: Thu, 6 Feb 2025 09:24:27 +0100 Subject: Merged 383bf2e2eeadcacfa519be7a56c9a301. --- html.c | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 82d2e55..8ad79de 100644 --- a/html.c +++ b/html.c @@ -13,6 +13,7 @@ #include "xs_html.h" #include "xs_curl.h" #include "xs_unicode.h" +#include "xs_url.h" #include "snac.h" @@ -115,7 +116,8 @@ xs_str *actor_name(xs_dict *actor, const char *proxy) xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, const char *udate, const char *url, int priv, - int in_people, const char *proxy, const char *lang) + int in_people, const char *proxy, const char *lang, + const char *md5) { xs_html *actor_icon = xs_html_tag("p", NULL); @@ -224,12 +226,29 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, if (xs_is_string(lang)) date_title = xs_str_cat(date_title, " (", lang, ")"); + xs_html *date_text = xs_html_text(date_label); + + if (user && md5) { + xs *lpost_url = xs_fmt("%s/admin/p/%s", + user->actor, md5); + date_text = xs_html_tag("a", + xs_html_attr("href", lpost_url), + date_text); + } + else if (user && url) { + xs *lpost_url = xs_fmt("%s/admin?q=%s", + user->actor, xs_url_enc(url)); + date_text = xs_html_tag("a", + xs_html_attr("href", lpost_url), + date_text); + } + xs_html_add(actor_icon, xs_html_text(" "), xs_html_tag("time", xs_html_attr("class", "dt-published snac-pubdate"), xs_html_attr("title", date_title), - xs_html_text(date_label))); + date_text)); } { @@ -261,7 +280,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, } -xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, const char *proxy) +xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, const char *proxy, const char *md5) { xs *actor = NULL; xs_html *actor_icon = NULL; @@ -292,7 +311,7 @@ xs_html *html_msg_icon(snac *user, const char *actor_id, const xs_dict *msg, con else lang = NULL; - actor_icon = html_actor_icon(user, actor, date, udate, url, priv, 0, proxy, lang); + actor_icon = html_actor_icon(user, actor, date, udate, url, priv, 0, proxy, lang, md5); } return actor_icon; @@ -1706,7 +1725,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, xs_html_tag("div", xs_html_attr("class", "snac-origin"), xs_html_text(L("follows you"))), - html_msg_icon(read_only ? NULL : user, xs_dict_get(msg, "actor"), msg, proxy))); + html_msg_icon(read_only ? NULL : user, xs_dict_get(msg, "actor"), msg, proxy, NULL))); } else if (!xs_match(type, POSTLIKE_OBJECT_TYPE)) { @@ -1887,7 +1906,7 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, } xs_html_add(post_header, - html_msg_icon(read_only ? NULL : user, actor, msg, proxy)); + html_msg_icon(read_only ? NULL : user, actor, msg, proxy, md5)); /** post content **/ @@ -2820,7 +2839,7 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t, cons xs_html_tag("div", xs_html_attr("class", "snac-post-header"), html_actor_icon(snac, actor, xs_dict_get(actor, "published"), - NULL, NULL, 0, 1, proxy, NULL))); + NULL, NULL, 0, 1, proxy, NULL, NULL))); /* content (user bio) */ const char *c = xs_dict_get(actor, "summary"); @@ -3118,7 +3137,7 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_add(entry, xs_html_tag("div", xs_html_attr("class", "snac-post"), - html_actor_icon(user, actor, NULL, NULL, NULL, 0, 0, proxy, NULL))); + html_actor_icon(user, actor, NULL, NULL, NULL, 0, 0, proxy, NULL, NULL))); } else if (strcmp(type, "Move") == 0) { @@ -3132,7 +3151,7 @@ xs_str *html_notifications(snac *user, int skip, int show) xs_html_add(entry, xs_html_tag("div", xs_html_attr("class", "snac-post"), - html_actor_icon(user, old_actor, NULL, NULL, NULL, 0, 0, proxy, NULL))); + html_actor_icon(user, old_actor, NULL, NULL, NULL, 0, 0, proxy, NULL, NULL))); } } } -- cgit v1.2.3 From 4ed3a01474dbb99597ce219ad5418df7557f6459 Mon Sep 17 00:00:00 2001 From: default Date: Thu, 6 Feb 2025 09:25:53 +0100 Subject: Added an anchor to the post link in the date. --- html.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index 8ad79de..13615b9 100644 --- a/html.c +++ b/html.c @@ -229,10 +229,11 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, xs_html *date_text = xs_html_text(date_label); if (user && md5) { - xs *lpost_url = xs_fmt("%s/admin/p/%s", - user->actor, md5); + xs *lpost_url = xs_fmt("%s/admin/p/%s#%s_entry", + user->actor, md5, md5); date_text = xs_html_tag("a", xs_html_attr("href", lpost_url), + xs_html_attr("class", "snac-pubdate"), date_text); } else if (user && url) { @@ -240,6 +241,7 @@ xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date, user->actor, xs_url_enc(url)); date_text = xs_html_tag("a", xs_html_attr("href", lpost_url), + xs_html_attr("class", "snac-pubdate"), date_text); } -- cgit v1.2.3 From f4fee170ce4d02182081f084975c3cd7d9ba4e93 Mon Sep 17 00:00:00 2001 From: default Date: Thu, 6 Feb 2025 19:16:49 +0100 Subject: If 'def_timeline_entries' is not set, 'max_timeline_entries' is used (instead of the default). --- html.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'html.c') diff --git a/html.c b/html.c index 13615b9..c12aea4 100644 --- a/html.c +++ b/html.c @@ -3327,7 +3327,8 @@ int html_get_handler(const xs_dict *req, const char *q_path, cache = 0; int skip = 0; - int def_show = xs_number_get(xs_dict_get_def(srv_config, "def_timeline_entries", "50")); + int def_show = xs_number_get(xs_dict_get_def(srv_config, "def_timeline_entries", + xs_dict_get_def(srv_config, "max_timeline_entries", "50"))); int show = def_show; if ((v = xs_dict_get(q_vars, "skip")) != NULL) -- cgit v1.2.3 From 5de52cb753abaab03e9405441542e73803c3fe08 Mon Sep 17 00:00:00 2001 From: default Date: Fri, 7 Feb 2025 09:26:54 +0100 Subject: Added support for multiple attachments in the same post. --- html.c | 168 ++++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 109 insertions(+), 59 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index c12aea4..1d6acfc 100644 --- a/html.c +++ b/html.c @@ -327,7 +327,7 @@ xs_html *html_note(snac *user, const char *summary, const xs_val *cw_yn, const char *cw_text, const xs_val *mnt_only, const char *redir, const char *in_reply_to, int poll, - const char *att_file, const char *att_alt_text, + const xs_list *att_files, const xs_list *att_alt_texts, int is_draft) /* Yes, this is a FUCKTON of arguments and I'm a bit embarrased */ { @@ -432,30 +432,71 @@ xs_html *html_note(snac *user, const char *summary, xs_html_tag("p", NULL), att = xs_html_tag("details", xs_html_tag("summary", - xs_html_text(L("Attachment..."))), + xs_html_text(L("Attachments..."))), xs_html_tag("p", NULL))); - if (att_file && *att_file) + int max_attachments = xs_number_get(xs_dict_get_def(srv_config, "max_attachments", "4")); + int att_n = 0; + + /* fields for the currently existing attachments */ + if (xs_is_list(att_files) && xs_is_list(att_alt_texts)) { + while (att_n < max_attachments) { + const char *att_file = xs_list_get(att_files, att_n); + const char *att_alt_text = xs_list_get(att_alt_texts, att_n); + + if (!xs_is_string(att_file) || !xs_is_string(att_alt_text)) + break; + + xs *att_lbl = xs_fmt("attach_url_%d", att_n); + xs *alt_lbl = xs_fmt("alt_text_%d", att_n); + + if (att_n) + xs_html_add(att, + xs_html_sctag("br", NULL)); + + xs_html_add(att, + xs_html_text(L("File:")), + xs_html_sctag("input", + xs_html_attr("type", "text"), + xs_html_attr("name", att_lbl), + xs_html_attr("title", L("Clear this field to delete the attachment")), + xs_html_attr("value", att_file))); + + xs_html_add(att, + xs_html_text(" "), + xs_html_sctag("input", + xs_html_attr("type", "text"), + xs_html_attr("name", alt_lbl), + xs_html_attr("value", att_alt_text), + xs_html_attr("placeholder", L("Attachment description")))); + + att_n++; + } + } + + /* the rest of possible attachments */ + while (att_n < max_attachments) { + xs *att_lbl = xs_fmt("attach_%d", att_n); + xs *alt_lbl = xs_fmt("alt_text_%d", att_n); + + if (att_n) + xs_html_add(att, + xs_html_sctag("br", NULL)); + 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_attr("type", "file"), + xs_html_attr("name", att_lbl))); + xs_html_add(att, + xs_html_text(" "), xs_html_sctag("input", - xs_html_attr("type", "file"), - xs_html_attr("name", "attach"))); + xs_html_attr("type", "text"), + xs_html_attr("name", alt_lbl), + xs_html_attr("placeholder", L("Attachment description")))); - 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")))); + att_n++; + } /* add poll controls */ if (poll) { @@ -1059,7 +1100,7 @@ xs_html *html_top_controls(snac *snac) NULL, NULL, xs_stock(XSTYPE_FALSE), "", xs_stock(XSTYPE_FALSE), NULL, - NULL, 1, "", "", 0), + NULL, 1, NULL, NULL, 0), /** operations **/ xs_html_tag("details", @@ -1631,17 +1672,22 @@ xs_html *html_entry_controls(snac *snac, const char *actor, xs *form_id = xs_fmt("%s_edit_form", md5); xs *redir = xs_fmt("%s_entry", md5); - const char *att_file = ""; - const char *att_alt_text = ""; + xs *att_files = xs_list_new(); + xs *att_alt_texts = xs_list_new(); + const 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)) { - const xs_dict *d = xs_list_get(att_list, 0); + if (xs_is_list(att_list)) { + const xs_dict *d; - if (xs_type(d) == XSTYPE_DICT) { - att_file = xs_dict_get_def(d, "url", ""); - att_alt_text = xs_dict_get_def(d, "name", ""); + xs_list_foreach(att_list, d) { + const char *att_file = xs_dict_get(d, "url"); + const char *att_alt_text = xs_dict_get(d, "name"); + + if (xs_is_string(att_file) && xs_is_string(att_alt_text)) { + att_files = xs_list_append(att_files, att_file); + att_alt_texts = xs_list_append(att_alt_texts, att_alt_text); + } } } @@ -1653,7 +1699,7 @@ xs_html *html_entry_controls(snac *snac, const char *actor, id, NULL, xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, - NULL, 0, att_file, att_alt_text, is_draft(snac, id))), + NULL, 0, att_files, att_alt_texts, is_draft(snac, id))), xs_html_tag("p", NULL)); } @@ -1672,7 +1718,7 @@ xs_html *html_entry_controls(snac *snac, const char *actor, NULL, NULL, xs_dict_get(msg, "sensitive"), xs_dict_get(msg, "summary"), xs_stock(is_msg_public(msg) ? XSTYPE_FALSE : XSTYPE_TRUE), redir, - id, 0, "", "", 0)), + id, 0, NULL, NULL, 0)), xs_html_tag("p", NULL)); } @@ -2938,7 +2984,7 @@ xs_html *html_people_list(snac *snac, xs_list *list, char *header, char *t, cons NULL, actor_id, xs_stock(XSTYPE_FALSE), "", xs_stock(XSTYPE_FALSE), NULL, - NULL, 0, "", "", 0), + NULL, 0, NULL, NULL, 0), xs_html_tag("p", NULL)); xs_html_add(snac_post, snac_controls); @@ -3966,52 +4012,56 @@ int html_post_handler(const xs_dict *req, const char *q_path, /* post note */ const xs_str *content = xs_dict_get(p_vars, "content"); const xs_str *in_reply_to = xs_dict_get(p_vars, "in_reply_to"); - const xs_str *attach_url = xs_dict_get(p_vars, "attach_url"); - const xs_list *attach_file = xs_dict_get(p_vars, "attach"); const xs_str *to = xs_dict_get(p_vars, "to"); const xs_str *sensitive = xs_dict_get(p_vars, "sensitive"); const xs_str *summary = xs_dict_get(p_vars, "summary"); const xs_str *edit_id = xs_dict_get(p_vars, "edit_id"); - const xs_str *alt_text = xs_dict_get(p_vars, "alt_text"); int priv = !xs_is_null(xs_dict_get(p_vars, "mentioned_only")); int store_as_draft = !xs_is_null(xs_dict_get(p_vars, "is_draft")); xs *attach_list = xs_list_new(); - /* default alt text */ - if (xs_is_null(alt_text)) - alt_text = ""; + /* iterate the attachments */ + int max_attachments = xs_number_get(xs_dict_get_def(srv_config, "max_attachments", "4")); - /* is attach_url set? */ - if (!xs_is_null(attach_url) && *attach_url != '\0') { - xs *l = xs_list_new(); + for (int att_n = 0; att_n < max_attachments; att_n++) { + xs *url_lbl = xs_fmt("attach_url_%d", att_n); + xs *att_lbl = xs_fmt("attach_%d", att_n); + xs *alt_lbl = xs_fmt("alt_text_%d", att_n); - l = xs_list_append(l, attach_url); - l = xs_list_append(l, alt_text); + const char *attach_url = xs_dict_get(p_vars, url_lbl); + const xs_list *attach_file = xs_dict_get(p_vars, att_lbl); + const char *alt_text = xs_dict_get_def(p_vars, alt_lbl, ""); - attach_list = xs_list_append(attach_list, l); - } + if (xs_is_string(attach_url) && *attach_url != '\0') { + xs *l = xs_list_new(); - /* is attach_file set? */ - if (!xs_is_null(attach_file) && xs_type(attach_file) == XSTYPE_LIST) { - const char *fn = xs_list_get(attach_file, 0); + l = xs_list_append(l, attach_url); + l = xs_list_append(l, alt_text); - if (*fn != '\0') { - char *ext = strrchr(fn, '.'); - xs *hash = xs_md5_hex(fn, strlen(fn)); - xs *id = xs_fmt("%s%s", hash, ext); - xs *url = xs_fmt("%s/s/%s", snac.actor, id); - int fo = xs_number_get(xs_list_get(attach_file, 1)); - int fs = xs_number_get(xs_list_get(attach_file, 2)); + attach_list = xs_list_append(attach_list, l); + } + else + if (xs_is_list(attach_file)) { + const char *fn = xs_list_get(attach_file, 0); - /* store */ - static_put(&snac, id, payload + fo, fs); + if (xs_is_string(fn) && *fn != '\0') { + char *ext = strrchr(fn, '.'); + xs *hash = xs_md5_hex(fn, strlen(fn)); + xs *id = xs_fmt("%s%s", hash, ext); + xs *url = xs_fmt("%s/s/%s", snac.actor, id); + int fo = xs_number_get(xs_list_get(attach_file, 1)); + int fs = xs_number_get(xs_list_get(attach_file, 2)); - xs *l = xs_list_new(); + /* store */ + static_put(&snac, id, payload + fo, fs); - l = xs_list_append(l, url); - l = xs_list_append(l, alt_text); + xs *l = xs_list_new(); - attach_list = xs_list_append(attach_list, l); + l = xs_list_append(l, url); + l = xs_list_append(l, alt_text); + + attach_list = xs_list_append(attach_list, l); + } } } -- cgit v1.2.3 From 54fe489c5f1582cbc8d627eccf2fe575dd38100c Mon Sep 17 00:00:00 2001 From: default Date: Sat, 8 Feb 2025 05:38:10 +0100 Subject: Show links to followed hashtags just below the list of lists. --- html.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'html.c') diff --git a/html.c b/html.c index 1d6acfc..f39bef4 100644 --- a/html.c +++ b/html.c @@ -2706,6 +2706,29 @@ xs_str *html_timeline(snac *user, const xs_list *list, int read_only, xs_html_attr("title", L("Post drafts")), xs_html_text("drafts")))); } + + /* the list of followed hashtags */ + const char *followed_hashtags = xs_dict_get(user->config, "followed_hashtags"); + + if (xs_is_list(followed_hashtags) && xs_list_len(followed_hashtags)) { + xs_html *loht = xs_html_tag("ul", + xs_html_attr("class", "snac-list-of-lists")); + xs_html_add(body, loht); + + const char *ht; + + xs_list_foreach(followed_hashtags, ht) { + xs *url = xs_fmt("%s/admin?q=%s", user->actor, ht); + url = xs_replace_i(url, "#", "%23"); + + xs_html_add(loht, + xs_html_tag("li", + xs_html_tag("a", + xs_html_attr("href", url), + xs_html_attr("class", "snac-list-link"), + xs_html_text(ht)))); + } + } } xs_html_add(body, -- cgit v1.2.3 From 99d28c3d6c476a1d70b83a5685fbc53dcb74dc2f Mon Sep 17 00:00:00 2001 From: default Date: Sat, 8 Feb 2025 16:59:26 +0100 Subject: Fixed crash in incomplete poll post. --- html.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'html.c') diff --git a/html.c b/html.c index f39bef4..e742e94 100644 --- a/html.c +++ b/html.c @@ -2099,16 +2099,17 @@ xs_html *html_entry(snac *user, xs_dict *msg, int read_only, const char *name = xs_dict_get(v, "name"); const xs_dict *replies = xs_dict_get(v, "replies"); - if (name && replies) { - char *ti = (char *)xs_number_str(xs_dict_get(replies, "totalItems")); + if (xs_is_string(name) && xs_is_dict(replies)) { + const char *ti = xs_number_str(xs_dict_get(replies, "totalItems")); - xs_html_add(poll_result, - xs_html_tag("tr", - xs_html_tag("td", - xs_html_text(name), - xs_html_text(":")), - xs_html_tag("td", - xs_html_text(ti)))); + if (xs_is_string(ti)) + xs_html_add(poll_result, + xs_html_tag("tr", + xs_html_tag("td", + xs_html_text(name), + xs_html_text(":")), + xs_html_tag("td", + xs_html_text(ti)))); } } -- cgit v1.2.3