feat(Windows): #2998, add 'signing in' state to system tray menu (#3157)

Depends on the new auth flow in #3147 

I couldn't find the UI mockups so I just modified the "Sign In" menu to
create this.
This commit is contained in:
Reactor Scram
2024-01-16 11:08:40 -06:00
committed by GitHub
parent ddf10cd502
commit d5f09ab342
3 changed files with 53 additions and 18 deletions

View File

@@ -86,6 +86,7 @@ impl Auth {
Ok(this)
}
/// Returns the session iff we are signed in.
pub fn session(&self) -> Option<&Session> {
match &self.state {
State::SignedIn(x) => Some(x),
@@ -175,7 +176,7 @@ impl Auth {
Ok(keyring::Entry::new_with_target(self.keyring_key, "", "")?)
}
fn ongoing_request(&self) -> Result<&Request> {
pub fn ongoing_request(&self) -> Result<&Request> {
match &self.state {
State::NeedResponse(x) => Ok(x),
_ => Err(Error::NoInflightRequest),

View File

@@ -295,7 +295,7 @@ struct Controller {
/// Debugging-only settings like API URL, auth URL, log filter
advanced_settings: AdvancedSettings,
app: tauri::AppHandle,
// Sign-in state
// Sign-in state with the portal / deep links
auth: client::auth::Auth,
ctlr_tx: CtlrTx,
/// connlib session for the currently signed-in user, if there is one
@@ -307,6 +307,7 @@ struct Controller {
logging_handles: client::logging::Handles,
/// Tells us when to wake up and look for a new resource list. Tokio docs say that memory reads and writes are synchronized when notifying, so we don't need an extra mutex on the resources.
notify_controller: Arc<Notify>,
tunnel_ready: bool,
}
/// Everything related to a signed-in user session
@@ -335,6 +336,7 @@ impl Controller {
log_counting_task: None,
logging_handles,
notify_controller,
tunnel_ready: false,
};
if let Some(token) = this.auth.token()? {
@@ -411,21 +413,38 @@ impl Controller {
Ok(())
}
fn reload_resource_list(&mut self) -> Result<()> {
let Some(session) = &self.session else {
tracing::warn!("got notified to update resources but there is no session");
return Ok(());
};
let resources = session.callback_handler.resources.load();
let actor_name = &self
.auth
.session()
.ok_or_else(|| anyhow!("connlib is signed in but auth module isn't"))?
.actor_name;
self.app
/// Returns a new system tray menu
fn build_system_tray_menu(&self) -> tauri::SystemTrayMenu {
// TODO: Refactor this and the auth module so that "Are we logged in"
// doesn't require such complicated control flow to answer.
if let Some(auth_session) = self.auth.session() {
if let Some(connlib_session) = &self.session {
if self.tunnel_ready {
// Signed in, tunnel ready
let resources = connlib_session.callback_handler.resources.load();
system_tray_menu::signed_in(&auth_session.actor_name, &resources)
} else {
// Signed in, raising tunnel
system_tray_menu::signing_in()
}
} else {
tracing::error!("We have an auth session but no connlib session");
system_tray_menu::signed_out()
}
} else if self.auth.ongoing_request().is_ok() {
// Signing in, waiting on deep link callback
system_tray_menu::signing_in()
} else {
system_tray_menu::signed_out()
}
}
/// Builds a new system tray menu and applies it to the app
fn refresh_system_tray_menu(&self) -> Result<()> {
Ok(self
.app
.tray_handle()
.set_menu(system_tray_menu::signed_in(actor_name, &resources))?;
Ok(())
.set_menu(self.build_system_tray_menu())?)
}
}
@@ -450,7 +469,7 @@ async fn run_controller(
loop {
tokio::select! {
() = controller.notify_controller.notified() => if let Err(e) = controller.reload_resource_list() {
() = controller.notify_controller.notified() => if let Err(e) = controller.refresh_system_tray_menu() {
tracing::error!("couldn't reload resource list: {e:#?}");
},
req = rx.recv() => {
@@ -463,6 +482,7 @@ async fn run_controller(
}
Req::Disconnected => {
tracing::debug!("connlib disconnected, tearing down Session");
controller.tunnel_ready = false;
if let Some(mut session) = controller.session.take() {
tracing::debug!("disconnecting connlib");
session.connlib.disconnect(None);
@@ -478,6 +498,7 @@ async fn run_controller(
Req::SignIn => {
if let Some(req) = controller.auth.start_sign_in()? {
let url = req.to_url(&controller.advanced_settings.auth_base_url);
controller.refresh_system_tray_menu()?;
tauri::api::shell::open(
&app.shell_scope(),
&url.expose_secret().inner,
@@ -487,6 +508,7 @@ async fn run_controller(
}
Req::SignOut => {
controller.auth.sign_out()?;
controller.tunnel_ready = false;
if let Some(mut session) = controller.session.take() {
tracing::debug!("disconnecting connlib");
session.connlib.disconnect(None);
@@ -494,7 +516,7 @@ async fn run_controller(
else {
tracing::error!("tried to sign out but there's no session");
}
app.tray_handle().set_menu(system_tray_menu::signed_out())?;
controller.refresh_system_tray_menu()?;
}
Req::StartStopLogCounting(enable) => {
if enable {
@@ -510,6 +532,8 @@ async fn run_controller(
}
}
Req::TunnelReady => {
controller.tunnel_ready = true;
// May say "Windows Powershell" in dev mode
// See https://github.com/tauri-apps/tauri/issues/3700
Notification::new(&controller.app.config().tauri.bundle.identifier)

View File

@@ -66,6 +66,16 @@ pub(crate) fn signed_in(user_name: &str, resources: &[ResourceDescription]) -> S
menu
}
pub(crate) fn signing_in() -> SystemTrayMenu {
// TODO: Check this layout with Jamil, I lost track of the Figma for it.
SystemTrayMenu::new()
.add_item(CustomMenuItem::new("".to_string(), "Signing In...").disabled())
.add_native_item(SystemTrayMenuItem::Separator)
.add_item(CustomMenuItem::new("/about".to_string(), "About"))
.add_item(CustomMenuItem::new("/settings".to_string(), "Settings"))
.add_item(CustomMenuItem::new("/quit".to_string(), "Quit Firezone").accelerator("Ctrl+Q"))
}
pub(crate) fn signed_out() -> SystemTrayMenu {
SystemTrayMenu::new()
.add_item(CustomMenuItem::new("/sign_in".to_string(), "Sign In"))