mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-05-01 18:28:38 +00:00
refactor: migrate openSettings and refreshProjects from window.* to PaletteOpsContext
This commit is contained in:
@@ -6,12 +6,20 @@ import Sidebar from '../sidebar/view/Sidebar';
|
||||
import MainContent from '../main-content/view/MainContent';
|
||||
import CommandPalette from '../command-palette/CommandPalette';
|
||||
import { useWebSocket } from '../../contexts/WebSocketContext';
|
||||
import { PaletteOpsProvider } from '../../contexts/PaletteOpsContext';
|
||||
import { PaletteOpsProvider, usePaletteOpsRegister } from '../../contexts/PaletteOpsContext';
|
||||
import { useDeviceSettings } from '../../hooks/useDeviceSettings';
|
||||
import { useSessionProtection } from '../../hooks/useSessionProtection';
|
||||
import { useProjectsState } from '../../hooks/useProjectsState';
|
||||
|
||||
export default function AppContent() {
|
||||
return (
|
||||
<PaletteOpsProvider>
|
||||
<AppContentInner />
|
||||
</PaletteOpsProvider>
|
||||
);
|
||||
}
|
||||
|
||||
function AppContentInner() {
|
||||
const navigate = useNavigate();
|
||||
const { sessionId } = useParams<{ sessionId?: string }>();
|
||||
const { t } = useTranslation('common');
|
||||
@@ -52,27 +60,10 @@ export default function AppContent() {
|
||||
activeSessions,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Expose a non-blocking refresh for chat/session flows.
|
||||
// Full loading refreshes are still available through direct fetchProjects calls.
|
||||
window.refreshProjects = refreshProjectsSilently;
|
||||
|
||||
return () => {
|
||||
if (window.refreshProjects === refreshProjectsSilently) {
|
||||
delete window.refreshProjects;
|
||||
}
|
||||
};
|
||||
}, [refreshProjectsSilently]);
|
||||
|
||||
useEffect(() => {
|
||||
window.openSettings = openSettings;
|
||||
|
||||
return () => {
|
||||
if (window.openSettings === openSettings) {
|
||||
delete window.openSettings;
|
||||
}
|
||||
};
|
||||
}, [openSettings]);
|
||||
usePaletteOpsRegister({
|
||||
openSettings,
|
||||
refreshProjects: refreshProjectsSilently,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof navigator === 'undefined' || !('serviceWorker' in navigator)) {
|
||||
@@ -147,7 +138,6 @@ export default function AppContent() {
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<PaletteOpsProvider>
|
||||
<div className="fixed inset-0 flex bg-background" style={{ bottom: 'var(--keyboard-height, 0px)' }}>
|
||||
{!isMobile ? (
|
||||
<div className="h-full flex-shrink-0 border-r border-border/50">
|
||||
@@ -214,6 +204,5 @@ export default function AppContent() {
|
||||
onShowTab={setActiveTab}
|
||||
/>
|
||||
</div>
|
||||
</PaletteOpsProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import type { Dispatch, MutableRefObject, SetStateAction } from 'react';
|
||||
import { usePaletteOps } from '../../../contexts/PaletteOpsContext';
|
||||
import type { PendingPermissionRequest } from '../types/types';
|
||||
import type { Project, ProjectSession, LLMProvider } from '../../../types/app';
|
||||
import type { SessionStore, NormalizedMessage } from '../../../stores/useSessionStore';
|
||||
@@ -99,6 +100,7 @@ export function useChatRealtimeHandlers({
|
||||
onWebSocketReconnect,
|
||||
sessionStore,
|
||||
}: UseChatRealtimeHandlersArgs) {
|
||||
const paletteOps = usePaletteOps();
|
||||
const lastProcessedMessageRef = useRef<LatestChatMessage | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -280,9 +282,7 @@ export function useChatRealtimeHandlers({
|
||||
onNavigateToSession?.(actualId);
|
||||
}
|
||||
sessionStorage.removeItem('pendingSessionId');
|
||||
if (window.refreshProjects) {
|
||||
setTimeout(() => window.refreshProjects?.(), 500);
|
||||
}
|
||||
setTimeout(() => { void paletteOps.refreshProjects(); }, 500);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -365,5 +365,6 @@ export function useChatRealtimeHandlers({
|
||||
onNavigateToSession,
|
||||
onWebSocketReconnect,
|
||||
sessionStore,
|
||||
paletteOps,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { unifiedMergeView } from '@codemirror/merge';
|
||||
import type { Extension } from '@codemirror/state';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { usePaletteOps } from '../../../contexts/PaletteOpsContext';
|
||||
import { useCodeEditorDocument } from '../hooks/useCodeEditorDocument';
|
||||
import { useCodeEditorSettings } from '../hooks/useCodeEditorSettings';
|
||||
import { useEditorKeyboardShortcuts } from '../hooks/useEditorKeyboardShortcuts';
|
||||
@@ -36,6 +37,7 @@ export default function CodeEditor({
|
||||
onPopOut = null,
|
||||
}: CodeEditorProps) {
|
||||
const { t } = useTranslation('codeEditor');
|
||||
const paletteOps = usePaletteOps();
|
||||
const [isFullscreen, setIsFullscreen] = useState(false);
|
||||
const [showDiff, setShowDiff] = useState(Boolean(file.diffInfo));
|
||||
const [markdownPreview, setMarkdownPreview] = useState(false);
|
||||
@@ -199,7 +201,7 @@ export default function CodeEditor({
|
||||
saving={saving}
|
||||
saveSuccess={saveSuccess}
|
||||
onToggleMarkdownPreview={() => setMarkdownPreview((previous) => !previous)}
|
||||
onOpenSettings={() => window.openSettings?.('appearance')}
|
||||
onOpenSettings={() => paletteOps.openSettings('appearance')}
|
||||
onDownload={handleDownload}
|
||||
onSave={handleSave}
|
||||
onToggleFullscreen={() => setIsFullscreen((previous) => !previous)}
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import type { TFunction } from 'i18next';
|
||||
|
||||
import { api } from '../../../utils/api';
|
||||
import { usePaletteOps } from '../../../contexts/PaletteOpsContext';
|
||||
import type { Project, ProjectSession, LLMProvider } from '../../../types/app';
|
||||
import type {
|
||||
DeleteProjectConfirmation,
|
||||
@@ -95,6 +96,7 @@ export function useSidebarController({
|
||||
setSidebarVisible,
|
||||
sidebarVisible,
|
||||
}: UseSidebarControllerArgs) {
|
||||
const paletteOps = usePaletteOps();
|
||||
const [expandedProjects, setExpandedProjects] = useState<Set<string>>(new Set());
|
||||
const [editingProject, setEditingProject] = useState<string | null>(null);
|
||||
const [showNewProject, setShowNewProject] = useState(false);
|
||||
@@ -536,11 +538,7 @@ export function useSidebarController({
|
||||
try {
|
||||
const response = await api.renameProject(projectId, editingName);
|
||||
if (response.ok) {
|
||||
if (window.refreshProjects) {
|
||||
await window.refreshProjects();
|
||||
} else {
|
||||
window.location.reload();
|
||||
}
|
||||
await paletteOps.refreshProjects();
|
||||
} else {
|
||||
console.error('Failed to rename project');
|
||||
}
|
||||
@@ -551,7 +549,7 @@ export function useSidebarController({
|
||||
setEditingName('');
|
||||
}
|
||||
},
|
||||
[editingName],
|
||||
[editingName, paletteOps],
|
||||
);
|
||||
|
||||
const showDeleteSessionConfirmation = useCallback(
|
||||
|
||||
@@ -6,6 +6,7 @@ import { useVersionCheck } from '../../../hooks/useVersionCheck';
|
||||
import { useUiPreferences } from '../../../hooks/useUiPreferences';
|
||||
import { useSidebarController } from '../hooks/useSidebarController';
|
||||
import { useTaskMaster } from '../../../contexts/TaskMasterContext';
|
||||
import { usePaletteOps } from '../../../contexts/PaletteOpsContext';
|
||||
import { useTasksSettings } from '../../../contexts/TasksSettingsContext';
|
||||
import type { Project, LLMProvider } from '../../../types/app';
|
||||
import type { MCPServerStatus, SidebarProps } from '../types/types';
|
||||
@@ -49,6 +50,7 @@ function Sidebar({
|
||||
const { sidebarVisible } = preferences;
|
||||
const { setCurrentProject, mcpServerStatus } = useTaskMaster() as TaskMasterSidebarContext;
|
||||
const { tasksEnabled } = useTasksSettings();
|
||||
const paletteOps = usePaletteOps();
|
||||
|
||||
const {
|
||||
isSidebarCollapsed,
|
||||
@@ -128,12 +130,7 @@ function Sidebar({
|
||||
}, [isPWA]);
|
||||
|
||||
const handleProjectCreated = () => {
|
||||
if (window.refreshProjects) {
|
||||
void window.refreshProjects();
|
||||
return;
|
||||
}
|
||||
|
||||
window.location.reload();
|
||||
void paletteOps.refreshProjects();
|
||||
};
|
||||
|
||||
const projectListProps: SidebarProjectListProps = {
|
||||
|
||||
2
src/types/global.d.ts
vendored
2
src/types/global.d.ts
vendored
@@ -3,8 +3,6 @@ export {};
|
||||
declare global {
|
||||
interface Window {
|
||||
__ROUTER_BASENAME__?: string;
|
||||
refreshProjects?: () => void | Promise<void>;
|
||||
openSettings?: (tab?: string) => void;
|
||||
}
|
||||
|
||||
interface EventSourceEventMap {
|
||||
|
||||
Reference in New Issue
Block a user