wip: refactor
This commit is contained in:
+107
-46
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
use gpui::*;
|
||||
use nostr_sdk::prelude::*;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{Arc, Mutex, RwLock},
|
||||
};
|
||||
|
||||
pub struct MetadataRegistry {
|
||||
seens: Arc<Mutex<Vec<PublicKey>>>,
|
||||
profiles: Arc<RwLock<HashMap<PublicKey, Metadata>>>,
|
||||
}
|
||||
|
||||
impl Global for MetadataRegistry {}
|
||||
|
||||
impl MetadataRegistry {
|
||||
pub fn set_global(cx: &mut AppContext) {
|
||||
cx.set_global(Self::new());
|
||||
}
|
||||
|
||||
pub fn seen(&mut self, public_key: PublicKey, metadata: Option<Metadata>) {
|
||||
let mut seens = self.seens.lock().unwrap();
|
||||
|
||||
if !seens.contains(&public_key) {
|
||||
seens.push(public_key);
|
||||
drop(seens);
|
||||
|
||||
if let Some(metadata) = metadata {
|
||||
self.profiles.write().unwrap().insert(public_key, metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, public_key: &PublicKey) -> Option<Metadata> {
|
||||
self.profiles.read().unwrap().get(public_key).cloned()
|
||||
}
|
||||
|
||||
fn new() -> Self {
|
||||
let seens = Arc::new(Mutex::new(Vec::new()));
|
||||
let profiles = Arc::new(RwLock::new(HashMap::new()));
|
||||
|
||||
Self { seens, profiles }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,2 @@
|
||||
pub mod account;
|
||||
pub mod chat;
|
||||
pub mod metadata;
|
||||
pub mod signal;
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
use gpui::*;
|
||||
use nostr_sdk::prelude::*;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Signal {
|
||||
/// Receive metadata
|
||||
Metadata(PublicKey),
|
||||
/// Receive event
|
||||
Event(Event),
|
||||
/// Receive EOSE
|
||||
Eose,
|
||||
}
|
||||
|
||||
pub struct SignalRegistry {
|
||||
pub tx: Arc<UnboundedSender<PublicKey>>,
|
||||
}
|
||||
|
||||
impl Global for SignalRegistry {}
|
||||
|
||||
impl SignalRegistry {
|
||||
pub fn set_global(cx: &mut AppContext, tx: UnboundedSender<PublicKey>) {
|
||||
cx.set_global(Self::new(tx));
|
||||
}
|
||||
|
||||
fn new(tx: UnboundedSender<PublicKey>) -> Self {
|
||||
Self { tx: Arc::new(tx) }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user