Skip to content

feat: add stop all controls#2768

Open
janburzinski wants to merge 5 commits into
mainfrom
emdash/stop-all-servers-z7iva
Open

feat: add stop all controls#2768
janburzinski wants to merge 5 commits into
mainfrom
emdash/stop-all-servers-z7iva

Conversation

@janburzinski

@janburzinski janburzinski commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Description

adds the ability to see and stop preview servers beyond a single pill.

  • adds a global "stop all servers" to the connection settings
  • settings -> connections card listing every server across all projects/tasks

Screenshot/Recording (if applicable)

https://cap.link/0xmcmymtrcdwfkb

Checklist
  • I kept this PR small and focused
  • I ran a self-review before opening this PR
  • I ran the relevant local checks or explained why not
  • I updated docs when behavior or setup changed
  • I added or updated tests when behavior changed, or explained why not
  • I only added comments where the logic is not obvious
  • I used Conventional Commits for commit
    messages and, when possible, the PR title

@greptile-apps

greptile-apps Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds "stop all" controls for preview servers at two levels: a workspace-scoped "Stop All Servers" badge in the task toolbar (collapsing multiple pills when more than one server is running) and a global PreviewServersSettingsCard in the Connections settings page that lists every running server across all projects with a confirmed bulk-stop action. A new app.stopAllPreviewServers command palette entry with proper error handling rounds out the feature.

  • Backend: PreviewServerService gains listAll() and stopAll() methods; the RPC controller exposes listAll, stopForWorkspace, and stopAll endpoints, all covered by new tests.
  • Frontend: PreviewServerPill menu items are extracted into a reusable PreviewServerMenuItems component consumed by both the existing pill and the new PreviewServersBadge; the settings card subscribes to the previewServerEventChannel to keep its list live.

Confidence Score: 4/5

The feature is well-structured and tested; the main concern is that the settings-page bulk-stop swallows errors silently after the user confirms the dialog.

After the user confirms "Stop preview servers", the settings card fires rpc.previewServers.stopAll() with void and no .catch(). If the IPC call fails, the modal has already closed and no toast or other feedback is shown — the servers remain running but the user receives no indication of failure. The command palette entry for the same action handles this correctly with a destructive toast on error, so the pattern is established; it just wasn't carried through to the settings card.

apps/emdash-desktop/src/renderer/features/settings/components/PreviewServersSettingsCard.tsx — the onSuccess callback in the bulk-stop confirmation dialog needs error handling.

Important Files Changed

