diff --git a/Cargo.lock b/Cargo.lock
index 7629c2b..14e09cb 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1199,7 +1199,6 @@ version = "0.1.0"
dependencies = [
"anyhow",
"chrono",
- "coop-ui",
"dirs 5.0.1",
"gpui",
"itertools 0.13.0",
@@ -1214,28 +1213,7 @@ dependencies = [
"smol",
"tokio",
"tracing-subscriber",
-]
-
-[[package]]
-name = "coop-ui"
-version = "0.1.0"
-dependencies = [
- "anyhow",
- "chrono",
- "gpui",
- "image",
- "itertools 0.13.0",
- "nostr-sdk",
- "once_cell",
- "paste",
- "regex",
- "rust-embed",
- "serde",
- "serde_json",
- "smallvec",
- "smol",
- "unicode-segmentation",
- "uuid",
+ "ui",
]
[[package]]
@@ -5941,6 +5919,28 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "ui"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "chrono",
+ "gpui",
+ "image",
+ "itertools 0.13.0",
+ "nostr-sdk",
+ "once_cell",
+ "paste",
+ "regex",
+ "rust-embed",
+ "serde",
+ "serde_json",
+ "smallvec",
+ "smol",
+ "unicode-segmentation",
+ "uuid",
+]
+
[[package]]
name = "unicase"
version = "2.8.1"
diff --git a/assets/icons/compose-fill.svg b/assets/icons/compose-fill.svg
new file mode 100644
index 0000000..4d4b4e0
--- /dev/null
+++ b/assets/icons/compose-fill.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/group-fill.svg b/assets/icons/group-fill.svg
new file mode 100644
index 0000000..e8e3704
--- /dev/null
+++ b/assets/icons/group-fill.svg
@@ -0,0 +1,3 @@
+
diff --git a/crates/app/Cargo.toml b/crates/app/Cargo.toml
index 6a4e27a..3bfab0f 100644
--- a/crates/app/Cargo.toml
+++ b/crates/app/Cargo.toml
@@ -9,7 +9,7 @@ name = "coop"
path = "src/main.rs"
[dependencies]
-coop-ui = { path = "../ui" }
+ui = { path = "../ui" }
gpui.workspace = true
reqwest_client.workspace = true
diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs
index 3e45206..03e0e7c 100644
--- a/crates/app/src/main.rs
+++ b/crates/app/src/main.rs
@@ -1,5 +1,4 @@
use asset::Assets;
-use coop_ui::Root;
use dirs::config_dir;
use gpui::*;
use nostr_sdk::prelude::*;
@@ -14,6 +13,7 @@ use tokio::{
sync::{mpsc, Mutex},
time::sleep,
};
+use ui::Root;
use constants::{ALL_MESSAGES_SUB_ID, APP_NAME, FAKE_SIG, METADATA_DELAY, NEW_MESSAGE_SUB_ID};
use states::{
@@ -81,7 +81,7 @@ async fn main() {
_ = client.connect().await;
// Signal
- let (signal_tx, mut signal_rx) = mpsc::channel::(10000);
+ let (signal_tx, mut signal_rx) = mpsc::channel::(4000); // TODO: adjust?
let (mta_tx, mut mta_rx) = mpsc::unbounded_channel::();
// Re use sender
@@ -92,6 +92,7 @@ async fn main() {
tokio::spawn(async move {
let sig = Signature::from_str(FAKE_SIG).unwrap();
let new_message = SubscriptionId::new(NEW_MESSAGE_SUB_ID);
+ let all_messages = SubscriptionId::new(ALL_MESSAGES_SUB_ID);
while let Ok(notification) = notifications.recv().await {
#[allow(clippy::collapsible_match)]
@@ -142,8 +143,10 @@ async fn main() {
}
}
} else if let RelayMessage::EndOfStoredEvents(subscription_id) = message {
- if let Err(e) = signal_tx.send(Signal::RecvEose(subscription_id)).await {
- println!("Send error: {}", e)
+ if subscription_id == all_messages {
+ if let Err(e) = signal_tx.send(Signal::RecvEose(subscription_id)).await {
+ println!("Send error: {}", e)
+ }
}
}
}
@@ -203,50 +206,32 @@ async fn main() {
SignalRegistry::set_global(cx, mta_tx_clone);
// Initialize components
- coop_ui::init(cx);
+ ui::init(cx);
// Set quit action
cx.on_action(quit);
- /*
cx.spawn(|async_cx| async move {
- let accounts = get_all_accounts_from_keyring();
+ let (tx, rx) = smol::channel::unbounded::();
- // Automatically Login if only have 1 account
- if let Some(account) = accounts.into_iter().next() {
- if let Ok(keys) = get_keys_by_account(account) {
- get_client().set_signer(keys).await;
-
- _ = async_cx.update_global::(|state, _| {
- state.set_user(Some(account));
- });
- }
- }
- })
- .detach();
- */
-
- cx.spawn(|async_cx| async move {
- let all_messages = SubscriptionId::new(ALL_MESSAGES_SUB_ID);
- let mut is_initialized = false;
-
- while let Some(signal) = signal_rx.recv().await {
- match signal {
- Signal::RecvEose(id) => {
- if id == all_messages {
- if !is_initialized {
- _ = async_cx.update_global::(|state, _| {
- state.set_init();
- });
-
- is_initialized = true;
- } else {
- _ = async_cx.update_global::(|state, _| {
- state.set_reload();
- });
- }
+ async_cx
+ .background_executor()
+ .spawn(async move {
+ while let Some(signal) = signal_rx.recv().await {
+ if let Err(e) = tx.send(signal).await {
+ println!("Send error: {}", e)
}
}
+ })
+ .detach();
+
+ while let Ok(signal) = rx.recv().await {
+ match signal {
+ Signal::RecvEose(_) => {
+ _ = async_cx.update_global::(|state, _| {
+ state.update();
+ });
+ }
Signal::RecvEvent(event) => {
let metadata = async_cx
.background_executor()
@@ -277,7 +262,7 @@ async fn main() {
_ = async_cx.update_global::(|state, _cx| {
state.seen(public_key, metadata);
- })
+ });
}
_ => {}
}
diff --git a/crates/app/src/states/chat.rs b/crates/app/src/states/chat.rs
index 6d3a0df..8981ac5 100644
--- a/crates/app/src/states/chat.rs
+++ b/crates/app/src/states/chat.rs
@@ -15,6 +15,7 @@ pub struct Room {
pub last_seen: Timestamp,
pub title: Option,
pub metadata: Option,
+ is_initialized: bool,
}
impl Room {
@@ -48,6 +49,7 @@ impl Room {
last_seen,
owner,
metadata,
+ is_initialized: false,
}
}
}
@@ -71,12 +73,12 @@ impl ChatRegistry {
cx.set_global(Self::new());
}
- pub fn set_init(&mut self) {
- self.is_initialized = true;
- }
-
- pub fn set_reload(&mut self) {
- self.reload = true;
+ 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) {
diff --git a/crates/app/src/views/account.rs b/crates/app/src/views/account.rs
index 3ac8d1f..785c70f 100644
--- a/crates/app/src/views/account.rs
+++ b/crates/app/src/views/account.rs
@@ -1,11 +1,11 @@
-use coop_ui::{
+use gpui::*;
+use nostr_sdk::prelude::*;
+use prelude::FluentBuilder;
+use ui::{
button::{Button, ButtonVariants},
popup_menu::PopupMenuExt,
Icon, IconName, Sizable,
};
-use gpui::*;
-use nostr_sdk::prelude::*;
-use prelude::FluentBuilder;
use crate::{
constants::IMAGE_SERVICE,
diff --git a/crates/app/src/views/app.rs b/crates/app/src/views/app.rs
index f34a5bb..67961ee 100644
--- a/crates/app/src/views/app.rs
+++ b/crates/app/src/views/app.rs
@@ -1,12 +1,12 @@
-use coop_ui::{
- dock::{DockArea, DockItem, DockPlacement},
- theme::Theme,
- Root, TitleBar,
-};
use gpui::*;
use prelude::FluentBuilder;
use serde::Deserialize;
use std::sync::Arc;
+use ui::{
+ dock::{DockArea, DockItem, DockPlacement},
+ theme::Theme,
+ Root, TitleBar,
+};
use super::{
account::Account, chat::ChatPanel, contact::ContactPanel, onboarding::Onboarding,
diff --git a/crates/app/src/views/chat/message.rs b/crates/app/src/views/chat/message.rs
index 086e601..6152062 100644
--- a/crates/app/src/views/chat/message.rs
+++ b/crates/app/src/views/chat/message.rs
@@ -1,7 +1,7 @@
-use coop_ui::{theme::ActiveTheme, StyledExt};
use gpui::*;
use nostr_sdk::prelude::*;
use prelude::FluentBuilder;
+use ui::{theme::ActiveTheme, StyledExt};
use crate::{
constants::IMAGE_SERVICE,
diff --git a/crates/app/src/views/chat/mod.rs b/crates/app/src/views/chat/mod.rs
index 229b67c..d534b75 100644
--- a/crates/app/src/views/chat/mod.rs
+++ b/crates/app/src/views/chat/mod.rs
@@ -1,13 +1,13 @@
use std::sync::Arc;
-use coop_ui::{
+use gpui::*;
+use nostr_sdk::prelude::*;
+use room::RoomPanel;
+use ui::{
button::Button,
dock::{Panel, PanelEvent, PanelState},
popup_menu::PopupMenu,
};
-use gpui::*;
-use nostr_sdk::prelude::*;
-use room::RoomPanel;
use crate::states::chat::Room;
diff --git a/crates/app/src/views/chat/room.rs b/crates/app/src/views/chat/room.rs
index 9ccd5d4..1f839a6 100644
--- a/crates/app/src/views/chat/room.rs
+++ b/crates/app/src/views/chat/room.rs
@@ -1,13 +1,13 @@
-use coop_ui::{
+use gpui::*;
+use itertools::Itertools;
+use nostr_sdk::prelude::*;
+use std::sync::Arc;
+use ui::{
button::{Button, ButtonVariants},
input::{InputEvent, TextInput},
theme::ActiveTheme,
v_flex, Icon, IconName,
};
-use gpui::*;
-use itertools::Itertools;
-use nostr_sdk::prelude::*;
-use std::sync::Arc;
use super::message::RoomMessage;
use crate::{
@@ -43,7 +43,7 @@ impl RoomPanel {
let input = cx.new_view(|cx| {
TextInput::new(cx)
.appearance(false)
- .text_size(coop_ui::Size::Small)
+ .text_size(ui::Size::Small)
.placeholder("Message...")
.cleanable()
});
diff --git a/crates/app/src/views/contact/item.rs b/crates/app/src/views/contact/item.rs
index 3303e98..9e4cec1 100644
--- a/crates/app/src/views/contact/item.rs
+++ b/crates/app/src/views/contact/item.rs
@@ -1,7 +1,7 @@
-use coop_ui::StyledExt;
use gpui::*;
use nostr_sdk::prelude::*;
use prelude::FluentBuilder;
+use ui::theme::ActiveTheme;
use crate::{
constants::IMAGE_SERVICE,
@@ -64,7 +64,7 @@ impl ContactListItem {
impl Render for ContactListItem {
fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement {
let fallback = show_npub(self.public_key, 16);
- let mut content = div();
+ let mut content = div().h_10().text_sm();
if let Some(metadata) = self.metadata.read(cx).as_ref() {
content = content
@@ -73,15 +73,14 @@ impl Render for ContactListItem {
.gap_2()
.map(|this| {
if let Some(picture) = metadata.picture.clone() {
- this.flex_shrink_0().child(
+ this.child(
img(format!("{}/?url={}&w=72&h=72&n=-1", IMAGE_SERVICE, picture))
- .size_6()
+ .size_8()
.rounded_full()
.object_fit(ObjectFit::Cover),
)
} else {
- this.flex_shrink_0()
- .child(img("brand/avatar.png").size_6().rounded_full())
+ this.child(img("brand/avatar.png").size_8().rounded_full())
}
})
.map(|this| {
@@ -96,20 +95,18 @@ impl Render for ContactListItem {
.flex()
.items_center()
.gap_2()
- .child(
- img("brand/avatar.png")
- .flex_shrink_0()
- .size_6()
- .rounded_full(),
- )
+ .child(img("brand/avatar.png").size_8().rounded_full())
.child(fallback)
}
div()
- .scrollable(
- cx.view().entity_id(),
- coop_ui::scroll::ScrollbarAxis::Vertical,
- )
+ .w_full()
+ .px_2()
+ .rounded_md()
+ .hover(|this| {
+ this.bg(cx.theme().muted)
+ .text_color(cx.theme().muted_foreground)
+ })
.child(content)
}
}
diff --git a/crates/app/src/views/contact/list.rs b/crates/app/src/views/contact/list.rs
deleted file mode 100644
index 2550789..0000000
--- a/crates/app/src/views/contact/list.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-use gpui::*;
-use prelude::FluentBuilder;
-use std::time::Duration;
-
-use super::item::ContactListItem;
-use crate::get_client;
-
-pub struct ContactList {
- contacts: Model