Files
warren/frontend/stores/index.ts

256 lines
7.1 KiB
TypeScript

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<string, WarrenData>,
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<string, DirectoryEntry>,
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 = '';
},
},
});