Spaces:
Running
Running
import { atom, computed, map, type MapStore, type WritableAtom } from 'nanostores'; | |
import type { EditorDocument, ScrollPosition } from '~/components/editor/codemirror/CodeMirrorEditor'; | |
import type { FileMap, FilesStore } from './files'; | |
export type EditorDocuments = Record<string, EditorDocument>; | |
type SelectedFile = WritableAtom<string | undefined>; | |
export class EditorStore { | |
#filesStore: FilesStore; | |
selectedFile: SelectedFile = import.meta.hot?.data.selectedFile ?? atom<string | undefined>(); | |
documents: MapStore<EditorDocuments> = import.meta.hot?.data.documents ?? map({}); | |
currentDocument = computed([this.documents, this.selectedFile], (documents, selectedFile) => { | |
if (!selectedFile) { | |
return undefined; | |
} | |
return documents[selectedFile]; | |
}); | |
constructor(filesStore: FilesStore) { | |
this.#filesStore = filesStore; | |
if (import.meta.hot) { | |
import.meta.hot.data.documents = this.documents; | |
import.meta.hot.data.selectedFile = this.selectedFile; | |
} | |
} | |
setDocuments(files: FileMap) { | |
const previousDocuments = this.documents.value; | |
this.documents.set( | |
Object.fromEntries<EditorDocument>( | |
Object.entries(files) | |
.map(([filePath, dirent]) => { | |
if (dirent === undefined || dirent.type === 'folder') { | |
return undefined; | |
} | |
const previousDocument = previousDocuments?.[filePath]; | |
return [ | |
filePath, | |
{ | |
value: dirent.content, | |
filePath, | |
scroll: previousDocument?.scroll, | |
}, | |
] as [string, EditorDocument]; | |
}) | |
.filter(Boolean) as Array<[string, EditorDocument]>, | |
), | |
); | |
} | |
setSelectedFile(filePath: string | undefined) { | |
this.selectedFile.set(filePath); | |
} | |
updateScrollPosition(filePath: string, position: ScrollPosition) { | |
const documents = this.documents.get(); | |
const documentState = documents[filePath]; | |
if (!documentState) { | |
return; | |
} | |
this.documents.setKey(filePath, { | |
...documentState, | |
scroll: position, | |
}); | |
} | |
updateFile(filePath: string, newContent: string) { | |
const documents = this.documents.get(); | |
const documentState = documents[filePath]; | |
if (!documentState) { | |
return; | |
} | |
const currentContent = documentState.value; | |
const contentChanged = currentContent !== newContent; | |
if (contentChanged) { | |
this.documents.setKey(filePath, { | |
...documentState, | |
value: newContent, | |
}); | |
} | |
} | |
} | |