add send reaction
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
use instant::Duration;
|
|
||||||
|
|
||||||
use anyhow::{Error, anyhow};
|
use anyhow::{Error, anyhow};
|
||||||
use common::EventExt;
|
use common::EventExt;
|
||||||
use device::DeviceRegistry;
|
use device::DeviceRegistry;
|
||||||
use gpui::{App, AppContext, Context, EventEmitter, SharedString, Task};
|
use gpui::{App, AppContext, Context, EventEmitter, SharedString, Task};
|
||||||
|
use instant::Duration;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use nostr_sdk::prelude::*;
|
use nostr_sdk::prelude::*;
|
||||||
use person::{Person, PersonRegistry};
|
use person::{Person, PersonRegistry};
|
||||||
@@ -419,12 +419,23 @@ impl Room {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Construct a rumor event for direct message
|
// Construct a rumor event for direct message
|
||||||
pub fn rumor<S, I>(&self, content: S, replies: I, cx: &App) -> Option<UnsignedEvent>
|
pub fn rumor<S, I>(
|
||||||
|
&self,
|
||||||
|
content: S,
|
||||||
|
replies: I,
|
||||||
|
reaction: bool,
|
||||||
|
cx: &App,
|
||||||
|
) -> Option<UnsignedEvent>
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<String>,
|
||||||
I: IntoIterator<Item = EventId>,
|
I: IntoIterator<Item = EventId>,
|
||||||
{
|
{
|
||||||
let kind = Kind::PrivateDirectMessage;
|
let kind = if reaction {
|
||||||
|
Kind::Reaction
|
||||||
|
} else {
|
||||||
|
Kind::PrivateDirectMessage
|
||||||
|
};
|
||||||
|
|
||||||
let content: String = content.into();
|
let content: String = content.into();
|
||||||
let replies: Vec<EventId> = replies.into_iter().collect();
|
let replies: Vec<EventId> = replies.into_iter().collect();
|
||||||
|
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ use ui::{
|
|||||||
|
|
||||||
use crate::text::RenderedText;
|
use crate::text::RenderedText;
|
||||||
|
|
||||||
|
const REACTION_EMOJIS: &[&str] = &["👍", "👎", "😄", "🎉", "😕", "❤️", "🚀", "👀"];
|
||||||
|
const COMPACT_REACTION_EMOJIS: &[&str] = &["👍", "❤️", "👀"];
|
||||||
|
|
||||||
mod actions;
|
mod actions;
|
||||||
mod text;
|
mod text;
|
||||||
|
|
||||||
@@ -331,24 +334,49 @@ impl ChatPanel {
|
|||||||
// Get the message which includes all attachments
|
// Get the message which includes all attachments
|
||||||
let content = self.get_input_value(cx);
|
let content = self.get_input_value(cx);
|
||||||
|
|
||||||
|
// Get the replies to this message
|
||||||
|
let replies: Vec<EventId> = self.replies_to.read(cx).iter().copied().collect();
|
||||||
|
|
||||||
// Return if message is empty
|
// Return if message is empty
|
||||||
if content.trim().is_empty() {
|
if content.trim().is_empty() {
|
||||||
window.push_notification("Cannot send an empty message", cx);
|
window.push_notification("Cannot send an empty message", cx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.send_message(&content, window, cx);
|
self.send_message(&content, replies, false, window, cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_reaction(
|
||||||
|
&mut self,
|
||||||
|
emoji: &str,
|
||||||
|
target: &EventId,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
|
// Return if emoji is empty
|
||||||
|
if emoji.trim().is_empty() {
|
||||||
|
window.push_notification("Cannot send an empty reaction", cx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.send_message(emoji, vec![*target], true, window, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send a message to all members of the chat
|
/// Send a message to all members of the chat
|
||||||
fn send_message(&mut self, value: &str, window: &mut Window, cx: &mut Context<Self>) {
|
fn send_message(
|
||||||
|
&mut self,
|
||||||
|
value: &str,
|
||||||
|
replies: Vec<EventId>,
|
||||||
|
reaction: bool,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) {
|
||||||
if value.trim().is_empty() {
|
if value.trim().is_empty() {
|
||||||
window.push_notification("Cannot send an empty message", cx);
|
window.push_notification("Cannot send an empty message", cx);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let room = self.room.clone();
|
let room = self.room.clone();
|
||||||
let replies: Vec<EventId> = self.replies_to.read(cx).iter().copied().collect();
|
|
||||||
let content = value.to_string();
|
let content = value.to_string();
|
||||||
let sent_ids = self.sent_ids.clone();
|
let sent_ids = self.sent_ids.clone();
|
||||||
|
|
||||||
@@ -357,7 +385,7 @@ impl ChatPanel {
|
|||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let (rumor, send_task) = match room_entity.read_with(cx, |room, cx| {
|
let (rumor, send_task) = match room_entity.read_with(cx, |room, cx| {
|
||||||
let rumor = room.rumor(content.clone(), replies, cx)?;
|
let rumor = room.rumor(content.clone(), replies, reaction, cx)?;
|
||||||
let send_task = room.send(rumor.clone(), cx)?;
|
let send_task = room.send(rumor.clone(), cx)?;
|
||||||
Some((rumor, send_task))
|
Some((rumor, send_task))
|
||||||
}) {
|
}) {
|
||||||
@@ -575,7 +603,10 @@ impl ChatPanel {
|
|||||||
fn on_command(&mut self, command: &Command, window: &mut Window, cx: &mut Context<Self>) {
|
fn on_command(&mut self, command: &Command, window: &mut Window, cx: &mut Context<Self>) {
|
||||||
match command {
|
match command {
|
||||||
Command::Insert(content) => {
|
Command::Insert(content) => {
|
||||||
self.send_message(content, window, cx);
|
self.input.update(cx, |this, cx| {
|
||||||
|
let new_value = format!("{} {}", this.value(), content);
|
||||||
|
this.set_value(new_value, window, cx);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Command::ChangeSubject(subject) => {
|
Command::ChangeSubject(subject) => {
|
||||||
if self
|
if self
|
||||||
@@ -990,13 +1021,9 @@ impl ChatPanel {
|
|||||||
.w_full()
|
.w_full()
|
||||||
.px_2()
|
.px_2()
|
||||||
.border_l_2()
|
.border_l_2()
|
||||||
.border_color(cx.theme().element_selected)
|
.border_color(cx.theme().element_active)
|
||||||
.text_sm()
|
.text_sm()
|
||||||
.child(
|
.child(div().child(author.name()))
|
||||||
div()
|
|
||||||
.text_color(cx.theme().text_accent)
|
|
||||||
.child(author.name()),
|
|
||||||
)
|
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.w_full()
|
.w_full()
|
||||||
@@ -1192,6 +1219,29 @@ impl ChatPanel {
|
|||||||
.border_1()
|
.border_1()
|
||||||
.border_color(cx.theme().border)
|
.border_color(cx.theme().border)
|
||||||
.bg(cx.theme().background)
|
.bg(cx.theme().background)
|
||||||
|
.children({
|
||||||
|
let mut items = vec![];
|
||||||
|
|
||||||
|
for emoji in COMPACT_REACTION_EMOJIS {
|
||||||
|
items.push(
|
||||||
|
Button::new(*emoji)
|
||||||
|
.label(*emoji)
|
||||||
|
.tooltip(*emoji)
|
||||||
|
.small()
|
||||||
|
.ghost()
|
||||||
|
.on_click({
|
||||||
|
let emoji = *emoji;
|
||||||
|
let id = *id;
|
||||||
|
cx.listener(move |this, _event, window, cx| {
|
||||||
|
this.send_reaction(emoji, &id, window, cx);
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
items
|
||||||
|
})
|
||||||
|
.child(div().flex_shrink_0().h_4().w_px().bg(cx.theme().border))
|
||||||
.child(
|
.child(
|
||||||
Button::new("reply")
|
Button::new("reply")
|
||||||
.icon(IconName::Reply)
|
.icon(IconName::Reply)
|
||||||
@@ -1305,7 +1355,7 @@ impl ChatPanel {
|
|||||||
.gap_1()
|
.gap_1()
|
||||||
.text_xs()
|
.text_xs()
|
||||||
.text_color(cx.theme().text_muted)
|
.text_color(cx.theme().text_muted)
|
||||||
.child(SharedString::from("Replying to:"))
|
.child("Replying to:")
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.text_color(cx.theme().text_accent)
|
.text_color(cx.theme().text_accent)
|
||||||
@@ -1402,15 +1452,10 @@ impl ChatPanel {
|
|||||||
.ghost()
|
.ghost()
|
||||||
.large()
|
.large()
|
||||||
.dropdown_menu_with_anchor(gpui::Anchor::BottomLeft, move |this, _window, _cx| {
|
.dropdown_menu_with_anchor(gpui::Anchor::BottomLeft, move |this, _window, _cx| {
|
||||||
this.horizontal()
|
let menu = this.horizontal();
|
||||||
.menu("👍", Box::new(Command::Insert("👍")))
|
REACTION_EMOJIS.iter().fold(menu, |this, emoji| {
|
||||||
.menu("👎", Box::new(Command::Insert("👎")))
|
this.menu(*emoji, Box::new(Command::Insert(emoji)))
|
||||||
.menu("😄", Box::new(Command::Insert("😄")))
|
})
|
||||||
.menu("🎉", Box::new(Command::Insert("🎉")))
|
|
||||||
.menu("😕", Box::new(Command::Insert("😕")))
|
|
||||||
.menu("❤️", Box::new(Command::Insert("❤️")))
|
|
||||||
.menu("🚀", Box::new(Command::Insert("🚀")))
|
|
||||||
.menu("👀", Box::new(Command::Insert("👀")))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user