wip: refactor

This commit is contained in:
reya
2025-01-08 08:02:24 +07:00
parent 402786ec3c
commit fe24f84b02
24 changed files with 521 additions and 945 deletions
+107 -46
View File
@@ -1,11 +1,15 @@
use gpui::*;
use crate::get_client;
use crate::utils::get_room_id;
use gpui::{AppContext, Context, Global, Model, SharedString};
use itertools::Itertools;
use nostr_sdk::prelude::*;
use rnglib::{Language, RNG};
use serde::Deserialize;
use std::sync::{Arc, RwLock};
use super::metadata::MetadataRegistry;
use crate::utils::get_room_id;
use std::{
cmp::Reverse,
collections::HashMap,
sync::{Arc, RwLock},
};
#[derive(Clone, PartialEq, Eq, Deserialize)]
pub struct Room {
@@ -15,23 +19,17 @@ pub struct Room {
pub last_seen: Timestamp,
pub title: Option<SharedString>,
pub metadata: Option<Metadata>,
is_initialized: bool,
}
impl Room {
pub fn new(
id: SharedString,
owner: PublicKey,
members: Vec<PublicKey>,
last_seen: Timestamp,
title: Option<SharedString>,
cx: &mut WindowContext<'_>,
metadata: Option<Metadata>,
) -> Self {
// Get unique id based on members
let id = get_room_id(&owner, &members).into();
// Get metadata for all members if exists
let metadata = cx.global::<MetadataRegistry>().get(&owner);
Self {
id,
title,
@@ -39,16 +37,17 @@ impl Room {
last_seen,
owner,
metadata,
is_initialized: false,
}
}
pub fn parse(event: &Event, cx: &mut WindowContext<'_>) -> Self {
pub fn parse(event: &Event, metadata: Option<Metadata>) -> Self {
let owner = event.pubkey;
let last_seen = event.created_at;
let id = SharedString::from(get_room_id(&owner, &event.tags));
// Get all members from event's tag
let members: Vec<PublicKey> = event.tags.public_keys().copied().collect();
let mut members: Vec<PublicKey> = event.tags.public_keys().copied().collect();
members.push(owner);
// Get title from event's tag
let title = if let Some(tag) = event.tags.find(TagKind::Title) {
@@ -60,20 +59,26 @@ impl Room {
Some(name.into())
};
Self::new(owner, members, last_seen, title, cx)
Self::new(id, owner, members, last_seen, title, metadata)
}
}
#[derive(Clone, Debug)]
pub struct Message {
pub room_id: SharedString,
pub event: Event,
pub metadata: Option<Metadata>,
}
impl Message {
pub fn new(event: Event, metadata: Option<Metadata>) -> Self {
// TODO: parse event's content
Self { event, metadata }
}
}
pub struct ChatRegistry {
pub new_messages: Arc<RwLock<Vec<Message>>>,
pub reload: bool,
pub messages: RwLock<HashMap<SharedString, Arc<RwLock<Vec<Message>>>>>,
pub rooms: Model<Vec<Event>>,
pub is_initialized: bool,
}
@@ -81,34 +86,90 @@ impl Global for ChatRegistry {}
impl ChatRegistry {
pub fn set_global(cx: &mut AppContext) {
cx.set_global(Self::new());
}
let rooms = cx.new_model(|_| Vec::new());
let messages = RwLock::new(HashMap::new());
pub fn update(&mut self) {
if !self.is_initialized {
self.is_initialized = true;
} else {
self.reload = true;
}
}
pub fn push(&mut self, event: Event, metadata: Option<Metadata>) {
let pubkeys: Vec<PublicKey> = event.tags.public_keys().copied().collect();
let room_id = get_room_id(&event.pubkey, &pubkeys);
let message = Message {
room_id: room_id.into(),
event,
metadata,
};
self.new_messages.write().unwrap().push(message);
}
fn new() -> Self {
Self {
new_messages: Arc::new(RwLock::new(Vec::new())),
reload: false,
cx.set_global(Self {
messages,
rooms,
is_initialized: false,
});
}
pub fn init(&mut self, cx: &mut AppContext) {
if self.is_initialized {
return;
}
let async_cx = cx.to_async();
// Get all current room's ids
let ids: Vec<String> = self
.rooms
.read(cx)
.iter()
.map(|ev| get_room_id(&ev.pubkey, &ev.tags))
.collect();
cx.foreground_executor()
.spawn(async move {
let client = get_client();
let signer = client.signer().await.unwrap();
let public_key = signer.get_public_key().await.unwrap();
let filter = Filter::new()
.kind(Kind::PrivateDirectMessage)
.pubkey(public_key);
let events = async_cx
.background_executor()
.spawn(async move {
if let Ok(events) = client.database().query(vec![filter]).await {
events
.into_iter()
.filter(|ev| ev.pubkey != public_key)
.filter(|ev| {
let new_id = get_room_id(&ev.pubkey, &ev.tags);
// Get new events only
!ids.iter().any(|id| id == &new_id)
}) // Filter all messages from current user
.unique_by(|ev| ev.pubkey)
.sorted_by_key(|ev| Reverse(ev.created_at))
.collect::<Vec<_>>()
} else {
Vec::new()
}
})
.await;
_ = async_cx.update_global::<Self, _>(|state, cx| {
state.rooms.update(cx, |model, cx| {
model.extend(events);
cx.notify();
});
state.is_initialized = true;
});
})
.detach();
}
pub fn new_message(&mut self, event: Event, metadata: Option<Metadata>) {
// Get room id
let room_id = SharedString::from(get_room_id(&event.pubkey, &event.tags));
// Create message
let message = Message::new(event, metadata);
self.messages
.write()
.unwrap()
.entry(room_id)
.or_insert(Arc::new(RwLock::new(Vec::new())))
.write()
.unwrap()
.push(message)
}
pub fn get_messages(&self, id: &SharedString) -> Option<Arc<RwLock<Vec<Message>>>> {
self.messages.read().unwrap().get(id).cloned()
}
}