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)
After (Fix)
**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()
+ })),
)
}