basic selection + download multiple files with selection

This commit is contained in:
2025-09-02 18:08:13 +02:00
parent be46f92ddf
commit e2085c1baa
22 changed files with 516 additions and 156 deletions

View File

@@ -8,19 +8,23 @@ import {
} from '@/components/ui/context-menu';
import { deleteWarrenDirectory, deleteWarrenFile } from '~/lib/api/warrens';
import type { DirectoryEntry } from '#shared/types';
import { toast } from 'vue-sonner';
const warrenStore = useWarrenStore();
const copyStore = useCopyStore();
const renameDialog = useRenameDirectoryDialog();
const { entry, disabled } = defineProps<{
const {
entry,
disabled,
draggable = true,
} = defineProps<{
entry: DirectoryEntry;
disabled: boolean;
draggable?: boolean;
}>();
const emit = defineEmits<{
'entry-click': [entry: DirectoryEntry];
'entry-click': [entry: DirectoryEntry, event: MouseEvent];
'entry-download': [entry: DirectoryEntry];
}>();
@@ -33,6 +37,7 @@ const isCopied = computed(
warrenStore.current.path === copyStore.file.path &&
entry.name === copyStore.file.name
);
const isSelected = computed(() => warrenStore.isSelected(entry));
async function submitDelete(force: boolean = false) {
if (warrenStore.current == null) {
@@ -63,8 +68,8 @@ async function openRenameDialog() {
renameDialog.openDialog(entry);
}
async function onClick() {
emit('entry-click', entry);
function onClick(event: MouseEvent) {
emit('entry-click', entry, event);
}
function onDragStart(e: DragEvent) {
@@ -97,6 +102,10 @@ function onShare() {
function onDownload() {
emit('entry-download', entry);
}
function onClearCopy() {
copyStore.clearFile();
}
</script>
<template>
@@ -105,10 +114,11 @@ function onDownload() {
<button
:disabled="warrenStore.loading || disabled"
:class="[
'bg-accent/30 border-border flex w-full translate-0 flex-row gap-4 overflow-hidden rounded-md border-1 px-4 py-2 select-none',
'bg-accent/30 border-border flex w-full translate-0 flex-row gap-4 overflow-hidden rounded-md border-1 px-4 py-2 outline-0 select-none',
isCopied && 'border-primary/50 border',
isSelected && 'bg-primary/20',
]"
draggable="true"
:draggable
@dragstart="onDragStart"
@drop="onDrop"
@click="onClick"
@@ -136,13 +146,25 @@ function onDownload() {
<Icon name="lucide:pencil" />
Rename
</ContextMenuItem>
<ContextMenuItem
:class="[warrenStore.current == null && 'hidden']"
@select="onCopy"
>
<Icon name="lucide:copy" />
Copy
</ContextMenuItem>
<template v-if="warrenStore.current != null">
<ContextMenuItem
v-if="
copyStore.file == null ||
copyStore.file.warrenId !==
warrenStore.current.warrenId ||
copyStore.file.path !== warrenStore.current.path ||
copyStore.file.name !== entry.name
"
@select="onCopy"
>
<Icon name="lucide:copy" />
Copy
</ContextMenuItem>
<ContextMenuItem v-else @select="onClearCopy">
<Icon name="lucide:copy-x" />
Clear clipboard
</ContextMenuItem>
</template>
<ContextMenuItem @select="onDownload">
<Icon name="lucide:download" />
Download

View File

@@ -33,10 +33,10 @@ const warrenStore = useWarrenStore();
:data="
route.meta.layout === 'share'
? getApiUrl(
`warrens/files/cat_share?shareId=${route.query.id}&path=${joinPaths(warrenStore.current.path, entry.name)}`
`warrens/files/cat_share?shareId=${route.query.id}&paths=${joinPaths(warrenStore.current.path, entry.name)}`
)
: getApiUrl(
`warrens/files/cat?warrenId=${warrenStore.current!.warrenId}&path=${joinPaths(warrenStore.current.path, entry.name)}`
`warrens/files/cat?warrenId=${warrenStore.current!.warrenId}&paths=${joinPaths(warrenStore.current.path, entry.name)}`
)
"
>

View File

@@ -7,15 +7,17 @@ const {
parent,
isOverDropZone,
disableEntries = false,
entriesDraggable = true,
} = defineProps<{
entries: DirectoryEntry[];
parent: DirectoryEntry | null;
isOverDropZone?: boolean;
disableEntries?: boolean;
entriesDraggable?: boolean;
}>();
const emit = defineEmits<{
'entry-click': [entry: DirectoryEntry];
'entry-click': [entry: DirectoryEntry, event: MouseEvent];
'entry-download': [entry: DirectoryEntry];
back: [];
}>();
@@ -26,8 +28,8 @@ const sortedEntries = computed(() =>
entries.toSorted((a, b) => a.name.localeCompare(b.name))
);
function onEntryClicked(entry: DirectoryEntry) {
emit('entry-click', entry);
function onEntryClicked(entry: DirectoryEntry, event: MouseEvent) {
emit('entry-click', entry, event);
}
function onEntryDownload(entry: DirectoryEntry) {
@@ -56,6 +58,7 @@ function onEntryDownload(entry: DirectoryEntry) {
:key="entry.name"
:entry="entry"
:disabled="isLoading || disableEntries"
:draggable="entriesDraggable"
@entry-click="onEntryClicked"
@entry-download="onEntryDownload"
/>

View File

@@ -27,12 +27,16 @@ async function onPaste() {
pasting.value = true;
await pasteFile(copyStore.file!, {
const success = await pasteFile(copyStore.file!, {
warrenId: warrenStore.current!.warrenId,
name: copyStore.file!.name,
path: warrenStore.current!.path,
});
if (success) {
copyStore.clearFile();
}
pasting.value = false;
}
</script>