253 lines
7.0 KiB
TypeScript
253 lines
7.0 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>,
|
|
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 = '';
|
|
},
|
|
},
|
|
});
|