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 })
    }
  },
}))