feat(03-01): add context switch overlay, hook, and store wiring
- Create ContextSwitchOverlay component with full-screen loading state - Create useContextSwitch hook exposing switchContext/isContextSwitching/activeContextId - Add ContextSlice to AppState type intersection - Compose createContextSlice into store creation
This commit is contained in:
parent
f129715dc8
commit
f01d545ee3
4 changed files with 70 additions and 0 deletions
38
src/renderer/components/common/ContextSwitchOverlay.tsx
Normal file
38
src/renderer/components/common/ContextSwitchOverlay.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
/**
|
||||
* ContextSwitchOverlay - Full-screen loading overlay during context switches.
|
||||
*
|
||||
* Displayed when isContextSwitching is true, preventing stale data flash
|
||||
* during workspace transitions.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import { useStore } from '@renderer/store';
|
||||
|
||||
export const ContextSwitchOverlay: React.FC = () => {
|
||||
const isContextSwitching = useStore((state) => state.isContextSwitching);
|
||||
const targetContextId = useStore((state) => state.targetContextId);
|
||||
|
||||
if (!isContextSwitching) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Format context label for display
|
||||
const contextLabel =
|
||||
targetContextId === 'local' ? 'Local' : (targetContextId?.replace(/^ssh-/, '') ?? 'Unknown');
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-[9999] flex items-center justify-center bg-surface">
|
||||
<div className="flex flex-col items-center gap-4">
|
||||
{/* Spinner */}
|
||||
<div className="size-8 animate-spin rounded-full border-4 border-text border-t-transparent" />
|
||||
|
||||
{/* Text */}
|
||||
<div className="flex flex-col items-center gap-1">
|
||||
<p className="text-text">Switching to {contextLabel}...</p>
|
||||
<p className="text-sm text-text-secondary">Loading workspace</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
28
src/renderer/hooks/useContextSwitch.ts
Normal file
28
src/renderer/hooks/useContextSwitch.ts
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* useContextSwitch - Hook for context switching actions.
|
||||
*
|
||||
* Thin wrapper exposing context switch functionality to components.
|
||||
*/
|
||||
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useStore } from '../store';
|
||||
|
||||
export function useContextSwitch() {
|
||||
const switchContext = useStore((state) => state.switchContext);
|
||||
const isContextSwitching = useStore((state) => state.isContextSwitching);
|
||||
const activeContextId = useStore((state) => state.activeContextId);
|
||||
|
||||
const handleSwitch = useCallback(
|
||||
async (targetContextId: string) => {
|
||||
await switchContext(targetContextId);
|
||||
},
|
||||
[switchContext]
|
||||
);
|
||||
|
||||
return {
|
||||
switchContext: handleSwitch,
|
||||
isContextSwitching,
|
||||
activeContextId,
|
||||
};
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import { create } from 'zustand';
|
|||
|
||||
import { createConfigSlice } from './slices/configSlice';
|
||||
import { createConnectionSlice } from './slices/connectionSlice';
|
||||
import { createContextSlice } from './slices/contextSlice';
|
||||
import { createConversationSlice } from './slices/conversationSlice';
|
||||
import { createNotificationSlice } from './slices/notificationSlice';
|
||||
import { createPaneSlice } from './slices/paneSlice';
|
||||
|
|
@ -41,6 +42,7 @@ export const useStore = create<AppState>()((...args) => ({
|
|||
...createNotificationSlice(...args),
|
||||
...createConfigSlice(...args),
|
||||
...createConnectionSlice(...args),
|
||||
...createContextSlice(...args),
|
||||
...createUpdateSlice(...args),
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import type { ConfigSlice } from './slices/configSlice';
|
||||
import type { ConnectionSlice } from './slices/connectionSlice';
|
||||
import type { ContextSlice } from './slices/contextSlice';
|
||||
import type { ConversationSlice } from './slices/conversationSlice';
|
||||
import type { NotificationSlice } from './slices/notificationSlice';
|
||||
import type { PaneSlice } from './slices/paneSlice';
|
||||
|
|
@ -88,4 +89,5 @@ export type AppState = ProjectSlice &
|
|||
NotificationSlice &
|
||||
ConfigSlice &
|
||||
ConnectionSlice &
|
||||
ContextSlice &
|
||||
UpdateSlice;
|
||||
|
|
|
|||
Loading…
Reference in a new issue