diff --git a/Cargo.lock b/Cargo.lock index c2e8ddc..abe0677 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1032,6 +1032,18 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "common" +version = "0.1.0" +dependencies = [ + "anyhow", + "chrono", + "gpui", + "itertools 0.13.0", + "nostr-sdk", + "random_name_generator", +] + [[package]] name = "concurrent-queue" version = "2.5.0" @@ -1073,11 +1085,11 @@ version = "0.1.0" dependencies = [ "anyhow", "chrono", + "common", "dirs 5.0.1", "gpui", "itertools 0.13.0", "nostr-sdk", - "random_name_generator", "reqwest_client", "rust-embed", "serde", diff --git a/crates/app/Cargo.toml b/crates/app/Cargo.toml index bf921e4..c5247c1 100644 --- a/crates/app/Cargo.toml +++ b/crates/app/Cargo.toml @@ -10,6 +10,7 @@ path = "src/main.rs" [dependencies] ui = { path = "../ui" } +common = { path = "../common" } gpui.workspace = true reqwest_client.workspace = true @@ -26,4 +27,3 @@ rust-embed.workspace = true smol.workspace = true tracing-subscriber = { version = "0.3.18", features = ["fmt"] } -random_name_generator = "0.3.6" diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index bcb5731..cec2f2b 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -1,12 +1,15 @@ use asset::Assets; -use constants::{ - ALL_MESSAGES_SUB_ID, APP_NAME, FAKE_SIG, KEYRING_SERVICE, METADATA_DELAY, NEW_MESSAGE_SUB_ID, +use common::constants::{ + ALL_MESSAGES_SUB_ID, APP_ID, APP_NAME, FAKE_SIG, KEYRING_SERVICE, METADATA_DELAY, + NEW_MESSAGE_SUB_ID, }; use dirs::config_dir; use gpui::{ actions, point, px, size, App, AppContext, Bounds, SharedString, TitlebarOptions, - VisualContext, WindowBounds, WindowDecorations, WindowKind, WindowOptions, + VisualContext, WindowBounds, WindowKind, WindowOptions, }; +#[cfg(target_os = "linux")] +use gpui::{WindowBackgroundAppearance, WindowDecorations}; use nostr_sdk::prelude::*; use states::{app::AppRegistry, chat::ChatRegistry}; use std::{ @@ -24,9 +27,7 @@ use ui::Root; use views::app::AppView; mod asset; -mod constants; mod states; -mod utils; mod views; actions!(main_menu, [Quit]); @@ -38,8 +39,6 @@ static CLIENT: OnceLock = OnceLock::new(); pub enum Signal { /// Receive event Event(Event), - /// Receive metadata - Metadata(PublicKey), /// Receive EOSE Eose, } @@ -157,11 +156,6 @@ async fn main() { }; } } - Kind::Metadata => { - if let Err(e) = signal_tx.send(Signal::Metadata(event.pubkey)).await { - println!("Send error: {}", e) - } - } _ => {} } } else if let RelayMessage::EndOfStoredEvents(subscription_id) = message { @@ -226,40 +220,6 @@ async fn main() { // Set quit action cx.on_action(quit); - cx.spawn(|async_cx| { - let task = cx.read_credentials(KEYRING_SERVICE); - - async move { - if let Ok(res) = task.await { - if let Some((npub, secret)) = res { - let public_key = PublicKey::from_bech32(&npub).unwrap(); - let hex = String::from_utf8(secret).unwrap(); - let keys = Keys::parse(&hex).unwrap(); - - // Update signer - async_cx - .background_executor() - .spawn(async move { client.set_signer(keys).await }) - .detach(); - - // Update global state - _ = async_cx.update_global::(|state, cx| { - state.set_user(public_key, cx); - }); - } else { - _ = async_cx.update_global::(|state, _| { - state.set_loading(); - }); - } - } else { - _ = async_cx.update_global::(|state, _| { - state.set_loading(); - }); - } - } - }) - .detach(); - cx.spawn(|async_cx| async move { let (tx, rx) = smol::channel::unbounded::(); @@ -281,11 +241,6 @@ async fn main() { chat.init(cx); }); } - Signal::Metadata(public_key) => { - _ = async_cx.update_global::(|state, cx| { - state.set_refresh(public_key, cx); - }); - } Signal::Event(event) => { _ = async_cx.update_global::(|state, cx| { state.receive(event, cx) @@ -296,8 +251,33 @@ async fn main() { }) .detach(); - // Set window size - let bounds = Bounds::centered(None, size(px(900.0), px(680.0)), cx); + cx.spawn(|async_cx| { + let task = cx.read_credentials(KEYRING_SERVICE); + + async move { + if let Ok(Some((npub, secret))) = task.await { + let public_key = PublicKey::from_bech32(&npub).expect("Something wrong."); + let hex = String::from_utf8(secret).expect("Something wrong."); + let keys = Keys::parse(&hex).expect("Something wrong."); + + // Update signer + async_cx + .background_executor() + .spawn(async move { client.set_signer(keys).await }) + .detach(); + + // Update global state + _ = async_cx.update_global::(|state, cx| { + state.set_user(public_key, cx); + }); + } else { + _ = async_cx.update_global::(|state, _| { + state.is_loading = false; + }); + } + } + }) + .detach(); let opts = WindowOptions { #[cfg(not(target_os = "linux"))] @@ -306,8 +286,11 @@ async fn main() { traffic_light_position: Some(point(px(9.0), px(9.0))), appears_transparent: true, }), - window_bounds: Some(WindowBounds::Windowed(bounds)), - window_decorations: Some(WindowDecorations::Client), + window_bounds: Some(WindowBounds::Windowed(Bounds::centered( + None, + size(px(900.0), px(680.0)), + cx, + ))), #[cfg(target_os = "linux")] window_background: WindowBackgroundAppearance::Transparent, #[cfg(target_os = "linux")] @@ -317,11 +300,11 @@ async fn main() { }; cx.open_window(opts, |cx| { - let app_view = cx.new_view(AppView::new); - - cx.set_window_title("Coop"); + cx.set_window_title(APP_NAME); + cx.set_app_id(APP_ID); cx.activate(true); - cx.new_view(|cx| Root::new(app_view.into(), cx)) + + cx.new_view(|cx| Root::new(cx.new_view(AppView::new).into(), cx)) }) .expect("System error"); }); diff --git a/crates/app/src/states/app.rs b/crates/app/src/states/app.rs index ceb8540..93c2b9a 100644 --- a/crates/app/src/states/app.rs +++ b/crates/app/src/states/app.rs @@ -1,7 +1,5 @@ -use crate::{ - constants::{ALL_MESSAGES_SUB_ID, NEW_MESSAGE_SUB_ID}, - get_client, -}; +use crate::get_client; +use common::constants::{ALL_MESSAGES_SUB_ID, NEW_MESSAGE_SUB_ID}; use gpui::*; use nostr_sdk::prelude::*; use std::time::Duration; @@ -81,10 +79,6 @@ impl AppRegistry { .detach(); } - pub fn set_loading(&mut self) { - self.is_loading = false - } - pub fn set_user(&mut self, public_key: PublicKey, cx: &mut AppContext) { self.user.update(cx, |model, cx| { *model = Some(public_key); @@ -94,13 +88,6 @@ impl AppRegistry { self.is_loading = false; } - pub fn set_refresh(&mut self, public_key: PublicKey, cx: &mut AppContext) { - self.refreshs.update(cx, |this, cx| { - this.push(public_key); - cx.notify(); - }) - } - pub fn current_user(&self) -> WeakModel> { self.user.downgrade() } diff --git a/crates/app/src/states/chat/mod.rs b/crates/app/src/states/chat/mod.rs index d33c6f0..bdbf2d0 100644 --- a/crates/app/src/states/chat/mod.rs +++ b/crates/app/src/states/chat/mod.rs @@ -1,13 +1,12 @@ -use crate::{ - get_client, - utils::{compare, room_hash}, -}; +use common::utils::{compare, room_hash}; use gpui::{AppContext, Context, Global, Model, WeakModel}; use itertools::Itertools; use nostr_sdk::prelude::*; use room::Room; use std::cmp::Reverse; +use crate::get_client; + pub mod room; pub struct Inbox { diff --git a/crates/app/src/states/chat/room.rs b/crates/app/src/states/chat/room.rs index c67a9bb..13d700d 100644 --- a/crates/app/src/states/chat/room.rs +++ b/crates/app/src/states/chat/room.rs @@ -1,4 +1,4 @@ -use crate::{ +use common::{ constants::IMAGE_SERVICE, utils::{compare, random_name, room_hash, shorted_public_key}, }; diff --git a/crates/app/src/views/account.rs b/crates/app/src/views/account.rs index 6a669ff..bc7b62d 100644 --- a/crates/app/src/views/account.rs +++ b/crates/app/src/views/account.rs @@ -1,4 +1,5 @@ -use crate::{constants::IMAGE_SERVICE, get_client, states::app::AppRegistry}; +use crate::{get_client, states::app::AppRegistry}; +use common::constants::IMAGE_SERVICE; use gpui::prelude::FluentBuilder; use gpui::{ actions, img, Context, IntoElement, Model, ObjectFit, ParentElement, Render, Styled, diff --git a/crates/app/src/views/chat/mod.rs b/crates/app/src/views/chat/mod.rs index 573320c..7d72306 100644 --- a/crates/app/src/views/chat/mod.rs +++ b/crates/app/src/views/chat/mod.rs @@ -1,10 +1,8 @@ -use crate::{ +use async_utility::task::spawn; +use common::{ constants::IMAGE_SERVICE, - get_client, - states::chat::room::Room, utils::{compare, message_time, nip96_upload}, }; -use async_utility::task::spawn; use gpui::{ div, img, list, px, white, AnyElement, AppContext, Context, EventEmitter, Flatten, FocusHandle, FocusableView, InteractiveElement, IntoElement, ListAlignment, ListState, Model, ObjectFit, @@ -29,6 +27,8 @@ use ui::{ v_flex, ContextModal, Icon, IconName, Sizable, }; +use crate::{get_client, states::chat::room::Room}; + mod message; #[derive(Clone)] @@ -363,7 +363,9 @@ impl ChatPanel { let (tx, rx) = oneshot::channel::(); spawn(async move { - if let Ok(url) = nip96_upload(file_data).await { + let client = get_client(); + + if let Ok(url) = nip96_upload(client, file_data).await { _ = tx.send(url); } }); diff --git a/crates/app/src/views/onboarding/mod.rs b/crates/app/src/views/onboarding/mod.rs index d330020..3fdf485 100644 --- a/crates/app/src/views/onboarding/mod.rs +++ b/crates/app/src/views/onboarding/mod.rs @@ -1,8 +1,10 @@ -use crate::{constants::KEYRING_SERVICE, get_client, states::app::AppRegistry}; +use common::constants::KEYRING_SERVICE; use gpui::{div, IntoElement, ParentElement, Render, Styled, View, ViewContext, VisualContext}; use nostr_sdk::prelude::*; use ui::input::{InputEvent, TextInput}; +use crate::{get_client, states::app::AppRegistry}; + pub struct Onboarding { input: View, } diff --git a/crates/app/src/views/sidebar/compose.rs b/crates/app/src/views/sidebar/compose.rs index e241740..0fe856c 100644 --- a/crates/app/src/views/sidebar/compose.rs +++ b/crates/app/src/views/sidebar/compose.rs @@ -4,8 +4,8 @@ use crate::{ app::AppRegistry, chat::room::{Member, Room}, }, - utils::{random_name, room_hash}, }; +use common::utils::{random_name, room_hash}; use gpui::{ div, img, impl_internal_actions, px, uniform_list, Context, FocusHandle, InteractiveElement, IntoElement, Model, ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, diff --git a/crates/app/src/views/sidebar/inbox.rs b/crates/app/src/views/sidebar/inbox.rs index e5c75c6..ddbee1d 100644 --- a/crates/app/src/views/sidebar/inbox.rs +++ b/crates/app/src/views/sidebar/inbox.rs @@ -1,8 +1,8 @@ use crate::{ states::chat::ChatRegistry, - utils::message_ago, views::app::{AddPanel, PanelKind}, }; +use common::utils::message_ago; use gpui::{ div, img, percentage, prelude::FluentBuilder, px, InteractiveElement, IntoElement, ParentElement, Render, SharedString, StatefulInteractiveElement, Styled, ViewContext, diff --git a/crates/common/Cargo.toml b/crates/common/Cargo.toml new file mode 100644 index 0000000..027ef19 --- /dev/null +++ b/crates/common/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "common" +version = "0.1.0" +edition = "2021" +publish = false + +[dependencies] +gpui.workspace = true +nostr-sdk.workspace = true +anyhow.workspace = true +itertools.workspace = true +chrono.workspace = true + +random_name_generator = "0.3.6" diff --git a/crates/app/src/constants.rs b/crates/common/src/constants.rs similarity index 84% rename from crates/app/src/constants.rs rename to crates/common/src/constants.rs index 6c5abce..8329061 100644 --- a/crates/app/src/constants.rs +++ b/crates/common/src/constants.rs @@ -1,8 +1,13 @@ pub const KEYRING_SERVICE: &str = "Coop Safe Storage"; pub const APP_NAME: &str = "Coop"; +pub const APP_ID: &str = "su.reya.coop"; pub const FAKE_SIG: &str = "f9e79d141c004977192d05a86f81ec7c585179c371f7350a5412d33575a2a356433f58e405c2296ed273e2fe0aafa25b641e39cc4e1f3f261ebf55bce0cbac83"; 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 = 200; + +/// Image Resizer Service pub const IMAGE_SERVICE: &str = "https://wsrv.nl"; + +/// NIP96 Media Server pub const NIP96_SERVER: &str = "https://nostrcheck.me"; diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs new file mode 100644 index 0000000..49f6ff0 --- /dev/null +++ b/crates/common/src/lib.rs @@ -0,0 +1,2 @@ +pub mod constants; +pub mod utils; diff --git a/crates/app/src/utils.rs b/crates/common/src/utils.rs similarity index 94% rename from crates/app/src/utils.rs rename to crates/common/src/utils.rs index e2a0d86..6567c4d 100644 --- a/crates/app/src/utils.rs +++ b/crates/common/src/utils.rs @@ -1,4 +1,4 @@ -use crate::{constants::NIP96_SERVER, get_client}; +use crate::constants::NIP96_SERVER; use chrono::{Datelike, Local, TimeZone}; use nostr_sdk::prelude::*; use rnglib::{Language, RNG}; @@ -7,8 +7,7 @@ use std::{ hash::{DefaultHasher, Hash, Hasher}, }; -pub async fn nip96_upload(file: Vec) -> anyhow::Result { - let client = get_client(); +pub async fn nip96_upload(client: &Client, file: Vec) -> anyhow::Result { let signer = client.signer().await?; let server_url = Url::parse(NIP96_SERVER)?;