Skip to content

Add multi-workspace support to desktop app#409

Merged
wesbillman merged 8 commits into
mainfrom
desktop-workspaces
Apr 28, 2026
Merged

Add multi-workspace support to desktop app#409
wesbillman merged 8 commits into
mainfrom
desktop-workspaces

Conversation

@wesbillman
Copy link
Copy Markdown
Collaborator

@wesbillman wesbillman commented Apr 27, 2026

Summary

  • Adds multi-workspace support: users can connect to multiple Sprout relays and switch between them via a workspace switcher in the sidebar
  • First-run welcome flow (WelcomeSetup) guides new users through initial workspace configuration with relay URL, name auto-derivation, and optional nsec/token
  • Workspace edit UX: 3-dot menu per workspace opens an EditWorkspaceDialog for name/relay URL changes, with in-dialog workspace removal
  • Backend apply_workspace Tauri command allows runtime relay reconfiguration without app restart (reloads when active workspace's relay URL or token changes)
  • E2E test infrastructure updated: workspace seeding in test helpers, apply_workspace / get_nsec / get_default_relay_url bridge mocks

Notable details

  • normalizeRelayUrl and deriveWorkspaceName extracted to shared workspaceStorage.ts — used by WelcomeSetup, AddWorkspaceDialog, and EditWorkspaceDialog
  • Duplicate relay URL prevention on both add and edit paths
  • Token edit on active workspace correctly triggers reload (backend only applies token at init)
  • Focus management: onCloseAutoFocus preventDefault on dropdown→dialog transitions matches existing codebase pattern

Nits from review (not addressed)

  • No confirmation dialog on workspace removal — consistent with the existing inline trash button behavior, but worth considering for a follow-up

Test plan

  • pnpm tsc --noEmit passes clean
  • All pre-commit hooks pass (biome, cargo fmt, clippy, dart format, flutter analyze)
  • All pre-push hooks pass (rust tests, mobile tests, desktop build, tauri check)
  • Manual: create workspace via "+" button, verify relay connection
  • Manual: edit workspace name/URL via 3-dot menu, verify changes persist
  • Manual: remove non-active workspace, verify switcher updates
  • Manual: edit active workspace's relay URL, verify page reload
  • Manual: fresh install shows WelcomeSetup flow
  • Manual: ws://localhost:3000 connects to local dev relay

🤖 Generated with Claude Code

wesbillman and others added 7 commits April 27, 2026 14:31
Adds workspace switching, creation, renaming, and removal to the desktop
app, mirroring the mobile implementation. Each workspace represents a
separate relay connection with its own identity and optional API token.

Frontend: localStorage-based workspace storage with legacy single-workspace
migration, React hooks for state management, WorkspaceSwitcher dropdown in
the sidebar, and AddWorkspaceDialog. Workspace switching triggers a full
page reload to avoid partial state bugs.

Backend: New apply_workspace Tauri command sets relay URL override, identity
keys, and session token. Relay URL resolution functions now check the
workspace override before falling back to env vars and compile-time defaults.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- B1: Convert all relay URL callers to workspace-aware _with_override
  variants (events, huddle, tokens, media, pairing, agents, proxy)
- B2: Add session_token fallback to build_authed_request and submit_event
  so workspace API tokens are used for auth
- B3: Validate nsec before mutating any state in apply_workspace to
  prevent partial state on parse failure
- C1: Fix misleading nsec field label (was "generates new if blank")
- C2: Fix dedup add+switch ID mismatch — addWorkspace now returns the
  resolved ID so switchWorkspace uses the correct workspace
- C3: Guard removeWorkspace against removing the last workspace
- C4: Fix relay URL precedence — workspace override now wins over env
  vars in relay_api_base_url_with_override

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Extract shared workspace_relay_override() in relay.rs
- Deduplicate deriveWorkspaceName between storage and dialog
- Remove unused setWorkspaces/setActiveWorkspaceId from useWorkspaces

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
ReturnType<typeof setTimeout> resolves to Node's Timeout type, but
window.setTimeout returns number in browser environments. Use number
directly since this is a Tauri/browser app.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
First-run: Remove auto-migration that silently created workspaces.
New users now see a WelcomeSetup screen with smart defaults
(internal builds get one-click staging connect, OSS gets editable URL).

Workspace UX: Replace broken inline rename (hover-dependent pencil icon)
with a 3-dot menu that opens an EditWorkspaceDialog for editing name,
relay URL, and API token. Move workspace switcher to top of sidebar.
Replace letter avatar with seedling emoji placeholder.

Also fixes pre-existing biome lint errors in ForumComposer/ForumThreadPanel.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…L dedup

BLOCK 1: Token edit on active workspace now triggers reload so the
backend picks up the new session token via apply_workspace on init.

BLOCK 2: E2E bridge seeds a default workspace in localStorage so
tests don't land on WelcomeSetup. Also adds apply_workspace no-op
mock to e2eBridge.

CHANGE 3: Add onCloseAutoFocus={(e) => e.preventDefault()} to
WorkspaceSwitcher dropdown to prevent focus race with Edit dialog.

CHANGE 4: updateWorkspace now rejects relay URL changes that would
duplicate an existing workspace's relay URL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…avatar

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wesbillman wesbillman changed the title feat(desktop): Add multi-workspace support Add multi-workspace support to desktop app Apr 28, 2026
@wesbillman
Copy link
Copy Markdown
Collaborator Author

Screenshot 2026-04-27 at 5 54 07 PM Screenshot 2026-04-27 at 5 54 11 PM

@wesbillman wesbillman enabled auto-merge (squash) April 28, 2026 00:56
skipOnboardingSeed was also skipping seedDefaultWorkspace(), causing
useWorkspaceInit to show WelcomeSetup instead of the onboarding flow.
The flag should only control onboarding completion seeding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@wesbillman wesbillman merged commit a9024c2 into main Apr 28, 2026
13 checks passed
@wesbillman wesbillman deleted the desktop-workspaces branch April 28, 2026 04:47
tlongwell-block added a commit that referenced this pull request Apr 28, 2026
* origin/main:
  Add multi-workspace support to desktop app (#409)
  feat(mobile): add #channel autocomplete to compose bar (#411)
  fix: close race window that dropped active channel messages (#410)
  feat(pulse): rich text editor with @mentions, media uploads, and formatting (#407)
  feat(mobile): multi-workspace support (#408)
  feat: always notify on DM messages like Slack/Discord (#405)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant