From a87111e13890901238df54fa0fbc0a1713733c4c Mon Sep 17 00:00:00 2001 From: reya Date: Thu, 29 Jan 2026 09:31:09 +0700 Subject: [PATCH] clean up --- Cargo.lock | 58 +-- crates/coop/src/dialogs/mod.rs | 1 + .../{user/viewer.rs => dialogs/profile.rs} | 46 ++- crates/coop/src/main.rs | 1 - crates/coop/src/panels/greeter.rs | 2 +- crates/coop/src/panels/import.rs | 2 +- crates/coop/src/user/mod.rs | 388 ------------------ crates/coop/src/workspace.rs | 57 +-- 8 files changed, 63 insertions(+), 492 deletions(-) rename crates/coop/src/{user/viewer.rs => dialogs/profile.rs} (87%) delete mode 100644 crates/coop/src/user/mod.rs diff --git a/Cargo.lock b/Cargo.lock index cfd7f5f..50d017b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1180,7 +1180,7 @@ dependencies = [ [[package]] name = "collections" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "indexmap", "rustc-hash 2.1.1", @@ -1619,7 +1619,7 @@ dependencies = [ [[package]] name = "derive_refineable" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "proc-macro2", "quote", @@ -2542,7 +2542,7 @@ dependencies = [ [[package]] name = "gpui" version = "0.2.2" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "anyhow", "as-raw-xcb-connection", @@ -2644,7 +2644,7 @@ dependencies = [ [[package]] name = "gpui_macros" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -2655,7 +2655,7 @@ dependencies = [ [[package]] name = "gpui_tokio" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "anyhow", "gpui", @@ -2877,7 +2877,7 @@ dependencies = [ [[package]] name = "http_client" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "anyhow", "async-compression", @@ -2902,7 +2902,7 @@ dependencies = [ [[package]] name = "http_client_tls" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "rustls", "rustls-platform-verifier", @@ -2997,9 +2997,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3663,7 +3663,7 @@ dependencies = [ [[package]] name = "media" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "anyhow", "bindgen", @@ -4264,9 +4264,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "oneshot" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ce66197e99546da6c6d991285f605192e794ceae69686c17163844a7bf8fcc2" +checksum = "269bca4c2591a28585d6bf10d9ed0332b7d76900a1b02bec41bdc3a2cdcda107" [[package]] name = "oo7" @@ -4502,7 +4502,7 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "perf" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "collections", "serde", @@ -5137,7 +5137,7 @@ dependencies = [ [[package]] name = "refineable" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "derive_refineable", ] @@ -5236,7 +5236,7 @@ dependencies = [ [[package]] name = "reqwest_client" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "anyhow", "bytes", @@ -5290,7 +5290,7 @@ dependencies = [ [[package]] name = "rope" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "arrayvec", "log", @@ -5569,7 +5569,7 @@ dependencies = [ [[package]] name = "scheduler" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "async-task", "backtrace", @@ -5942,9 +5942,9 @@ dependencies = [ [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" [[package]] name = "skrifa" @@ -6161,7 +6161,7 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "sum_tree" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "arrayvec", "log", @@ -7102,7 +7102,7 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "util" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "anyhow", "async-fs", @@ -7140,7 +7140,7 @@ dependencies = [ [[package]] name = "util_macros" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "perf", "quote", @@ -8521,18 +8521,18 @@ checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" [[package]] name = "zerocopy" -version = "0.8.33" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" +checksum = "fdea86ddd5568519879b8187e1cf04e24fce28f7fe046ceecbce472ff19a2572" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.33" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" +checksum = "0c15e1b46eff7c6c91195752e0eeed8ef040e391cdece7c25376957d5f15df22" dependencies = [ "proc-macro2", "quote", @@ -8616,7 +8616,7 @@ dependencies = [ [[package]] name = "zlog" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "anyhow", "chrono", @@ -8633,7 +8633,7 @@ checksum = "02aae0f83f69aafc94776e879363e9771d7ecbffe2c7fbb6c14c5e00dfe88439" [[package]] name = "ztracing" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" dependencies = [ "tracing", "tracing-subscriber", @@ -8644,7 +8644,7 @@ dependencies = [ [[package]] name = "ztracing_macro" version = "0.1.0" -source = "git+https://github.com/zed-industries/zed#aceff52f8a93a31009d6f5284253f0b334a043dc" +source = "git+https://github.com/zed-industries/zed#1870425b2b262e3f28c90931782aba435afd5b99" [[package]] name = "zune-core" diff --git a/crates/coop/src/dialogs/mod.rs b/crates/coop/src/dialogs/mod.rs index 429c676..ff57b85 100644 --- a/crates/coop/src/dialogs/mod.rs +++ b/crates/coop/src/dialogs/mod.rs @@ -1,2 +1,3 @@ pub mod compose; +pub mod profile; pub mod screening; diff --git a/crates/coop/src/user/viewer.rs b/crates/coop/src/dialogs/profile.rs similarity index 87% rename from crates/coop/src/user/viewer.rs rename to crates/coop/src/dialogs/profile.rs index 4423981..27d784a 100644 --- a/crates/coop/src/user/viewer.rs +++ b/crates/coop/src/dialogs/profile.rs @@ -9,7 +9,7 @@ use gpui::{ }; use gpui_tokio::Tokio; use nostr_sdk::prelude::*; -use person::{Person, PersonRegistry}; +use person::PersonRegistry; use smallvec::{smallvec, SmallVec}; use state::NostrRegistry; use theme::ActiveTheme; @@ -17,13 +17,13 @@ use ui::avatar::Avatar; use ui::button::{Button, ButtonVariants}; use ui::{h_flex, v_flex, Icon, IconName, Sizable, StyledExt}; -pub fn init(public_key: PublicKey, window: &mut Window, cx: &mut App) -> Entity { - cx.new(|cx| ProfileViewer::new(public_key, window, cx)) +pub fn init(public_key: PublicKey, window: &mut Window, cx: &mut App) -> Entity { + cx.new(|cx| ProfileDialog::new(public_key, window, cx)) } #[derive(Debug)] -pub struct ProfileViewer { - profile: Person, +pub struct ProfileDialog { + public_key: PublicKey, /// Follow status followed: bool, @@ -38,13 +38,13 @@ pub struct ProfileViewer { _tasks: SmallVec<[Task<()>; 1]>, } -impl ProfileViewer { - pub fn new(target: PublicKey, window: &mut Window, cx: &mut Context) -> Self { +impl ProfileDialog { + pub fn new(public_key: PublicKey, window: &mut Window, cx: &mut Context) -> Self { let nostr = NostrRegistry::global(cx); let client = nostr.read(cx).client(); let persons = PersonRegistry::global(cx); - let profile = persons.read(cx).get(&target, cx); + let profile = persons.read(cx).get(&public_key, cx); let mut tasks = smallvec![]; @@ -53,12 +53,12 @@ impl ProfileViewer { let public_key = signer.get_public_key().await?; let contact_list = client.database().contacts_public_keys(public_key).await?; - Ok(contact_list.contains(&target)) + Ok(contact_list.contains(&public_key)) }); let verify_nip05 = if let Some(address) = profile.metadata().nip05 { Some(Tokio::spawn(cx, async move { - nip05_verify(target, &address).await.unwrap_or(false) + nip05_verify(public_key, &address).await.unwrap_or(false) })) } else { None @@ -90,7 +90,7 @@ impl ProfileViewer { ); Self { - profile, + public_key, followed: false, verified: false, copied: false, @@ -98,12 +98,18 @@ impl ProfileViewer { } } - fn address(&self, _cx: &Context) -> Option { - self.profile.metadata().nip05 + fn address(&self, cx: &Context) -> Option { + let persons = PersonRegistry::global(cx); + let profile = persons.read(cx).get(&self.public_key, cx); + + profile.metadata().nip05 } fn copy_pubkey(&mut self, window: &mut Window, cx: &mut Context) { - let Ok(bech32) = self.profile.public_key().to_bech32(); + let persons = PersonRegistry::global(cx); + let profile = persons.read(cx).get(&self.public_key, cx); + + let Ok(bech32) = profile.public_key().to_bech32(); let item = ClipboardItem::new_string(bech32); cx.write_to_clipboard(item); @@ -132,9 +138,11 @@ impl ProfileViewer { } } -impl Render for ProfileViewer { +impl Render for ProfileDialog { fn render(&mut self, _window: &mut Window, cx: &mut Context) -> impl IntoElement { - let bech32 = shorten_pubkey(self.profile.public_key(), 16); + let persons = PersonRegistry::global(cx); + let profile = persons.read(cx).get(&self.public_key, cx); + let bech32 = shorten_pubkey(profile.public_key(), 16); let shared_bech32 = SharedString::from(bech32); v_flex() @@ -146,14 +154,14 @@ impl Render for ProfileViewer { .items_center() .justify_center() .text_center() - .child(Avatar::new(self.profile.avatar()).size(rems(4.))) + .child(Avatar::new(profile.avatar()).size(rems(4.))) .child( v_flex() .child( div() .font_semibold() .line_height(relative(1.25)) - .child(self.profile.name()), + .child(profile.name()), ) .when_some(self.address(cx), |this, address| { this.child( @@ -208,7 +216,7 @@ impl Render for ProfileViewer { .rounded(cx.theme().radius) .bg(cx.theme().elevated_surface_background) .child( - self.profile + profile .metadata() .about .map(SharedString::from) diff --git a/crates/coop/src/main.rs b/crates/coop/src/main.rs index 57a866b..1a0fd73 100644 --- a/crates/coop/src/main.rs +++ b/crates/coop/src/main.rs @@ -15,7 +15,6 @@ mod actions; mod dialogs; mod panels; mod sidebar; -mod user; mod workspace; fn main() { diff --git a/crates/coop/src/panels/greeter.rs b/crates/coop/src/panels/greeter.rs index f61077f..a66598f 100644 --- a/crates/coop/src/panels/greeter.rs +++ b/crates/coop/src/panels/greeter.rs @@ -140,7 +140,7 @@ impl Render for GreeterPanel { .gap_2() .when(relay_list_state == RelayState::NotSet, |this| { this.child( - Button::new("connect") + Button::new("relaylist") .icon(Icon::new(IconName::Door)) .label("Set up relay list") .ghost() diff --git a/crates/coop/src/panels/import.rs b/crates/coop/src/panels/import.rs index f133f0c..ea1281f 100644 --- a/crates/coop/src/panels/import.rs +++ b/crates/coop/src/panels/import.rs @@ -47,7 +47,7 @@ pub struct ImportPanel { impl ImportPanel { fn new(window: &mut Window, cx: &mut Context) -> Self { - let key_input = cx.new(|cx| InputState::new(window, cx)); + let key_input = cx.new(|cx| InputState::new(window, cx).masked(true)); let pass_input = cx.new(|cx| InputState::new(window, cx).masked(true)); let error = cx.new(|_| None); diff --git a/crates/coop/src/user/mod.rs b/crates/coop/src/user/mod.rs deleted file mode 100644 index 54b1ea1..0000000 --- a/crates/coop/src/user/mod.rs +++ /dev/null @@ -1,388 +0,0 @@ -use std::str::FromStr; -use std::time::Duration; - -use anyhow::{anyhow, Error}; -use common::{nip96_upload, shorten_pubkey}; -use gpui::prelude::FluentBuilder; -use gpui::{ - div, img, App, AppContext, ClipboardItem, Context, Entity, IntoElement, ParentElement, - PathPromptOptions, Render, SharedString, Styled, Task, Window, -}; -use gpui_tokio::Tokio; -use nostr_sdk::prelude::*; -use person::Person; -use settings::AppSettings; -use smallvec::{smallvec, SmallVec}; -use smol::fs; -use state::NostrRegistry; -use theme::ActiveTheme; -use ui::button::{Button, ButtonVariants}; -use ui::input::{InputState, TextInput}; -use ui::{h_flex, v_flex, Disableable, IconName, Sizable, StyledExt, WindowExtension}; - -pub mod viewer; - -pub fn init(window: &mut Window, cx: &mut App) -> Entity { - cx.new(|cx| UserProfile::new(window, cx)) -} - -#[derive(Debug)] -pub struct UserProfile { - /// User profile - profile: Option, - - /// User's name text input - name_input: Entity, - - /// User's avatar url text input - avatar_input: Entity, - - /// User's bio multi line input - bio_input: Entity, - - /// User's website url text input - website_input: Entity, - - /// Uploading state - uploading: bool, - - /// Copied states - copied: bool, - - /// Async operations - _tasks: SmallVec<[Task<()>; 1]>, -} - -impl UserProfile { - pub fn new(window: &mut Window, cx: &mut Context) -> Self { - let name_input = cx.new(|cx| InputState::new(window, cx).placeholder("Alice")); - let avatar_input = cx.new(|cx| InputState::new(window, cx).placeholder("alice.me/a.jpg")); - let website_input = cx.new(|cx| InputState::new(window, cx).placeholder("alice.me")); - - // Use multi-line input for bio - let bio_input = cx.new(|cx| { - InputState::new(window, cx) - .multi_line() - .auto_grow(3, 8) - .placeholder("A short introduce about you.") - }); - - let get_profile = Self::get_profile(cx); - let mut tasks = smallvec![]; - - tasks.push( - // Get metadata in the background - cx.spawn_in(window, async move |this, cx| { - if let Ok(profile) = get_profile.await { - this.update_in(cx, |this, window, cx| { - this.set_profile(profile, window, cx); - }) - .ok(); - } - }), - ); - - Self { - profile: None, - name_input, - avatar_input, - bio_input, - website_input, - uploading: false, - copied: false, - _tasks: tasks, - } - } - - fn get_profile(cx: &App) -> Task> { - let nostr = NostrRegistry::global(cx); - let client = nostr.read(cx).client(); - - cx.background_spawn(async move { - let signer = client.signer().await?; - let public_key = signer.get_public_key().await?; - - let metadata = client - .database() - .metadata(public_key) - .await? - .unwrap_or_default(); - - Ok(Profile::new(public_key, metadata)) - }) - } - - fn set_profile(&mut self, profile: Profile, window: &mut Window, cx: &mut Context) { - let metadata = profile.metadata(); - - self.avatar_input.update(cx, |this, cx| { - if let Some(avatar) = metadata.picture.as_ref() { - this.set_value(avatar, window, cx); - } - }); - - self.bio_input.update(cx, |this, cx| { - if let Some(bio) = metadata.about.as_ref() { - this.set_value(bio, window, cx); - } - }); - - self.name_input.update(cx, |this, cx| { - if let Some(display_name) = metadata.display_name.as_ref() { - this.set_value(display_name, window, cx); - } - }); - - self.website_input.update(cx, |this, cx| { - if let Some(website) = metadata.website.as_ref() { - this.set_value(website, window, cx); - } - }); - - self.profile = Some(profile); - cx.notify(); - } - - fn copy(&mut self, value: String, window: &mut Window, cx: &mut Context) { - let item = ClipboardItem::new_string(value); - cx.write_to_clipboard(item); - - self.set_copied(true, window, cx); - } - - fn set_copied(&mut self, status: bool, window: &mut Window, cx: &mut Context) { - self.copied = status; - cx.notify(); - - if status { - self._tasks.push( - // Reset the copied state after a delay - cx.spawn_in(window, async move |this, cx| { - cx.background_executor().timer(Duration::from_secs(2)).await; - cx.update(|window, cx| { - this.update(cx, |this, cx| { - this.set_copied(false, window, cx); - }) - .ok(); - }) - .ok(); - }), - ); - } - } - - fn uploading(&mut self, status: bool, cx: &mut Context) { - self.uploading = status; - cx.notify(); - } - - fn upload(&mut self, window: &mut Window, cx: &mut Context) { - self.uploading(true, cx); - - let nostr = NostrRegistry::global(cx); - let client = nostr.read(cx).client(); - - // Get the user's configured NIP96 server - let nip96_server = AppSettings::get_file_server(cx); - - // Open native file dialog - let paths = cx.prompt_for_paths(PathPromptOptions { - files: true, - directories: false, - multiple: false, - prompt: None, - }); - - let task = Tokio::spawn(cx, async move { - match paths.await { - Ok(Ok(Some(mut paths))) => { - if let Some(path) = paths.pop() { - let file = fs::read(path).await?; - let url = nip96_upload(&client, &nip96_server, file).await?; - - Ok(url) - } else { - Err(anyhow!("Path not found")) - } - } - _ => Err(anyhow!("Error")), - } - }); - - cx.spawn_in(window, async move |this, cx| { - let result = task.await; - - this.update_in(cx, |this, window, cx| { - match result { - Ok(Ok(url)) => { - this.avatar_input.update(cx, |this, cx| { - this.set_value(url.to_string(), window, cx); - }); - } - Ok(Err(e)) => { - window.push_notification(e.to_string(), cx); - } - Err(e) => { - log::warn!("Failed to upload avatar: {e}"); - } - }; - this.uploading(false, cx); - }) - .expect("Entity has been released"); - }) - .detach(); - } - - pub fn set_metadata(&mut self, cx: &mut Context) -> Task> { - let avatar = self.avatar_input.read(cx).value().to_string(); - let name = self.name_input.read(cx).value().to_string(); - let bio = self.bio_input.read(cx).value().to_string(); - let website = self.website_input.read(cx).value().to_string(); - - // Get the current profile metadata - let old_metadata = self - .profile - .as_ref() - .map(|profile| profile.metadata()) - .unwrap_or_default(); - - // Construct the new metadata - let mut new_metadata = old_metadata.display_name(name).about(bio); - - if let Ok(url) = Url::from_str(&avatar) { - new_metadata = new_metadata.picture(url); - }; - - if let Ok(url) = Url::from_str(&website) { - new_metadata = new_metadata.website(url); - } - - let nostr = NostrRegistry::global(cx); - let client = nostr.read(cx).client(); - let public_key = nostr.read(cx).identity().read(cx).public_key(); - let write_relays = nostr.read(cx).write_relays(&public_key, cx); - - cx.background_spawn(async move { - let urls = write_relays.await; - let signer = client.signer().await?; - - // Sign the new metadata event - let event = EventBuilder::metadata(&new_metadata).sign(&signer).await?; - - // Send event to user's write relayss - client.send_event_to(urls, &event).await?; - - // Return the updated profile - let metadata = Metadata::from_json(&event.content).unwrap_or_default(); - let profile = Person::new(event.pubkey, metadata); - - Ok(profile) - }) - } -} - -impl Render for UserProfile { - fn render(&mut self, _window: &mut gpui::Window, cx: &mut Context) -> impl IntoElement { - v_flex() - .gap_3() - .child( - v_flex() - .relative() - .w_full() - .h_32() - .items_center() - .justify_center() - .gap_2() - .bg(cx.theme().surface_background) - .rounded(cx.theme().radius) - .map(|this| { - let picture = self.avatar_input.read(cx).value(); - let source = if picture.is_empty() { - "brand/avatar.png" - } else { - picture.as_str() - }; - this.child(img(source).rounded_full().size_10().flex_shrink_0()) - }) - .child( - Button::new("upload") - .icon(IconName::Upload) - .label("Change") - .ghost() - .small() - .disabled(self.uploading) - .on_click(cx.listener(move |this, _, window, cx| { - this.upload(window, cx); - })), - ), - ) - .child( - v_flex() - .gap_1() - .text_sm() - .child(SharedString::from("Name:")) - .child(TextInput::new(&self.name_input).small()), - ) - .child( - v_flex() - .gap_1() - .text_sm() - .child(SharedString::from("Bio:")) - .child(TextInput::new(&self.bio_input).small()), - ) - .child( - v_flex() - .gap_1() - .text_sm() - .child(SharedString::from("Website:")) - .child(TextInput::new(&self.website_input).small()), - ) - .when_some(self.profile.as_ref(), |this, profile| { - let public_key = profile.public_key(); - let display = SharedString::from(shorten_pubkey(profile.public_key(), 8)); - - this.child(div().my_1().h_px().w_full().bg(cx.theme().border)) - .child( - v_flex() - .gap_1() - .child( - div() - .text_xs() - .text_color(cx.theme().text_placeholder) - .font_semibold() - .child(SharedString::from("Public Key:")), - ) - .child( - h_flex() - .gap_2() - .w_full() - .h_12() - .justify_center() - .bg(cx.theme().surface_background) - .rounded(cx.theme().radius) - .text_sm() - .child(display) - .child( - Button::new("copy") - .icon({ - if self.copied { - IconName::CheckCircle - } else { - IconName::Copy - } - }) - .xsmall() - .ghost() - .on_click(cx.listener(move |this, _e, window, cx| { - this.copy( - public_key.to_bech32().unwrap(), - window, - cx, - ); - })), - ), - ), - ) - }) - } -} diff --git a/crates/coop/src/workspace.rs b/crates/coop/src/workspace.rs index 591fde5..094fc71 100644 --- a/crates/coop/src/workspace.rs +++ b/crates/coop/src/workspace.rs @@ -11,17 +11,16 @@ use gpui::{ IntoElement, ParentElement, Render, SharedString, Styled, Subscription, Window, }; use nostr_connect::prelude::*; -use person::PersonRegistry; use smallvec::{smallvec, SmallVec}; use theme::{ActiveTheme, Theme, ThemeRegistry}; use ui::button::{Button, ButtonVariants}; use ui::modal::ModalButtonProps; use ui::{h_flex, v_flex, Root, Sizable, WindowExtension}; -use crate::actions::{reset, KeyringPopup, Logout, Themes, ViewProfile}; +use crate::actions::{reset, KeyringPopup, Logout, Themes}; +use crate::dialogs::profile; use crate::panels::greeter; -use crate::user::viewer; -use crate::{sidebar, user}; +use crate::sidebar; pub fn init(window: &mut Window, cx: &mut App) -> Entity { cx.new(|cx| Workspace::new(window, cx)) @@ -150,53 +149,6 @@ impl Workspace { }); } - fn on_profile(&mut self, _ev: &ViewProfile, window: &mut Window, cx: &mut Context) { - let view = user::init(window, cx); - let entity = view.downgrade(); - - window.open_modal(cx, move |modal, _window, _cx| { - let entity = entity.clone(); - - modal - .title("Profile") - .confirm() - .child(view.clone()) - .button_props(ModalButtonProps::default().ok_text("Update")) - .on_ok(move |_, window, cx| { - entity - .update(cx, |this, cx| { - let persons = PersonRegistry::global(cx); - let set_metadata = this.set_metadata(cx); - - cx.spawn_in(window, async move |this, cx| { - let result = set_metadata.await; - - this.update_in(cx, |_, window, cx| { - match result { - Ok(person) => { - persons.update(cx, |this, cx| { - this.insert(person, cx); - // Close the edit profile modal - window.close_all_modals(cx); - }); - } - Err(e) => { - window.push_notification(e.to_string(), cx); - } - }; - }) - .ok(); - }) - .detach(); - }) - .ok(); - - // false to keep the modal open - false - }) - }); - } - fn on_themes(&mut self, _ev: &Themes, window: &mut Window, cx: &mut Context) { window.open_modal(cx, move |this, _window, cx| { let registry = ThemeRegistry::global(cx); @@ -255,7 +207,7 @@ impl Workspace { fn on_open_pubkey(&mut self, ev: &OpenPublicKey, window: &mut Window, cx: &mut Context) { let public_key = ev.0; - let view = viewer::init(public_key, window, cx); + let view = profile::init(public_key, window, cx); window.open_modal(cx, move |this, _window, _cx| { this.alert() @@ -319,7 +271,6 @@ impl Render for Workspace { div() .id(SharedString::from("workspace")) - .on_action(cx.listener(Self::on_profile)) .on_action(cx.listener(Self::on_themes)) .on_action(cx.listener(Self::on_sign_out)) .on_action(cx.listener(Self::on_open_pubkey))