chore: Improve Auto Login (#71)

* improve auto login

* add auto login status

* add reset button on startup
This commit is contained in:
reya
2025-06-29 08:01:08 +07:00
committed by GitHub
parent 2dfb48b538
commit b212095334
3 changed files with 70 additions and 24 deletions

View File

@@ -22,8 +22,6 @@ use ui::notification::Notification;
use ui::popup_menu::PopupMenu;
use ui::{ContextModal, Disableable, Sizable, StyledExt};
const TIMEOUT: u64 = 30;
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Login> {
Login::new(window, cx)
}
@@ -348,7 +346,7 @@ impl Login {
};
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
let mut signer = NostrConnect::new(uri, client_keys, timeout, None).unwrap();
// Handle auth url with the default browser
@@ -356,7 +354,7 @@ impl Login {
// Start countdown
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 {
this.update(cx, |this, cx| {
this.set_countdown(None, cx);

View File

@@ -1,13 +1,15 @@
use gpui::prelude::FluentBuilder;
use gpui::{
div, svg, AnyElement, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable,
IntoElement, ParentElement, Render, SharedString, Styled, Window,
};
use identity::Identity;
use theme::ActiveTheme;
use ui::button::Button;
use ui::button::{Button, ButtonVariants};
use ui::dock_area::panel::{Panel, PanelEvent};
use ui::indicator::Indicator;
use ui::popup_menu::PopupMenu;
use ui::Sizable;
use ui::{Sizable, StyledExt};
pub fn init(window: &mut Window, cx: &mut App) -> Entity<Startup> {
Startup::new(window, cx)
@@ -55,7 +57,11 @@ impl Focusable for Startup {
impl Render for Startup {
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()
.relative()
.size_full()
.flex()
.items_center()
@@ -80,8 +86,46 @@ impl Render for Startup {
.flex()
.items_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(
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);
});
}),
),
),
)
}
}

View File

@@ -31,6 +31,7 @@ impl Global for GlobalIdentity {}
pub struct Identity {
profile: Option<Profile>,
auto_logging_in_progress: bool,
#[allow(dead_code)]
subscriptions: SmallVec<[Subscription; 1]>,
}
@@ -62,6 +63,7 @@ impl Identity {
// Skip auto login if the user hasn't enabled auto login
if has_client_keys && auto_login {
this.set_logging_in(true, cx);
this.load(window, cx);
} else {
this.set_profile(None, cx);
@@ -71,6 +73,7 @@ impl Identity {
Self {
profile: None,
auto_logging_in_progress: false,
subscriptions,
}
}
@@ -167,32 +170,24 @@ impl Identity {
window: &mut Window,
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 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);
return;
};
// Automatically open auth url
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| {
match rx.await {
Ok(Some(signer)) => {
// Call .bunker_uri() to verify the connection
match signer.bunker_uri().await {
Ok(_) => {
cx.update(|window, cx| {
this.update(cx, |this, cx| {
this.set_signer(signer, window, cx);
@@ -201,10 +196,10 @@ impl Identity {
})
.ok();
}
_ => {
Err(e) => {
cx.update(|window, cx| {
window.push_notification(
Notification::error("Failed to connect to the remote signer"),
Notification::error(e.to_string()).title("Nostr Connect"),
cx,
);
this.update(cx, |this, cx| {
@@ -512,4 +507,13 @@ impl Identity {
pub fn has_profile(&self) -> bool {
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();
}
}