import type { Document, DirEntry, FileEntry, FUID, DirList } from '@/repositories/Document' import { formatSize, formatUnixDate } from '@/utils' import { defineStore } from 'pinia' // @ts-ignore import { localeIncludes } from 'locale-includes' type FileData = { id: string, mtime: number, size: number, dir: DirectoryData}; type DirectoryData = { [filename: string]: FileData; }; type User = { isOpenLoginModal: boolean, isLoggedIn : boolean, } export type DocumentStore = { root: DirEntry, document: Document[], selected: Set, loading: boolean, uploadingDocuments: Array<{key: number, name: string, progress: number}>, uploadCount: number, wsWatch: WebSocket | undefined, wsUpload: WebSocket | undefined, user: User, error: string, } export const useDocumentStore = defineStore({ id: 'documents', state: (): DocumentStore => ({ root: {} as DirEntry, document: [] as Document[], selected: new Set(), loading: true as boolean, uploadingDocuments: [], uploadCount: 0 as number, wsWatch: undefined, wsUpload: undefined, error: '' as string, user: { isLoggedIn: false, isOpenLoginModal: false } as User }), actions: { updateTable(matched: DirList) { // Transform data const dataMapped = [] for (const [name, attr] of Object.entries(matched)) { const {id, size, mtime} = attr const element: Document = { name, key: id, size, sizedisp: formatSize(size), mtime, modified: formatUnixDate(mtime), type: "dir" in attr ? 'folder' : 'file', } dataMapped.push(element) } // Pre sort directory entries folders first then files, names in natural ordering dataMapped.sort((a, b) => a.type === b.type ? a.name.localeCompare(b.name) : a.type === "folder" ? -1 : 1) this.document = dataMapped this.loading = false; }, setFilter(filter: string){ function traverseDir(data: DirEntry | FileEntry, path: string){ if (!("dir" in data)) return for (const [name, attr] of Object.entries(data.dir)) { const fullname = `${path}/${name}` if (localeIncludes(name, filter, {usage: "search", sensitivity: "base"})) { matched[fullname.slice(1)] = attr // No initial slash on name } traverseDir(attr, fullname) } } this.loading = true const matched: any = {} traverseDir(this.root, "") this.updateTable(matched) }, setActualDocument(location: string){ location = decodeURIComponent(location) this.loading = true let data: FileEntry | DirEntry = this.root const actualDirArr = [] try { // Navigate to target folder for (const dirname of location.split('/').slice(1)) { if (!dirname) continue if (!("dir" in data)) throw Error("Target folder not available") actualDirArr.push(dirname) data = data.dir[dirname] } } catch (error) { console.error("Cannot show requested folder", location, actualDirArr.join('/'), error) } if (!("dir" in data)) { // Target folder not available this.document = [] return } this.updateTable(data.dir) }, updateUploadingDocuments(key: number, progress: number){ for (const d of this.uploadingDocuments) { if(d.key === key) d.progress = progress } }, pushUploadingDocuments(name: string){ this.uploadCount++; const document = { key: this.uploadCount, name: name, progress: 0 } this.uploadingDocuments.push(document) return document }, deleteUploadingDocument(key: number){ this.uploadingDocuments = this.uploadingDocuments.filter((e)=> e.key !== key) }, updateModified() { for (const d of this.document) { if ("mtime" in d) d.modified = formatUnixDate(d.mtime) } }, }, getters: { mainDocument(): Document[] { return this.document; }, isUserLogged(): boolean{ return this.user.isLoggedIn } }, });