chore: improve data requests (#81)
* refactor * refactor * add documents * clean up * refactor * clean up * refactor identity * . * . * rename
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
use std::cell::RefCell;
|
||||
use std::iter::IntoIterator;
|
||||
use std::rc::Rc;
|
||||
|
||||
use chrono::{Local, TimeZone};
|
||||
use gpui::SharedString;
|
||||
use nostr_sdk::prelude::*;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
|
||||
use crate::room::SendError;
|
||||
|
||||
/// Represents a message in the chat system.
|
||||
///
|
||||
/// Contains information about the message content, author, creation time,
|
||||
/// mentions, replies, and any errors that occurred during sending.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Message {
|
||||
/// Unique identifier of the message (EventId from nostr_sdk)
|
||||
pub id: EventId,
|
||||
/// Author's public key
|
||||
pub author: PublicKey,
|
||||
/// The content/text of the message
|
||||
pub content: SharedString,
|
||||
/// When the message was created
|
||||
pub created_at: Timestamp,
|
||||
/// List of mentioned public keys in the message
|
||||
pub mentions: SmallVec<[PublicKey; 2]>,
|
||||
/// List of EventIds this message is replying to
|
||||
pub replies_to: Option<SmallVec<[EventId; 1]>>,
|
||||
/// Any errors that occurred while sending this message
|
||||
pub errors: Option<SmallVec<[SendError; 1]>>,
|
||||
}
|
||||
|
||||
/// Builder pattern implementation for constructing Message objects.
|
||||
#[derive(Debug)]
|
||||
pub struct MessageBuilder {
|
||||
id: EventId,
|
||||
author: PublicKey,
|
||||
content: Option<SharedString>,
|
||||
created_at: Option<Timestamp>,
|
||||
mentions: SmallVec<[PublicKey; 2]>,
|
||||
replies_to: Option<SmallVec<[EventId; 1]>>,
|
||||
errors: Option<SmallVec<[SendError; 1]>>,
|
||||
}
|
||||
|
||||
impl MessageBuilder {
|
||||
/// Creates a new MessageBuilder with default values
|
||||
pub fn new(id: EventId, author: PublicKey) -> Self {
|
||||
Self {
|
||||
id,
|
||||
author,
|
||||
content: None,
|
||||
created_at: None,
|
||||
mentions: smallvec![],
|
||||
replies_to: None,
|
||||
errors: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the message content
|
||||
pub fn content(mut self, content: impl Into<SharedString>) -> Self {
|
||||
self.content = Some(content.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the creation timestamp
|
||||
pub fn created_at(mut self, created_at: Timestamp) -> Self {
|
||||
self.created_at = Some(created_at);
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a single mention to the message
|
||||
pub fn mention(mut self, mention: PublicKey) -> Self {
|
||||
self.mentions.push(mention);
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds multiple mentions to the message
|
||||
pub fn mentions<I>(mut self, mentions: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = PublicKey>,
|
||||
{
|
||||
self.mentions.extend(mentions);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets a single message this is replying to
|
||||
pub fn reply_to(mut self, reply_to: EventId) -> Self {
|
||||
self.replies_to = Some(smallvec![reply_to]);
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets multiple messages this is replying to
|
||||
pub fn replies_to<I>(mut self, replies_to: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = EventId>,
|
||||
{
|
||||
let replies: SmallVec<[EventId; 1]> = replies_to.into_iter().collect();
|
||||
if !replies.is_empty() {
|
||||
self.replies_to = Some(replies);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds errors that occurred during sending
|
||||
pub fn errors<I>(mut self, errors: I) -> Self
|
||||
where
|
||||
I: IntoIterator<Item = SendError>,
|
||||
{
|
||||
self.errors = Some(errors.into_iter().collect());
|
||||
self
|
||||
}
|
||||
|
||||
/// Builds the message wrapped in an Rc<RefCell<Message>>
|
||||
pub fn build_rc(self) -> Result<Rc<RefCell<Message>>, String> {
|
||||
self.build().map(|m| Rc::new(RefCell::new(m)))
|
||||
}
|
||||
|
||||
/// Builds the message
|
||||
pub fn build(self) -> Result<Message, String> {
|
||||
Ok(Message {
|
||||
id: self.id,
|
||||
author: self.author,
|
||||
content: self.content.ok_or("Content is required")?,
|
||||
created_at: self.created_at.unwrap_or_else(Timestamp::now),
|
||||
mentions: self.mentions,
|
||||
replies_to: self.replies_to,
|
||||
errors: self.errors,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Message {
|
||||
/// Creates a new MessageBuilder
|
||||
pub fn builder(id: EventId, author: PublicKey) -> MessageBuilder {
|
||||
MessageBuilder::new(id, author)
|
||||
}
|
||||
|
||||
/// Converts the message into an Rc<RefCell<Message>>
|
||||
pub fn into_rc(self) -> Rc<RefCell<Self>> {
|
||||
Rc::new(RefCell::new(self))
|
||||
}
|
||||
|
||||
/// Builds a message from a builder and wraps it in Rc<RefCell>
|
||||
pub fn build_rc(builder: MessageBuilder) -> Result<Rc<RefCell<Self>>, String> {
|
||||
builder.build().map(|m| Rc::new(RefCell::new(m)))
|
||||
}
|
||||
|
||||
/// Returns a human-readable string representing how long ago the message was created
|
||||
pub fn ago(&self) -> SharedString {
|
||||
let input_time = match Local.timestamp_opt(self.created_at.as_u64() as i64, 0) {
|
||||
chrono::LocalResult::Single(time) => time,
|
||||
_ => return "Invalid timestamp".into(),
|
||||
};
|
||||
|
||||
let now = Local::now();
|
||||
let input_date = input_time.date_naive();
|
||||
let now_date = now.date_naive();
|
||||
let yesterday_date = (now - chrono::Duration::days(1)).date_naive();
|
||||
|
||||
let time_format = input_time.format("%H:%M %p");
|
||||
|
||||
match input_date {
|
||||
date if date == now_date => format!("Today at {time_format}"),
|
||||
date if date == yesterday_date => format!("Yesterday at {time_format}"),
|
||||
_ => format!("{}, {time_format}", input_time.format("%d/%m/%y")),
|
||||
}
|
||||
.into()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user