Add multi-workspace support to desktop app#409
Merged
Conversation
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>
Collaborator
Author
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>
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)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
apply_workspaceTauri command allows runtime relay reconfiguration without app restart (reloads when active workspace's relay URL or token changes)apply_workspace/get_nsec/get_default_relay_urlbridge mocksNotable details
normalizeRelayUrlandderiveWorkspaceNameextracted to sharedworkspaceStorage.ts— used by WelcomeSetup, AddWorkspaceDialog, and EditWorkspaceDialogonCloseAutoFocuspreventDefault on dropdown→dialog transitions matches existing codebase patternNits from review (not addressed)
Test plan
pnpm tsc --noEmitpasses cleanws://localhost:3000connects to local dev relay🤖 Generated with Claude Code