feat: improve chat state

This commit is contained in:
reya
2025-02-10 09:03:29 +07:00
parent 6805ed8be5
commit c4573ef1da
13 changed files with 171 additions and 181 deletions
+64 -10
View File
@@ -1,3 +1,4 @@
use chrono::{Datelike, Local, TimeZone};
use common::{
profile::NostrProfile,
utils::{compare, random_name, room_hash},
@@ -6,13 +7,66 @@ use gpui::SharedString;
use nostr_sdk::prelude::*;
use std::collections::HashSet;
#[derive(Debug)]
pub struct LastSeen(pub Timestamp);
impl LastSeen {
pub fn ago(&self) -> SharedString {
let now = Local::now();
let input_time = Local.timestamp_opt(self.0.as_u64() as i64, 0).unwrap();
let diff = (now - input_time).num_hours();
if diff < 24 {
let duration = now.signed_duration_since(input_time);
if duration.num_seconds() < 60 {
"now".to_string().into()
} else if duration.num_minutes() == 1 {
"1m".to_string().into()
} else if duration.num_minutes() < 60 {
format!("{}m", duration.num_minutes()).into()
} else if duration.num_hours() == 1 {
"1h".to_string().into()
} else if duration.num_hours() < 24 {
format!("{}h", duration.num_hours()).into()
} else if duration.num_days() == 1 {
"1d".to_string().into()
} else {
format!("{}d", duration.num_days()).into()
}
} else {
input_time.format("%b %d").to_string().into()
}
}
pub fn human_readable(&self) -> SharedString {
let now = Local::now();
let input_time = Local.timestamp_opt(self.0.as_u64() as i64, 0).unwrap();
if input_time.day() == now.day() {
format!("Today at {}", input_time.format("%H:%M %p")).into()
} else if input_time.day() == now.day() - 1 {
format!("Yesterday at {}", input_time.format("%H:%M %p")).into()
} else {
format!(
"{}, {}",
input_time.format("%d/%m/%y"),
input_time.format("%H:%M %p")
)
.into()
}
}
pub fn set(&mut self, created_at: Timestamp) {
self.0 = created_at
}
}
pub struct Room {
pub id: u64,
pub title: Option<SharedString>,
pub owner: NostrProfile, // Owner always match current user
pub members: Vec<NostrProfile>, // Extract from event's tags
pub last_seen: Timestamp,
pub last_seen: LastSeen,
pub is_group: bool,
pub new_messages: Vec<Event>, // Hold all new messages
}
@@ -35,7 +89,7 @@ impl Room {
owner: NostrProfile,
members: Vec<NostrProfile>,
title: Option<SharedString>,
last_seen: Timestamp,
last_seen: LastSeen,
) -> Self {
let is_group = members.len() > 1;
let title = if title.is_none() {
@@ -57,8 +111,8 @@ impl Room {
/// Convert nostr event to room
pub fn parse(event: &Event) -> Room {
let id = room_hash(&event.tags);
let last_seen = event.created_at;
let id = room_hash(event);
let last_seen = LastSeen(event.created_at);
// Always equal to current user
let owner = NostrProfile::new(event.pubkey, Metadata::default());
@@ -73,7 +127,7 @@ impl Room {
.collect();
// Get title from event's tags
let title = if let Some(tag) = event.tags.find(TagKind::Title) {
let title = if let Some(tag) = event.tags.find(TagKind::Subject) {
tag.content().map(|s| s.to_owned().into())
} else {
None
@@ -113,7 +167,7 @@ impl Room {
self.members
.iter()
.map(|profile| profile.name())
.collect::<Vec<String>>()
.collect::<Vec<_>>()
.join(", ")
} else {
let name = self
@@ -121,15 +175,15 @@ impl Room {
.iter()
.take(2)
.map(|profile| profile.name())
.collect::<Vec<String>>()
.collect::<Vec<_>>()
.join(", ");
format!("{}, +{}", name, self.members.len() - 2)
}
}
/// Get all public keys from room's contacts
pub fn get_pubkeys(&self) -> Vec<PublicKey> {
/// Get all public keys from current room
pub fn pubkeys(&self) -> Vec<PublicKey> {
let mut pubkeys: Vec<_> = self.members.iter().map(|m| m.public_key()).collect();
pubkeys.push(self.owner.public_key());