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