File size: 4,158 Bytes
1f21206 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | import { create } from 'zustand'
import { memoryApi } from '../api/memory'
import type { MemoryFile, MemoryFileDetail, MemoryProject } from '../types/memory'
type MemoryStore = {
projects: MemoryProject[]
files: MemoryFile[]
selectedProjectId: string | null
selectedFile: MemoryFileDetail | null
draftContent: string
isLoadingProjects: boolean
isLoadingFiles: boolean
isLoadingFile: boolean
isSaving: boolean
error: string | null
lastSavedAt: string | null
fetchProjects: (cwd?: string) => Promise<void>
selectProject: (projectId: string) => void
fetchFiles: (projectId: string) => Promise<void>
openFile: (projectId: string, path: string) => Promise<void>
updateDraft: (content: string) => void
saveFile: () => Promise<void>
createFile: (projectId: string, path: string, content: string) => Promise<void>
}
export const useMemoryStore = create<MemoryStore>((set, get) => ({
projects: [],
files: [],
selectedProjectId: null,
selectedFile: null,
draftContent: '',
isLoadingProjects: false,
isLoadingFiles: false,
isLoadingFile: false,
isSaving: false,
error: null,
lastSavedAt: null,
fetchProjects: async (cwd) => {
set({ isLoadingProjects: true, error: null })
try {
const { projects } = await memoryApi.listProjects(cwd)
const current = projects.find((project) => project.isCurrent)
const selectedProjectId =
get().selectedProjectId && projects.some((project) => project.id === get().selectedProjectId)
? get().selectedProjectId
: current?.id ?? projects[0]?.id ?? null
set({ projects, selectedProjectId, isLoadingProjects: false })
} catch (err) {
set({ error: (err as Error).message, isLoadingProjects: false })
}
},
selectProject: (projectId) => {
set({
selectedProjectId: projectId,
files: [],
selectedFile: null,
draftContent: '',
error: null,
lastSavedAt: null,
})
},
fetchFiles: async (projectId) => {
set({ isLoadingFiles: true, error: null })
try {
const { files } = await memoryApi.listFiles(projectId)
set((state) => {
const stillSelected = state.selectedFile && files.some((file) => file.path === state.selectedFile?.path)
return {
files,
selectedFile: stillSelected ? state.selectedFile : null,
draftContent: stillSelected ? state.draftContent : '',
isLoadingFiles: false,
}
})
} catch (err) {
set({ error: (err as Error).message, isLoadingFiles: false })
}
},
openFile: async (projectId, path) => {
set({ isLoadingFile: true, error: null })
try {
const { file } = await memoryApi.readFile(projectId, path)
set({
selectedFile: file,
draftContent: file.content,
isLoadingFile: false,
lastSavedAt: null,
})
} catch (err) {
set({ error: (err as Error).message, isLoadingFile: false })
}
},
updateDraft: (content) => set({ draftContent: content }),
saveFile: async () => {
const { selectedProjectId, selectedFile, draftContent } = get()
if (!selectedProjectId || !selectedFile) return
set({ isSaving: true, error: null })
try {
const { file } = await memoryApi.saveFile({
projectId: selectedProjectId,
path: selectedFile.path,
content: draftContent,
})
set({
selectedFile: {
...selectedFile,
updatedAt: file.updatedAt,
bytes: file.bytes,
content: draftContent,
},
isSaving: false,
lastSavedAt: file.updatedAt,
})
await get().fetchFiles(selectedProjectId)
} catch (err) {
set({ error: (err as Error).message, isSaving: false })
}
},
createFile: async (projectId, path, content) => {
set({ isSaving: true, error: null })
try {
await memoryApi.saveFile({ projectId, path, content })
set({ isSaving: false })
await get().fetchFiles(projectId)
await get().openFile(projectId, path)
} catch (err) {
set({ error: (err as Error).message, isSaving: false })
}
},
}))
|