2024-04-22 09:38:51 +02:00
|
|
|
<template>
|
2024-06-10 06:33:14 +02:00
|
|
|
<div class="aspect-video relative">
|
|
|
|
|
<div tabindex="0" aria-label="Open attachment in lightbox" role="button"
|
|
|
|
|
class="w-full h-full rounded ring-white/5 shadow overflow-hidden ring-1 hover:ring-2 duration-100 relative">
|
|
|
|
|
<img v-if="attachment.type === 'image'"
|
|
|
|
|
class="object-cover w-full h-full rounded duration-150 hover:scale-[102%] ease-in-out"
|
|
|
|
|
:src="attachment.url" :alt="attachment.description ?? undefined" @click="openLightbox"
|
|
|
|
|
@keydown="openLightbox" />
|
|
|
|
|
<video v-else-if="attachment.type === 'video'" class="object-contain w-full h-full rounded aspect-video"
|
|
|
|
|
controls :alt="attachment.description ?? undefined" :src="attachment.url">
|
|
|
|
|
Your browser does not support the video tag.
|
|
|
|
|
</video>
|
2024-07-22 01:05:51 +02:00
|
|
|
<a v-else class="bg-background-800 w-full h-full rounded flex items-center justify-center"
|
|
|
|
|
:href="attachment.url" target="_blank" download>
|
2024-06-10 06:33:14 +02:00
|
|
|
<div class="flex flex-col items-center gap-2 text-center max-w-56 overflow-hidden text-ellipsis">
|
2024-07-22 01:05:51 +02:00
|
|
|
<iconify-icon icon="tabler:file" width="none" class="size-10 text-text-300" />
|
|
|
|
|
<p class="text-text-300 text-sm font-mono">{{ getFilename(attachment.url) }}</p>
|
|
|
|
|
<p class="text-text-300 text-xs" v-if="attachment.meta?.length">{{
|
2024-06-20 01:57:38 +02:00
|
|
|
formatBytes(Number(attachment.meta?.length)) }}</p>
|
2024-06-10 06:33:14 +02:00
|
|
|
</div>
|
|
|
|
|
</a>
|
|
|
|
|
</div>
|
2024-06-06 05:19:03 +02:00
|
|
|
<!-- Alt text viewer -->
|
|
|
|
|
<Popover.Root :positioning="{
|
2024-06-20 01:57:38 +02:00
|
|
|
strategy: 'fixed',
|
|
|
|
|
}" v-if="attachment.description">
|
2024-06-06 05:48:12 +02:00
|
|
|
<Popover.Trigger aria-hidden="true"
|
2024-07-22 01:05:51 +02:00
|
|
|
class="absolute top-2 right-2 p-1 bg-background-800 ring-1 ring-white/5 text-white text-xs rounded size-8">
|
2024-06-06 05:19:03 +02:00
|
|
|
<iconify-icon icon="tabler:alt" width="none" class="size-6" />
|
|
|
|
|
</Popover.Trigger>
|
2024-06-10 05:24:55 +02:00
|
|
|
<Popover.Positioner class="!z-10">
|
2024-07-22 01:05:51 +02:00
|
|
|
<Popover.Content
|
|
|
|
|
class="p-4 bg-background-400 rounded text-sm ring-1 ring-background-100 shadow-lg text-text-300">
|
2024-06-06 05:19:03 +02:00
|
|
|
<Popover.Description>{{ attachment.description }}</Popover.Description>
|
|
|
|
|
</Popover.Content>
|
|
|
|
|
</Popover.Positioner>
|
|
|
|
|
</Popover.Root>
|
2024-04-22 09:38:51 +02:00
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
2024-06-06 05:19:03 +02:00
|
|
|
import { Popover } from "@ark-ui/vue";
|
2024-06-20 01:57:38 +02:00
|
|
|
import type { Attachment } from "@lysand-org/client/types";
|
2024-04-22 09:38:51 +02:00
|
|
|
|
2024-06-05 02:03:15 +02:00
|
|
|
const props = defineProps<{
|
2024-04-22 09:38:51 +02:00
|
|
|
attachment: Attachment;
|
|
|
|
|
}>();
|
2024-06-05 02:03:15 +02:00
|
|
|
|
|
|
|
|
const openLightbox = () => {
|
|
|
|
|
useEvent("attachment:view", props.attachment);
|
|
|
|
|
};
|
2024-06-06 06:05:55 +02:00
|
|
|
|
|
|
|
|
const formatBytes = (bytes: number) => {
|
2024-06-20 02:07:56 +02:00
|
|
|
if (bytes === 0) {
|
|
|
|
|
return "0 Bytes";
|
|
|
|
|
}
|
2024-06-06 06:05:55 +02:00
|
|
|
const k = 1000;
|
|
|
|
|
const dm = 2;
|
|
|
|
|
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
|
|
|
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
|
|
return `${Number.parseFloat((bytes / k ** i).toFixed(dm))} ${sizes[i]}`;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getFilename = (url: string) => {
|
|
|
|
|
// Handle proxy case
|
|
|
|
|
if (url.includes("/media/proxy")) {
|
|
|
|
|
// Decode last part of URL as base64url, which is the real URL
|
|
|
|
|
const realUrl = atob(url.split("/").pop() ?? "");
|
2024-06-06 08:42:44 +02:00
|
|
|
return decodeURIComponent(
|
|
|
|
|
realUrl.substring(realUrl.lastIndexOf("/") + 1),
|
|
|
|
|
);
|
2024-06-06 06:05:55 +02:00
|
|
|
}
|
|
|
|
|
const path = new URL(url).pathname;
|
|
|
|
|
return path.substring(path.lastIndexOf("/") + 1);
|
|
|
|
|
};
|
2024-04-22 09:38:51 +02:00
|
|
|
</script>
|