import { defineStore } from 'pinia'; import type { DirectoryEntry } from '#shared/types'; import type { WarrenData } from '#shared/types/warrens'; import { getParentPath } from '~/utils/files'; export const useWarrenStore = defineStore('warrens', { state: () => ({ warrens: {} as Record, imageViewer: { src: null as string | null, }, current: null as { warrenId: string; path: string; dir: { parent: DirectoryEntry | null; entries: DirectoryEntry[]; } | null; } | null, selection: new Map() as Map, selectionRangeAnchor: null as DirectoryEntry | null, loading: false, }), actions: { setCurrentWarren(warrenId: string, path: string) { this.current = { warrenId, path, dir: null, }; this.clearSelection(); }, setCurrentWarrenEntries( entries: DirectoryEntry[], parent: DirectoryEntry | null ) { if (this.current == null) { return; } this.current.dir = { entries: entries.toSorted((a, b) => a.name.localeCompare(b.name) ), parent, }; }, addToCurrentWarrenPath(path: string) { if (this.current == null) { return; } if (!this.current.path.endsWith('/')) { path = '/' + path; } this.setCurrentWarrenPath(this.current.path + path); }, backCurrentPath(): boolean { if (this.current == null || this.current.path === '/') { return false; } this.setCurrentWarrenPath(getParentPath(this.current.path)); return true; }, setCurrentWarrenPath(path: string) { if (this.current == null) { return; } const previous = this.current.path; if (!path.startsWith('/')) { path = '/' + path; } this.current.path = path; if (previous !== path) { this.clearSelection(); this.current.dir = null; } }, clearCurrentWarren() { this.current = null; }, addToSelection(entry: DirectoryEntry) { this.selection.set(entry.name, entry); }, setSelection(entries: DirectoryEntry[]) { this.selection = entries.reduce( (acc, entry) => acc.set(entry.name, entry), new Map() ); if ( this.selectionRangeAnchor != null && !this.selection.has(this.selectionRangeAnchor.name) ) { this.selectionRangeAnchor = null; } }, addMultipleToSelection(entries: DirectoryEntry[]) { for (const entry of entries) { this.selection.set(entry.name, entry); } }, removeMultipleFromSelection(entries: DirectoryEntry[]) { for (const entry of entries) { this.selection.delete(entry.name); } }, setSelectedRangeAnchor(entry: DirectoryEntry) { this.selectionRangeAnchor = entry; }, removeFromSelection(entry: DirectoryEntry): boolean { return this.selection.delete(entry.name); }, toggleSelection(entry: DirectoryEntry): boolean { if (this.selection.has(entry.name)) { this.removeFromSelection(entry); return false; } else { this.addToSelection(entry); return true; } }, isSelected(entry: DirectoryEntry): boolean { if (this.current == null) { return false; } return this.selection.has(entry.name); }, handleSelectionClick( selectedEntry: DirectoryEntry, event: MouseEvent ): boolean { if (!event.ctrlKey && !event.shiftKey) { return false; } if (this.current == null || this.current.dir == null) { return true; } if ( event.ctrlKey || (event.shiftKey && this.selection.size === 0) ) { if ( this.toggleSelection(selectedEntry) || this.selectionRangeAnchor == null ) { this.setSelectedRangeAnchor(selectedEntry); } return true; } if (!event.shiftKey) { return false; } const anchor = this.selectionRangeAnchor; if (anchor == null) { return true; } const entries = this.current.dir.entries; const anchorIndex = entries.findIndex( (entry) => entry.name === anchor.name ); const clickedIndex = entries.findIndex( (e) => e.name === selectedEntry.name ); const targetSelection = []; if (clickedIndex > anchorIndex) { for (let i = anchorIndex; i <= clickedIndex; i++) { targetSelection.push(entries[i]); } } else { for (let i = clickedIndex; i <= anchorIndex; i++) { targetSelection.push(entries[i]); } } this.setSelection(targetSelection); return true; }, clearSelection() { this.selection.clear(); this.selectionRangeAnchor = null; }, }, }); export const useCreateDirectoryDialog = defineStore('create_directory_dialog', { state: () => ({ open: false, value: '', }), actions: { openDialog() { this.open = true; }, reset() { this.open = false; this.value = ''; }, }, }); export const useRenameDirectoryDialog = defineStore('rename_directory_dialog', { state: () => ({ open: false, entry: null as DirectoryEntry | null, value: '', }), actions: { openDialog(entry: DirectoryEntry) { this.entry = entry; this.value = entry.name; this.open = true; }, reset() { this.open = false; this.entry = null; this.value = ''; }, }, }); export const useShareDialog = defineStore('share_dialog', { state: () => ({ target: null as DirectoryEntry | null, password: '', }), actions: { openDialog(target: DirectoryEntry) { this.target = target; this.password = ''; }, reset() { this.target = null; this.password = ''; }, }, });