Support sending custom emoji in messages and reactions
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use std::hash::Hash;
|
||||
use std::ops::Range;
|
||||
|
||||
use common::{EventExt, NostrParser, extract_and_remove_media_urls};
|
||||
use common::{EventExt, NostrParser, emojis_from_tags, extract_and_remove_media_urls};
|
||||
use gpui::{SharedString, SharedUri};
|
||||
use nostr_sdk::prelude::*;
|
||||
use state::FileAttachment;
|
||||
@@ -87,7 +87,7 @@ fn from_parts(
|
||||
let has_file = file.is_some();
|
||||
|
||||
let replies_to = extract_reply_ids(tags);
|
||||
let emojis = Message::emojis_from_tags(tags);
|
||||
let emojis = emojis_from_tags(tags);
|
||||
|
||||
// For file messages `.content` is the encrypted blob URL, not text or media
|
||||
let mentions = if has_file {
|
||||
@@ -151,28 +151,6 @@ impl Message {
|
||||
self.content.clone().into()
|
||||
}
|
||||
|
||||
/// Custom emoji (NIP-30) declared by `emoji` tags, first per shortcode wins
|
||||
pub fn emojis_from_tags(tags: &Tags) -> Vec<(String, Url)> {
|
||||
let mut emojis: Vec<(String, Url)> = Vec::new();
|
||||
|
||||
for tag in tags.iter() {
|
||||
let Ok(Nip30Tag::Emoji {
|
||||
shortcode,
|
||||
image_url,
|
||||
..
|
||||
}) = Nip30Tag::try_from(tag)
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if !emojis.iter().any(|(existing, _)| *existing == shortcode) {
|
||||
emojis.push((shortcode, image_url));
|
||||
}
|
||||
}
|
||||
|
||||
emojis
|
||||
}
|
||||
|
||||
/// Image URL of a `:shortcode:` reaction, if the shortcode is declared
|
||||
pub fn reaction_image(content: &str, emojis: &[(String, Url)]) -> Option<Url> {
|
||||
let shortcode = content.strip_prefix(':')?.strip_suffix(':')?;
|
||||
@@ -278,24 +256,6 @@ mod tests {
|
||||
Tag::parse(vec!["emoji", shortcode, url]).expect("valid emoji tag")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn emojis_from_tags_parses_and_deduplicates() {
|
||||
let tags = Tags::from_list(vec![
|
||||
emoji_tag("soapbox", "https://example.com/soapbox.png"),
|
||||
emoji_tag("soapbox", "https://example.com/other.png"),
|
||||
emoji_tag("bad shortcode", "https://example.com/bad.png"),
|
||||
]);
|
||||
|
||||
let emojis = Message::emojis_from_tags(&tags);
|
||||
|
||||
assert_eq!(emojis.len(), 1);
|
||||
assert_eq!(emojis[0].0, "soapbox");
|
||||
assert_eq!(
|
||||
emojis[0].1,
|
||||
Url::parse("https://example.com/soapbox.png").unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn message_parses_emoji_tags() {
|
||||
let tags = Tags::from_list(vec![emoji_tag(
|
||||
|
||||
@@ -405,8 +405,11 @@ impl Room {
|
||||
|
||||
// Construct a direct message rumor event
|
||||
// WARNING: never sign and send this event to relays
|
||||
let mut tags = self.conversation_tags(&replies, sender, cx);
|
||||
tags.extend(PersonRegistry::emoji_tags(&content, cx));
|
||||
|
||||
let mut event = EventBuilder::new(kind, content)
|
||||
.tags(self.conversation_tags(&replies, sender, cx))
|
||||
.tags(tags)
|
||||
.finalize_unsigned(sender);
|
||||
|
||||
// Ensure that the ID is set
|
||||
|
||||
Reference in New Issue
Block a user