.
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m48s
Rust / build (ubuntu-latest, stable) (pull_request) Failing after 1m37s
Some checks failed
Rust / build (ubuntu-latest, stable) (push) Failing after 1m48s
Rust / build (ubuntu-latest, stable) (pull_request) Failing after 1m37s
This commit is contained in:
2
crates/coop/src/dialogs/mod.rs
Normal file
2
crates/coop/src/dialogs/mod.rs
Normal file
@@ -0,0 +1,2 @@
|
||||
pub mod compose;
|
||||
pub mod screening;
|
||||
@@ -12,10 +12,10 @@ use ui::Root;
|
||||
use crate::actions::Quit;
|
||||
|
||||
mod actions;
|
||||
mod dialogs;
|
||||
mod panels;
|
||||
mod sidebar;
|
||||
mod user;
|
||||
mod views;
|
||||
mod workspace;
|
||||
|
||||
fn main() {
|
||||
|
||||
@@ -10,7 +10,7 @@ use theme::ActiveTheme;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::{h_flex, v_flex, Icon, IconName, Sizable, StyledExt};
|
||||
|
||||
use crate::panels::{connect, import, profile, relay_list};
|
||||
use crate::panels::{connect, import, messaging_relays, profile, relay_list};
|
||||
use crate::workspace::Workspace;
|
||||
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<GreeterPanel> {
|
||||
@@ -166,7 +166,7 @@ impl Render for GreeterPanel {
|
||||
.small()
|
||||
.on_click(move |_ev, window, cx| {
|
||||
Workspace::add_panel(
|
||||
import::init(window, cx),
|
||||
messaging_relays::init(window, cx),
|
||||
DockPlacement::Center,
|
||||
window,
|
||||
cx,
|
||||
|
||||
@@ -2,11 +2,12 @@ use std::collections::HashSet;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::{anyhow, Error};
|
||||
use dock::panel::{Panel, PanelEvent};
|
||||
use gpui::prelude::FluentBuilder;
|
||||
use gpui::{
|
||||
div, px, uniform_list, App, AppContext, Context, Entity, InteractiveElement, IntoElement,
|
||||
ParentElement, Render, SharedString, Styled, Subscription, Task, TextAlign, UniformList,
|
||||
Window,
|
||||
div, relative, uniform_list, AnyElement, App, AppContext, Context, Entity, EventEmitter,
|
||||
FocusHandle, Focusable, InteractiveElement, IntoElement, ParentElement, Render, SharedString,
|
||||
Styled, Subscription, Task, TextAlign, UniformList, Window,
|
||||
};
|
||||
use nostr_sdk::prelude::*;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
@@ -14,15 +15,21 @@ use state::NostrRegistry;
|
||||
use theme::ActiveTheme;
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::input::{InputEvent, InputState, TextInput};
|
||||
use ui::{h_flex, v_flex, IconName, Sizable, WindowExtension};
|
||||
use ui::{divider, h_flex, v_flex, IconName, Sizable, StyledExt};
|
||||
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<SetupRelay> {
|
||||
cx.new(|cx| SetupRelay::new(window, cx))
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<MessagingRelayPanel> {
|
||||
cx.new(|cx| MessagingRelayPanel::new(window, cx))
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SetupRelay {
|
||||
pub struct MessagingRelayPanel {
|
||||
name: SharedString,
|
||||
focus_handle: FocusHandle,
|
||||
|
||||
/// Relay URL input
|
||||
input: Entity<InputState>,
|
||||
|
||||
/// Error message
|
||||
error: Option<SharedString>,
|
||||
|
||||
// All relays
|
||||
@@ -35,13 +42,12 @@ pub struct SetupRelay {
|
||||
_tasks: SmallVec<[Task<()>; 1]>,
|
||||
}
|
||||
|
||||
impl SetupRelay {
|
||||
impl MessagingRelayPanel {
|
||||
pub fn new(window: &mut Window, cx: &mut Context<Self>) -> Self {
|
||||
let input = cx.new(|cx| InputState::new(window, cx).placeholder("wss://example.com"));
|
||||
let nostr = NostrRegistry::global(cx);
|
||||
let client = nostr.read(cx).client();
|
||||
|
||||
let input = cx.new(|cx| InputState::new(window, cx).placeholder("wss://example.com"));
|
||||
|
||||
let mut subscriptions = smallvec![];
|
||||
let mut tasks = smallvec![];
|
||||
|
||||
@@ -64,18 +70,16 @@ impl SetupRelay {
|
||||
|
||||
subscriptions.push(
|
||||
// Subscribe to user's input events
|
||||
cx.subscribe_in(
|
||||
&input,
|
||||
window,
|
||||
move |this: &mut Self, _, event, window, cx| {
|
||||
cx.subscribe_in(&input, window, move |this, _input, event, window, cx| {
|
||||
if let InputEvent::PressEnter { .. } = event {
|
||||
this.add(window, cx);
|
||||
}
|
||||
},
|
||||
),
|
||||
}),
|
||||
);
|
||||
|
||||
Self {
|
||||
name: "Update Messaging Relays".into(),
|
||||
focus_handle: cx.focus_handle(),
|
||||
input,
|
||||
relays: HashSet::new(),
|
||||
error: None,
|
||||
@@ -94,8 +98,7 @@ impl SetupRelay {
|
||||
.limit(1);
|
||||
|
||||
if let Some(event) = client.database().query(filter).await?.first_owned() {
|
||||
let urls = nip17::extract_owned_relay_list(event).collect();
|
||||
Ok(urls)
|
||||
Ok(nip17::extract_owned_relay_list(event).collect())
|
||||
} else {
|
||||
Err(anyhow!("Not found."))
|
||||
}
|
||||
@@ -133,10 +136,9 @@ impl SetupRelay {
|
||||
self.error = Some(error.into());
|
||||
cx.notify();
|
||||
|
||||
// Clear the error message after a delay
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
cx.background_executor().timer(Duration::from_secs(2)).await;
|
||||
|
||||
// Clear the error message after a delay
|
||||
this.update(cx, |this, cx| {
|
||||
this.error = None;
|
||||
cx.notify();
|
||||
@@ -148,11 +150,7 @@ impl SetupRelay {
|
||||
|
||||
pub fn set_relays(&mut self, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if self.relays.is_empty() {
|
||||
self.set_error(
|
||||
"You need to add at least 1 relay to receive messages from others.",
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
self.set_error("You need to add at least 1 relay", window, cx);
|
||||
return;
|
||||
};
|
||||
|
||||
@@ -160,7 +158,6 @@ impl SetupRelay {
|
||||
let client = nostr.read(cx).client();
|
||||
let public_key = nostr.read(cx).identity().read(cx).public_key();
|
||||
let write_relays = nostr.read(cx).write_relays(&public_key, cx);
|
||||
|
||||
let relays = self.relays.clone();
|
||||
|
||||
let task: Task<Result<(), Error>> = cx.background_spawn(async move {
|
||||
@@ -192,10 +189,7 @@ impl SetupRelay {
|
||||
cx.spawn_in(window, async move |this, cx| {
|
||||
match task.await {
|
||||
Ok(_) => {
|
||||
cx.update(|window, cx| {
|
||||
window.close_modal(cx);
|
||||
})
|
||||
.ok();
|
||||
// TODO
|
||||
}
|
||||
Err(e) => {
|
||||
this.update_in(cx, |this, window, cx| {
|
||||
@@ -219,7 +213,10 @@ impl SetupRelay {
|
||||
let mut items = Vec::new();
|
||||
|
||||
for ix in range {
|
||||
if let Some(url) = relays.iter().nth(ix) {
|
||||
let Some(url) = relays.iter().nth(ix) else {
|
||||
continue;
|
||||
};
|
||||
|
||||
items.push(
|
||||
div()
|
||||
.id(SharedString::from(url.to_string()))
|
||||
@@ -228,17 +225,15 @@ impl SetupRelay {
|
||||
.h_9()
|
||||
.py_0p5()
|
||||
.child(
|
||||
div()
|
||||
h_flex()
|
||||
.px_2()
|
||||
.h_full()
|
||||
.w_full()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.rounded(cx.theme().radius)
|
||||
.bg(cx.theme().elevated_surface_background)
|
||||
.text_xs()
|
||||
.child(SharedString::from(url.to_string()))
|
||||
.child(
|
||||
div().text_sm().child(SharedString::from(url.to_string())),
|
||||
)
|
||||
.child(
|
||||
Button::new("remove_{ix}")
|
||||
.icon(IconName::Close)
|
||||
@@ -256,39 +251,69 @@ impl SetupRelay {
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
items
|
||||
}),
|
||||
)
|
||||
.w_full()
|
||||
.min_h(px(200.))
|
||||
.h_full()
|
||||
}
|
||||
|
||||
fn render_empty(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render_empty(&mut self, _window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
h_flex()
|
||||
.mt_2()
|
||||
.h_20()
|
||||
.mb_2()
|
||||
.justify_center()
|
||||
.border_2()
|
||||
.border_dashed()
|
||||
.border_color(cx.theme().border)
|
||||
.rounded(cx.theme().radius_lg)
|
||||
.text_sm()
|
||||
.text_align(TextAlign::Center)
|
||||
.child(SharedString::from("Please add some relays."))
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for SetupRelay {
|
||||
impl Panel for MessagingRelayPanel {
|
||||
fn panel_id(&self) -> SharedString {
|
||||
self.name.clone()
|
||||
}
|
||||
|
||||
fn title(&self, _cx: &App) -> AnyElement {
|
||||
self.name.clone().into_any_element()
|
||||
}
|
||||
}
|
||||
|
||||
impl EventEmitter<PanelEvent> for MessagingRelayPanel {}
|
||||
|
||||
impl Focusable for MessagingRelayPanel {
|
||||
fn focus_handle(&self, _: &App) -> gpui::FocusHandle {
|
||||
self.focus_handle.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for MessagingRelayPanel {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
v_flex()
|
||||
.gap_3()
|
||||
.text_sm()
|
||||
.size_full()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.p_2()
|
||||
.gap_10()
|
||||
.child(
|
||||
div()
|
||||
.text_color(cx.theme().text_muted)
|
||||
.child(SharedString::from("In order to receive messages from others, you need to set up at least one Messaging Relay.")),
|
||||
.text_center()
|
||||
.font_semibold()
|
||||
.line_height(relative(1.25))
|
||||
.child(SharedString::from("Update Messaging Relays")),
|
||||
)
|
||||
.child(
|
||||
v_flex()
|
||||
.w_112()
|
||||
.gap_2()
|
||||
.text_sm()
|
||||
.child(
|
||||
v_flex()
|
||||
.gap_1p5()
|
||||
.child(
|
||||
h_flex()
|
||||
.gap_1()
|
||||
@@ -321,5 +346,15 @@ impl Render for SetupRelay {
|
||||
this.child(self.render_empty(window, cx))
|
||||
}
|
||||
})
|
||||
.child(divider(cx))
|
||||
.child(
|
||||
Button::new("submit")
|
||||
.label("Update")
|
||||
.primary()
|
||||
.on_click(cx.listener(move |this, _ev, window, cx| {
|
||||
this.set_relays(window, cx);
|
||||
})),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod connect;
|
||||
pub mod greeter;
|
||||
pub mod import;
|
||||
pub mod messaging_relays;
|
||||
pub mod profile;
|
||||
pub mod relay_list;
|
||||
|
||||
@@ -100,7 +100,7 @@ impl RelayListPanel {
|
||||
let public_key = signer.get_public_key().await?;
|
||||
|
||||
let filter = Filter::new()
|
||||
.kind(Kind::InboxRelays)
|
||||
.kind(Kind::RelayList)
|
||||
.author(public_key)
|
||||
.limit(1);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ use ui::context_menu::ContextMenuExt;
|
||||
use ui::modal::ModalButtonProps;
|
||||
use ui::{h_flex, StyledExt, WindowExtension};
|
||||
|
||||
use crate::views::screening;
|
||||
use crate::dialogs::screening;
|
||||
|
||||
#[derive(IntoElement)]
|
||||
pub struct RoomListItem {
|
||||
|
||||
@@ -25,7 +25,7 @@ use ui::input::{InputEvent, InputState, TextInput};
|
||||
use ui::{h_flex, v_flex, Icon, IconName, Sizable, StyledExt, WindowExtension};
|
||||
|
||||
use crate::actions::{RelayStatus, Reload};
|
||||
use crate::views::compose::compose_button;
|
||||
use crate::dialogs::compose::compose_button;
|
||||
|
||||
mod list_item;
|
||||
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
pub mod compose;
|
||||
pub mod preferences;
|
||||
pub mod screening;
|
||||
pub mod setup_relay;
|
||||
@@ -1,21 +0,0 @@
|
||||
use gpui::{div, App, AppContext, Context, Entity, IntoElement, Render, Window};
|
||||
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Preferences> {
|
||||
cx.new(|cx| Preferences::new(window, cx))
|
||||
}
|
||||
|
||||
pub struct Preferences {
|
||||
//
|
||||
}
|
||||
|
||||
impl Preferences {
|
||||
pub fn new(_window: &mut Window, _cx: &mut App) -> Self {
|
||||
Self {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Render for Preferences {
|
||||
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement {
|
||||
div()
|
||||
}
|
||||
}
|
||||
@@ -13,17 +13,14 @@ use gpui::{
|
||||
use nostr_connect::prelude::*;
|
||||
use person::PersonRegistry;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use theme::{ActiveTheme, Theme, ThemeMode, ThemeRegistry};
|
||||
use theme::{ActiveTheme, Theme, ThemeRegistry};
|
||||
use ui::button::{Button, ButtonVariants};
|
||||
use ui::modal::ModalButtonProps;
|
||||
use ui::{h_flex, v_flex, Root, Sizable, WindowExtension};
|
||||
|
||||
use crate::actions::{
|
||||
reset, DarkMode, KeyringPopup, Logout, Settings, Themes, ViewProfile, ViewRelays,
|
||||
};
|
||||
use crate::actions::{reset, KeyringPopup, Logout, Themes, ViewProfile};
|
||||
use crate::panels::greeter;
|
||||
use crate::user::viewer;
|
||||
use crate::views::{preferences, setup_relay};
|
||||
use crate::{sidebar, user};
|
||||
|
||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Workspace> {
|
||||
@@ -153,17 +150,6 @@ impl Workspace {
|
||||
});
|
||||
}
|
||||
|
||||
fn on_settings(&mut self, _ev: &Settings, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let view = preferences::init(window, cx);
|
||||
|
||||
window.open_modal(cx, move |modal, _window, _cx| {
|
||||
modal
|
||||
.title(SharedString::from("Preferences"))
|
||||
.width(px(520.))
|
||||
.child(view.clone())
|
||||
});
|
||||
}
|
||||
|
||||
fn on_profile(&mut self, _ev: &ViewProfile, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let view = user::init(window, cx);
|
||||
let entity = view.downgrade();
|
||||
@@ -211,38 +197,6 @@ impl Workspace {
|
||||
});
|
||||
}
|
||||
|
||||
fn on_relays(&mut self, _ev: &ViewRelays, window: &mut Window, cx: &mut Context<Self>) {
|
||||
let view = setup_relay::init(window, cx);
|
||||
let entity = view.downgrade();
|
||||
|
||||
window.open_modal(cx, move |this, _window, _cx| {
|
||||
let entity = entity.clone();
|
||||
|
||||
this.confirm()
|
||||
.title(SharedString::from("Set Up Messaging Relays"))
|
||||
.child(view.clone())
|
||||
.button_props(ModalButtonProps::default().ok_text("Update"))
|
||||
.on_ok(move |_, window, cx| {
|
||||
entity
|
||||
.update(cx, |this, cx| {
|
||||
this.set_relays(window, cx);
|
||||
})
|
||||
.ok();
|
||||
|
||||
// false to keep the modal open
|
||||
false
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
fn on_dark_mode(&mut self, _ev: &DarkMode, window: &mut Window, cx: &mut Context<Self>) {
|
||||
if cx.theme().mode.is_dark() {
|
||||
Theme::change(ThemeMode::Light, Some(window), cx);
|
||||
} else {
|
||||
Theme::change(ThemeMode::Dark, Some(window), cx);
|
||||
}
|
||||
}
|
||||
|
||||
fn on_themes(&mut self, _ev: &Themes, window: &mut Window, cx: &mut Context<Self>) {
|
||||
window.open_modal(cx, move |this, _window, cx| {
|
||||
let registry = ThemeRegistry::global(cx);
|
||||
@@ -365,10 +319,7 @@ impl Render for Workspace {
|
||||
|
||||
div()
|
||||
.id(SharedString::from("workspace"))
|
||||
.on_action(cx.listener(Self::on_settings))
|
||||
.on_action(cx.listener(Self::on_profile))
|
||||
.on_action(cx.listener(Self::on_relays))
|
||||
.on_action(cx.listener(Self::on_dark_mode))
|
||||
.on_action(cx.listener(Self::on_themes))
|
||||
.on_action(cx.listener(Self::on_sign_out))
|
||||
.on_action(cx.listener(Self::on_open_pubkey))
|
||||
|
||||
@@ -488,6 +488,18 @@ impl NostrRegistry {
|
||||
match res {
|
||||
Ok(event) => {
|
||||
log::info!("Received relay list event: {event:?}");
|
||||
|
||||
// Construct a filter to continuously receive relay list events
|
||||
let filter = Filter::new()
|
||||
.kind(Kind::RelayList)
|
||||
.author(public_key)
|
||||
.since(Timestamp::now());
|
||||
|
||||
// Subscribe to the relay list events
|
||||
client
|
||||
.subscribe_to(BOOTSTRAP_RELAYS, vec![filter], None)
|
||||
.await?;
|
||||
|
||||
return Ok(RelayState::Set);
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -578,13 +590,23 @@ impl NostrRegistry {
|
||||
|
||||
// Stream events from the write relays
|
||||
let mut stream = client
|
||||
.stream_events_from(urls, vec![filter], Duration::from_secs(TIMEOUT))
|
||||
.stream_events_from(&urls, vec![filter], Duration::from_secs(TIMEOUT))
|
||||
.await?;
|
||||
|
||||
while let Some((_url, res)) = stream.next().await {
|
||||
match res {
|
||||
Ok(event) => {
|
||||
log::info!("Received messaging relays event: {event:?}");
|
||||
|
||||
// Construct a filter to continuously receive relay list events
|
||||
let filter = Filter::new()
|
||||
.kind(Kind::InboxRelays)
|
||||
.author(public_key)
|
||||
.since(Timestamp::now());
|
||||
|
||||
// Subscribe to the relay list events
|
||||
client.subscribe_to(&urls, vec![filter], None).await?;
|
||||
|
||||
return Ok(RelayState::Set);
|
||||
}
|
||||
Err(e) => {
|
||||
|
||||
Reference in New Issue
Block a user