import { useEffect, useMemo, useState } from 'react' import type { ReactNode } from 'react' import { BookOpenText, Database, FileText, FolderGit2, RefreshCw, RotateCcw, Save, Search, X } from 'lucide-react' import { Button } from '../components/shared/Button' import { MarkdownRenderer } from '../components/markdown/MarkdownRenderer' import { useTranslation } from '../i18n' import { formatBytes } from '../lib/formatBytes' import { useMemoryStore } from '../stores/memoryStore' import { useSessionStore } from '../stores/sessionStore' import { useUIStore } from '../stores/uiStore' import type { MemoryFile, MemoryProject } from '../types/memory' const DEFAULT_MEMORY_PATH = 'MEMORY.md' export function MemorySettings() { const t = useTranslation() const { projects, files, selectedProjectId, selectedFile, draftContent, isLoadingProjects, isLoadingFiles, isLoadingFile, isSaving, error, lastSavedAt, fetchProjects, selectProject, fetchFiles, openFile, updateDraft, saveFile, } = useMemoryStore() const sessions = useSessionStore((s) => s.sessions) const activeSessionId = useSessionStore((s) => s.activeSessionId) const pendingMemoryPath = useUIStore((s) => s.pendingMemoryPath) const setPendingMemoryPath = useUIStore((s) => s.setPendingMemoryPath) const [projectQuery, setProjectQuery] = useState('') const [fileQuery, setFileQuery] = useState('') const activeSession = useMemo( () => sessions.find((session) => session.id === activeSessionId), [activeSessionId, sessions], ) const activeCwd = activeSession?.workDir || activeSession?.projectPath || undefined const selectedProject = projects.find((project) => project.id === selectedProjectId) ?? null const isDirty = Boolean(selectedFile && draftContent !== selectedFile.content) const filteredProjects = useMemo( () => filterProjects(projects, projectQuery), [projectQuery, projects], ) const filteredFiles = useMemo( () => filterFiles(files, fileQuery), [fileQuery, files], ) const previewContent = stripMarkdownFrontmatter(draftContent) useEffect(() => { void fetchProjects(activeCwd) }, [activeCwd, fetchProjects]) useEffect(() => { if (!selectedProjectId) return void fetchFiles(selectedProjectId) }, [fetchFiles, selectedProjectId]) useEffect(() => { if (!projectQuery.trim() || filteredProjects.length === 0) return if (selectedProjectId && filteredProjects.some((project) => project.id === selectedProjectId)) return selectProject(filteredProjects[0]!.id) }, [filteredProjects, projectQuery, selectProject, selectedProjectId]) useEffect(() => { if (!selectedProjectId || selectedFile || isLoadingFiles || isLoadingFile) return if (pendingMemoryPath) return const firstFile = files[0] if (firstFile) { void openFile(selectedProjectId, firstFile.path) } }, [files, isLoadingFile, isLoadingFiles, openFile, pendingMemoryPath, selectedFile, selectedProjectId]) useEffect(() => { if (!pendingMemoryPath || isLoadingProjects || projects.length === 0) return const target = resolveMemoryFileTarget(projects, pendingMemoryPath) if (!target) { setPendingMemoryPath(null) return } if (selectedProjectId !== target.projectId) { selectProject(target.projectId) return } if (selectedFile?.path === target.path && !isLoadingFile) { setPendingMemoryPath(null) return } void openFile(target.projectId, target.path).then(() => { setPendingMemoryPath(null) }) }, [ isLoadingFile, isLoadingProjects, openFile, pendingMemoryPath, projects, selectProject, selectedFile?.path, selectedProjectId, setPendingMemoryPath, ]) const handleRefresh = () => { void fetchProjects(activeCwd) if (selectedProjectId) { void fetchFiles(selectedProjectId) } } const handleProjectSelect = (projectId: string) => { if (projectId === selectedProjectId) return selectProject(projectId) } const handleFileOpen = (file: MemoryFile) => { if (!selectedProjectId || file.path === selectedFile?.path) return void openFile(selectedProjectId, file.path) } return (

{t('settings.memory.title')}

{activeCwd ? projectDisplayName(activeCwd) : '~/.claude/projects'} {t('settings.memory.fileCount', { count: files.length })}
{error && (
{error}
)}

{selectedFile?.path ?? t('settings.memory.noFileSelected')}

{isDirty && {t('settings.memory.unsaved')}} {lastSavedAt && !isDirty && {t('settings.memory.saved')}}

{selectedProject?.memoryDir ?? t('settings.memory.selectProject')}

{selectedFile ? (
{t('settings.memory.editor')} {formatBytes(selectedFile.bytes)}