Main process — worker thread for team data: - New team-data-worker thread handles getTeamData and findLogsForTask, isolating heavy file I/O (scanning 300+ subagent JSONL files) from Electron's main event loop. getTeamData dropped from ~2000ms on the main thread to ~110ms via the worker. - Worker-side dedup and 10s result cache for findLogsForTask prevents redundant scans when the same task is queried multiple times. - Discovery cache TTL raised from 5s to 30s — avoids re-scanning the entire project directory on every call. - Message cap at 200 in TeamDataService to keep IPC payloads under 1MB (was sending 2200+ messages / ~3MB, stalling Chromium IPC serialization). - IPC handlers fall back to main-thread execution if the worker is unavailable (graceful degradation). Renderer — useShallow and memoization (55 files): - Added useShallow to store selectors across 55 renderer files. Batched individual useStore() calls (e.g. 17 calls in ExtensionStoreView, 10 in ConnectionSection) into single useShallow selectors, cutting unnecessary re-render checks on every store update. - MemberLogsTab: three 5-second polling intervals now pause when the parent tab is hidden (display:none). Previously 5 hidden tabs × 3 intervals = 15 polling timers firing continuously. - KanbanColumn wrapped in React.memo to skip re-renders when props haven't changed. - MemberList: memoized activeMembers/removedMembers/colorMap; replaced O(n×m) per-member task scan with a pre-computed reviewer map. - Bounded timer Maps in store initialization to prevent unbounded growth of debounce/throttle tracking maps during long sessions.
56 lines
2 KiB
TypeScript
56 lines
2 KiB
TypeScript
/**
|
|
* ConnectionStatusBadge - Visual indicator for workspace connection status.
|
|
*
|
|
* Renders appropriate icon based on connection state:
|
|
* - Local: Monitor icon (muted)
|
|
* - SSH connected: Wifi icon (green)
|
|
* - SSH connecting: Animated spinner (muted)
|
|
* - SSH disconnected: WifiOff icon (muted)
|
|
* - SSH error: WifiOff icon (red)
|
|
*/
|
|
|
|
import { useStore } from '@renderer/store';
|
|
import { Loader2, Monitor, Wifi, WifiOff } from 'lucide-react';
|
|
import { useShallow } from 'zustand/react/shallow';
|
|
|
|
interface ConnectionStatusBadgeProps {
|
|
contextId: string;
|
|
className?: string;
|
|
}
|
|
|
|
export const ConnectionStatusBadge = ({
|
|
contextId,
|
|
className,
|
|
}: Readonly<ConnectionStatusBadgeProps>): React.JSX.Element => {
|
|
const { connectionState, connectedHost } = useStore(
|
|
useShallow((s) => ({
|
|
connectionState: s.connectionState,
|
|
connectedHost: s.connectedHost,
|
|
}))
|
|
);
|
|
|
|
// Local context always shows Monitor icon
|
|
if (contextId === 'local') {
|
|
return <Monitor className={`size-3.5 text-text-muted ${className ?? ''}`} />;
|
|
}
|
|
|
|
// SSH context - determine if this specific SSH context matches connected host
|
|
const isConnectedToThisHost = connectedHost != null && contextId === `ssh-${connectedHost}`;
|
|
|
|
// If this SSH context doesn't match the connected host, treat as disconnected
|
|
const effectiveState = isConnectedToThisHost ? connectionState : 'disconnected';
|
|
|
|
// Render icon based on connection state
|
|
switch (effectiveState) {
|
|
case 'connected':
|
|
return <Wifi className={`size-3.5 text-green-400 ${className ?? ''}`} />;
|
|
case 'connecting':
|
|
return <Loader2 className={`size-3.5 animate-spin text-text-muted ${className ?? ''}`} />;
|
|
case 'disconnected':
|
|
return <WifiOff className={`size-3.5 text-text-muted ${className ?? ''}`} />;
|
|
case 'error':
|
|
return <WifiOff className={`size-3.5 text-red-400 ${className ?? ''}`} />;
|
|
default:
|
|
return <WifiOff className={`size-3.5 text-text-muted ${className ?? ''}`} />;
|
|
}
|
|
};
|