From 15d8660748b508b3525d3403e5d172f1a557bfa5 Mon Sep 17 00:00:00 2001 From: Jose Garcia <47431411+ruxwez@users.noreply.github.com> Date: Thu, 26 Mar 2026 12:37:35 +0000 Subject: [PATCH] collab_ui: Fix "lost session" visual bug in Collab Panel (#52486) ## Context This PR fixes a UX issue ("visual bug") in the collaboration panel documented in issue [#51800](https://github.com/zed-industries/zed/issues/51800), where users who had already signed in were still seeing the "Sign In" screen after restarting the editor. As I mentioned in my response there ([Link to comment #4132366441](https://github.com/zed-industries/zed/issues/51800#issuecomment-4132366441)), I have investigated the problem thoroughly and found that the session is not actually lost. What I discovered is that in Zed, only "staff" users automatically connect to the collaboration servers when opening the editor (by design, this logic is in `crates/client/src/client.rs` starting at line `962`). Therefore, regular users keep their saved session and `Authenticated` status, but since they don't automatically connect upon startup, the UI didn't detect this correctly. It erroneously showed the GitHub account request and the "Sign in to enable collaboration" text, giving the false impression that the user had been logged out. ### Screenshots Before (Bug) image After (Fix) image **Note:** This PR specifically addresses the visual issue in the **Collab Panel**. Similar behaviors might exist in other parts of the editor, but this change focuses on correcting the collaboration interface. This current PR: 1. Improves the `render_signed_out` function in `crates/collab_ui/src/collab_panel.rs`. 2. Simplifies the connection check using `self.client.user_id().is_some()`, which is more robust against volatile network states and perfectly covers connection transitions. 3. During rendering, it detects existing credentials and shows the correct message "Connect" / "Connecting...", replacing the GitHub icon with the appropriate network icon (`SignalHigh`). ## How to Review - Review the cleaner and simplified code in `crates/collab_ui/src/collab_panel.rs:render_signed_out`. - Verify that instead of verbose validations on the `Status` enum, simply checking the user ID correctly captures any subsequent subtype, properly differentiating between account authorization and a simple network reconnection. ## Self-Review Checklist - [x] I've reviewed my own diff for quality, security, and reliability - [x] Unsafe blocks (if any) have justifying comments - [x] The content is consistent with the [UI/UX checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist) - [x] Tests cover the new/changed behavior - [x] Performance impact has been considered and is acceptable Release Notes: - Fixed an issue (#51800) in the Collab Panel where the UI appeared to log users out. Implemented improvements to properly differentiate between "Sign In" and "Connect," avoiding false authentication prompts when users are already logged in but not automatically connected to the servers. --------- Co-authored-by: Danilo Leal --- crates/collab_ui/src/collab_panel.rs | 77 ++++++++++++++++------------ 1 file changed, 44 insertions(+), 33 deletions(-) diff --git a/crates/collab_ui/src/collab_panel.rs b/crates/collab_ui/src/collab_panel.rs index 3c32e76fea6dcd64b2a8b74c565544954af28c44..392e2340f14c5b633bcd9a0a8128d9423aed6a22 100644 --- a/crates/collab_ui/src/collab_panel.rs +++ b/crates/collab_ui/src/collab_panel.rs @@ -2340,46 +2340,57 @@ impl CollabPanel { fn render_signed_out(&mut self, cx: &mut Context) -> Div { let collab_blurb = "Work with your team in realtime with collaborative editing, voice, shared notes and more."; - let is_signing_in = self.client.status().borrow().is_signing_in(); - let button_label = if is_signing_in { - "Signing in…" + + // Two distinct "not connected" states: + // - Authenticated (has credentials): user just needs to connect. + // - Unauthenticated (no credentials): user needs to sign in via GitHub. + let is_authenticated = self.client.user_id().is_some(); + let status = *self.client.status().borrow(); + let is_busy = status.is_signing_in(); + + let (button_id, button_label, button_icon) = if is_authenticated { + ( + "connect", + if is_busy { "Connecting…" } else { "Connect" }, + IconName::Public, + ) } else { - "Sign in" + ( + "sign_in", + if is_busy { + "Signing in…" + } else { + "Sign In with GitHub" + }, + IconName::Github, + ) }; v_flex() - .gap_6() .p_4() + .gap_4() + .size_full() + .text_center() + .justify_center() .child(Label::new(collab_blurb)) .child( - v_flex() - .gap_2() - .child( - Button::new("sign_in", button_label) - .start_icon(Icon::new(IconName::Github).color(Color::Muted)) - .style(ButtonStyle::Filled) - .full_width() - .disabled(is_signing_in) - .on_click(cx.listener(|this, _, window, cx| { - let client = this.client.clone(); - let workspace = this.workspace.clone(); - cx.spawn_in(window, async move |_, mut cx| { - client - .connect(true, &mut cx) - .await - .into_response() - .notify_workspace_async_err(workspace, &mut cx); - }) - .detach() - })), - ) - .child( - v_flex().w_full().items_center().child( - Label::new("Sign in to enable collaboration.") - .color(Color::Muted) - .size(LabelSize::Small), - ), - ), + Button::new(button_id, button_label) + .full_width() + .start_icon(Icon::new(button_icon).color(Color::Muted)) + .style(ButtonStyle::Outlined) + .disabled(is_busy) + .on_click(cx.listener(|this, _, window, cx| { + let client = this.client.clone(); + let workspace = this.workspace.clone(); + cx.spawn_in(window, async move |_, mut cx| { + client + .connect(true, &mut cx) + .await + .into_response() + .notify_workspace_async_err(workspace, &mut cx); + }) + .detach() + })), ) }