commit 6e42d34

grunfink  ·  2025-05-06 03:55:43 +0000 UTC
parents 97568a7, 0c03e6c
Merge pull request 'Display custom emoji in more places' (#343) from dandelions/snac2:emoji-pr into master

Reviewed-on: https://codeberg.org/grunfink/snac2/pulls/343
6 files changed,  +54, -18
M html.c
M snac.h
+4, -0
 1@@ -1332,6 +1332,10 @@ xs_dict *msg_actor(snac *snac)
 2     msg = xs_dict_set(msg, "preferredUsername", snac->uid);
 3     msg = xs_dict_set(msg, "published",         xs_dict_get(snac->config, "published"));
 4 
 5+    // this exists so we get the emoji tags from our name too.
 6+    // and then we just throw away the result, because it's kinda useless to have markdown in the display name.
 7+    xs *name_dummy = not_really_markdown(xs_dict_get(snac->config, "name"), NULL, &tags);
 8+
 9     xs *f_bio_2 = not_really_markdown(xs_dict_get(snac->config, "bio"), NULL, &tags);
10     f_bio = process_tags(snac, f_bio_2, &tags);
11     msg = xs_dict_set(msg, "summary", f_bio);
+3, -2
 1@@ -405,10 +405,11 @@ xs_str *not_really_markdown(const char *content, xs_list **attach, xs_list **tag
 2         const char *k, *v;
 3 
 4         while (xs_dict_next(d, &k, &v, &c)) {
 5-            const char *t = NULL;
 6+            const char *t = xs_mime_by_ext(v);
 7 
 8             /* is it an URL to an image? */
 9-            if (xs_startswith(v, "https:/" "/") && xs_startswith((t = xs_mime_by_ext(v)), "image/")) {
10+            if (xs_startswith(v, "https:/" "/") &&
11+                (xs_startswith(t, "image/") || strcmp(t, "application/octet-stream") == 0)) {
12                 if (tag && xs_str_in(s, k) != -1) {
13                     /* add the emoji to the tag list */
14                     xs *e = xs_dict_new();
M html.c
+42, -15
  1@@ -69,6 +69,7 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p
  2         }
  3 
  4         xs *style = xs_fmt("height: %dem; width: %dem; vertical-align: middle;", ems, ems);
  5+        xs *class = xs_fmt("snac-emoji snac-emoji-%d-em", ems);
  6 
  7         const xs_dict *v;
  8         int c = 0;
  9@@ -91,7 +92,13 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p
 10                     const char *u = xs_dict_get(i, "url");
 11                     const char *mt = xs_dict_get(i, "mediaType");
 12 
 13-                    if (xs_is_string(u) && xs_is_string(mt)) {
 14+                    if (xs_is_string(u)) {
 15+                        // on akkoma instances mediaType is not present.
 16+                        // but we need to to know if the image is an svg or not.
 17+                        // for now, i just use the file extention, which may not be the most reliable...
 18+                        if (!xs_is_string(mt))
 19+                            mt = xs_mime_by_ext(u);
 20+
 21                         if (strcmp(mt, "image/svg+xml") == 0 && !xs_is_true(xs_dict_get(srv_config, "enable_svg")))
 22                             s = xs_replace_i(s, n, "");
 23                         else {
 24@@ -102,7 +109,7 @@ xs_str *replace_shortnames(xs_str *s, const xs_list *tag, int ems, const char *p
 25                                 xs_html_attr("src", url),
 26                                 xs_html_attr("alt", n),
 27                                 xs_html_attr("title", n),
 28-                                xs_html_attr("class", "snac-emoji"),
 29+                                xs_html_attr("class", class),
 30                                 xs_html_attr("style", style));
 31 
 32                             xs *s1 = xs_html_render(img);
 33@@ -137,6 +144,26 @@ xs_str *actor_name(xs_dict *actor, const char *proxy)
 34 }
 35 
 36 
 37+xs_str *format_text_with_emoji(snac *user, const char *text, int ems, const char *proxy)
 38+/* needed when we have local text with no tags attached */
 39+{
 40+    xs *tags = xs_list_new();
 41+    xs *name1 = not_really_markdown(text, NULL, &tags);
 42+
 43+    xs_str *name3;
 44+    if (user) {
 45+        xs *name2 = process_tags(user, name1, &tags);
 46+        name3 = sanitize(name2);
 47+    }
 48+    else {
 49+        name3 = sanitize(name1);
 50+        name3 = xs_replace_i(name3, "<br>", "");
 51+    }
 52+
 53+    return replace_shortnames(name3, tags, ems, proxy);
 54+}
 55+
 56+
 57 xs_html *html_actor_icon(snac *user, xs_dict *actor, const char *date,
 58                         const char *udate, const char *url, int priv,
 59                         int in_people, const char *proxy, const char *lang,
 60@@ -970,10 +997,12 @@ static xs_html *html_user_body(snac *user, int read_only)
 61         xs_dict_get(user->config, "uid"),
 62         xs_dict_get(srv_config, "host"));
 63 
 64+    xs *display_name = format_text_with_emoji(NULL, xs_dict_get(user->config, "name"), 1, proxy);
 65+
 66     xs_html_add(top_user,
 67         xs_html_tag("p",
 68             xs_html_attr("class", "p-name snac-top-user-name"),
 69-            xs_html_text(xs_dict_get(user->config, "name"))),
 70+            xs_html_raw(display_name)),
 71         xs_html_tag("p",
 72             xs_html_attr("class", "snac-top-user-id"),
 73             xs_html_text(handle)));
 74@@ -1001,16 +1030,11 @@ static xs_html *html_user_body(snac *user, int read_only)
 75     }
 76 
 77     if (read_only) {
 78-        xs *tags = xs_list_new();
 79-        xs *bio1 = not_really_markdown(xs_dict_get(user->config, "bio"), NULL, &tags);
 80-        xs *bio2 = process_tags(user, bio1, &tags);
 81-        xs *bio3 = sanitize(bio2);
 82-
 83-        bio3 = replace_shortnames(bio3, tags, 2, proxy);
 84+        xs *bio = format_text_with_emoji(user, xs_dict_get(user->config, "bio"), 2, proxy);
 85 
 86         xs_html *top_user_bio = xs_html_tag("div",
 87             xs_html_attr("class", "p-note snac-top-user-bio"),
 88-            xs_html_raw(bio3)); /* already sanitized */
 89+            xs_html_raw(bio)); /* already sanitized */
 90 
 91         xs_html_add(top_user,
 92             top_user_bio);
 93@@ -3134,6 +3158,7 @@ xs_html *html_people_list(snac *user, xs_list *list, const char *header, const c
 94 
 95             if (!xs_is_null(c)) {
 96                 xs *sc = sanitize(c);
 97+                sc = replace_shortnames(sc, xs_dict_get(actor, "tag"), 2, proxy);
 98 
 99                 xs_html *snac_content = xs_html_tag("div",
100                     xs_html_attr("class", "snac-content"));
101@@ -3351,7 +3376,8 @@ xs_str *html_notifications(snac *user, int skip, int show)
102             continue;
103 
104         xs *a_name = actor_name(actor, proxy);
105-        const char *label = type;
106+        xs *label_sanatized = sanitize(type);
107+        const char *label = label_sanatized;
108 
109         if (strcmp(type, "Create") == 0)
110             label = L("Mention");
111@@ -3362,11 +3388,12 @@ xs_str *html_notifications(snac *user, int skip, int show)
112         if (strcmp(type, "Undo") == 0 && strcmp(utype, "Follow") == 0)
113             label = L("Unfollow");
114         else
115-        if (strcmp(type, "EmojiReact") == 0) {
116+        if (strcmp(type, "EmojiReact") == 0 || strcmp(type, "Like") == 0) {
117             const char *content = xs_dict_get_path(noti, "msg.content");
118 
119             if (xs_type(content) == XSTYPE_STRING) {
120-                wrk = xs_fmt("%s (%s)", type, content);
121+                xs *emoji = replace_shortnames(xs_dup(content), xs_dict_get_path(noti, "msg.tag"), 1, proxy);
122+                wrk = xs_fmt("%s (%s&#xFE0F;)", type, emoji);
123                 label = wrk;
124             }
125         }
126@@ -3378,7 +3405,7 @@ xs_str *html_notifications(snac *user, int skip, int show)
127 
128         xs_html *this_html_label = xs_html_container(
129                 xs_html_tag("b",
130-                    xs_html_text(label),
131+                    xs_html_raw(label),
132                     xs_html_text(" by "),
133                     xs_html_tag("a",
134                         xs_html_attr("href", actor_id),
135@@ -3678,7 +3705,7 @@ int html_get_handler(const xs_dict *req, const char *q_path,
136 
137             if (xs_is_true(xs_dict_get(srv_config, "strict_public_timelines")))
138                 list = timeline_simple_list(&snac, "public", skip, show, &more);
139-            else 
140+            else
141                 list = timeline_list(&snac, "public", skip, show, &more);
142 
143             xs *pins = pinned_list(&snac);
+3, -1
 1@@ -139,6 +139,8 @@ static xs_str *greeting_html(void)
 2                 snac user;
 3 
 4                 if (strcmp(uid, "relay") && user_open(&user, uid)) {
 5+                    xs *formatted_name = format_text_with_emoji(NULL, xs_dict_get(user.config, "name"), 1, NULL);
 6+
 7                     xs_html_add(ul,
 8                         xs_html_tag("li",
 9                             xs_html_tag("a",
10@@ -148,7 +150,7 @@ static xs_str *greeting_html(void)
11                                 xs_html_text("@"),
12                                 xs_html_text(host),
13                                 xs_html_text(" ("),
14-                                xs_html_text(xs_dict_get(user.config, "name")),
15+                                xs_html_raw(formatted_name),
16                                 xs_html_text(")"))));
17 
18                     user_free(&user);
M snac.h
+1, -0
1@@ -375,6 +375,7 @@ int activitypub_post_handler(const xs_dict *req, const char *q_path,
2                              char **body, int *b_size, char **ctype);
3 
4 xs_dict *emojis(void);
5+xs_str *format_text_with_emoji(snac *user, const char *text, int ems, const char *proxy);
6 xs_str *not_really_markdown(const char *content, xs_list **attach, xs_list **tag);
7 xs_str *sanitize(const char *content);
8 xs_str *encode_html(const char *str);
+1, -0
1@@ -16,6 +16,7 @@ extern const char *xs_mime_types[];
2 const char *xs_mime_types[] = {
3     "3gp",      "video/3gpp",
4     "aac",      "audio/aac",
5+    "apng",     "image/apng",
6     "avif",     "image/avif",
7     "css",      "text/css",
8     "flac",     "audio/flac",