diff --git a/cbd-web/src/app.rs b/cbd-web/src/app.rs index 61c6ff9..2db02bc 100644 --- a/cbd-web/src/app.rs +++ b/cbd-web/src/app.rs @@ -80,6 +80,9 @@ struct Store { /// Set once the proactive "auth is enabled" prompt has been shown, so /// stream reconnects do not re-open it after the user dismissed it. login_prompted: RwSignal, + /// Whether the server has auth configured (from `Init.auth_enabled`), + /// so the top bar can offer a login only where it is meaningful. + auth_enabled: RwSignal, queue: RwSignal>, queue_pos: RwSignal, resolving: RwSignal, @@ -110,6 +113,7 @@ impl Store { needs_login: RwSignal::new(false), guest_ok: RwSignal::new(false), login_prompted: RwSignal::new(false), + auth_enabled: RwSignal::new(false), queue: RwSignal::new(Vec::new()), queue_pos: RwSignal::new(0), resolving: RwSignal::new(false), @@ -530,10 +534,12 @@ fn run_stream(store: Store) { store.apply(StreamUpdate::Position(position)); } // We connected — as the unauthenticated fallback - // role if we sent no credentials. When the server - // has auth configured and the user has none stored, - // offer a login once, but let them dismiss it to - // stay on the fallback role. + // role if we sent no credentials. Record whether + // the server has auth at all (drives the top-bar + // login button), then, when it does and the user + // has none stored, offer a login once — dismissible + // so they can stay on the fallback role. + store.auth_enabled.set(init.auth_enabled); let no_stored_creds = load_pref("user").unwrap_or_default().is_empty(); if init.auth_enabled && no_stored_creds @@ -666,6 +672,47 @@ fn TopBar(store: Store) -> impl IntoView { {move || if store.connected.get() { "" } else { "disconnected — reconnecting…" }} + {move || { + // A login is only meaningful where the server has auth + // (offer "log in"); once credentials are stored, offer + // "log out" to drop back to the guest/fallback role. + let logged_in = !load_pref("user").unwrap_or_default().is_empty(); + (store.auth_enabled.get() || logged_in) + .then(|| { + if logged_in { + view! { + + } + .into_any() + } else { + view! { + + } + .into_any() + } + }) + }}