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