wip: refactor
This commit is contained in:
12
Cargo.toml
12
Cargo.toml
@@ -35,3 +35,15 @@ keyring = { version = "3", features = [
|
|||||||
"windows-native",
|
"windows-native",
|
||||||
"sync-secret-service",
|
"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
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ pub const FAKE_SIG: &str = "f9e79d141c004977192d05a86f81ec7c585179c371f7350a5412
|
|||||||
pub const NEW_MESSAGE_SUB_ID: &str = "listen_new_giftwrap";
|
pub const NEW_MESSAGE_SUB_ID: &str = "listen_new_giftwrap";
|
||||||
pub const ALL_MESSAGES_SUB_ID: &str = "listen_all_giftwraps";
|
pub const ALL_MESSAGES_SUB_ID: &str = "listen_all_giftwraps";
|
||||||
pub const METADATA_DELAY: u64 = 150;
|
pub const METADATA_DELAY: u64 = 150;
|
||||||
|
pub const IMAGE_SERVICE: &str = "https://wsrv.nl";
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ impl AppView {
|
|||||||
let dock = cx.new_view(|cx| DockArea::new(DOCK_AREA.id, Some(DOCK_AREA.version), cx));
|
let dock = cx.new_view(|cx| DockArea::new(DOCK_AREA.id, Some(DOCK_AREA.version), cx));
|
||||||
|
|
||||||
cx.observe_global::<AccountRegistry>(|view, 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() {
|
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);
|
Self::init_layout(view.dock.downgrade(), cx);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -71,6 +71,7 @@ impl AppView {
|
|||||||
|
|
||||||
// Change theme
|
// Change theme
|
||||||
Theme::change(mode, cx);
|
Theme::change(mode, cx);
|
||||||
|
|
||||||
// Rerender
|
// Rerender
|
||||||
cx.refresh();
|
cx.refresh();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use nostr_sdk::prelude::*;
|
|||||||
use prelude::FluentBuilder;
|
use prelude::FluentBuilder;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
constants::IMAGE_SERVICE,
|
||||||
get_client,
|
get_client,
|
||||||
states::{chat::Room, metadata::MetadataRegistry, signal::SignalRegistry},
|
states::{chat::Room, metadata::MetadataRegistry, signal::SignalRegistry},
|
||||||
utils::{ago, show_npub},
|
utils::{ago, show_npub},
|
||||||
@@ -70,10 +71,13 @@ impl RenderOnce for Item {
|
|||||||
.map(|this| {
|
.map(|this| {
|
||||||
if let Some(picture) = metadata.picture {
|
if let Some(picture) = metadata.picture {
|
||||||
this.flex_shrink_0().child(
|
this.flex_shrink_0().child(
|
||||||
img(picture)
|
img(format!(
|
||||||
.size_6()
|
"{}/?url={}&w=100&h=100&n=-1",
|
||||||
.rounded_full()
|
IMAGE_SERVICE, picture
|
||||||
.object_fit(ObjectFit::Cover),
|
))
|
||||||
|
.size_6()
|
||||||
|
.rounded_full()
|
||||||
|
.object_fit(ObjectFit::Cover),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
this.flex_shrink_0()
|
this.flex_shrink_0()
|
||||||
|
|||||||
@@ -14,33 +14,43 @@ pub mod item;
|
|||||||
|
|
||||||
pub struct Inbox {
|
pub struct Inbox {
|
||||||
label: SharedString,
|
label: SharedString,
|
||||||
events: Model<Option<Vec<Event>>>,
|
items: Model<Option<Vec<View<InboxItem>>>>,
|
||||||
chats: Model<Vec<View<InboxItem>>>,
|
|
||||||
is_loading: bool,
|
is_loading: bool,
|
||||||
is_fetching: bool,
|
|
||||||
is_collapsed: bool,
|
is_collapsed: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Inbox {
|
impl Inbox {
|
||||||
pub fn new(cx: &mut ViewContext<'_, Self>) -> Self {
|
pub fn new(cx: &mut ViewContext<'_, Self>) -> Self {
|
||||||
let chats = cx.new_model(|_| Vec::new());
|
let items = cx.new_model(|_| None);
|
||||||
let events = cx.new_model(|_| None);
|
|
||||||
|
|
||||||
cx.observe_global::<ChatRegistry>(|inbox, cx| {
|
cx.observe_global::<ChatRegistry>(|this, cx| {
|
||||||
let state = cx.global::<ChatRegistry>();
|
let state = cx.global::<ChatRegistry>();
|
||||||
|
|
||||||
if state.reload || (state.is_initialized && state.new_messages.is_empty()) {
|
if state.reload || (state.is_initialized && state.new_messages.is_empty()) {
|
||||||
inbox.load(cx);
|
this.load(cx);
|
||||||
} else {
|
} 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() {
|
// Get all current chats
|
||||||
cx.update_model(&inbox.events, |model, b| {
|
let current: Vec<PublicKey> = items
|
||||||
if let Some(events) = model {
|
.iter()
|
||||||
if !events.iter().any(|ev| ev.pubkey == message.event.pubkey) {
|
.map(|item| item.model.read(cx).sender)
|
||||||
events.push(message.event);
|
.collect();
|
||||||
b.notify();
|
|
||||||
}
|
// 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();
|
.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| {
|
cx.observe_new_views::<InboxItem>(|chat, cx| {
|
||||||
chat.load_metadata(cx);
|
chat.load_metadata(cx);
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
events,
|
items,
|
||||||
chats,
|
|
||||||
label: "Inbox".into(),
|
label: "Inbox".into(),
|
||||||
is_loading: true,
|
is_loading: true,
|
||||||
is_fetching: false,
|
|
||||||
is_collapsed: false,
|
is_collapsed: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -97,7 +75,7 @@ impl Inbox {
|
|||||||
// Hide loading indicator
|
// Hide loading indicator
|
||||||
self.set_loading(cx);
|
self.set_loading(cx);
|
||||||
|
|
||||||
let async_events = self.events.clone();
|
let async_items = self.items.clone();
|
||||||
let mut async_cx = cx.to_async();
|
let mut async_cx = cx.to_async();
|
||||||
|
|
||||||
cx.foreground_executor()
|
cx.foreground_executor()
|
||||||
@@ -118,6 +96,7 @@ impl Inbox {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|ev| ev.pubkey != public_key) // Filter all messages from current user
|
.filter(|ev| ev.pubkey != public_key) // Filter all messages from current user
|
||||||
.unique_by(|ev| ev.pubkey)
|
.unique_by(|ev| ev.pubkey)
|
||||||
|
.sorted_by_key(|ev| Reverse(ev.created_at))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
} else {
|
} else {
|
||||||
Vec::new()
|
Vec::new()
|
||||||
@@ -125,8 +104,13 @@ impl Inbox {
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
async_cx.update_model(&async_events, |a, b| {
|
let views: Vec<View<InboxItem>> = events
|
||||||
*a = Some(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();
|
b.notify();
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -137,11 +121,6 @@ impl Inbox {
|
|||||||
self.is_loading = false;
|
self.is_loading = false;
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_fetching(&mut self, cx: &mut ViewContext<Self>) {
|
|
||||||
self.is_fetching = !self.is_fetching;
|
|
||||||
cx.notify();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Collapsible for Inbox {
|
impl Collapsible for Inbox {
|
||||||
@@ -158,7 +137,6 @@ impl Collapsible for Inbox {
|
|||||||
impl Render for Inbox {
|
impl Render for Inbox {
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
let mut content = div();
|
let mut content = div();
|
||||||
let chats = self.chats.read(cx);
|
|
||||||
|
|
||||||
if self.is_loading {
|
if self.is_loading {
|
||||||
content = content.children((0..5).map(|_| {
|
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().flex_shrink_0().size_6().rounded_full())
|
||||||
.child(Skeleton::new().w_20().h_3().rounded_sm())
|
.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 {
|
} else {
|
||||||
content = content
|
// TODO: handle error
|
||||||
.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())
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
v_flex()
|
v_flex()
|
||||||
|
|||||||
Reference in New Issue
Block a user