diff --git a/assets/icons/arrow-up-circle.svg b/assets/icons/arrow-up-circle.svg
deleted file mode 100644
index a098b52..0000000
--- a/assets/icons/arrow-up-circle.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/assets/icons/edit-fill.svg b/assets/icons/edit-fill.svg
deleted file mode 100644
index e263643..0000000
--- a/assets/icons/edit-fill.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
diff --git a/assets/icons/forward.svg b/assets/icons/forward.svg
deleted file mode 100644
index 98c932b..0000000
--- a/assets/icons/forward.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/assets/icons/search-fill.svg b/assets/icons/search-fill.svg
deleted file mode 100644
index 3e8bb4e..0000000
--- a/assets/icons/search-fill.svg
+++ /dev/null
@@ -1,3 +0,0 @@
-
diff --git a/assets/icons/signal.svg b/assets/icons/signal.svg
new file mode 100644
index 0000000..5c46c01
--- /dev/null
+++ b/assets/icons/signal.svg
@@ -0,0 +1,3 @@
+
diff --git a/assets/icons/users-three-fill.svg b/assets/icons/users-three-fill.svg
deleted file mode 100644
index 89b75f3..0000000
--- a/assets/icons/users-three-fill.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/assets/icons/warning.svg b/assets/icons/warning.svg
new file mode 100644
index 0000000..8ac94eb
--- /dev/null
+++ b/assets/icons/warning.svg
@@ -0,0 +1,3 @@
+
diff --git a/crates/coop/src/actions.rs b/crates/coop/src/actions.rs
index 5a33cfb..327525a 100644
--- a/crates/coop/src/actions.rs
+++ b/crates/coop/src/actions.rs
@@ -3,6 +3,7 @@ use std::sync::Mutex;
use gpui::{actions, App};
actions!(coop, [DarkMode, Settings, Logout, Quit]);
+actions!(sidebar, [Reload, RelayStatus]);
pub fn load_embedded_fonts(cx: &App) {
let asset_source = cx.asset_source();
diff --git a/crates/coop/src/chatspace.rs b/crates/coop/src/chatspace.rs
index 1038382..c1d4b26 100644
--- a/crates/coop/src/chatspace.rs
+++ b/crates/coop/src/chatspace.rs
@@ -1313,7 +1313,7 @@ impl ChatSpace {
)
})
.when(!self.has_nip17_relays, |this| {
- this.child(setup_nip17_relay(t!("relays.button_label")))
+ this.child(setup_nip17_relay(t!("relays.button")))
})
.child(
Button::new("user")
diff --git a/crates/coop/src/views/preferences.rs b/crates/coop/src/views/preferences.rs
index e398080..251fb83 100644
--- a/crates/coop/src/views/preferences.rs
+++ b/crates/coop/src/views/preferences.rs
@@ -86,7 +86,6 @@ impl Preferences {
}
fn open_relays(&self, window: &mut Window, cx: &mut Context) {
- let title = SharedString::new(t!("relays.modal_title"));
let view = setup_relay::init(Kind::InboxRelays, window, cx);
let weak_view = view.downgrade();
@@ -94,7 +93,7 @@ impl Preferences {
let weak_view = weak_view.clone();
this.confirm()
- .title(title.clone())
+ .title(shared_t!("relays.modal"))
.child(view.clone())
.button_props(ModalButtonProps::default().ok_text(t!("common.update")))
.on_ok(move |_, window, cx| {
diff --git a/crates/coop/src/views/setup_relay.rs b/crates/coop/src/views/setup_relay.rs
index 22361a9..586e0dd 100644
--- a/crates/coop/src/views/setup_relay.rs
+++ b/crates/coop/src/views/setup_relay.rs
@@ -45,7 +45,7 @@ where
modal
.confirm()
- .title(shared_t!("relays.modal_title"))
+ .title(shared_t!("relays.modal"))
.child(view.clone())
.button_props(ModalButtonProps::default().ok_text(t!("common.update")))
.on_ok(move |_, window, cx| {
@@ -299,7 +299,7 @@ impl SetupRelay {
.justify_center()
.text_sm()
.text_align(TextAlign::Center)
- .child(shared_t!("relays.add_some_relays"))
+ .child(shared_t!("relays.help_text"))
}
}
@@ -339,7 +339,7 @@ impl Render for SetupRelay {
.text_xs()
.font_semibold()
.text_color(cx.theme().text_muted)
- .child(shared_t!("relays.recommended")),
+ .child(shared_t!("common.recommended")),
)
.child(h_flex().gap_1().children({
NIP17_RELAYS.iter().map(|&relay| {
diff --git a/crates/coop/src/views/sidebar/mod.rs b/crates/coop/src/views/sidebar/mod.rs
index 67bee8b..d170e10 100644
--- a/crates/coop/src/views/sidebar/mod.rs
+++ b/crates/coop/src/views/sidebar/mod.rs
@@ -6,15 +6,15 @@ use anyhow::{anyhow, Error};
use common::debounced_delay::DebouncedDelay;
use common::display::{ReadableTimestamp, TextUtils};
use global::constants::{BOOTSTRAP_RELAYS, SEARCH_RELAYS};
-use global::{nostr_client, UnwrappingStatus};
+use global::{css, nostr_client, UnwrappingStatus};
use gpui::prelude::FluentBuilder;
use gpui::{
div, uniform_list, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle,
- Focusable, IntoElement, ParentElement, Render, RetainAllImageCache, SharedString, Styled,
- Subscription, Task, Window,
+ Focusable, InteractiveElement, IntoElement, ParentElement, Render, RetainAllImageCache,
+ SharedString, Styled, Subscription, Task, Window,
};
use gpui_tokio::Tokio;
-use i18n::t;
+use i18n::{shared_t, t};
use itertools::Itertools;
use list_item::RoomListItem;
use nostr_sdk::prelude::*;
@@ -26,8 +26,10 @@ use theme::ActiveTheme;
use ui::button::{Button, ButtonRounded, ButtonVariants};
use ui::dock_area::panel::{Panel, PanelEvent};
use ui::input::{InputEvent, InputState, TextInput};
-use ui::popup_menu::PopupMenu;
-use ui::{v_flex, ContextModal, IconName, Selectable, Sizable, StyledExt};
+use ui::popup_menu::{PopupMenu, PopupMenuExt};
+use ui::{h_flex, v_flex, ContextModal, Icon, IconName, Selectable, Sizable, StyledExt};
+
+use crate::actions::{RelayStatus, Reload};
mod list_item;
@@ -69,17 +71,16 @@ impl Sidebar {
let global_result = cx.new(|_| None);
let cancel_handle = cx.new(|_| None);
- let find_input = cx.new(|cx| {
- InputState::new(window, cx).placeholder(t!("sidebar.find_or_start_conversation"))
- });
+ let find_input =
+ cx.new(|cx| InputState::new(window, cx).placeholder(t!("sidebar.search_label")));
- let chats = Registry::global(cx);
+ let registry = Registry::global(cx);
let mut subscriptions = smallvec![];
subscriptions.push(cx.subscribe_in(
- &chats,
+ ®istry,
window,
- move |this, _chats, event, _window, cx| {
+ move |this, _, event, _window, cx| {
if let RegistryEvent::NewRequest(kind) = event {
this.indicator.update(cx, |this, cx| {
*this = Some(kind.to_owned());
@@ -519,6 +520,88 @@ impl Sidebar {
});
}
+ fn on_reload(&mut self, _ev: &Reload, window: &mut Window, cx: &mut Context) {
+ Registry::global(cx).update(cx, |this, cx| {
+ this.load_rooms(window, cx);
+ });
+ window.push_notification(t!("common.refreshed"), cx);
+ }
+
+ fn on_manage(&mut self, _ev: &RelayStatus, window: &mut Window, cx: &mut Context) {
+ let task: Task, Error>> = cx.background_spawn(async move {
+ let client = nostr_client();
+ let css = css();
+ let subscription = client.subscription(&css.gift_wrap_sub_id).await;
+ let mut relays: Vec = vec![];
+
+ for (url, _filter) in subscription.into_iter() {
+ relays.push(client.pool().relay(url).await?);
+ }
+
+ Ok(relays)
+ });
+
+ cx.spawn_in(window, async move |this, cx| {
+ if let Ok(relays) = task.await {
+ this.update_in(cx, |this, window, cx| {
+ this.manage_relays(relays, window, cx);
+ })
+ .ok();
+ }
+ })
+ .detach();
+ }
+
+ fn manage_relays(&mut self, relays: Vec, window: &mut Window, cx: &mut Context) {
+ window.open_modal(cx, move |this, _window, cx| {
+ this.show_close(true)
+ .overlay_closable(true)
+ .keyboard(true)
+ .title(shared_t!("manage_relays.modal"))
+ .child(v_flex().pb_4().gap_2().children({
+ let mut items = Vec::with_capacity(relays.len());
+
+ for relay in relays.clone().into_iter() {
+ let url = relay.url().to_string();
+ let time = relay.stats().connected_at().to_ago();
+ let connected = relay.is_connected();
+
+ items.push(
+ h_flex()
+ .h_8()
+ .px_2()
+ .justify_between()
+ .text_xs()
+ .bg(cx.theme().elevated_surface_background)
+ .rounded(cx.theme().radius)
+ .child(
+ h_flex()
+ .gap_1()
+ .font_semibold()
+ .child(
+ Icon::new(IconName::Signal)
+ .small()
+ .text_color(cx.theme().danger_active)
+ .when(connected, |this| {
+ this.text_color(gpui::green().alpha(0.75))
+ }),
+ )
+ .child(url),
+ )
+ .child(
+ div()
+ .text_right()
+ .text_color(cx.theme().text_muted)
+ .child(shared_t!("manage_relays.time", t = time)),
+ ),
+ );
+ }
+
+ items
+ }))
+ });
+ }
+
fn list_items(
&self,
rooms: &[Entity],
@@ -610,6 +693,8 @@ impl Render for Sidebar {
}
v_flex()
+ .on_action(cx.listener(Self::on_reload))
+ .on_action(cx.listener(Self::on_manage))
.image_cache(self.image_cache.clone())
.size_full()
.relative()
@@ -632,7 +717,7 @@ impl Render for Sidebar {
.suffix(
Button::new("find")
.icon(IconName::Search)
- .tooltip(t!("sidebar.press_enter_to_search"))
+ .tooltip(t!("sidebar.search_tooltip"))
.transparent()
.small(),
),
@@ -693,6 +778,31 @@ impl Render for Sidebar {
.on_click(cx.listener(|this, _, _, cx| {
this.set_filter(RoomKind::default(), cx);
})),
+ )
+ .child(
+ h_flex()
+ .flex_1()
+ .w_full()
+ .justify_end()
+ .items_center()
+ .text_xs()
+ .child(
+ Button::new("option")
+ .icon(IconName::Ellipsis)
+ .xsmall()
+ .ghost()
+ .rounded(ButtonRounded::Full)
+ .popup_menu(move |this, _window, _cx| {
+ this.menu(
+ t!("sidebar.reload_menu"),
+ Box::new(Reload),
+ )
+ .menu(
+ t!("sidebar.status_menu"),
+ Box::new(RelayStatus),
+ )
+ }),
+ ),
),
)
.child(
diff --git a/crates/ui/src/icon.rs b/crates/ui/src/icon.rs
index 9c9288d..19d0a7a 100644
--- a/crates/ui/src/icon.rs
+++ b/crates/ui/src/icon.rs
@@ -14,8 +14,6 @@ pub enum IconName {
ArrowLeft,
ArrowRight,
ArrowUp,
- ArrowUpCircle,
- Bell,
CaretUp,
CaretDown,
CaretDownFill,
@@ -28,7 +26,6 @@ pub enum IconName {
CloseCircleFill,
Copy,
Edit,
- EditFill,
Ellipsis,
Eye,
EyeOff,
@@ -52,9 +49,8 @@ pub enum IconName {
Reply,
Report,
Refresh,
- Forward,
+ Signal,
Search,
- SearchFill,
Settings,
SortAscending,
SortDescending,
@@ -62,8 +58,8 @@ pub enum IconName {
ThumbsDown,
ThumbsUp,
Upload,
- UsersThreeFill,
OpenUrl,
+ Warning,
WindowClose,
WindowMaximize,
WindowMinimize,
@@ -78,8 +74,6 @@ impl IconName {
Self::ArrowLeft => "icons/arrow-left.svg",
Self::ArrowRight => "icons/arrow-right.svg",
Self::ArrowUp => "icons/arrow-up.svg",
- Self::ArrowUpCircle => "icons/arrow-up-circle.svg",
- Self::Bell => "icons/bell.svg",
Self::CaretRight => "icons/caret-right.svg",
Self::CaretUp => "icons/caret-up.svg",
Self::CaretDown => "icons/caret-down.svg",
@@ -92,7 +86,6 @@ impl IconName {
Self::CloseCircleFill => "icons/close-circle-fill.svg",
Self::Copy => "icons/copy.svg",
Self::Edit => "icons/edit.svg",
- Self::EditFill => "icons/edit-fill.svg",
Self::Ellipsis => "icons/ellipsis.svg",
Self::Eye => "icons/eye.svg",
Self::EmojiFill => "icons/emoji-fill.svg",
@@ -116,9 +109,8 @@ impl IconName {
Self::Reply => "icons/reply.svg",
Self::Report => "icons/report.svg",
Self::Refresh => "icons/refresh.svg",
- Self::Forward => "icons/forward.svg",
+ Self::Signal => "icons/signal.svg",
Self::Search => "icons/search.svg",
- Self::SearchFill => "icons/search-fill.svg",
Self::Settings => "icons/settings.svg",
Self::SortAscending => "icons/sort-ascending.svg",
Self::SortDescending => "icons/sort-descending.svg",
@@ -126,8 +118,8 @@ impl IconName {
Self::ThumbsDown => "icons/thumbs-down.svg",
Self::ThumbsUp => "icons/thumbs-up.svg",
Self::Upload => "icons/upload.svg",
- Self::UsersThreeFill => "icons/users-three-fill.svg",
Self::OpenUrl => "icons/open-url.svg",
+ Self::Warning => "icons/warning.svg",
Self::WindowClose => "icons/window-close.svg",
Self::WindowMaximize => "icons/window-maximize.svg",
Self::WindowMinimize => "icons/window-minimize.svg",
diff --git a/crates/ui/src/notification.rs b/crates/ui/src/notification.rs
index 701650a..bdb74f5 100644
--- a/crates/ui/src/notification.rs
+++ b/crates/ui/src/notification.rs
@@ -30,14 +30,10 @@ pub enum NotificationType {
impl NotificationType {
fn icon(&self, cx: &App) -> Icon {
match self {
- Self::Info => Icon::new(IconName::Info).text_color(cx.theme().element_active),
- Self::Warning => Icon::new(IconName::Report).text_color(cx.theme().warning_foreground),
- Self::Success => {
- Icon::new(IconName::CheckCircle).text_color(cx.theme().element_foreground)
- }
- Self::Error => {
- Icon::new(IconName::CloseCircle).text_color(cx.theme().danger_foreground)
- }
+ Self::Info => Icon::new(IconName::Info).text_color(cx.theme().element_foreground),
+ Self::Success => Icon::new(IconName::Info).text_color(cx.theme().secondary_foreground),
+ Self::Warning => Icon::new(IconName::Warning).text_color(cx.theme().warning_foreground),
+ Self::Error => Icon::new(IconName::Warning).text_color(cx.theme().danger_foreground),
}
}
}
diff --git a/locales/app.yml b/locales/app.yml
index b7a66f7..23b61a1 100644
--- a/locales/app.yml
+++ b/locales/app.yml
@@ -45,6 +45,10 @@ common:
en: "Ignore"
relay:
en: "Relay"
+ relay_invalid:
+ en: "Relay URL is not valid."
+ recommended:
+ en: "Recommended:"
auto_update:
updating:
@@ -167,20 +171,22 @@ login:
en: "Logging in..."
relays:
- button_label:
+ button:
en: "Configure the Messaging Relays to receive messages"
- modal_title:
+ modal:
en: "Set Up Messaging Relays"
description:
en: "In order to receive messages from others, you need to set up at least one Messaging Relay."
- add_some_relays:
+ help_text:
en: "Please add some relays."
- invalid:
- en: "Relay URL is not valid."
empty:
- en: "You need to add at least 1 relay to receive messages."
- recommended:
- en: "Recommended:"
+ en: "You need to add at least 1 relay to receive messages from others."
+
+manage_relays:
+ modal:
+ en: "Messaging Relay Status"
+ time:
+ en: "Last activity: %{t}"
subject:
title:
@@ -353,9 +359,13 @@ chat:
en: "%{u} has not set up Messaging Relays, so they won't receive your message."
sidebar:
- find_or_start_conversation:
+ reload_menu:
+ en: "Reload"
+ status_menu:
+ en: "Relay Status"
+ search_label:
en: "Find or start a conversation"
- press_enter_to_search:
+ search_tooltip:
en: "Press Enter to search"
empty:
en: "There are no users matching query %{query}"