view image files

This commit is contained in:
2025-07-23 13:47:42 +02:00
parent b3e68deb38
commit 7f8726c225
23 changed files with 553 additions and 45 deletions

View File

@@ -6,7 +6,11 @@ import {
ContextMenuItem,
ContextMenuSeparator,
} from '@/components/ui/context-menu';
import { deleteWarrenDirectory, deleteWarrenFile } from '~/lib/api/warrens';
import {
deleteWarrenDirectory,
deleteWarrenFile,
fetchFile,
} from '~/lib/api/warrens';
import type { DirectoryEntry } from '#shared/types';
const warrenStore = useWarrenStore();
@@ -49,11 +53,30 @@ async function openRenameDialog() {
}
async function onClick() {
if (warrenStore.loading) {
if (warrenStore.loading || warrenStore.current == null) {
return;
}
warrenStore.addToCurrentWarrenPath(entry.name);
if (entry.fileType === 'directory') {
warrenStore.addToCurrentWarrenPath(entry.name);
return;
}
if (entry.mimeType == null) {
return;
}
if (entry.mimeType.startsWith('image/')) {
const result = await fetchFile(
warrenStore.current.warrenId,
warrenStore.current.path,
entry.name
);
if (result.success) {
const url = URL.createObjectURL(result.data);
warrenStore.imageViewer.src = url;
}
}
}
</script>
@@ -62,12 +85,7 @@ async function onClick() {
<ContextMenuTrigger>
<button
:disabled="warrenStore.loading || disabled"
:class="[
'bg-accent/30 border-border flex w-52 flex-row gap-4 overflow-hidden rounded-md border-1 px-4 py-2 select-none',
{
'pointer-events-none': entry.fileType === 'file',
},
]"
class="bg-accent/30 border-border select-none, flex w-52 flex-row gap-4 overflow-hidden rounded-md border-1 px-4 py-2"
@click="onClick"
>
<div class="flex flex-row items-center">

View File

@@ -0,0 +1,29 @@
<script setup lang="ts">
const warrenStore = useWarrenStore();
function onOpenUpdate(state: boolean) {
if (!state) {
warrenStore.imageViewer.src = null;
}
}
</script>
<template>
<Dialog
:open="warrenStore.imageViewer.src != null"
@update:open="onOpenUpdate"
>
<DialogTrigger>
<slot />
</DialogTrigger>
<DialogContent
class="w-full overflow-hidden p-0 sm:!max-h-[90vh] sm:!max-w-[90vw]"
>
<img
v-if="warrenStore.imageViewer.src"
class="h-full w-full overflow-hidden !object-contain"
:src="warrenStore.imageViewer.src"
/>
</DialogContent>
</Dialog>
</template>

View File

@@ -16,6 +16,7 @@ await useAsyncData('warrens', async () => {
<template>
<SidebarProvider>
<ImageViewer />
<AppSidebar />
<SidebarInset class="flex flex-col-reverse md:flex-col">
<header

View File

@@ -265,3 +265,35 @@ export async function renameWarrenEntry(
return { success: true };
}
export async function fetchFile(
warrenId: string,
path: string,
fileName: string
): Promise<{ success: true; data: Blob } | { success: false }> {
if (!path.endsWith('/')) {
path += '/';
}
path += fileName;
const { data, error } = await useFetch<Blob>(
getApiUrl(`warrens/files/fetch?warrenId=${warrenId}&path=${path}`),
{
method: 'GET',
headers: getApiHeaders(),
responseType: 'blob',
cache: 'default',
}
);
if (data.value == null || error.value != null) {
return {
success: false,
};
}
return {
success: true,
data: data.value,
};
}

View File

@@ -5,6 +5,9 @@ import type { WarrenData } from '#shared/types/warrens';
export const useWarrenStore = defineStore('warrens', {
state: () => ({
warrens: {} as Record<string, WarrenData>,
imageViewer: {
src: null as string | null,
},
current: null as { warrenId: string; path: string } | null,
loading: false,
}),