wip: refactor

This commit is contained in:
2024-12-24 12:08:33 +07:00
parent 063bb97f84
commit 37d810d9e5
5 changed files with 61 additions and 73 deletions

View File

@@ -35,3 +35,15 @@ keyring = { version = "3", features = [
"windows-native",
"sync-secret-service",
] }
[profile.release]
codegen-units = 1
lto = true
panic = "abort"
incremental = false
opt-level = "z"
strip = true
rpath = false
debug = false
debug-assertions = false
overflow-checks = false

View File

@@ -4,3 +4,4 @@ pub const FAKE_SIG: &str = "f9e79d141c004977192d05a86f81ec7c585179c371f7350a5412
pub const NEW_MESSAGE_SUB_ID: &str = "listen_new_giftwrap";
pub const ALL_MESSAGES_SUB_ID: &str = "listen_all_giftwraps";
pub const METADATA_DELAY: u64 = 150;
pub const IMAGE_SERVICE: &str = "https://wsrv.nl";

View File

@@ -53,8 +53,8 @@ impl AppView {
let dock = cx.new_view(|cx| DockArea::new(DOCK_AREA.id, Some(DOCK_AREA.version), cx));
cx.observe_global::<AccountRegistry>(|view, cx| {
// TODO: save dock state and load previous state on startup
if cx.global::<AccountRegistry>().is_user_logged_in() {
// TODO: save dock state and load previous state on startup
Self::init_layout(view.dock.downgrade(), cx);
}
})
@@ -71,6 +71,7 @@ impl AppView {
// Change theme
Theme::change(mode, cx);
// Rerender
cx.refresh();
}

View File

@@ -6,6 +6,7 @@ use nostr_sdk::prelude::*;
use prelude::FluentBuilder;
use crate::{
constants::IMAGE_SERVICE,
get_client,
states::{chat::Room, metadata::MetadataRegistry, signal::SignalRegistry},
utils::{ago, show_npub},
@@ -70,10 +71,13 @@ impl RenderOnce for Item {
.map(|this| {
if let Some(picture) = metadata.picture {
this.flex_shrink_0().child(
img(picture)
.size_6()
.rounded_full()
.object_fit(ObjectFit::Cover),
img(format!(
"{}/?url={}&w=100&h=100&n=-1",
IMAGE_SERVICE, picture
))
.size_6()
.rounded_full()
.object_fit(ObjectFit::Cover),
)
} else {
this.flex_shrink_0()

View File

@@ -14,33 +14,43 @@ pub mod item;
pub struct Inbox {
label: SharedString,
events: Model<Option<Vec<Event>>>,
chats: Model<Vec<View<InboxItem>>>,
items: Model<Option<Vec<View<InboxItem>>>>,
is_loading: bool,
is_fetching: bool,
is_collapsed: bool,
}
impl Inbox {
pub fn new(cx: &mut ViewContext<'_, Self>) -> Self {
let chats = cx.new_model(|_| Vec::new());
let events = cx.new_model(|_| None);
let items = cx.new_model(|_| None);
cx.observe_global::<ChatRegistry>(|inbox, cx| {
cx.observe_global::<ChatRegistry>(|this, cx| {
let state = cx.global::<ChatRegistry>();
if state.reload || (state.is_initialized && state.new_messages.is_empty()) {
inbox.load(cx);
this.load(cx);
} else {
let new_messages = state.new_messages.clone();
#[allow(clippy::collapsible_if)]
if let Some(items) = this.items.read(cx).as_ref() {
// Get all new messages
let new_messages = state.new_messages.clone();
for message in new_messages.into_iter() {
cx.update_model(&inbox.events, |model, b| {
if let Some(events) = model {
if !events.iter().any(|ev| ev.pubkey == message.event.pubkey) {
events.push(message.event);
b.notify();
}
// Get all current chats
let current: Vec<PublicKey> = items
.iter()
.map(|item| item.model.read(cx).sender)
.collect();
// Create view for only new chats
let new = new_messages
.into_iter()
.filter(|m| current.iter().any(|pk| pk == &m.event.pubkey))
.map(|m| cx.new_view(|cx| InboxItem::new(m.event, cx)))
.collect::<Vec<_>>();
cx.update_model(&this.items, |a, b| {
if let Some(items) = a {
items.extend(new);
b.notify();
}
});
}
@@ -48,47 +58,15 @@ impl Inbox {
})
.detach();
cx.observe(&events, |inbox, model, cx| {
// Show fetching indicator
inbox.set_fetching(cx);
let events: Option<Vec<Event>> = model.read(cx).clone();
if let Some(events) = events {
let views = inbox.chats.read(cx);
let public_keys: Vec<PublicKey> = views.iter().map(|v| v.read(cx).sender).collect();
for event in events
.into_iter()
.sorted_by_key(|ev| Reverse(ev.created_at))
{
if !public_keys.contains(&event.pubkey) {
let view = cx.new_view(|cx| InboxItem::new(event, cx));
cx.update_model(&inbox.chats, |a, b| {
a.push(view);
b.notify();
});
}
}
// Hide fetching indicator
inbox.set_fetching(cx);
}
})
.detach();
cx.observe_new_views::<InboxItem>(|chat, cx| {
chat.load_metadata(cx);
})
.detach();
Self {
events,
chats,
items,
label: "Inbox".into(),
is_loading: true,
is_fetching: false,
is_collapsed: false,
}
}
@@ -97,7 +75,7 @@ impl Inbox {
// Hide loading indicator
self.set_loading(cx);
let async_events = self.events.clone();
let async_items = self.items.clone();
let mut async_cx = cx.to_async();
cx.foreground_executor()
@@ -118,6 +96,7 @@ impl Inbox {
.into_iter()
.filter(|ev| ev.pubkey != public_key) // Filter all messages from current user
.unique_by(|ev| ev.pubkey)
.sorted_by_key(|ev| Reverse(ev.created_at))
.collect::<Vec<_>>()
} else {
Vec::new()
@@ -125,8 +104,13 @@ impl Inbox {
})
.await;
async_cx.update_model(&async_events, |a, b| {
*a = Some(events);
let views: Vec<View<InboxItem>> = events
.into_iter()
.map(|ev| async_cx.new_view(|cx| InboxItem::new(ev, cx)).unwrap())
.collect();
async_cx.update_model(&async_items, |a, b| {
*a = Some(views);
b.notify();
})
})
@@ -137,11 +121,6 @@ impl Inbox {
self.is_loading = false;
cx.notify();
}
fn set_fetching(&mut self, cx: &mut ViewContext<Self>) {
self.is_fetching = !self.is_fetching;
cx.notify();
}
}
impl Collapsible for Inbox {
@@ -158,7 +137,6 @@ impl Collapsible for Inbox {
impl Render for Inbox {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
let mut content = div();
let chats = self.chats.read(cx);
if self.is_loading {
content = content.children((0..5).map(|_| {
@@ -171,18 +149,10 @@ impl Render for Inbox {
.child(Skeleton::new().flex_shrink_0().size_6().rounded_full())
.child(Skeleton::new().w_20().h_3().rounded_sm())
}))
} else if let Some(items) = self.items.read(cx).as_ref() {
content = content.children(items.clone())
} else {
content = content
.children(chats.clone())
.when(self.is_fetching, |this| {
this.h_8()
.px_1()
.flex()
.items_center()
.gap_2()
.child(Skeleton::new().flex_shrink_0().size_6().rounded_full())
.child(Skeleton::new().w_20().h_3().rounded_sm())
});
// TODO: handle error
}
v_flex()