chore: Improve Auto Login (#71)
* improve auto login * add auto login status * add reset button on startup
This commit is contained in:
@@ -22,8 +22,6 @@ use ui::notification::Notification;
|
|||||||
use ui::popup_menu::PopupMenu;
|
use ui::popup_menu::PopupMenu;
|
||||||
use ui::{ContextModal, Disableable, Sizable, StyledExt};
|
use ui::{ContextModal, Disableable, Sizable, StyledExt};
|
||||||
|
|
||||||
const TIMEOUT: u64 = 30;
|
|
||||||
|
|
||||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Login> {
|
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Login> {
|
||||||
Login::new(window, cx)
|
Login::new(window, cx)
|
||||||
}
|
}
|
||||||
@@ -348,7 +346,7 @@ impl Login {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let client_keys = ClientKeys::get_global(cx).keys();
|
let client_keys = ClientKeys::get_global(cx).keys();
|
||||||
let timeout = Duration::from_secs(TIMEOUT);
|
let timeout = Duration::from_secs(NOSTR_CONNECT_TIMEOUT / 8);
|
||||||
// .unwrap() is fine here because there's no error handling for bunker uri
|
// .unwrap() is fine here because there's no error handling for bunker uri
|
||||||
let mut signer = NostrConnect::new(uri, client_keys, timeout, None).unwrap();
|
let mut signer = NostrConnect::new(uri, client_keys, timeout, None).unwrap();
|
||||||
// Handle auth url with the default browser
|
// Handle auth url with the default browser
|
||||||
@@ -356,7 +354,7 @@ impl Login {
|
|||||||
|
|
||||||
// Start countdown
|
// Start countdown
|
||||||
cx.spawn_in(window, async move |this, cx| {
|
cx.spawn_in(window, async move |this, cx| {
|
||||||
for i in (0..=TIMEOUT).rev() {
|
for i in (0..=NOSTR_CONNECT_TIMEOUT / 8).rev() {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
this.set_countdown(None, cx);
|
this.set_countdown(None, cx);
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
|
use gpui::prelude::FluentBuilder;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, svg, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
div, svg, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
|
||||||
IntoElement, ParentElement, Render, SharedString, Styled, Window,
|
IntoElement, ParentElement, Render, SharedString, Styled, Window,
|
||||||
};
|
};
|
||||||
|
use identity::Identity;
|
||||||
use theme::ActiveTheme;
|
use theme::ActiveTheme;
|
||||||
use ui::button::Button;
|
use ui::button::{Button, ButtonVariants};
|
||||||
use ui::dock_area::panel::{Panel, PanelEvent};
|
use ui::dock_area::panel::{Panel, PanelEvent};
|
||||||
use ui::indicator::Indicator;
|
use ui::indicator::Indicator;
|
||||||
use ui::popup_menu::PopupMenu;
|
use ui::popup_menu::PopupMenu;
|
||||||
use ui::Sizable;
|
use ui::{Sizable, StyledExt};
|
||||||
|
|
||||||
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Startup> {
|
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Startup> {
|
||||||
Startup::new(window, cx)
|
Startup::new(window, cx)
|
||||||
@@ -55,7 +57,11 @@ impl Focusable for Startup {
|
|||||||
|
|
||||||
impl Render for Startup {
|
impl Render for Startup {
|
||||||
fn render(&mut self, _window: &mut gpui::Window, cx: &mut Context<Self>) -> impl IntoElement {
|
fn render(&mut self, _window: &mut gpui::Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||||
|
let identity = Identity::global(cx);
|
||||||
|
let logging_in = identity.read(cx).logging_in();
|
||||||
|
|
||||||
div()
|
div()
|
||||||
|
.relative()
|
||||||
.size_full()
|
.size_full()
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
@@ -80,8 +86,46 @@ impl Render for Startup {
|
|||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.justify_center()
|
.justify_center()
|
||||||
|
.gap_2()
|
||||||
|
.when(logging_in, |this| {
|
||||||
|
this.child(
|
||||||
|
div()
|
||||||
|
.text_sm()
|
||||||
|
.text_color(cx.theme().text)
|
||||||
|
.child("Auto login in progress"),
|
||||||
|
)
|
||||||
|
})
|
||||||
.child(Indicator::new().small()),
|
.child(Indicator::new().small()),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
.child(
|
||||||
|
div().absolute().bottom_3().right_3().child(
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.justify_end()
|
||||||
|
.gap_1p5()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.font_semibold()
|
||||||
|
.text_color(cx.theme().text_muted)
|
||||||
|
.child("Stuck?"),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
Button::new("reset")
|
||||||
|
.label("Reset")
|
||||||
|
.small()
|
||||||
|
.ghost()
|
||||||
|
.on_click(|_, window, cx| {
|
||||||
|
Identity::global(cx).update(cx, |this, cx| {
|
||||||
|
this.unload(window, cx);
|
||||||
|
// Restart application
|
||||||
|
cx.restart(None);
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ impl Global for GlobalIdentity {}
|
|||||||
|
|
||||||
pub struct Identity {
|
pub struct Identity {
|
||||||
profile: Option<Profile>,
|
profile: Option<Profile>,
|
||||||
|
auto_logging_in_progress: bool,
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
subscriptions: SmallVec<[Subscription; 1]>,
|
subscriptions: SmallVec<[Subscription; 1]>,
|
||||||
}
|
}
|
||||||
@@ -62,6 +63,7 @@ impl Identity {
|
|||||||
|
|
||||||
// Skip auto login if the user hasn't enabled auto login
|
// Skip auto login if the user hasn't enabled auto login
|
||||||
if has_client_keys && auto_login {
|
if has_client_keys && auto_login {
|
||||||
|
this.set_logging_in(true, cx);
|
||||||
this.load(window, cx);
|
this.load(window, cx);
|
||||||
} else {
|
} else {
|
||||||
this.set_profile(None, cx);
|
this.set_profile(None, cx);
|
||||||
@@ -71,6 +73,7 @@ impl Identity {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
profile: None,
|
profile: None,
|
||||||
|
auto_logging_in_progress: false,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,32 +170,24 @@ impl Identity {
|
|||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) {
|
) {
|
||||||
let timeout = Duration::from_secs(NOSTR_CONNECT_TIMEOUT);
|
let timeout = Duration::from_secs(NOSTR_CONNECT_TIMEOUT / 10);
|
||||||
let client_keys = ClientKeys::get_global(cx).keys();
|
let client_keys = ClientKeys::get_global(cx).keys();
|
||||||
|
|
||||||
let Ok(mut signer) = NostrConnect::new(uri, client_keys, timeout, None) else {
|
let Ok(mut signer) = NostrConnect::new(uri, client_keys, timeout, None) else {
|
||||||
window.push_notification(Notification::error("Bunker URI is invalid"), cx);
|
window.push_notification(
|
||||||
|
Notification::error("Bunker URI is invalid").title("Nostr Connect"),
|
||||||
|
cx,
|
||||||
|
);
|
||||||
self.set_profile(None, cx);
|
self.set_profile(None, cx);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
// Automatically open auth url
|
// Automatically open auth url
|
||||||
signer.auth_url_handler(CoopAuthUrlHandler);
|
signer.auth_url_handler(CoopAuthUrlHandler);
|
||||||
|
|
||||||
let (tx, rx) = oneshot::channel::<Option<NostrConnect>>();
|
|
||||||
|
|
||||||
// Verify the signer, make sure Remote Signer is connected
|
|
||||||
cx.background_spawn(async move {
|
|
||||||
if signer.bunker_uri().await.is_ok() {
|
|
||||||
tx.send(Some(signer)).ok();
|
|
||||||
} else {
|
|
||||||
tx.send(None).ok();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.detach();
|
|
||||||
|
|
||||||
cx.spawn_in(window, async move |this, cx| {
|
cx.spawn_in(window, async move |this, cx| {
|
||||||
match rx.await {
|
// Call .bunker_uri() to verify the connection
|
||||||
Ok(Some(signer)) => {
|
match signer.bunker_uri().await {
|
||||||
|
Ok(_) => {
|
||||||
cx.update(|window, cx| {
|
cx.update(|window, cx| {
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
this.set_signer(signer, window, cx);
|
this.set_signer(signer, window, cx);
|
||||||
@@ -201,10 +196,10 @@ impl Identity {
|
|||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
_ => {
|
Err(e) => {
|
||||||
cx.update(|window, cx| {
|
cx.update(|window, cx| {
|
||||||
window.push_notification(
|
window.push_notification(
|
||||||
Notification::error("Failed to connect to the remote signer"),
|
Notification::error(e.to_string()).title("Nostr Connect"),
|
||||||
cx,
|
cx,
|
||||||
);
|
);
|
||||||
this.update(cx, |this, cx| {
|
this.update(cx, |this, cx| {
|
||||||
@@ -512,4 +507,13 @@ impl Identity {
|
|||||||
pub fn has_profile(&self) -> bool {
|
pub fn has_profile(&self) -> bool {
|
||||||
self.profile.is_some()
|
self.profile.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn logging_in(&self) -> bool {
|
||||||
|
self.auto_logging_in_progress
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn set_logging_in(&mut self, status: bool, cx: &mut Context<Self>) {
|
||||||
|
self.auto_logging_in_progress = status;
|
||||||
|
cx.notify();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user