Files
warren/frontend/components/DirectoryEntry.vue

182 lines
5.4 KiB
Vue

<script setup lang="ts">
import {
ContextMenu,
ContextMenuTrigger,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
} from '@/components/ui/context-menu';
import type { DirectoryEntry } from '#shared/types';
const warrenStore = useWarrenStore();
const copyStore = useCopyStore();
const renameDialog = useRenameDirectoryDialog();
const {
entry,
disabled,
draggable = true,
} = defineProps<{
entry: DirectoryEntry;
disabled: boolean;
draggable?: boolean;
}>();
const emit = defineEmits<{
'entry-click': [entry: DirectoryEntry, event: MouseEvent];
'entry-download': [entry: DirectoryEntry];
'entry-delete': [entry: DirectoryEntry, force: boolean];
}>();
const isCopied = computed(
() =>
warrenStore.current != null &&
copyStore.file != null &&
warrenStore.current.warrenId === copyStore.file.warrenId &&
warrenStore.current.path === copyStore.file.path &&
entry.name === copyStore.file.name
);
const isSelected = computed(() => warrenStore.isSelected(entry));
function onDelete(force: boolean = false) {
emit('entry-delete', entry, force);
}
function openRenameDialog() {
renameDialog.openDialog(entry);
}
function onClick(event: MouseEvent) {
emit('entry-click', entry, event);
}
function onDragStart(e: DragEvent) {
if (e.dataTransfer == null) {
return;
}
e.dataTransfer.setData('application/warren', entry.name);
e.dataTransfer.dropEffect = 'move';
}
const onDrop = onDirectoryEntryDrop(entry);
function onCopy() {
if (warrenStore.current == null) {
return;
}
copyStore.copyFile(
warrenStore.current.warrenId,
warrenStore.current.path,
entry.name
);
}
function onShare() {
useShareDialog().openDialog(entry);
}
function onDownload() {
emit('entry-download', entry);
}
function onClearCopy() {
copyStore.clearFile();
}
</script>
<template>
<ContextMenu>
<ContextMenuTrigger class="flex sm:w-52">
<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 outline-0 select-none',
isCopied && 'border-primary/50 border',
isSelected && 'bg-primary/20',
]"
:draggable
@dragstart="onDragStart"
@drop="onDrop"
@click="onClick"
>
<DirectoryEntryIcon :entry />
<div
class="flex w-full flex-col items-start justify-stretch gap-0 overflow-hidden text-left leading-6"
>
<span class="w-full truncate">{{ entry.name }}</span>
<NuxtTime
v-if="entry.createdAt != null"
:datetime="entry.createdAt * 1000"
class="text-muted-foreground w-full truncate text-sm"
relative
></NuxtTime>
</div>
</button>
</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem
:class="[warrenStore.current == null && 'hidden']"
@select="openRenameDialog"
>
<Icon name="lucide:pencil" />
Rename
</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
</ContextMenuItem>
<ContextMenuItem
:class="[warrenStore.current == null && 'hidden']"
@select="onShare"
>
<Icon name="lucide:share" />
Share
</ContextMenuItem>
<ContextMenuSeparator
:class="[warrenStore.current == null && 'hidden']"
/>
<ContextMenuItem
:class="[warrenStore.current == null && 'hidden']"
@select="() => onDelete(false)"
>
<Icon name="lucide:trash-2" />
Delete
</ContextMenuItem>
<ContextMenuItem
:class="[warrenStore.current == null && 'hidden']"
@select="() => onDelete(true)"
>
<Icon
class="text-destructive-foreground"
name="lucide:trash-2"
/>
Force delete
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
</template>