R7 custom emoji in decePub: the server's own, administered, picked, suggested and shown

Administration has a Custom emoji section (EmojiPanel, data-admin-section=emoji): the server's emoji by category, added
with a picture streamed from the file, changed (category, picker, disabled, picture; never the shortcode) and deleted,
asked first, with PrivaPub's 409 and 422 in the dialog. EmojiService reads /clientapi/admin/emoji and, for everyone,
/api/v1/custom_emojis, kept a day in localStorage (CustomEmojiCache) and read again after a change here. EmojiPicker
(a DDropdown sheet on a phone, rendered only while open) offers them by category with common unicode emoji, searchable:
the composer writes the choice at the caret, a card and the announcements banner react with it. The composer suggests
custom emoji after `:` and two letters. Custom reactions toggle as :shortcode: and show their picture, notifications of
one too; located posts, announcements and NavMenu's persona names render the server's emoji.

Verified: Release build, 0 errors (the 3 warnings were there before). Not run against PrivaPub or in the pasture.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WpVCoDeM1qUTRp4fXQdfof
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-18 08:24:43 +02:00
1 parent c572471b88
commit 566b0e33ea
26 files changed
+1385 -56

No files matched your search

+119
View File
@@ -0,0 +1,119 @@
namespace decePubClient.Helpers
{
/// <summary>
/// The unicode emoji the picker offers (Components/EmojiPicker.razor) next to the server's custom ones: common ones by
/// group, not the whole of Unicode, each a single emoji with no skin tone or joined sequence, as PrivaPub takes a
/// reaction. Each has the shortcode Mastodon's and GitHub's pickers know it by, and a few words, which the search
/// matches (codes, never shown as text); a group's Name is a localization key.
/// </summary>
public static class UnicodeEmojis
{
public sealed record Emoji(string Character, string Shortcode, string Words = null);
public sealed record Group(string Key, string Name, IReadOnlyList<Emoji> Emojis);
public static readonly IReadOnlyList<Group> Groups =
[
new("smileys", "Smileys",
[
new("😀", "grinning", "smile happy"), new("😃", "smiley", "happy"), new("😄", "smile", "happy"), new("😁", "grin", "teeth"),
new("😆", "laughing", "lol"), new("😅", "sweat_smile", "relief"), new("🤣", "rofl", "laugh floor"), new("😂", "joy", "tears laugh lol"),
new("🙂", "slightly_smiling_face", "smile"), new("🙃", "upside_down_face", "silly"), new("😉", "wink"), new("😊", "blush", "smile"),
new("😇", "innocent", "halo angel"), new("🥰", "smiling_face_with_three_hearts", "love"), new("😍", "heart_eyes", "love"),
new("🤩", "star_struck", "wow"), new("😘", "kissing_heart", "kiss"), new("😋", "yum", "tasty"), new("😛", "stuck_out_tongue", "tongue"),
new("😜", "stuck_out_tongue_winking_eye", "tongue wink"), new("🤪", "zany_face", "crazy"), new("🤔", "thinking", "hmm"),
new("🤗", "hugs", "hug"), new("🤭", "hand_over_mouth", "oops"), new("🤫", "shushing_face", "quiet"), new("😐", "neutral_face", "meh"),
new("😑", "expressionless"), new("😶", "no_mouth", "silent"), new("😏", "smirk"), new("😒", "unamused"),
new("🙄", "roll_eyes", "eyeroll"), new("😬", "grimacing", "awkward"), new("😌", "relieved"), new("😔", "pensive", "sad"),
new("😪", "sleepy", "tired"), new("😴", "sleeping", "zzz"), new("😷", "mask", "sick"), new("🤒", "face_with_thermometer", "ill"),
new("🤢", "nauseated_face", "sick"), new("🥵", "hot_face", "heat"), new("🥶", "cold_face", "freezing"), new("🥴", "woozy_face", "dizzy"),
new("🤯", "exploding_head", "mind blown"), new("🥳", "partying_face", "party"), new("😎", "sunglasses", "cool"),
new("🤓", "nerd_face", "geek"), new("😕", "confused"), new("😟", "worried"), new("😮", "open_mouth", "wow surprised"),
new("😲", "astonished", "shocked"), new("😳", "flushed", "embarrassed"), new("🥺", "pleading_face", "please"), new("😢", "cry", "sad tear"),
new("😭", "sob", "crying"), new("😱", "scream", "fear"), new("😤", "triumph", "huff"), new("😠", "angry", "mad"), new("😡", "rage", "angry"),
new("🤬", "cursing_face", "swear"), new("💀", "skull", "dead"), new("💩", "poop", "poo"), new("🤡", "clown_face", "clown"),
new("👻", "ghost", "boo"), new("👽", "alien", "ufo"), new("🤖", "robot", "bot")
]),
new("people", "People",
[
new("👍", "thumbsup", "+1 like yes"), new("👎", "thumbsdown", "-1 dislike no"), new("👌", "ok_hand", "okay"), new("✌️", "v", "peace victory"),
new("🤞", "crossed_fingers", "luck"), new("🤟", "love_you_gesture"), new("🤘", "metal", "rock"), new("👋", "wave", "hello bye"),
new("👏", "clap", "applause"), new("🙌", "raised_hands", "hooray"), new("👐", "open_hands"), new("🤝", "handshake", "deal"),
new("🙏", "pray", "thanks please"), new("✍️", "writing_hand", "write"), new("💪", "muscle", "strong"), new("👀", "eyes", "look"),
new("🧠", "brain", "smart"), new("👶", "baby"), new("🧑", "adult", "person"), new("🤷", "shrug", "dunno"),
new("🤦", "facepalm"), new("🙋", "raising_hand", "me"), new("🙇", "bow", "sorry"), new("💃", "dancer", "dance"),
new("🕺", "man_dancing", "dance")
]),
new("nature", "Animals and nature",
[
new("🐶", "dog", "puppy"), new("🐱", "cat", "kitten"), new("🐭", "mouse"), new("🐰", "rabbit", "bunny"), new("🦊", "fox_face", "fox"),
new("🐻", "bear"), new("🐼", "panda_face", "panda"), new("🐨", "koala"), new("🐯", "tiger"), new("🦁", "lion"),
new("🐮", "cow"), new("🐷", "pig"), new("🐸", "frog"), new("🐵", "monkey_face", "monkey"), new("🐔", "chicken"),
new("🐧", "penguin"), new("🐦", "bird"), new("🦆", "duck"), new("🦉", "owl"), new("🦇", "bat"), new("🐺", "wolf"),
new("🐴", "horse"), new("🦄", "unicorn"), new("🐝", "bee"), new("🐛", "bug"), new("🦋", "butterfly"),
new("🐌", "snail"), new("🐢", "turtle"), new("🐍", "snake"), new("🐙", "octopus"), new("🐟", "fish"),
new("🐬", "dolphin"), new("🐳", "whale"), new("🦀", "crab"), new("🌵", "cactus"), new("🌲", "evergreen_tree", "tree"),
new("🌳", "deciduous_tree", "tree"), new("🌴", "palm_tree", "tree"), new("🌱", "seedling", "plant"), new("🍀", "four_leaf_clover", "luck"),
new("🍁", "maple_leaf", "autumn"), new("🍄", "mushroom"), new("🌸", "cherry_blossom", "flower"), new("🌹", "rose", "flower"),
new("🌻", "sunflower", "flower"), new("🌷", "tulip", "flower"), new("🌍", "earth_africa", "world globe"), new("🌙", "crescent_moon", "moon night"),
new("☀️", "sunny", "sun"), new("🌈", "rainbow"), new("☁️", "cloud"), new("❄️", "snowflake", "snow winter"), new("⚡", "zap", "lightning"),
new("🌊", "ocean", "wave sea")
]),
new("food", "Food and drink",
[
new("🍎", "apple"), new("🍐", "pear"), new("🍊", "tangerine", "orange"), new("🍋", "lemon"), new("🍌", "banana"),
new("🍉", "watermelon"), new("🍇", "grapes"), new("🍓", "strawberry"), new("🍒", "cherries"), new("🍑", "peach"),
new("🥑", "avocado"), new("🍅", "tomato"), new("🌶️", "hot_pepper", "chili"), new("🥕", "carrot"), new("🌽", "corn"),
new("🥐", "croissant"), new("🍞", "bread"), new("🧀", "cheese"), new("🍕", "pizza"), new("🍔", "hamburger", "burger"),
new("🍟", "fries"), new("🌭", "hotdog"), new("🌮", "taco"), new("🍝", "spaghetti", "pasta"), new("🍜", "ramen", "noodles"),
new("🍣", "sushi"), new("🍦", "icecream"), new("🍩", "doughnut", "donut"), new("🍪", "cookie"), new("🎂", "birthday", "cake"),
new("🍰", "cake"), new("🍫", "chocolate_bar", "chocolate"), new("🍿", "popcorn"), new("☕", "coffee"), new("🍵", "tea"),
new("🍺", "beer"), new("🍻", "beers", "cheers"), new("🍷", "wine_glass", "wine"), new("🥂", "clinking_glasses", "cheers toast"),
new("🍸", "cocktail")
]),
new("activities", "Activities",
[
new("⚽", "soccer", "football"), new("🏀", "basketball"), new("🏈", "football"), new("⚾", "baseball"), new("🎾", "tennis"),
new("🏐", "volleyball"), new("🎱", "8ball", "pool"), new("🏓", "ping_pong"), new("🏆", "trophy", "win"),
new("🥇", "1st_place_medal", "gold"), new("🎮", "video_game", "game"), new("🎲", "game_die", "dice"), new("♟️", "chess_pawn", "chess"),
new("🎯", "dart", "target"), new("🎨", "art", "paint"), new("🎭", "performing_arts", "theatre"), new("🎬", "clapper", "film"),
new("🎤", "microphone", "sing"), new("🎧", "headphones", "music"), new("🎸", "guitar"), new("🎹", "musical_keyboard", "piano"),
new("🎵", "musical_note", "music"), new("🎉", "tada", "party hooray"), new("🎊", "confetti_ball", "party"), new("🎈", "balloon"),
new("🎁", "gift", "present"), new("🎄", "christmas_tree"), new("🎃", "jack_o_lantern", "halloween")
]),
new("travel", "Travel and places",
[
new("🚗", "car"), new("🚕", "taxi"), new("🚌", "bus"), new("🚲", "bike", "bicycle"), new("🛴", "kick_scooter", "scooter"),
new("🚂", "steam_locomotive", "train"), new("🚆", "train2", "train"), new("✈️", "airplane", "plane flight"), new("🚀", "rocket", "launch"),
new("🛸", "flying_saucer", "ufo"), new("⛵", "boat", "sail"), new("🚢", "ship"), new("🏠", "house", "home"),
new("🏡", "house_with_garden", "home"), new("🏢", "office", "building"), new("🏰", "european_castle", "castle"), new("⛪", "church"),
new("🗼", "tokyo_tower", "tower"), new("🗽", "statue_of_liberty"), new("🏔️", "mountain_snow", "mountain"),
new("🏖️", "beach_umbrella", "beach"), new("🏕️", "camping"), new("🌋", "volcano"), new("🗺️", "world_map", "map"),
new("🧭", "compass"), new("⛺", "tent", "camping"), new("🌃", "night_with_stars", "night city"), new("🌅", "sunrise")
]),
new("objects", "Objects",
[
new("📱", "iphone", "phone mobile"), new("💻", "computer", "laptop"), new("⌨️", "keyboard"), new("🖥️", "desktop_computer", "computer"),
new("💾", "floppy_disk", "save"), new("📷", "camera", "photo"), new("🎥", "movie_camera", "video"), new("📺", "tv", "television"),
new("📻", "radio"), new("⏰", "alarm_clock", "time"), new("⌛", "hourglass", "time"), new("💡", "bulb", "idea"),
new("🔦", "flashlight", "torch"), new("📚", "books", "read"), new("📖", "book", "read"), new("📝", "memo", "note write"),
new("✏️", "pencil2", "pencil write"), new("📌", "pushpin", "pin"), new("📎", "paperclip"), new("✂️", "scissors", "cut"),
new("🔒", "lock", "private"), new("🔑", "key"), new("🔨", "hammer", "tool"), new("🔧", "wrench", "tool"), new("⚙️", "gear", "settings"),
new("🧲", "magnet"), new("🧪", "test_tube", "science"), new("🔭", "telescope", "space"), new("💊", "pill", "medicine"),
new("🛒", "shopping_cart", "shop"), new("💰", "moneybag", "money"), new("💸", "money_with_wings", "money"), new("📦", "package", "box"),
new("✉️", "envelope", "mail letter"), new("📣", "mega", "announce"), new("🔔", "bell", "notification")
]),
new("symbols", "Symbols",
[
new("❤️", "heart", "love red"), new("🧡", "orange_heart", "love"), new("💛", "yellow_heart", "love"), new("💚", "green_heart", "love"),
new("💙", "blue_heart", "love"), new("💜", "purple_heart", "love"), new("🖤", "black_heart", "love"), new("🤍", "white_heart", "love"),
new("💔", "broken_heart", "sad"), new("💕", "two_hearts", "love"), new("💖", "sparkling_heart", "love"), new("💯", "100", "perfect"),
new("✨", "sparkles", "shiny"), new("⭐", "star"), new("🌟", "star2", "glowing star"), new("💫", "dizzy", "star"), new("🔥", "fire", "hot lit"),
new("💥", "boom", "explosion"), new("💢", "anger", "angry"), new("💬", "speech_balloon", "comment talk"), new("💤", "zzz", "sleep"),
new("✅", "white_check_mark", "done yes"), new("❌", "x", "no cross"), new("❓", "question"), new("❗", "exclamation"),
new("⚠️", "warning"), new("♻️", "recycle"), new("➕", "heavy_plus_sign", "plus"), new("➖", "heavy_minus_sign", "minus"),
new("🆗", "ok"), new("🆒", "cool"), new("🆕", "new")
])
];
}
}