Filename Overview
apps/emdash-desktop/src/renderer/features/settings/components/PreviewServersSettingsCard.tsx New settings card showing all running preview servers with per-row and bulk-stop actions; error from the bulk-stop RPC call is silently swallowed after the confirmation dialog closes.
apps/emdash-desktop/src/renderer/features/tasks/components/preview-servers/preview-servers-badge.tsx New multi-server badge with nested sub-menus per server and a one-click "Stop All Servers" that fires without confirmation, inconsistent with the settings-page equivalent.
apps/emdash-desktop/src/main/core/preview-servers/preview-server-service.ts Adds listAll() and stopAll() to the service, mirroring the existing stopForWorkspace pattern cleanly.
apps/emdash-desktop/src/main/core/preview-servers/controller.ts Exposes three new RPC endpoints (listAll, stopForWorkspace, stopAll) wiring directly to the service methods.
apps/emdash-desktop/src/renderer/features/tasks/stores/preview-server-store.ts Adds stopAll() which calls stopForWorkspace RPC then clears local state; straightforward and covered by the new test.
apps/emdash-desktop/src/renderer/features/tasks/components/preview-servers/preview-server-menu-items.tsx Extracts the per-server dropdown items from the pill into a reusable component; purely mechanical refactor with no logic changes.
apps/emdash-desktop/src/renderer/lib/commands/app-commands.ts Registers app.stopAllPreviewServers command with proper .catch() error handling that surfaces a destructive toast.
apps/emdash-desktop/src/renderer/features/tasks/components/preview-servers/preview-server-format.ts Refactors status-class helper and adds previewServersSummaryStatusKind for computing aggregate badge state across multiple servers.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User
    participant SettingsCard as PreviewServersSettingsCard
    participant Badge as PreviewServersBadge
    participant Store as PreviewServerStore
    participant RPC as IPC / RPC
    participant Service as PreviewServerService
    participant Events as previewServerEventChannel

    User->>SettingsCard: Click Stop all then confirm dialog
    SettingsCard->>RPC: rpc.previewServers.stopAll()
    RPC->>Service: stopAll()
    Service->>Service: stop(id) x N via Promise.all
    Service-->>Events: emit remove x N
    Events-->>SettingsCard: update server list

    User->>Badge: Click Stop All Servers no dialog
    Badge->>Store: previews.stopAll()
    Store->>RPC: rpc.previewServers.stopForWorkspace(projectId, workspaceId)
    RPC->>Service: stopForWorkspace(projectId, workspaceId)
    Service-->>Events: emit remove x N
    Store->>Store: serversResource.setValue(empty Map)

    Note over SettingsCard,Events: Settings card keeps list live via event subscription and initial listAll() fetch
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User
    participant SettingsCard as PreviewServersSettingsCard
    participant Badge as PreviewServersBadge
    participant Store as PreviewServerStore
    participant RPC as IPC / RPC
    participant Service as PreviewServerService
    participant Events as previewServerEventChannel

    User->>SettingsCard: Click Stop all then confirm dialog
    SettingsCard->>RPC: rpc.previewServers.stopAll()
    RPC->>Service: stopAll()
    Service->>Service: stop(id) x N via Promise.all
    Service-->>Events: emit remove x N
    Events-->>SettingsCard: update server list

    User->>Badge: Click Stop All Servers no dialog
    Badge->>Store: previews.stopAll()
    Store->>RPC: rpc.previewServers.stopForWorkspace(projectId, workspaceId)
    RPC->>Service: stopForWorkspace(projectId, workspaceId)
    Service-->>Events: emit remove x N
    Store->>Store: serversResource.setValue(empty Map)

    Note over SettingsCard,Events: Settings card keeps list live via event subscription and initial listAll() fetch
Loading

Comments Outside Diff (1)

  1. apps/emdash-desktop/src/renderer/features/tasks/components/preview-servers/preview-servers-badge.tsx, line 720-723 (link)

    P2 No confirmation before stopping all workspace servers

    "Stop All Servers" executes immediately without a confirmation dialog, while the equivalent action in PreviewServersSettingsCard requires the user to confirm first. The badge can be clicked accidentally, silently stopping every server visible in the current workspace with no undo path.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/emdash-desktop/src/renderer/features/tasks/components/preview-servers/preview-servers-badge.tsx
    Line: 720-723
    
    Comment:
    **No confirmation before stopping all workspace servers**
    
    "Stop All Servers" executes immediately without a confirmation dialog, while the equivalent action in `PreviewServersSettingsCard` requires the user to confirm first. The badge can be clicked accidentally, silently stopping every server visible in the current workspace with no undo path.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
apps/emdash-desktop/src/renderer/features/settings/components/PreviewServersSettingsCard.tsx:175-177
**Silent error swallowed after user confirmation**

`rpc.previewServers.stopAll()` is fired with `void` after the user confirms the destructive dialog, so any RPC failure is silently dropped. The modal closes and the servers remain running, but the user receives no feedback. Compare with the command palette implementation in `app-commands.ts`, which handles the same call with `.catch()` and surfaces a destructive toast on failure.

### Issue 2 of 2
apps/emdash-desktop/src/renderer/features/tasks/components/preview-servers/preview-servers-badge.tsx:720-723
**No confirmation before stopping all workspace servers**

"Stop All Servers" executes immediately without a confirmation dialog, while the equivalent action in `PreviewServersSettingsCard` requires the user to confirm first. The badge can be clicked accidentally, silently stopping every server visible in the current workspace with no undo path.

Reviews (1): Last reviewed commit: "fix(preview): confirm stopping all serve..." | Re-trigger Greptile

@arnestrickmann

Copy link
Copy Markdown
Contributor

I'm not able to watch the recording:)

@arnestrickmann arnestrickmann requested a review from Davidknp July 6, 2026 21:16
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.

2 participants