migrate to gpui-component
This commit is contained in:
@@ -28,9 +28,7 @@ icons = [
|
||||
|
||||
[dependencies]
|
||||
assets = { path = "../crates/assets" }
|
||||
ui = { path = "../crates/ui" }
|
||||
title_bar = { path = "../crates/title_bar" }
|
||||
theme = { path = "../crates/theme" }
|
||||
common = { path = "../crates/common" }
|
||||
state = { path = "../crates/state" }
|
||||
device = { path = "../crates/device" }
|
||||
@@ -47,6 +45,7 @@ gpui_linux.workspace = true
|
||||
gpui_windows.workspace = true
|
||||
gpui_macos.workspace = true
|
||||
gpui_tokio.workspace = true
|
||||
gpui-component.workspace = true
|
||||
reqwest_client.workspace = true
|
||||
|
||||
nostr-connect.workspace = true
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use anyhow::Error;
|
||||
use common::CoopIcon;
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
App, AppContext, Context, Entity, InteractiveElement, IntoElement, ParentElement, Render,
|
||||
SharedString, StatefulInteractiveElement, Styled, Subscription, Task, Window, div, px,
|
||||
};
|
||||
use gpui_component::avatar::Avatar;
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::spinner::Spinner;
|
||||
use gpui_component::{ActiveTheme, Disableable, Icon, Sizable, WindowExt, h_flex, v_flex};
|
||||
use nostr_sdk::prelude::*;
|
||||
use person::PersonRegistry;
|
||||
use state::{NostrRegistry, StateEvent};
|
||||
use theme::ActiveTheme;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::indicator::Indicator;
|
||||
use ui::{Disableable, Icon, IconName, Sizable, WindowExtension, h_flex, v_flex};
|
||||
|
||||
use crate::dialogs::connect::ConnectSigner;
|
||||
use crate::dialogs::import::ImportKey;
|
||||
@@ -45,7 +45,7 @@ impl AccountSelector {
|
||||
let subscription = cx.subscribe_in(&nostr, window, |this, _state, event, window, cx| {
|
||||
match event {
|
||||
StateEvent::SignerSet => {
|
||||
window.close_all_modals(cx);
|
||||
window.close_all_dialogs(cx);
|
||||
window.refresh();
|
||||
}
|
||||
StateEvent::Error(e) => {
|
||||
@@ -124,10 +124,10 @@ impl AccountSelector {
|
||||
fn open_import(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let import = cx.new(|cx| ImportKey::new(window, cx));
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
window.open_dialog(cx, move |this, _window, _cx| {
|
||||
this.width(px(460.))
|
||||
.title("Import a Secret Key or Bunker Connection")
|
||||
.show_close(true)
|
||||
.close_button(true)
|
||||
.pb_2()
|
||||
.child(import.clone())
|
||||
});
|
||||
@@ -136,10 +136,10 @@ impl AccountSelector {
|
||||
fn open_connect(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let connect = cx.new(|cx| ConnectSigner::new(window, cx));
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
window.open_dialog(cx, move |this, _window, _cx| {
|
||||
this.width(px(460.))
|
||||
.title("Scan QR Code to Connect")
|
||||
.show_close(true)
|
||||
.close_button(true)
|
||||
.pb_2()
|
||||
.child(connect.clone())
|
||||
});
|
||||
@@ -162,7 +162,7 @@ impl Render for AccountSelector {
|
||||
.italic()
|
||||
.text_xs()
|
||||
.text_center()
|
||||
.text_color(cx.theme().text_danger)
|
||||
.text_color(cx.theme().danger_active)
|
||||
.child(error.clone()),
|
||||
)
|
||||
})
|
||||
@@ -182,15 +182,15 @@ impl Render for AccountSelector {
|
||||
.justify_between()
|
||||
.w_full()
|
||||
.rounded(cx.theme().radius)
|
||||
.bg(cx.theme().ghost_element_background)
|
||||
.hover(|this| this.bg(cx.theme().ghost_element_hover))
|
||||
.bg(cx.theme().secondary)
|
||||
.hover(|this| this.bg(cx.theme().secondary_hover))
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.child(Avatar::new(profile.avatar()).small())
|
||||
.child(Avatar::new().src(profile.avatar()).small())
|
||||
.child(div().text_sm().child(profile.name())),
|
||||
)
|
||||
.when(logging_in, |this| this.child(Indicator::new().small()))
|
||||
.when(logging_in, |this| this.child(Spinner::new().small()))
|
||||
.when(!logging_in, |this| {
|
||||
this.child(
|
||||
h_flex()
|
||||
@@ -199,7 +199,7 @@ impl Render for AccountSelector {
|
||||
.group_hover("", |this| this.visible())
|
||||
.child(
|
||||
Button::new(format!("del-{ix}"))
|
||||
.icon(IconName::Close)
|
||||
.icon(CoopIcon::Close)
|
||||
.ghost()
|
||||
.small()
|
||||
.disabled(logging_in)
|
||||
@@ -224,7 +224,7 @@ impl Render for AccountSelector {
|
||||
|
||||
items
|
||||
})
|
||||
.child(div().w_full().h_px().bg(cx.theme().border_variant))
|
||||
.child(div().w_full().h_px().bg(cx.theme().border))
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
@@ -232,7 +232,7 @@ impl Render for AccountSelector {
|
||||
.w_full()
|
||||
.child(
|
||||
Button::new("input")
|
||||
.icon(Icon::new(IconName::Usb))
|
||||
.icon(Icon::new(CoopIcon::Usb))
|
||||
.label("Import")
|
||||
.ghost()
|
||||
.small()
|
||||
@@ -243,7 +243,7 @@ impl Render for AccountSelector {
|
||||
)
|
||||
.child(
|
||||
Button::new("qr")
|
||||
.icon(Icon::new(IconName::Scan))
|
||||
.icon(Icon::new(CoopIcon::Scan))
|
||||
.label("Scan QR to connect")
|
||||
.ghost()
|
||||
.small()
|
||||
|
||||
@@ -7,13 +7,12 @@ use gpui::{
|
||||
AppContext, Context, Entity, Image, IntoElement, ParentElement, Render, SharedString, Styled,
|
||||
Subscription, Window, div, img, px,
|
||||
};
|
||||
use gpui_component::{ActiveTheme, v_flex};
|
||||
use nostr_connect::prelude::*;
|
||||
use state::{
|
||||
CLIENT_NAME, CoopAuthUrlHandler, NOSTR_CONNECT_RELAY, NOSTR_CONNECT_TIMEOUT, NostrRegistry,
|
||||
StateEvent,
|
||||
};
|
||||
use theme::ActiveTheme;
|
||||
use ui::v_flex;
|
||||
|
||||
pub struct ConnectSigner {
|
||||
/// QR Code
|
||||
@@ -101,14 +100,14 @@ impl Render for ConnectSigner {
|
||||
div()
|
||||
.text_xs()
|
||||
.text_center()
|
||||
.text_color(cx.theme().text_danger)
|
||||
.text_color(cx.theme().danger_active)
|
||||
.child(error.clone()),
|
||||
)
|
||||
})
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from(MSG)),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,13 +6,12 @@ use gpui::{
|
||||
AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString, Styled,
|
||||
Subscription, Task, Window, div,
|
||||
};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::input::{Input, InputEvent, InputState};
|
||||
use gpui_component::{ActiveTheme, Disableable, v_flex};
|
||||
use nostr_connect::prelude::*;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use state::{CoopAuthUrlHandler, NostrRegistry, StateEvent};
|
||||
use theme::ActiveTheme;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::input::{InputEvent, InputState, TextInput};
|
||||
use ui::{Disableable, v_flex};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImportKey {
|
||||
@@ -248,9 +247,9 @@ impl Render for ImportKey {
|
||||
v_flex()
|
||||
.gap_1()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child("nsec or bunker://")
|
||||
.child(TextInput::new(&self.key_input)),
|
||||
.child(Input::new(&self.key_input)),
|
||||
)
|
||||
.when(
|
||||
self.key_input.read(cx).value().starts_with("ncryptsec1"),
|
||||
@@ -259,9 +258,9 @@ impl Render for ImportKey {
|
||||
v_flex()
|
||||
.gap_1()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child("Password:")
|
||||
.child(TextInput::new(&self.pass_input)),
|
||||
.child(Input::new(&self.pass_input)),
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -280,7 +279,7 @@ impl Render for ImportKey {
|
||||
div()
|
||||
.text_xs()
|
||||
.text_center()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from(format!(
|
||||
"Approve connection request from your signer in {} seconds",
|
||||
i
|
||||
@@ -292,7 +291,7 @@ impl Render for ImportKey {
|
||||
div()
|
||||
.text_xs()
|
||||
.text_center()
|
||||
.text_color(cx.theme().text_danger)
|
||||
.text_color(cx.theme().danger_active)
|
||||
.child(error.clone()),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -7,11 +7,10 @@ use gpui::{
|
||||
AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString, Styled,
|
||||
Subscription, Task, Window, div,
|
||||
};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::input::{Input, InputEvent, InputState};
|
||||
use gpui_component::{ActiveTheme, WindowExt, v_flex};
|
||||
use nostr_connect::prelude::*;
|
||||
use theme::ActiveTheme;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::input::{InputEvent, InputState, TextInput};
|
||||
use ui::{WindowExtension, v_flex};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RestoreEncryption {
|
||||
@@ -66,7 +65,7 @@ impl RestoreEncryption {
|
||||
});
|
||||
|
||||
// Close the current modal
|
||||
window.close_modal(cx);
|
||||
window.close_dialog(cx);
|
||||
}
|
||||
|
||||
fn set_error<S>(&mut self, message: S, cx: &mut Context<Self>)
|
||||
@@ -105,9 +104,9 @@ impl Render for RestoreEncryption {
|
||||
v_flex()
|
||||
.gap_1()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child("Secret Key")
|
||||
.child(TextInput::new(&self.key_input)),
|
||||
.child(Input::new(&self.key_input)),
|
||||
)
|
||||
.child(
|
||||
Button::new("restore")
|
||||
@@ -122,7 +121,7 @@ impl Render for RestoreEncryption {
|
||||
div()
|
||||
.text_xs()
|
||||
.text_center()
|
||||
.text_color(cx.theme().text_danger)
|
||||
.text_color(cx.theme().danger_active)
|
||||
.child(error.clone()),
|
||||
)
|
||||
})
|
||||
|
||||
@@ -2,21 +2,20 @@ use std::collections::HashMap;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as AnyhowContext, Error};
|
||||
use common::TimestampExt;
|
||||
use common::{CoopIcon, TimestampExt};
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
App, AppContext, Context, Div, Entity, InteractiveElement, IntoElement, ParentElement, Render,
|
||||
SharedString, Styled, Subscription, Task, Window, div, px, relative, uniform_list,
|
||||
};
|
||||
use gpui_component::avatar::Avatar;
|
||||
use gpui_component::button::{Button, ButtonRounded, ButtonVariants};
|
||||
use gpui_component::spinner::Spinner;
|
||||
use gpui_component::{ActiveTheme, Icon, Sizable, StyledExt, WindowExt, h_flex, v_flex};
|
||||
use nostr_sdk::prelude::*;
|
||||
use person::{Person, PersonRegistry, shorten_pubkey};
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use state::{BOOTSTRAP_RELAYS, NostrAddress, NostrRegistry, TIMEOUT};
|
||||
use theme::ActiveTheme;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::indicator::Indicator;
|
||||
use ui::{Icon, IconName, Sizable, StyledExt, WindowExtension, h_flex, v_flex};
|
||||
|
||||
pub fn init(public_key: PublicKey, window: &mut Window, cx: &mut App) -> Entity<Screening> {
|
||||
cx.new(|cx| Screening::new(public_key, window, cx))
|
||||
@@ -52,7 +51,7 @@ impl Screening {
|
||||
|
||||
subscriptions.push(cx.on_release_in(window, move |this, window, cx| {
|
||||
this.tasks.clear();
|
||||
window.close_all_modals(cx);
|
||||
window.close_all_dialogs(cx);
|
||||
}));
|
||||
|
||||
cx.defer_in(window, move |this, _window, cx| {
|
||||
@@ -238,7 +237,7 @@ impl Screening {
|
||||
self.tasks.push(cx.spawn_in(window, async move |_, cx| {
|
||||
if task.await.is_ok() {
|
||||
cx.update(|window, cx| {
|
||||
window.close_modal(cx);
|
||||
window.close_dialog(cx);
|
||||
window.push_notification("Report submitted successfully", cx);
|
||||
})
|
||||
.ok();
|
||||
@@ -249,7 +248,7 @@ impl Screening {
|
||||
fn mutual_contacts(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let contacts = self.mutual_contacts.clone();
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
window.open_dialog(cx, move |this, _window, _cx| {
|
||||
let contacts = contacts.clone();
|
||||
let total = contacts.len();
|
||||
|
||||
@@ -273,8 +272,8 @@ impl Screening {
|
||||
.gap_1p5()
|
||||
.rounded(cx.theme().radius)
|
||||
.text_sm()
|
||||
.hover(|this| this.bg(cx.theme().elevated_surface_background))
|
||||
.child(Avatar::new(profile.avatar()).small())
|
||||
.hover(|this| this.bg(cx.theme().muted))
|
||||
.child(Avatar::new().src(profile.avatar()).small())
|
||||
.child(profile.name()),
|
||||
);
|
||||
}
|
||||
@@ -314,7 +313,7 @@ impl Render for Screening {
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.text_center()
|
||||
.child(Avatar::new(profile.avatar()).large())
|
||||
.child(Avatar::new().src(profile.avatar()).large())
|
||||
.child(
|
||||
div()
|
||||
.font_semibold()
|
||||
@@ -332,7 +331,8 @@ impl Render for Screening {
|
||||
.h_7()
|
||||
.justify_center()
|
||||
.rounded_full()
|
||||
.bg(cx.theme().surface_background)
|
||||
.bg(cx.theme().muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.text_sm()
|
||||
.truncate()
|
||||
.text_ellipsis()
|
||||
@@ -348,7 +348,7 @@ impl Render for Screening {
|
||||
.label("View on njump.me")
|
||||
.secondary()
|
||||
.small()
|
||||
.rounded()
|
||||
.rounded(ButtonRounded::Large)
|
||||
.on_click(cx.listener(move |this, _e, window, cx| {
|
||||
this.open_njump(window, cx);
|
||||
})),
|
||||
@@ -356,10 +356,10 @@ impl Render for Screening {
|
||||
.child(
|
||||
Button::new("report")
|
||||
.tooltip("Report as a scam or impostor")
|
||||
.icon(IconName::Warning)
|
||||
.icon(CoopIcon::Warning)
|
||||
.small()
|
||||
.warning()
|
||||
.rounded()
|
||||
.rounded(ButtonRounded::Large)
|
||||
.on_click(cx.listener(move |this, _e, window, cx| {
|
||||
this.report(window, cx);
|
||||
})),
|
||||
@@ -382,7 +382,7 @@ impl Render for Screening {
|
||||
.child(
|
||||
div()
|
||||
.line_clamp(1)
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child({
|
||||
if self.followed {
|
||||
SharedString::from(CONTACT)
|
||||
@@ -408,10 +408,10 @@ impl Render for Screening {
|
||||
.child(SharedString::from("Activity on Public Relays"))
|
||||
.child(
|
||||
Button::new("active")
|
||||
.icon(IconName::Info)
|
||||
.icon(CoopIcon::Info)
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.rounded()
|
||||
.rounded(ButtonRounded::Large)
|
||||
.tooltip(RELAY_INFO),
|
||||
),
|
||||
)
|
||||
@@ -419,7 +419,7 @@ impl Render for Screening {
|
||||
div()
|
||||
.w_full()
|
||||
.line_clamp(1)
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.map(|this| {
|
||||
if let Some(t) = self.last_active {
|
||||
this.child(SharedString::from(format!(
|
||||
@@ -453,7 +453,7 @@ impl Render for Screening {
|
||||
.child(
|
||||
div()
|
||||
.line_clamp(1)
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child({
|
||||
if self.address(cx).is_some() {
|
||||
if self.verified {
|
||||
@@ -482,10 +482,10 @@ impl Render for Screening {
|
||||
.child(SharedString::from("Mutual contacts"))
|
||||
.child(
|
||||
Button::new("mutuals")
|
||||
.icon(IconName::Info)
|
||||
.icon(CoopIcon::Info)
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.rounded()
|
||||
.rounded(ButtonRounded::Large)
|
||||
.on_click(cx.listener(
|
||||
move |this, _, window, cx| {
|
||||
this.mutual_contacts(window, cx);
|
||||
@@ -496,7 +496,7 @@ impl Render for Screening {
|
||||
.child(
|
||||
div()
|
||||
.line_clamp(1)
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child({
|
||||
if mutuals > 0 {
|
||||
SharedString::from(mutuals_str)
|
||||
@@ -518,15 +518,15 @@ fn status_badge(status: Option<bool>, cx: &App) -> Div {
|
||||
.flex_shrink_0()
|
||||
.map(|this| {
|
||||
if let Some(status) = status {
|
||||
this.child(Icon::new(IconName::CheckCircle).small().text_color({
|
||||
this.child(Icon::new(CoopIcon::CheckCircle).small().text_color({
|
||||
if status {
|
||||
cx.theme().icon_accent
|
||||
cx.theme().primary_active
|
||||
} else {
|
||||
cx.theme().icon_muted
|
||||
cx.theme().muted_foreground
|
||||
}
|
||||
}))
|
||||
} else {
|
||||
this.child(Indicator::new().small())
|
||||
this.child(Spinner::new().small())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use common::CoopIcon;
|
||||
use gpui::http_client::Url;
|
||||
use gpui::{
|
||||
App, AppContext, Context, Entity, IntoElement, ParentElement, Render, SharedString, Styled,
|
||||
Window, div, px,
|
||||
};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::group_box::{GroupBox, GroupBoxVariants};
|
||||
use gpui_component::input::{Input, InputState};
|
||||
use gpui_component::menu::{DropdownMenu, PopupMenuItem};
|
||||
use gpui_component::notification::Notification;
|
||||
use gpui_component::switch::Switch;
|
||||
use gpui_component::{ActiveTheme, Sizable, WindowExt, h_flex, v_flex};
|
||||
use settings::{AppSettings, AuthMode};
|
||||
use theme::{ActiveTheme, Theme, ThemeMode};
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::group_box::{GroupBox, GroupBoxVariants};
|
||||
use ui::input::{InputState, TextInput};
|
||||
use ui::menu::{DropdownMenu, PopupMenuItem};
|
||||
use ui::notification::Notification;
|
||||
use ui::switch::Switch;
|
||||
use ui::{IconName, Sizable, WindowExtension, h_flex, v_flex};
|
||||
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Preferences> {
|
||||
cx.new(|cx| Preferences::new(window, cx))
|
||||
@@ -46,12 +46,6 @@ impl Preferences {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the theme mode (light or dark)
|
||||
fn set_theme_mode(mode: ThemeMode, window: &mut Window, cx: &mut App) {
|
||||
AppSettings::update_theme_mode(mode, cx);
|
||||
Theme::change(mode, Some(window), cx);
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Preferences {
|
||||
@@ -68,7 +62,6 @@ impl Render for Preferences {
|
||||
let screening = AppSettings::get_screening(cx);
|
||||
let hide_avatar = AppSettings::get_hide_avatar(cx);
|
||||
let auth_mode = AppSettings::get_auth_mode(cx);
|
||||
let theme_mode = AppSettings::get_theme_mode(cx);
|
||||
|
||||
v_flex()
|
||||
.gap_4()
|
||||
@@ -80,7 +73,7 @@ impl Render for Preferences {
|
||||
.child(
|
||||
Switch::new("screening")
|
||||
.label("Screening")
|
||||
.description(SCREENING)
|
||||
.tooltip(SCREENING)
|
||||
.checked(screening)
|
||||
.on_click(move |_, _window, cx| {
|
||||
AppSettings::update_screening(!screening, cx);
|
||||
@@ -89,7 +82,7 @@ impl Render for Preferences {
|
||||
.child(
|
||||
Switch::new("avatar")
|
||||
.label("Hide user avatar")
|
||||
.description(AVATAR)
|
||||
.tooltip(AVATAR)
|
||||
.checked(hide_avatar)
|
||||
.on_click(move |_, _window, cx| {
|
||||
AppSettings::update_hide_avatar(!hide_avatar, cx);
|
||||
@@ -109,14 +102,14 @@ impl Render for Preferences {
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from(AUTH)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Button::new("auth")
|
||||
.label(auth_mode.to_string())
|
||||
.ghost_alt()
|
||||
.ghost()
|
||||
.small()
|
||||
.dropdown_menu(|this, _window, _cx| {
|
||||
this.min_w(px(256.))
|
||||
@@ -157,28 +150,11 @@ impl Render for Preferences {
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from(MODE)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Button::new("theme-mode")
|
||||
.label(theme_mode.name())
|
||||
.ghost_alt()
|
||||
.small()
|
||||
.dropdown_menu(|this, _window, _cx| {
|
||||
this.item(PopupMenuItem::new("Light").on_click(
|
||||
|_, window, cx| {
|
||||
Self::set_theme_mode(ThemeMode::Light, window, cx);
|
||||
},
|
||||
))
|
||||
.item(
|
||||
PopupMenuItem::new("Dark").on_click(|_, window, cx| {
|
||||
Self::set_theme_mode(ThemeMode::Dark, window, cx);
|
||||
}),
|
||||
)
|
||||
}),
|
||||
),
|
||||
.child(Button::new("theme-mode").label("Auto").ghost().small()),
|
||||
)
|
||||
.child(
|
||||
h_flex()
|
||||
@@ -190,21 +166,11 @@ impl Render for Preferences {
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from(RESET)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
Button::new("reset")
|
||||
.label("Reset")
|
||||
.ghost_alt()
|
||||
.small()
|
||||
.on_click(move |_ev, window, cx| {
|
||||
AppSettings::global(cx).update(cx, |this, cx| {
|
||||
this.reset_theme(window, cx);
|
||||
})
|
||||
}),
|
||||
),
|
||||
.child(Button::new("reset").label("Reset").ghost().small()),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
@@ -218,10 +184,10 @@ impl Render for Preferences {
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(TextInput::new(&self.file_input).text_xs().small())
|
||||
.child(Input::new(&self.file_input).text_xs().small())
|
||||
.child(
|
||||
Button::new("update-file-server")
|
||||
.icon(IconName::Check)
|
||||
.icon(CoopIcon::Check)
|
||||
.ghost()
|
||||
.size_8()
|
||||
.on_click(cx.listener(move |this, _ev, window, cx| {
|
||||
@@ -233,7 +199,7 @@ impl Render for Preferences {
|
||||
div()
|
||||
.text_size(px(10.))
|
||||
.italic()
|
||||
.text_color(cx.theme().text_placeholder)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("Only support blossom service")),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -6,9 +6,9 @@ use gpui::{
|
||||
WindowBackgroundAppearance, WindowBounds, WindowDecorations, WindowKind, WindowOptions,
|
||||
actions, point, px, size,
|
||||
};
|
||||
use gpui_component::Root;
|
||||
use gpui_platform::application;
|
||||
use state::{APP_ID, CLIENT_NAME};
|
||||
use ui::Root;
|
||||
|
||||
mod dialogs;
|
||||
mod panels;
|
||||
@@ -75,10 +75,7 @@ fn main() {
|
||||
gpui_tokio::init(cx);
|
||||
|
||||
// Initialize components
|
||||
ui::init(cx);
|
||||
|
||||
// Initialize theme registry
|
||||
theme::init(cx);
|
||||
gpui_component::init(cx);
|
||||
|
||||
// Initialize settings
|
||||
settings::init(window, cx);
|
||||
@@ -104,7 +101,7 @@ fn main() {
|
||||
auto_update::init(window, cx);
|
||||
|
||||
// Root Entity
|
||||
Root::new(workspace::init(window, cx).into(), window, cx)
|
||||
Root::new(workspace::init(window, cx), window, cx)
|
||||
})
|
||||
})
|
||||
.expect("Failed to open window. Please restart the application.");
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Error;
|
||||
use common::CoopIcon;
|
||||
use gpui::{
|
||||
AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
|
||||
Focusable, IntoElement, ParentElement, Render, SharedString, Styled, Task, Window, div,
|
||||
App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
IntoElement, ParentElement, Render, SharedString, Styled, Task, Window, div,
|
||||
};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dock::{Panel, PanelEvent};
|
||||
use gpui_component::input::{Input, InputState};
|
||||
use gpui_component::{ActiveTheme, Sizable, StyledExt, v_flex};
|
||||
use nostr_sdk::prelude::*;
|
||||
use state::KEYRING;
|
||||
use theme::ActiveTheme;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::dock::{Panel, PanelEvent};
|
||||
use ui::input::{InputState, TextInput};
|
||||
use ui::{IconName, Sizable, StyledExt, divider, v_flex};
|
||||
|
||||
const MSG: &str = "Store your account keys in a safe location. \
|
||||
You can restore your account or move to another client anytime you want.";
|
||||
@@ -22,7 +22,6 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity<BackupPanel> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BackupPanel {
|
||||
name: SharedString,
|
||||
focus_handle: FocusHandle,
|
||||
|
||||
/// Public key input
|
||||
@@ -40,8 +39,8 @@ pub struct BackupPanel {
|
||||
|
||||
impl BackupPanel {
|
||||
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let npub_input = cx.new(|cx| InputState::new(window, cx).disabled(true));
|
||||
let nsec_input = cx.new(|cx| InputState::new(window, cx).disabled(true).masked(true));
|
||||
let npub_input = cx.new(|cx| InputState::new(window, cx));
|
||||
let nsec_input = cx.new(|cx| InputState::new(window, cx).masked(true));
|
||||
|
||||
// Run at the end of current cycle
|
||||
cx.defer_in(window, |this, window, cx| {
|
||||
@@ -49,7 +48,6 @@ impl BackupPanel {
|
||||
});
|
||||
|
||||
Self {
|
||||
name: "Backup".into(),
|
||||
focus_handle: cx.focus_handle(),
|
||||
npub_input,
|
||||
nsec_input,
|
||||
@@ -108,12 +106,8 @@ impl BackupPanel {
|
||||
}
|
||||
|
||||
impl Panel for BackupPanel {
|
||||
fn panel_id(&self) -> SharedString {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn title(&self, _cx: &App) -> AnyElement {
|
||||
self.name.clone().into_any_element()
|
||||
fn panel_name(&self) -> &'static str {
|
||||
"Backup"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,10 +128,10 @@ impl Render for BackupPanel {
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from(MSG)),
|
||||
)
|
||||
.child(divider(cx))
|
||||
.child(div().h_1().w_full().bg(cx.theme().border))
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_2()
|
||||
@@ -152,11 +146,11 @@ impl Render for BackupPanel {
|
||||
div()
|
||||
.text_xs()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("Public Key:")),
|
||||
)
|
||||
.child(
|
||||
TextInput::new(&self.npub_input)
|
||||
Input::new(&self.npub_input)
|
||||
.small()
|
||||
.bordered(false)
|
||||
.disabled(true),
|
||||
@@ -170,11 +164,11 @@ impl Render for BackupPanel {
|
||||
div()
|
||||
.text_xs()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("Secret Key:")),
|
||||
)
|
||||
.child(
|
||||
TextInput::new(&self.nsec_input)
|
||||
Input::new(&self.nsec_input)
|
||||
.small()
|
||||
.bordered(false)
|
||||
.disabled(true),
|
||||
@@ -182,7 +176,7 @@ impl Render for BackupPanel {
|
||||
)
|
||||
.child(
|
||||
Button::new("copy")
|
||||
.icon(IconName::Copy)
|
||||
.icon(CoopIcon::Copy)
|
||||
.label({
|
||||
if self.copied {
|
||||
"Copied"
|
||||
|
||||
@@ -2,22 +2,22 @@ use std::collections::HashSet;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as AnyhowContext, Error};
|
||||
use common::CoopIcon;
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Subscription,
|
||||
Task, TextAlign, Window, div, rems,
|
||||
App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
|
||||
IntoElement, ParentElement, Render, SharedString, Styled, Subscription, Task, TextAlign,
|
||||
Window, div, rems,
|
||||
};
|
||||
use gpui_component::avatar::Avatar;
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dock::{Panel, PanelEvent};
|
||||
use gpui_component::input::{Input, InputEvent, InputState};
|
||||
use gpui_component::{ActiveTheme, Disableable, Sizable, StyledExt, WindowExt, h_flex, v_flex};
|
||||
use nostr_sdk::prelude::*;
|
||||
use person::PersonRegistry;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use state::NostrRegistry;
|
||||
use theme::ActiveTheme;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::dock::{Panel, PanelEvent};
|
||||
use ui::input::{InputEvent, InputState, TextInput};
|
||||
use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, h_flex, v_flex};
|
||||
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<ContactListPanel> {
|
||||
cx.new(|cx| ContactListPanel::new(window, cx))
|
||||
@@ -25,7 +25,6 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity<ContactListPanel> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ContactListPanel {
|
||||
name: SharedString,
|
||||
focus_handle: FocusHandle,
|
||||
|
||||
/// Npub input
|
||||
@@ -67,7 +66,6 @@ impl ContactListPanel {
|
||||
});
|
||||
|
||||
Self {
|
||||
name: "Contact List".into(),
|
||||
focus_handle: cx.focus_handle(),
|
||||
input,
|
||||
updating: false,
|
||||
@@ -217,18 +215,18 @@ impl ContactListPanel {
|
||||
.px_2()
|
||||
.justify_between()
|
||||
.rounded(cx.theme().radius)
|
||||
.bg(cx.theme().secondary_background)
|
||||
.bg(cx.theme().secondary)
|
||||
.text_color(cx.theme().secondary_foreground)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_2()
|
||||
.text_sm()
|
||||
.child(Avatar::new(profile.avatar()).small())
|
||||
.child(Avatar::new().src(profile.avatar()).small())
|
||||
.child(profile.name()),
|
||||
)
|
||||
.child(
|
||||
Button::new("remove_{ix}")
|
||||
.icon(IconName::Close)
|
||||
.icon(CoopIcon::Close)
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.invisible()
|
||||
@@ -261,12 +259,8 @@ impl ContactListPanel {
|
||||
}
|
||||
|
||||
impl Panel for ContactListPanel {
|
||||
fn panel_id(&self) -> SharedString {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn title(&self, _cx: &App) -> AnyElement {
|
||||
self.name.clone().into_any_element()
|
||||
fn panel_name(&self) -> &'static str {
|
||||
"Contact List"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,7 +284,7 @@ impl Render for ContactListPanel {
|
||||
div()
|
||||
.text_xs()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("New contact:")),
|
||||
)
|
||||
.child(
|
||||
@@ -301,14 +295,14 @@ impl Render for ContactListPanel {
|
||||
.gap_1()
|
||||
.w_full()
|
||||
.child(
|
||||
TextInput::new(&self.input)
|
||||
Input::new(&self.input)
|
||||
.small()
|
||||
.bordered(false)
|
||||
.cleanable(),
|
||||
.cleanable(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("add")
|
||||
.icon(IconName::Plus)
|
||||
.icon(CoopIcon::Plus)
|
||||
.tooltip("Add contact")
|
||||
.ghost()
|
||||
.size(rems(2.))
|
||||
@@ -322,7 +316,7 @@ impl Render for ContactListPanel {
|
||||
div()
|
||||
.italic()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_danger)
|
||||
.text_color(cx.theme().danger_active)
|
||||
.child(error.clone()),
|
||||
)
|
||||
}),
|
||||
@@ -342,7 +336,7 @@ impl Render for ContactListPanel {
|
||||
})
|
||||
.child(
|
||||
Button::new("submit")
|
||||
.icon(IconName::CheckCircle)
|
||||
.icon(CoopIcon::CheckCircle)
|
||||
.label("Update")
|
||||
.primary()
|
||||
.small()
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
use common::CoopIcon;
|
||||
use gpui::{
|
||||
AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
IntoElement, ParentElement, Render, SharedString, Styled, Window, div, svg,
|
||||
App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable, IntoElement,
|
||||
ParentElement, Render, SharedString, Styled, Window, div, svg,
|
||||
};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dock::{DockPlacement, Panel, PanelEvent};
|
||||
use gpui_component::{ActiveTheme, Icon, Sizable, StyledExt, h_flex, v_flex};
|
||||
use state::NostrRegistry;
|
||||
use theme::ActiveTheme;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::dock::{DockPlacement, Panel, PanelEvent};
|
||||
use ui::{Icon, IconName, Sizable, StyledExt, h_flex, v_flex};
|
||||
|
||||
use crate::panels::profile;
|
||||
use crate::workspace::Workspace;
|
||||
@@ -16,14 +16,12 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity<GreeterPanel> {
|
||||
}
|
||||
|
||||
pub struct GreeterPanel {
|
||||
name: SharedString,
|
||||
focus_handle: FocusHandle,
|
||||
}
|
||||
|
||||
impl GreeterPanel {
|
||||
fn new(_window: &mut Window, cx: &mut App) -> Self {
|
||||
Self {
|
||||
name: "Onboarding".into(),
|
||||
focus_handle: cx.focus_handle(),
|
||||
}
|
||||
}
|
||||
@@ -50,19 +48,17 @@ impl GreeterPanel {
|
||||
}
|
||||
|
||||
impl Panel for GreeterPanel {
|
||||
fn panel_id(&self) -> SharedString {
|
||||
self.name.clone()
|
||||
fn panel_name(&self) -> &'static str {
|
||||
"Greeter"
|
||||
}
|
||||
|
||||
fn title(&self, cx: &App) -> AnyElement {
|
||||
div()
|
||||
.child(
|
||||
svg()
|
||||
.path("brand/coop.svg")
|
||||
.size_4()
|
||||
.text_color(cx.theme().text_muted),
|
||||
)
|
||||
.into_any_element()
|
||||
fn title(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div().child(
|
||||
svg()
|
||||
.path("brand/coop.svg")
|
||||
.size_4()
|
||||
.text_color(cx.theme().muted_foreground),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,20 +96,15 @@ impl Render for GreeterPanel {
|
||||
svg()
|
||||
.path("brand/coop.svg")
|
||||
.size_12()
|
||||
.text_color(cx.theme().icon_muted),
|
||||
.text_color(cx.theme().muted),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
.child(
|
||||
div()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text)
|
||||
.child(SharedString::from(TITLE)),
|
||||
)
|
||||
.child(div().font_semibold().child(SharedString::from(TITLE)))
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from(DESCRIPTION)),
|
||||
),
|
||||
),
|
||||
@@ -128,7 +119,7 @@ impl Render for GreeterPanel {
|
||||
.w_full()
|
||||
.text_xs()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("Get Started"))
|
||||
.child(div().flex_1().h_px().bg(cx.theme().border)),
|
||||
)
|
||||
@@ -138,7 +129,7 @@ impl Render for GreeterPanel {
|
||||
.w_full()
|
||||
.child(
|
||||
Button::new("profile")
|
||||
.icon(Icon::new(IconName::Profile))
|
||||
.icon(Icon::new(CoopIcon::Profile))
|
||||
.label("Update profile")
|
||||
.ghost()
|
||||
.small()
|
||||
@@ -149,7 +140,7 @@ impl Render for GreeterPanel {
|
||||
)
|
||||
.child(
|
||||
Button::new("invite")
|
||||
.icon(Icon::new(IconName::Invite))
|
||||
.icon(Icon::new(CoopIcon::Invite))
|
||||
.label("Invite friends")
|
||||
.ghost()
|
||||
.small()
|
||||
|
||||
@@ -2,20 +2,20 @@ use std::collections::HashSet;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as AnyhowContext, Error, anyhow};
|
||||
use common::CoopIcon;
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Subscription,
|
||||
Task, TextAlign, Window, div, rems,
|
||||
App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable, InteractiveElement,
|
||||
IntoElement, ParentElement, Render, SharedString, Styled, Subscription, Task, TextAlign,
|
||||
Window, div, rems,
|
||||
};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dock::{Panel, PanelEvent};
|
||||
use gpui_component::input::{Input, InputEvent, InputState};
|
||||
use gpui_component::{ActiveTheme, Disableable, Sizable, StyledExt, WindowExt, h_flex, v_flex};
|
||||
use nostr_sdk::prelude::*;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use state::NostrRegistry;
|
||||
use theme::ActiveTheme;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::dock::{Panel, PanelEvent};
|
||||
use ui::input::{InputEvent, InputState, TextInput};
|
||||
use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, divider, h_flex, v_flex};
|
||||
|
||||
const MSG: &str = "Messaging Relays are relays that hosted all your messages. \
|
||||
Other users will find your relays and send messages to it.";
|
||||
@@ -26,7 +26,6 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity<MessagingRelayPanel> {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MessagingRelayPanel {
|
||||
name: SharedString,
|
||||
focus_handle: FocusHandle,
|
||||
|
||||
/// Relay URL input
|
||||
@@ -68,7 +67,6 @@ impl MessagingRelayPanel {
|
||||
});
|
||||
|
||||
Self {
|
||||
name: "Update Messaging Relays".into(),
|
||||
focus_handle: cx.focus_handle(),
|
||||
input,
|
||||
updating: false,
|
||||
@@ -228,12 +226,12 @@ impl MessagingRelayPanel {
|
||||
.px_2()
|
||||
.justify_between()
|
||||
.rounded(cx.theme().radius)
|
||||
.bg(cx.theme().secondary_background)
|
||||
.bg(cx.theme().secondary)
|
||||
.text_color(cx.theme().secondary_foreground)
|
||||
.child(div().text_sm().child(SharedString::from(url.to_string())))
|
||||
.child(
|
||||
Button::new("remove_{ix}")
|
||||
.icon(IconName::Close)
|
||||
.icon(CoopIcon::Close)
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.invisible()
|
||||
@@ -266,12 +264,8 @@ impl MessagingRelayPanel {
|
||||
}
|
||||
|
||||
impl Panel for MessagingRelayPanel {
|
||||
fn panel_id(&self) -> SharedString {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn title(&self, _cx: &App) -> AnyElement {
|
||||
self.name.clone().into_any_element()
|
||||
fn panel_name(&self) -> &'static str {
|
||||
"Update Messaging Relays"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,10 +286,10 @@ impl Render for MessagingRelayPanel {
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from(MSG)),
|
||||
)
|
||||
.child(divider(cx))
|
||||
.child(div().h_1().w_full().bg(cx.theme().border))
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_2()
|
||||
@@ -306,7 +300,7 @@ impl Render for MessagingRelayPanel {
|
||||
div()
|
||||
.text_xs()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("Relays:")),
|
||||
)
|
||||
.child(
|
||||
@@ -317,14 +311,14 @@ impl Render for MessagingRelayPanel {
|
||||
.gap_1()
|
||||
.w_full()
|
||||
.child(
|
||||
TextInput::new(&self.input)
|
||||
Input::new(&self.input)
|
||||
.small()
|
||||
.bordered(false)
|
||||
.cleanable(),
|
||||
.bordered(true)
|
||||
.cleanable(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("add")
|
||||
.icon(IconName::Plus)
|
||||
.icon(CoopIcon::Plus)
|
||||
.tooltip("Add relay")
|
||||
.ghost()
|
||||
.size(rems(2.))
|
||||
@@ -338,7 +332,7 @@ impl Render for MessagingRelayPanel {
|
||||
div()
|
||||
.italic()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_danger)
|
||||
.text_color(cx.theme().danger_active)
|
||||
.child(error.clone()),
|
||||
)
|
||||
}),
|
||||
@@ -358,7 +352,7 @@ impl Render for MessagingRelayPanel {
|
||||
})
|
||||
.child(
|
||||
Button::new("submit")
|
||||
.icon(IconName::CheckCircle)
|
||||
.icon(CoopIcon::CheckCircle)
|
||||
.label("Update")
|
||||
.primary()
|
||||
.small()
|
||||
|
||||
@@ -2,22 +2,21 @@ use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as AnyhowContext, Error};
|
||||
use common::CoopIcon;
|
||||
use gpui::{
|
||||
AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
|
||||
Focusable, IntoElement, ParentElement, PathPromptOptions, Render, SharedString, Styled, Task,
|
||||
Window, div,
|
||||
App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
IntoElement, ParentElement, PathPromptOptions, Render, SharedString, Styled, Task, Window, div,
|
||||
};
|
||||
use gpui_component::avatar::Avatar;
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dock::{Panel, PanelEvent};
|
||||
use gpui_component::input::{Input, InputState};
|
||||
use gpui_component::notification::Notification;
|
||||
use gpui_component::{ActiveTheme, Disableable, Sizable, StyledExt, WindowExt, h_flex, v_flex};
|
||||
use nostr_sdk::prelude::*;
|
||||
use person::{Person, PersonRegistry, shorten_pubkey};
|
||||
use settings::AppSettings;
|
||||
use state::{NostrRegistry, upload};
|
||||
use theme::ActiveTheme;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::dock::{Panel, PanelEvent};
|
||||
use ui::input::{InputState, TextInput};
|
||||
use ui::notification::Notification;
|
||||
use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, h_flex, v_flex};
|
||||
|
||||
pub fn init(public_key: PublicKey, window: &mut Window, cx: &mut App) -> Entity<ProfilePanel> {
|
||||
cx.new(|cx| ProfilePanel::new(public_key, window, cx))
|
||||
@@ -25,7 +24,6 @@ pub fn init(public_key: PublicKey, window: &mut Window, cx: &mut App) -> Entity<
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProfilePanel {
|
||||
name: SharedString,
|
||||
focus_handle: FocusHandle,
|
||||
|
||||
/// User's public key
|
||||
@@ -65,7 +63,7 @@ impl ProfilePanel {
|
||||
// Use multi-line input for bio
|
||||
let bio_input = cx.new(|cx| {
|
||||
InputState::new(window, cx)
|
||||
.multi_line()
|
||||
.multi_line(true)
|
||||
.auto_grow(3, 8)
|
||||
.placeholder("A short introduce about you.")
|
||||
});
|
||||
@@ -76,7 +74,6 @@ impl ProfilePanel {
|
||||
});
|
||||
|
||||
Self {
|
||||
name: "Update Profile".into(),
|
||||
focus_handle: cx.focus_handle(),
|
||||
public_key,
|
||||
name_input,
|
||||
@@ -286,12 +283,8 @@ impl ProfilePanel {
|
||||
}
|
||||
|
||||
impl Panel for ProfilePanel {
|
||||
fn panel_id(&self) -> SharedString {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn title(&self, _cx: &App) -> AnyElement {
|
||||
self.name.clone().into_any_element()
|
||||
fn panel_name(&self) -> &'static str {
|
||||
"Update Profile"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,14 +321,13 @@ impl Render for ProfilePanel {
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.gap_4()
|
||||
.child(Avatar::new(avatar).large())
|
||||
.child(Avatar::new().src(avatar).large())
|
||||
.child(
|
||||
Button::new("upload")
|
||||
.icon(IconName::PlusCircle)
|
||||
.icon(CoopIcon::PlusCircle)
|
||||
.label("Add an avatar")
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.rounded()
|
||||
.disabled(self.uploading)
|
||||
.loading(self.uploading)
|
||||
.on_click(cx.listener(move |this, _, window, cx| {
|
||||
@@ -349,10 +341,10 @@ impl Render for ProfilePanel {
|
||||
.child(
|
||||
div()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("What should people call you?")),
|
||||
)
|
||||
.child(TextInput::new(&self.name_input).bordered(false).small()),
|
||||
.child(Input::new(&self.name_input).bordered(false).small()),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
@@ -360,10 +352,10 @@ impl Render for ProfilePanel {
|
||||
.child(
|
||||
div()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("A short introduction about you:")),
|
||||
)
|
||||
.child(TextInput::new(&self.bio_input).bordered(false).small()),
|
||||
.child(Input::new(&self.bio_input).bordered(false).small()),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
@@ -371,10 +363,10 @@ impl Render for ProfilePanel {
|
||||
.child(
|
||||
div()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("Website:")),
|
||||
)
|
||||
.child(TextInput::new(&self.website_input).bordered(false).small()),
|
||||
.child(Input::new(&self.website_input).bordered(false).small()),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
@@ -382,7 +374,7 @@ impl Render for ProfilePanel {
|
||||
.child(
|
||||
div()
|
||||
.text_sm()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("Public Key:")),
|
||||
)
|
||||
.child(
|
||||
@@ -392,7 +384,7 @@ impl Render for ProfilePanel {
|
||||
.justify_center()
|
||||
.gap_3()
|
||||
.rounded(cx.theme().radius)
|
||||
.bg(cx.theme().secondary_background)
|
||||
.bg(cx.theme().secondary)
|
||||
.text_sm()
|
||||
.text_color(cx.theme().secondary_foreground)
|
||||
.child(shorten_pkey)
|
||||
@@ -400,9 +392,9 @@ impl Render for ProfilePanel {
|
||||
Button::new("copy")
|
||||
.icon({
|
||||
if self.copied {
|
||||
IconName::CheckCircle
|
||||
CoopIcon::CheckCircle
|
||||
} else {
|
||||
IconName::Copy
|
||||
CoopIcon::Copy
|
||||
}
|
||||
})
|
||||
.xsmall()
|
||||
@@ -415,7 +407,7 @@ impl Render for ProfilePanel {
|
||||
)
|
||||
.child(
|
||||
Button::new("submit")
|
||||
.icon(IconName::CheckCircle)
|
||||
.icon(CoopIcon::CheckCircle)
|
||||
.label("Update")
|
||||
.primary()
|
||||
.small()
|
||||
|
||||
@@ -2,22 +2,22 @@ use std::collections::HashSet;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as AnyhowContext, Error, anyhow};
|
||||
use common::CoopIcon;
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
Action, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
Action, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
InteractiveElement, IntoElement, ParentElement, Render, SharedString, Styled, Subscription,
|
||||
Task, TextAlign, Window, div, px, rems,
|
||||
};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dock::{Panel, PanelEvent};
|
||||
use gpui_component::input::{Input, InputEvent, InputState};
|
||||
use gpui_component::menu::DropdownMenu;
|
||||
use gpui_component::{ActiveTheme, Disableable, Sizable, StyledExt, WindowExt, h_flex, v_flex};
|
||||
use nostr_sdk::prelude::*;
|
||||
use serde::Deserialize;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use state::NostrRegistry;
|
||||
use theme::ActiveTheme;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::dock::{Panel, PanelEvent};
|
||||
use ui::input::{InputEvent, InputState, TextInput};
|
||||
use ui::menu::DropdownMenu;
|
||||
use ui::{Disableable, IconName, Sizable, StyledExt, WindowExtension, divider, h_flex, v_flex};
|
||||
|
||||
const MSG: &str = "Relay List (or Gossip Relays) are a set of relays \
|
||||
where you will publish all your events. Others also publish events \
|
||||
@@ -259,7 +259,7 @@ impl RelayListPanel {
|
||||
.px_2()
|
||||
.justify_between()
|
||||
.rounded(cx.theme().radius)
|
||||
.bg(cx.theme().secondary_background)
|
||||
.bg(cx.theme().secondary)
|
||||
.text_color(cx.theme().secondary_foreground)
|
||||
.child(
|
||||
h_flex()
|
||||
@@ -284,7 +284,7 @@ impl RelayListPanel {
|
||||
)
|
||||
.child(
|
||||
Button::new("remove_{ix}")
|
||||
.icon(IconName::Close)
|
||||
.icon(CoopIcon::Close)
|
||||
.xsmall()
|
||||
.ghost()
|
||||
.invisible()
|
||||
@@ -317,12 +317,12 @@ impl RelayListPanel {
|
||||
}
|
||||
|
||||
impl Panel for RelayListPanel {
|
||||
fn panel_id(&self) -> SharedString {
|
||||
self.name.clone()
|
||||
fn panel_name(&self) -> &'static str {
|
||||
"Relay List"
|
||||
}
|
||||
|
||||
fn title(&self, _cx: &App) -> AnyElement {
|
||||
self.name.clone().into_any_element()
|
||||
fn title(&mut self, window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
self.name.clone()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,10 +344,10 @@ impl Render for RelayListPanel {
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from(MSG)),
|
||||
)
|
||||
.child(divider(cx))
|
||||
.child(div().h_1().w_full().bg(cx.theme().border))
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_2()
|
||||
@@ -358,7 +358,7 @@ impl Render for RelayListPanel {
|
||||
div()
|
||||
.text_xs()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("Relays:")),
|
||||
)
|
||||
.child(
|
||||
@@ -369,10 +369,10 @@ impl Render for RelayListPanel {
|
||||
.gap_1()
|
||||
.w_full()
|
||||
.child(
|
||||
TextInput::new(&self.input)
|
||||
Input::new(&self.input)
|
||||
.small()
|
||||
.bordered(false)
|
||||
.cleanable(),
|
||||
.cleanable(true),
|
||||
)
|
||||
.child(
|
||||
Button::new("metadata")
|
||||
@@ -394,7 +394,7 @@ impl Render for RelayListPanel {
|
||||
)
|
||||
.child(
|
||||
Button::new("add")
|
||||
.icon(IconName::Plus)
|
||||
.icon(CoopIcon::Plus)
|
||||
.tooltip("Add relay")
|
||||
.ghost()
|
||||
.size(rems(2.))
|
||||
@@ -408,7 +408,7 @@ impl Render for RelayListPanel {
|
||||
div()
|
||||
.italic()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_danger)
|
||||
.text_color(cx.theme().danger_active)
|
||||
.child(error.clone()),
|
||||
)
|
||||
}),
|
||||
@@ -428,7 +428,7 @@ impl Render for RelayListPanel {
|
||||
})
|
||||
.child(
|
||||
Button::new("submit")
|
||||
.icon(IconName::CheckCircle)
|
||||
.icon(CoopIcon::CheckCircle)
|
||||
.label("Update")
|
||||
.primary()
|
||||
.small()
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
use chat::ChatRegistry;
|
||||
use common::CoopIcon;
|
||||
use gpui::{
|
||||
AnyElement, App, AppContext, ClipboardItem, Context, Entity, EventEmitter, FocusHandle,
|
||||
Focusable, InteractiveElement, IntoElement, ListAlignment, ListState, ParentElement, Render,
|
||||
SharedString, Styled, Window, div, list, px, relative,
|
||||
Styled, Window, div, list, px, relative,
|
||||
};
|
||||
use theme::ActiveTheme;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::dock::{Panel, PanelEvent};
|
||||
use ui::scroll::Scrollbar;
|
||||
use ui::{Icon, IconName, Sizable, h_flex, v_flex};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dock::{Panel, PanelEvent};
|
||||
use gpui_component::scroll::Scrollbar;
|
||||
use gpui_component::{ActiveTheme, Icon, Sizable, h_flex, v_flex};
|
||||
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<TrashPanel> {
|
||||
cx.new(|cx| TrashPanel::new(window, cx))
|
||||
}
|
||||
|
||||
pub struct TrashPanel {
|
||||
name: SharedString,
|
||||
focus_handle: FocusHandle,
|
||||
|
||||
/// List state for messages
|
||||
list_state: ListState,
|
||||
}
|
||||
@@ -29,7 +27,6 @@ impl TrashPanel {
|
||||
let list_state = ListState::new(count, ListAlignment::Bottom, px(1024.));
|
||||
|
||||
Self {
|
||||
name: "Trash".into(),
|
||||
focus_handle: cx.focus_handle(),
|
||||
list_state,
|
||||
}
|
||||
@@ -65,11 +62,11 @@ impl TrashPanel {
|
||||
.w_full()
|
||||
.gap_1()
|
||||
.rounded(cx.theme().radius_lg)
|
||||
.bg(cx.theme().surface_background)
|
||||
.bg(cx.theme().muted)
|
||||
.text_sm()
|
||||
.child(
|
||||
div()
|
||||
.text_color(cx.theme().text_danger)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(message.reason.clone()),
|
||||
)
|
||||
.child(
|
||||
@@ -78,7 +75,7 @@ impl TrashPanel {
|
||||
.w_full()
|
||||
.px_2()
|
||||
.justify_between()
|
||||
.bg(cx.theme().elevated_surface_background)
|
||||
.bg(cx.theme().muted)
|
||||
.border_1()
|
||||
.border_color(cx.theme().border)
|
||||
.rounded(cx.theme().radius)
|
||||
@@ -92,7 +89,7 @@ impl TrashPanel {
|
||||
)
|
||||
.child(
|
||||
Button::new(format!("copy-{ix}"))
|
||||
.icon(IconName::Copy)
|
||||
.icon(CoopIcon::Copy)
|
||||
.ghost()
|
||||
.small()
|
||||
.on_click(cx.listener(move |this, _ev, _window, cx| {
|
||||
@@ -109,17 +106,16 @@ impl TrashPanel {
|
||||
}
|
||||
|
||||
impl Panel for TrashPanel {
|
||||
fn panel_id(&self) -> SharedString {
|
||||
self.name.clone()
|
||||
fn panel_name(&self) -> &'static str {
|
||||
"Trash"
|
||||
}
|
||||
|
||||
fn title(&self, _cx: &App) -> AnyElement {
|
||||
fn title(&mut self, window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.text_sm()
|
||||
.child(Icon::new(IconName::Warning).small())
|
||||
.child(Icon::new(CoopIcon::Warning).small())
|
||||
.child("Errors")
|
||||
.into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
use std::rc::Rc;
|
||||
|
||||
use chat::RoomKind;
|
||||
use common::CoopIcon;
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
App, ClickEvent, InteractiveElement, IntoElement, ParentElement as _, RenderOnce, SharedString,
|
||||
StatefulInteractiveElement, Styled, Window, div,
|
||||
};
|
||||
use gpui_component::avatar::Avatar;
|
||||
use gpui_component::dialog::DialogButtonProps;
|
||||
use gpui_component::dock::ClosePanel;
|
||||
use gpui_component::{ActiveTheme, Icon, Selectable, Sizable, StyledExt, WindowExt, h_flex};
|
||||
use nostr_sdk::prelude::*;
|
||||
use settings::AppSettings;
|
||||
use theme::ActiveTheme;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::dock::ClosePanel;
|
||||
use ui::modal::ModalButtonProps;
|
||||
use ui::{Icon, IconName, Selectable, Sizable, StyledExt, WindowExtension, h_flex};
|
||||
|
||||
use crate::dialogs::screening;
|
||||
|
||||
@@ -106,7 +106,7 @@ impl RenderOnce for RoomEntry {
|
||||
.rounded(cx.theme().radius)
|
||||
.when(!hide_avatar, |this| {
|
||||
this.when_some(self.avatar, |this, avatar| {
|
||||
this.child(Avatar::new(avatar).small().flex_shrink_0())
|
||||
this.child(Avatar::new().src(avatar).small().flex_shrink_0())
|
||||
})
|
||||
})
|
||||
.child(
|
||||
@@ -127,9 +127,9 @@ impl RenderOnce for RoomEntry {
|
||||
.child(name)
|
||||
.when(is_selected, |this| {
|
||||
this.child(
|
||||
Icon::new(IconName::CheckCircle)
|
||||
Icon::new(CoopIcon::CheckCircle)
|
||||
.small()
|
||||
.text_color(cx.theme().icon_accent),
|
||||
.text_color(cx.theme().primary_active),
|
||||
)
|
||||
}),
|
||||
)
|
||||
@@ -139,11 +139,11 @@ impl RenderOnce for RoomEntry {
|
||||
.gap_1p5()
|
||||
.flex_shrink_0()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_placeholder)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.when_some(self.created_at, |this, created_at| this.child(created_at)),
|
||||
),
|
||||
)
|
||||
.hover(|this| this.bg(cx.theme().elevated_surface_background))
|
||||
.hover(|this| this.bg(cx.theme().muted))
|
||||
.when_some(self.handler, |this, handler| {
|
||||
this.on_click(move |event, window, cx| {
|
||||
handler(event, window, cx);
|
||||
@@ -154,11 +154,10 @@ impl RenderOnce for RoomEntry {
|
||||
{
|
||||
let screening = screening::init(public_key, window, cx);
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
this.confirm()
|
||||
.child(screening.clone())
|
||||
window.open_dialog(cx, move |this, _window, _cx| {
|
||||
this.child(screening.clone())
|
||||
.button_props(
|
||||
ModalButtonProps::default()
|
||||
DialogButtonProps::default()
|
||||
.cancel_text("Ignore")
|
||||
.ok_text("Response"),
|
||||
)
|
||||
|
||||
@@ -4,26 +4,27 @@ use std::time::Duration;
|
||||
|
||||
use anyhow::{Context as AnyhowContext, Error};
|
||||
use chat::{ChatEvent, ChatRegistry, Room, RoomKind};
|
||||
use common::{DebouncedDelay, TimestampExt, coop_cache};
|
||||
use common::{CoopIcon, DebouncedDelay, TimestampExt, coop_cache};
|
||||
use entry::RoomEntry;
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable, IntoElement,
|
||||
ParentElement, Render, SharedString, Styled, Subscription, Task, UniformListScrollHandle,
|
||||
Window, div, uniform_list,
|
||||
Window, div, px, uniform_list,
|
||||
};
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dock::{Panel, PanelEvent};
|
||||
use gpui_component::input::{Input, InputEvent, InputState};
|
||||
use gpui_component::notification::Notification;
|
||||
use gpui_component::scroll::Scrollbar;
|
||||
use gpui_component::spinner::Spinner;
|
||||
use gpui_component::{
|
||||
ActiveTheme, Icon, Selectable, Sizable, StyledExt, WindowExt, h_flex, v_flex,
|
||||
};
|
||||
use nostr_sdk::prelude::*;
|
||||
use person::PersonRegistry;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use state::{FIND_DELAY, IMAGE_CACHE_SIZE, NostrRegistry};
|
||||
use theme::{ActiveTheme, SIDEBAR_WIDTH, TABBAR_HEIGHT};
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::dock::{Panel, PanelEvent};
|
||||
use ui::indicator::Indicator;
|
||||
use ui::input::{InputEvent, InputState, TextInput};
|
||||
use ui::notification::Notification;
|
||||
use ui::scroll::Scrollbar;
|
||||
use ui::{Icon, IconName, Selectable, Sizable, StyledExt, WindowExtension, h_flex, v_flex};
|
||||
|
||||
mod entry;
|
||||
|
||||
@@ -35,7 +36,6 @@ pub fn init(window: &mut Window, cx: &mut App) -> Entity<Sidebar> {
|
||||
|
||||
/// Sidebar.
|
||||
pub struct Sidebar {
|
||||
name: SharedString,
|
||||
focus_handle: FocusHandle,
|
||||
scroll_handle: UniformListScrollHandle,
|
||||
|
||||
@@ -135,7 +135,6 @@ impl Sidebar {
|
||||
);
|
||||
|
||||
Self {
|
||||
name: "Sidebar".into(),
|
||||
focus_handle: cx.focus_handle(),
|
||||
scroll_handle: UniformListScrollHandle::new(),
|
||||
find_input,
|
||||
@@ -249,11 +248,10 @@ impl Sidebar {
|
||||
}
|
||||
|
||||
/// Set the finding status
|
||||
fn set_finding(&mut self, status: bool, _window: &mut Window, cx: &mut Context<Self>) {
|
||||
fn set_finding(&mut self, status: bool, window: &mut Window, cx: &mut Context<Self>) {
|
||||
// Disable the input to prevent duplicate requests
|
||||
self.find_input.update(cx, |this, cx| {
|
||||
this.set_disabled(status, cx);
|
||||
this.set_loading(status, cx);
|
||||
this.set_loading(status, window, cx);
|
||||
});
|
||||
// Set the search status
|
||||
self.finding = status;
|
||||
@@ -473,8 +471,8 @@ impl Sidebar {
|
||||
}
|
||||
|
||||
impl Panel for Sidebar {
|
||||
fn panel_id(&self) -> SharedString {
|
||||
self.name.clone()
|
||||
fn panel_name(&self) -> &'static str {
|
||||
"Sidebar"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -508,25 +506,27 @@ impl Render for Sidebar {
|
||||
.gap_2()
|
||||
.child(
|
||||
h_flex()
|
||||
.h(TABBAR_HEIGHT)
|
||||
.h(px(28.0))
|
||||
.border_b_1()
|
||||
.border_color(cx.theme().border)
|
||||
.bg(cx.theme().tab_background)
|
||||
.bg(cx.theme().tab_bar)
|
||||
.child(
|
||||
TextInput::new(&self.find_input)
|
||||
Input::new(&self.find_input)
|
||||
.appearance(false)
|
||||
.bordered(false)
|
||||
.small()
|
||||
.text_xs()
|
||||
.when(!self.find_input.read(cx).loading, |this| {
|
||||
this.suffix(
|
||||
Button::new("find-icon")
|
||||
.icon(IconName::Search)
|
||||
.tooltip("Press Enter to search")
|
||||
.transparent()
|
||||
.small(),
|
||||
)
|
||||
}),
|
||||
.text_xs(),
|
||||
/*
|
||||
.when(!self.find_input.read(cx).loading, |this| {
|
||||
this.suffix(
|
||||
Button::new("find-icon")
|
||||
.icon(CoopIcon::Search)
|
||||
.tooltip("Press Enter to search")
|
||||
.transparent()
|
||||
.small(),
|
||||
)
|
||||
})
|
||||
*/
|
||||
),
|
||||
)
|
||||
.child(
|
||||
@@ -537,11 +537,10 @@ impl Render for Sidebar {
|
||||
.when(show_find_panel, |this| {
|
||||
this.child(
|
||||
Button::new("search-results")
|
||||
.icon(IconName::Search)
|
||||
.icon(CoopIcon::Search)
|
||||
.tooltip("All search results")
|
||||
.small()
|
||||
.ghost_alt()
|
||||
.font_semibold()
|
||||
.ghost()
|
||||
.flex_1()
|
||||
.selected(true),
|
||||
)
|
||||
@@ -550,16 +549,15 @@ impl Render for Sidebar {
|
||||
Button::new("all")
|
||||
.map(|this| {
|
||||
if self.current_filter(&RoomKind::Ongoing, cx) {
|
||||
this.icon(IconName::InboxFill)
|
||||
this.icon(CoopIcon::InboxFill)
|
||||
} else {
|
||||
this.icon(IconName::Inbox)
|
||||
this.icon(CoopIcon::Inbox)
|
||||
}
|
||||
})
|
||||
.when(!show_find_panel, |this| this.label("Inbox"))
|
||||
.tooltip("All ongoing conversations")
|
||||
.small()
|
||||
.ghost_alt()
|
||||
.font_semibold()
|
||||
.ghost()
|
||||
.flex_1()
|
||||
.selected(
|
||||
!show_find_panel && self.current_filter(&RoomKind::Ongoing, cx),
|
||||
@@ -572,22 +570,21 @@ impl Render for Sidebar {
|
||||
Button::new("requests")
|
||||
.map(|this| {
|
||||
if self.current_filter(&RoomKind::Request, cx) {
|
||||
this.icon(IconName::FistbumpFill)
|
||||
this.icon(CoopIcon::FistbumpFill)
|
||||
} else {
|
||||
this.icon(IconName::Fistbump)
|
||||
this.icon(CoopIcon::Fistbump)
|
||||
}
|
||||
})
|
||||
.when(!show_find_panel, |this| this.label("Requests"))
|
||||
.tooltip("Incoming new conversations")
|
||||
.small()
|
||||
.ghost_alt()
|
||||
.font_semibold()
|
||||
.ghost()
|
||||
.flex_1()
|
||||
.selected(
|
||||
!show_find_panel && !self.current_filter(&RoomKind::Ongoing, cx),
|
||||
)
|
||||
.when(self.new_requests, |this| {
|
||||
this.child(div().size_1().rounded_full().bg(cx.theme().cursor))
|
||||
this.child(div().size_1().rounded_full().bg(cx.theme().caret))
|
||||
})
|
||||
.on_click(cx.listener(|this, _ev, window, cx| {
|
||||
this.set_filter(RoomKind::default(), window, cx);
|
||||
@@ -596,14 +593,14 @@ impl Render for Sidebar {
|
||||
)
|
||||
.when(!show_find_panel && !loading && total_rooms == 0, |this| {
|
||||
this.child(
|
||||
div().w(SIDEBAR_WIDTH).px_2().child(
|
||||
div().w(px(240.)).px_2().child(
|
||||
v_flex()
|
||||
.p_3()
|
||||
.h_24()
|
||||
.w_full()
|
||||
.border_2()
|
||||
.border_dashed()
|
||||
.border_color(cx.theme().border_variant)
|
||||
.border_color(cx.theme().border)
|
||||
.rounded(cx.theme().radius_lg)
|
||||
.items_center()
|
||||
.justify_center()
|
||||
@@ -614,11 +611,14 @@ impl Render for Sidebar {
|
||||
.font_semibold()
|
||||
.child(SharedString::from("No conversations")),
|
||||
)
|
||||
.child(div().text_xs().text_color(cx.theme().text_muted).child(
|
||||
SharedString::from(
|
||||
"Start a conversation with someone to get started.",
|
||||
),
|
||||
)),
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from(
|
||||
"Start a conversation with someone to get started.",
|
||||
)),
|
||||
),
|
||||
),
|
||||
)
|
||||
})
|
||||
@@ -635,14 +635,14 @@ impl Render for Sidebar {
|
||||
.gap_1()
|
||||
.flex_1()
|
||||
.border_b_1()
|
||||
.border_color(cx.theme().border_variant)
|
||||
.border_color(cx.theme().border)
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_0p5()
|
||||
.text_xs()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child(Icon::new(IconName::ChevronDown))
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(Icon::new(CoopIcon::ChevronDown))
|
||||
.child(SharedString::from("Results")),
|
||||
)
|
||||
.child(
|
||||
@@ -668,8 +668,8 @@ impl Render for Sidebar {
|
||||
.gap_0p5()
|
||||
.text_xs()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child(Icon::new(IconName::ChevronDown).small())
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(Icon::new(CoopIcon::ChevronDown).small())
|
||||
.child(SharedString::from("Suggestions")),
|
||||
)
|
||||
.child(
|
||||
@@ -740,14 +740,14 @@ impl Render for Sidebar {
|
||||
.h_9()
|
||||
.justify_center()
|
||||
.bg(cx.theme().background.opacity(0.85))
|
||||
.border_color(cx.theme().border_disabled)
|
||||
.border_color(cx.theme().border)
|
||||
.border_1()
|
||||
.when(cx.theme().shadow, |this| this.shadow_xs())
|
||||
.rounded_full()
|
||||
.text_xs()
|
||||
.font_semibold()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child(Indicator::new().small().color(cx.theme().icon_accent))
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(Spinner::new().small().color(cx.theme().primary_active))
|
||||
.child(SharedString::from("Getting messages...")),
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use ::settings::AppSettings;
|
||||
use chat::{ChatEvent, ChatRegistry};
|
||||
use common::{CoopImageCache, download_dir};
|
||||
use common::{CoopIcon, CoopImageCache, download_dir};
|
||||
use device::{DeviceEvent, DeviceRegistry};
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
@@ -10,19 +9,18 @@ use gpui::{
|
||||
Render, SharedString, StatefulInteractiveElement, Styled, Subscription, Window, div,
|
||||
image_cache, px, relative,
|
||||
};
|
||||
use gpui_component::avatar::Avatar;
|
||||
use gpui_component::button::{Button, ButtonVariants};
|
||||
use gpui_component::dock::{ClosePanel, DockArea, DockItem, DockPlacement, PanelView};
|
||||
use gpui_component::menu::{DropdownMenu, PopupMenuItem};
|
||||
use gpui_component::notification::{Notification, NotificationType};
|
||||
use gpui_component::{ActiveTheme, Icon, Root, Sizable, Theme, WindowExt, h_flex, v_flex};
|
||||
use nostr_sdk::prelude::*;
|
||||
use person::{PersonRegistry, shorten_pubkey};
|
||||
use serde::Deserialize;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
use state::{IMAGE_CACHE_SIZE, NostrRegistry, StateEvent};
|
||||
use theme::{ActiveTheme, SIDEBAR_WIDTH, Theme, ThemeRegistry};
|
||||
use title_bar::TitleBar;
|
||||
use ui::avatar::Avatar;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::dock::{ClosePanel, DockArea, DockItem, DockPlacement, PanelView};
|
||||
use ui::menu::{DropdownMenu, PopupMenuItem};
|
||||
use ui::notification::{Notification, NotificationKind};
|
||||
use ui::{Icon, IconName, Root, Sizable, WindowExtension, h_flex, v_flex};
|
||||
|
||||
use crate::dialogs::restore::RestoreEncryption;
|
||||
use crate::dialogs::{accounts, settings};
|
||||
@@ -84,7 +82,7 @@ impl Workspace {
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
|
||||
let titlebar = cx.new(|_| TitleBar::new());
|
||||
let dock = cx.new(|cx| DockArea::new(window, cx));
|
||||
let dock = cx.new(|cx| DockArea::new("dock", None, window, cx));
|
||||
let image_cache = CoopImageCache::new(IMAGE_CACHE_SIZE, cx);
|
||||
|
||||
let mut subscriptions = smallvec![];
|
||||
@@ -106,7 +104,7 @@ impl Workspace {
|
||||
.title("Preparing a new identity")
|
||||
.message(PREPARE_MSG)
|
||||
.autohide(false)
|
||||
.with_kind(NotificationKind::Info);
|
||||
.with_type(NotificationType::Info);
|
||||
|
||||
window.push_notification(note, cx);
|
||||
}
|
||||
@@ -114,7 +112,7 @@ impl Workspace {
|
||||
let note = Notification::new()
|
||||
.id::<RelayNotifcation>()
|
||||
.message("Connecting to the bootstrap relays...")
|
||||
.with_kind(NotificationKind::Info);
|
||||
.with_type(NotificationType::Info);
|
||||
|
||||
window.push_notification(note, cx);
|
||||
}
|
||||
@@ -122,14 +120,14 @@ impl Workspace {
|
||||
let note = Notification::new()
|
||||
.id::<RelayNotifcation>()
|
||||
.message("Connected to the bootstrap relays")
|
||||
.with_kind(NotificationKind::Success);
|
||||
.with_type(NotificationType::Success);
|
||||
|
||||
window.push_notification(note, cx);
|
||||
}
|
||||
StateEvent::SignerSet => {
|
||||
this.set_center_layout(window, cx);
|
||||
// Clear the signer notification
|
||||
window.clear_notification::<SignerNotifcation>(cx);
|
||||
window.remove_notification::<SignerNotifcation>(cx);
|
||||
}
|
||||
StateEvent::Show => {
|
||||
this.account_selector(window, cx);
|
||||
@@ -152,7 +150,7 @@ impl Workspace {
|
||||
.autohide(false)
|
||||
.title("Wait for approval")
|
||||
.message(MSG)
|
||||
.with_kind(NotificationKind::Info);
|
||||
.with_type(NotificationType::Info);
|
||||
|
||||
window.push_notification(note, cx);
|
||||
}
|
||||
@@ -161,7 +159,7 @@ impl Workspace {
|
||||
.id::<DeviceNotifcation>()
|
||||
.autohide(false)
|
||||
.message("Creating encryption key")
|
||||
.with_kind(NotificationKind::Info);
|
||||
.with_type(NotificationType::Info);
|
||||
|
||||
window.push_notification(note, cx);
|
||||
}
|
||||
@@ -169,7 +167,7 @@ impl Workspace {
|
||||
let note = Notification::new()
|
||||
.id::<DeviceNotifcation>()
|
||||
.message("Encryption Key has been set")
|
||||
.with_kind(NotificationKind::Success);
|
||||
.with_type(NotificationType::Success);
|
||||
|
||||
window.push_notification(note, cx);
|
||||
}
|
||||
@@ -190,6 +188,7 @@ impl Workspace {
|
||||
this.add_panel(
|
||||
Arc::new(chat_ui::init(room, window, cx)),
|
||||
DockPlacement::Center,
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
@@ -197,14 +196,11 @@ impl Workspace {
|
||||
}
|
||||
}
|
||||
ChatEvent::CloseRoom(..) => {
|
||||
this.dock.update(cx, |this, cx| {
|
||||
// Force focus to the tab panel
|
||||
this.focus_tab_panel(window, cx);
|
||||
|
||||
this.dock.update(cx, |_this, cx| {
|
||||
// Dispatch the close panel action
|
||||
cx.defer_in(window, |_, window, cx| {
|
||||
window.dispatch_action(Box::new(ClosePanel), cx);
|
||||
window.close_all_modals(cx);
|
||||
window.close_all_dialogs(cx);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -219,11 +215,13 @@ impl Workspace {
|
||||
subscriptions.push(
|
||||
// Observe the chat registry
|
||||
cx.observe(&chat, move |this, chat, cx| {
|
||||
/*
|
||||
let ids = this.panel_ids(cx);
|
||||
|
||||
chat.update(cx, |this, cx| {
|
||||
this.refresh_rooms(&ids, cx);
|
||||
});
|
||||
*/
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -250,30 +248,19 @@ impl Workspace {
|
||||
{
|
||||
workspace.update(cx, |this, cx| {
|
||||
this.dock.update(cx, |this, cx| {
|
||||
this.add_panel(Arc::new(panel), placement, window, cx);
|
||||
this.add_panel(Arc::new(panel), placement, None, window, cx);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Get all panel ids
|
||||
fn panel_ids(&self, cx: &App) -> Vec<u64> {
|
||||
self.dock
|
||||
.read(cx)
|
||||
.items
|
||||
.panel_ids(cx)
|
||||
.into_iter()
|
||||
.filter_map(|panel| panel.parse::<u64>().ok())
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Set the dock layout
|
||||
fn set_layout(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let left = DockItem::panel(Arc::new(sidebar::init(window, cx)));
|
||||
|
||||
// Update the dock layout with sidebar on the left
|
||||
self.dock.update(cx, |this, cx| {
|
||||
this.set_left_dock(left, Some(SIDEBAR_WIDTH), true, window, cx);
|
||||
this.set_left_dock(left, Some(px(240.)), true, window, cx);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -281,7 +268,7 @@ impl Workspace {
|
||||
fn set_center_layout(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let dock = self.dock.downgrade();
|
||||
let greeter = Arc::new(greeter::init(window, cx));
|
||||
let tabs = DockItem::tabs(vec![greeter], None, &dock, window, cx);
|
||||
let tabs = DockItem::tabs(vec![greeter], &dock, window, cx);
|
||||
let center = DockItem::split(Axis::Vertical, vec![tabs], &dock, window, cx);
|
||||
|
||||
// Update the layout with center dock
|
||||
@@ -296,9 +283,9 @@ impl Workspace {
|
||||
Command::ShowSettings => {
|
||||
let view = settings::init(window, cx);
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
window.open_dialog(cx, move |this, _window, _cx| {
|
||||
this.width(px(520.))
|
||||
.show_close(true)
|
||||
.close_button(true)
|
||||
.pb_2()
|
||||
.title("Preferences")
|
||||
.child(view.clone())
|
||||
@@ -313,6 +300,7 @@ impl Workspace {
|
||||
this.add_panel(
|
||||
Arc::new(profile::init(public_key, window, cx)),
|
||||
DockPlacement::Right,
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
@@ -324,6 +312,7 @@ impl Workspace {
|
||||
this.add_panel(
|
||||
Arc::new(contact_list::init(window, cx)),
|
||||
DockPlacement::Right,
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
@@ -334,6 +323,7 @@ impl Workspace {
|
||||
this.add_panel(
|
||||
Arc::new(backup::init(window, cx)),
|
||||
DockPlacement::Right,
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
@@ -344,6 +334,7 @@ impl Workspace {
|
||||
this.add_panel(
|
||||
Arc::new(messaging_relays::init(window, cx)),
|
||||
DockPlacement::Right,
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
@@ -361,6 +352,7 @@ impl Workspace {
|
||||
this.add_panel(
|
||||
Arc::new(relay_list::init(window, cx)),
|
||||
DockPlacement::Right,
|
||||
None,
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
@@ -426,11 +418,10 @@ impl Workspace {
|
||||
let device = DeviceRegistry::global(cx);
|
||||
let ent = device.downgrade();
|
||||
|
||||
window.open_modal(cx, move |this, _window, cx| {
|
||||
window.open_dialog(cx, move |this, _window, cx| {
|
||||
let ent = ent.clone();
|
||||
|
||||
this.confirm()
|
||||
.show_close(true)
|
||||
this.close_button(true)
|
||||
.title("Reset Encryption Key")
|
||||
.child(
|
||||
v_flex()
|
||||
@@ -440,7 +431,7 @@ impl Workspace {
|
||||
.child(
|
||||
div()
|
||||
.italic()
|
||||
.text_color(cx.theme().text_danger)
|
||||
.text_color(cx.theme().danger_active)
|
||||
.child(SharedString::from(ENC_WARN)),
|
||||
),
|
||||
)
|
||||
@@ -458,7 +449,7 @@ impl Workspace {
|
||||
fn import_encryption(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let restore = cx.new(|cx| RestoreEncryption::new(window, cx));
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
window.open_dialog(cx, move |this, _window, _cx| {
|
||||
this.width(px(520.))
|
||||
.title("Restore Encryption")
|
||||
.child(restore.clone())
|
||||
@@ -468,10 +459,10 @@ impl Workspace {
|
||||
fn account_selector(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let accounts = accounts::init(window, cx);
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
window.open_dialog(cx, move |this, _window, _cx| {
|
||||
this.width(px(520.))
|
||||
.title("Continue with")
|
||||
.show_close(false)
|
||||
.close_button(false)
|
||||
.keyboard(false)
|
||||
.overlay_closable(false)
|
||||
.child(accounts.clone())
|
||||
@@ -479,7 +470,8 @@ impl Workspace {
|
||||
}
|
||||
|
||||
fn theme_selector(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
window.open_modal(cx, move |this, _window, cx| {
|
||||
/*
|
||||
* window.open_modal(cx, move |this, _window, cx| {
|
||||
let registry = ThemeRegistry::global(cx);
|
||||
let themes = registry.read(cx).themes();
|
||||
|
||||
@@ -522,7 +514,7 @@ impl Workspace {
|
||||
.group_hover("", |this| this.visible())
|
||||
.child(
|
||||
Button::new(format!("url-{ix}"))
|
||||
.icon(IconName::Link)
|
||||
.icon(CoopIcon::Link)
|
||||
.ghost()
|
||||
.small()
|
||||
.on_click({
|
||||
@@ -534,7 +526,7 @@ impl Workspace {
|
||||
)
|
||||
.child(
|
||||
Button::new(format!("set-{ix}"))
|
||||
.icon(IconName::Check)
|
||||
.icon(CoopIcon::Check)
|
||||
.primary()
|
||||
.small()
|
||||
.on_click({
|
||||
@@ -556,6 +548,7 @@ impl Workspace {
|
||||
items
|
||||
}))
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
fn titlebar_left(&mut self, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
@@ -570,7 +563,7 @@ impl Workspace {
|
||||
this.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(SharedString::from("Choose an account to continue...")),
|
||||
)
|
||||
})
|
||||
@@ -582,11 +575,11 @@ impl Workspace {
|
||||
|
||||
this.child(
|
||||
Button::new("current-user")
|
||||
.child(Avatar::new(avatar.clone()).xsmall())
|
||||
.child(Avatar::new().src(avatar.clone()).xsmall())
|
||||
.small()
|
||||
.caret()
|
||||
.compact()
|
||||
.transparent()
|
||||
.ghost()
|
||||
.dropdown_caret(true)
|
||||
.dropdown_menu(move |this, _window, _cx| {
|
||||
let avatar = avatar.clone();
|
||||
let name = name.clone();
|
||||
@@ -596,40 +589,40 @@ impl Workspace {
|
||||
h_flex()
|
||||
.gap_1p5()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child(Avatar::new(avatar.clone()).xsmall())
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(Avatar::new().src(avatar.clone()).xsmall())
|
||||
.child(name.clone())
|
||||
}))
|
||||
.separator()
|
||||
.menu_with_icon(
|
||||
"Profile",
|
||||
IconName::Profile,
|
||||
CoopIcon::Profile,
|
||||
Box::new(Command::ShowProfile),
|
||||
)
|
||||
.menu_with_icon(
|
||||
"Contact List",
|
||||
IconName::Book,
|
||||
CoopIcon::Book,
|
||||
Box::new(Command::ShowContactList),
|
||||
)
|
||||
.menu_with_icon(
|
||||
"Backup",
|
||||
IconName::UserKey,
|
||||
CoopIcon::UserKey,
|
||||
Box::new(Command::ShowBackup),
|
||||
)
|
||||
.menu_with_icon(
|
||||
"Themes",
|
||||
IconName::Sun,
|
||||
CoopIcon::Sun,
|
||||
Box::new(Command::ToggleTheme),
|
||||
)
|
||||
.separator()
|
||||
.menu_with_icon(
|
||||
"Accounts",
|
||||
IconName::Group,
|
||||
CoopIcon::Group,
|
||||
Box::new(Command::ToggleAccount),
|
||||
)
|
||||
.menu_with_icon(
|
||||
"Settings",
|
||||
IconName::Settings,
|
||||
CoopIcon::Settings,
|
||||
Box::new(Command::ShowSettings),
|
||||
)
|
||||
}),
|
||||
@@ -657,7 +650,6 @@ impl Workspace {
|
||||
let announcement = profile.announcement();
|
||||
|
||||
h_flex()
|
||||
.when(!cx.theme().platform.is_mac(), |this| this.pr_2())
|
||||
.gap_2()
|
||||
.when(trash_messages > 0, |this| {
|
||||
this.child(
|
||||
@@ -667,11 +659,11 @@ impl Workspace {
|
||||
.px_1()
|
||||
.gap_1()
|
||||
.rounded(cx.theme().radius)
|
||||
.hover(|this| this.bg(cx.theme().ghost_element_hover))
|
||||
.hover(|this| this.bg(cx.theme().danger_hover))
|
||||
.child(
|
||||
Icon::new(IconName::Warning)
|
||||
Icon::new(CoopIcon::Warning)
|
||||
.small()
|
||||
.text_color(cx.theme().text_danger),
|
||||
.text_color(cx.theme().danger_foreground),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
@@ -693,7 +685,7 @@ impl Workspace {
|
||||
})
|
||||
.child(
|
||||
Button::new("key")
|
||||
.icon(IconName::UserKey)
|
||||
.icon(CoopIcon::UserKey)
|
||||
.tooltip("Decoupled encryption key")
|
||||
.small()
|
||||
.ghost()
|
||||
@@ -715,9 +707,9 @@ impl Workspace {
|
||||
.gap_1()
|
||||
.text_sm()
|
||||
.child(
|
||||
Icon::new(IconName::Device)
|
||||
Icon::new(CoopIcon::Device)
|
||||
.small()
|
||||
.text_color(cx.theme().icon_muted),
|
||||
.text_color(cx.theme().muted_foreground),
|
||||
)
|
||||
.child(name.clone())
|
||||
}))
|
||||
@@ -726,9 +718,9 @@ impl Workspace {
|
||||
.gap_1()
|
||||
.text_sm()
|
||||
.child(
|
||||
Icon::new(IconName::UserKey)
|
||||
Icon::new(CoopIcon::UserKey)
|
||||
.small()
|
||||
.text_color(cx.theme().icon_muted),
|
||||
.text_color(cx.theme().muted_foreground),
|
||||
)
|
||||
.child(SharedString::from(pkey.clone()))
|
||||
}))
|
||||
@@ -736,30 +728,30 @@ impl Workspace {
|
||||
.separator()
|
||||
.menu_with_icon(
|
||||
"Backup",
|
||||
IconName::Shield,
|
||||
CoopIcon::Shield,
|
||||
Box::new(Command::BackupEncryption),
|
||||
)
|
||||
.menu_with_icon(
|
||||
"Restore from secret key",
|
||||
IconName::Usb,
|
||||
CoopIcon::Usb,
|
||||
Box::new(Command::ImportEncryption),
|
||||
)
|
||||
.separator()
|
||||
.menu_with_icon(
|
||||
"Reload",
|
||||
IconName::Refresh,
|
||||
CoopIcon::Refresh,
|
||||
Box::new(Command::RefreshEncryption),
|
||||
)
|
||||
.menu_with_icon(
|
||||
"Reset",
|
||||
IconName::Warning,
|
||||
CoopIcon::Warning,
|
||||
Box::new(Command::ResetEncryption),
|
||||
)
|
||||
}),
|
||||
)
|
||||
.child(
|
||||
Button::new("inbox")
|
||||
.icon(IconName::Inbox)
|
||||
.icon(CoopIcon::Inbox)
|
||||
.small()
|
||||
.ghost()
|
||||
.loading(initializing)
|
||||
@@ -798,14 +790,14 @@ impl Workspace {
|
||||
div()
|
||||
.size_1p5()
|
||||
.rounded_full()
|
||||
.bg(cx.theme().icon_accent),
|
||||
.bg(cx.theme().primary_foreground),
|
||||
)
|
||||
.child(url.clone()),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_xs()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.text_color(cx.theme().muted_foreground)
|
||||
.child(count.clone()),
|
||||
)
|
||||
}))
|
||||
@@ -815,17 +807,17 @@ impl Workspace {
|
||||
menu.separator()
|
||||
.menu_with_icon(
|
||||
"Reload",
|
||||
IconName::Refresh,
|
||||
CoopIcon::Refresh,
|
||||
Box::new(Command::RefreshMessagingRelays),
|
||||
)
|
||||
.menu_with_icon(
|
||||
"Manage gossip relays",
|
||||
IconName::Relay,
|
||||
CoopIcon::Relay,
|
||||
Box::new(Command::ShowRelayList),
|
||||
)
|
||||
.menu_with_icon(
|
||||
"Manage messaging relays",
|
||||
IconName::Settings,
|
||||
CoopIcon::Settings,
|
||||
Box::new(Command::ShowMessaging),
|
||||
)
|
||||
}),
|
||||
@@ -835,7 +827,7 @@ impl Workspace {
|
||||
|
||||
impl Render for Workspace {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let modal_layer = Root::render_modal_layer(window, cx);
|
||||
let modal_layer = Root::render_dialog_layer(window, cx);
|
||||
let notification_layer = Root::render_notification_layer(window, cx);
|
||||
|
||||
// Titlebar elements
|
||||
|
||||
Reference in New Issue
Block a user