mirror of
https://github.com/youwen5/iamb.git
synced 2025-06-20 05:39:52 -07:00
Support sending and completing Emoji shortcodes in the message bar (#100)
This commit is contained in:
parent
529073f4d4
commit
8d22b83d85
5 changed files with 83 additions and 5 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -494,6 +494,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "482aa5695bca086022be453c700a40c02893f1ba7098a2c88351de55341ae894"
|
checksum = "482aa5695bca086022be453c700a40c02893f1ba7098a2c88351de55341ae894"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
|
"emojis",
|
||||||
"entities",
|
"entities",
|
||||||
"memchr",
|
"memchr",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
|
@ -18,7 +18,7 @@ arboard = "3.2.0"
|
||||||
bitflags = "1.3.2"
|
bitflags = "1.3.2"
|
||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
clap = {version = "4.0", features = ["derive"]}
|
clap = {version = "4.0", features = ["derive"]}
|
||||||
comrak = "0.18.0"
|
comrak = {version = "0.18.0", features = ["shortcodes"]}
|
||||||
css-color-parser = "0.1.2"
|
css-color-parser = "0.1.2"
|
||||||
dirs = "4.0.0"
|
dirs = "4.0.0"
|
||||||
emojis = "~0.5.2"
|
emojis = "~0.5.2"
|
||||||
|
|
74
src/base.rs
74
src/base.rs
|
@ -788,9 +788,7 @@ impl ApplicationInfo for IambInfo {
|
||||||
IambBufferId::Command(CommandType::Command) => complete_cmdbar(text, cursor, store),
|
IambBufferId::Command(CommandType::Command) => complete_cmdbar(text, cursor, store),
|
||||||
IambBufferId::Command(CommandType::Search) => vec![],
|
IambBufferId::Command(CommandType::Search) => vec![],
|
||||||
|
|
||||||
IambBufferId::Room(_, RoomFocus::MessageBar) => {
|
IambBufferId::Room(_, RoomFocus::MessageBar) => complete_msgbar(text, cursor, store),
|
||||||
complete_matrix_names(text, cursor, store)
|
|
||||||
},
|
|
||||||
IambBufferId::Room(_, RoomFocus::Scrollback) => vec![],
|
IambBufferId::Room(_, RoomFocus::Scrollback) => vec![],
|
||||||
|
|
||||||
IambBufferId::DirectList => vec![],
|
IambBufferId::DirectList => vec![],
|
||||||
|
@ -822,6 +820,53 @@ fn complete_users(text: &EditRope, cursor: &mut Cursor, store: &ProgramStore) ->
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn complete_msgbar(text: &EditRope, cursor: &mut Cursor, store: &ProgramStore) -> Vec<String> {
|
||||||
|
let id = text
|
||||||
|
.get_prefix_word_mut(cursor, &MATRIX_ID_WORD)
|
||||||
|
.unwrap_or_else(EditRope::empty);
|
||||||
|
let id = Cow::from(&id);
|
||||||
|
|
||||||
|
match id.chars().next() {
|
||||||
|
// Complete room aliases.
|
||||||
|
Some('#') => {
|
||||||
|
return store.application.names.complete(id.as_ref());
|
||||||
|
},
|
||||||
|
|
||||||
|
// Complete room identifiers.
|
||||||
|
Some('!') => {
|
||||||
|
return store
|
||||||
|
.application
|
||||||
|
.rooms
|
||||||
|
.complete(id.as_ref())
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| i.to_string())
|
||||||
|
.collect();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Complete Emoji shortcodes.
|
||||||
|
Some(':') => {
|
||||||
|
let list = store.application.emojis.complete(&id[1..]);
|
||||||
|
let iter = list.into_iter().take(200).map(|s| format!(":{}:", s));
|
||||||
|
|
||||||
|
return iter.collect();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Complete usernames for @ and empty strings.
|
||||||
|
Some('@') | None => {
|
||||||
|
return store
|
||||||
|
.application
|
||||||
|
.presences
|
||||||
|
.complete(id.as_ref())
|
||||||
|
.into_iter()
|
||||||
|
.map(|i| i.to_string())
|
||||||
|
.collect();
|
||||||
|
},
|
||||||
|
|
||||||
|
// Unknown sigil.
|
||||||
|
Some(_) => return vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn complete_matrix_names(
|
fn complete_matrix_names(
|
||||||
text: &EditRope,
|
text: &EditRope,
|
||||||
cursor: &mut Cursor,
|
cursor: &mut Cursor,
|
||||||
|
@ -1011,6 +1056,29 @@ pub mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_complete_msgbar() {
|
||||||
|
let store = mock_store().await;
|
||||||
|
|
||||||
|
let text = EditRope::from("going for a walk :walk ");
|
||||||
|
let mut cursor = Cursor::new(0, 22);
|
||||||
|
let res = complete_msgbar(&text, &mut cursor, &store);
|
||||||
|
assert_eq!(res, vec![":walking:", ":walking_man:", ":walking_woman:"]);
|
||||||
|
assert_eq!(cursor, Cursor::new(0, 17));
|
||||||
|
|
||||||
|
let text = EditRope::from("hello @user1 ");
|
||||||
|
let mut cursor = Cursor::new(0, 12);
|
||||||
|
let res = complete_msgbar(&text, &mut cursor, &store);
|
||||||
|
assert_eq!(res, vec!["@user1:example.com"]);
|
||||||
|
assert_eq!(cursor, Cursor::new(0, 6));
|
||||||
|
|
||||||
|
let text = EditRope::from("see #room ");
|
||||||
|
let mut cursor = Cursor::new(0, 9);
|
||||||
|
let res = complete_msgbar(&text, &mut cursor, &store);
|
||||||
|
assert_eq!(res, vec!["#room1:example.com"]);
|
||||||
|
assert_eq!(cursor, Cursor::new(0, 4));
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_complete_cmdbar() {
|
async fn test_complete_cmdbar() {
|
||||||
let store = mock_store().await;
|
let store = mock_store().await;
|
||||||
|
|
|
@ -97,6 +97,7 @@ const TIME_GUTTER_EMPTY_SPAN: Span<'static> = span_static(TIME_GUTTER_EMPTY);
|
||||||
|
|
||||||
fn text_to_message_content(input: String) -> TextMessageEventContent {
|
fn text_to_message_content(input: String) -> TextMessageEventContent {
|
||||||
let mut options = ComrakOptions::default();
|
let mut options = ComrakOptions::default();
|
||||||
|
options.extension.shortcodes = true;
|
||||||
options.render.hardbreaks = true;
|
options.render.hardbreaks = true;
|
||||||
let html = markdown_to_html(input.as_str(), &options);
|
let html = markdown_to_html(input.as_str(), &options);
|
||||||
|
|
||||||
|
@ -1013,6 +1014,11 @@ pub mod tests {
|
||||||
"<pre><code class=\"language-rust\">const A: usize = 1;\n</code></pre>\n"
|
"<pre><code class=\"language-rust\">const A: usize = 1;\n</code></pre>\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let input = ":heart:\n";
|
||||||
|
let content = text_to_message_content(input.into());
|
||||||
|
assert_eq!(content.body, input);
|
||||||
|
assert_eq!(content.formatted.unwrap().body, "<p>\u{2764}\u{FE0F}</p>\n");
|
||||||
|
|
||||||
let input = "para 1\n\npara 2\n";
|
let input = "para 1\n\npara 2\n";
|
||||||
let content = text_to_message_content(input.into());
|
let content = text_to_message_content(input.into());
|
||||||
assert_eq!(content.body, input);
|
assert_eq!(content.body, input);
|
||||||
|
|
|
@ -42,6 +42,8 @@ use crate::{
|
||||||
worker::Requester,
|
worker::Requester,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const TEST_ROOM1_ALIAS: &str = "#room1:example.com";
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref TEST_ROOM1_ID: OwnedRoomId = RoomId::new(server_name!("example.com")).to_owned();
|
pub static ref TEST_ROOM1_ID: OwnedRoomId = RoomId::new(server_name!("example.com")).to_owned();
|
||||||
pub static ref TEST_USER1: OwnedUserId = user_id!("@user1:example.com").to_owned();
|
pub static ref TEST_USER1: OwnedUserId = user_id!("@user1:example.com").to_owned();
|
||||||
|
@ -223,7 +225,8 @@ pub async fn mock_store() -> ProgramStore {
|
||||||
let room_id = TEST_ROOM1_ID.clone();
|
let room_id = TEST_ROOM1_ID.clone();
|
||||||
let info = mock_room();
|
let info = mock_room();
|
||||||
|
|
||||||
store.rooms.insert(room_id, info);
|
store.rooms.insert(room_id.clone(), info);
|
||||||
|
store.names.insert(TEST_ROOM1_ALIAS.to_string(), room_id);
|
||||||
|
|
||||||
ProgramStore::new(store)
|
ProgramStore::new(store)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue