upend/webui/src/components/display/BlobPreview.svelte

122 lines
2.7 KiB
Svelte

<script lang="ts">
import { useEntity } from "../../lib/entity";
import Spinner from "../utils/Spinner.svelte";
import ModelViewer from "./blobs/ModelViewer.svelte";
import TextViewer from "./blobs/TextViewer.svelte";
export let address: string;
$: ({ entity } = useEntity(address));
$: mimeType = String($entity?.get("FILE_MIME"));
$: audio = ["audio", "application/x-riff"].some((p) =>
mimeType.startsWith(p)
);
$: video = ["video", "application/x-matroska"].some((p) =>
mimeType.startsWith(p)
);
$: image = mimeType.startsWith("image");
$: text = mimeType.startsWith("text");
$: pdf = mimeType.startsWith("application/pdf");
$: model = mimeType?.startsWith("model");
$: handled = audio || video || image || text || pdf || model;
let imageLoaded = null;
</script>
{#if handled}
<div class="preview">
{#if text}
<div class="text">
<TextViewer {address} />
</div>
{/if}
{#if audio}
{#if imageLoaded != address}
<Spinner />
{/if}
<img
src="api/thumb/{address}"
alt={address}
on:load={() => (imageLoaded = address)}
on:error={() => (imageLoaded = address)}
/>
<audio controls preload="auto" src="api/raw/{address}" />
{/if}
{#if video}
{#if imageLoaded != address}
<Spinner />
<img
src="api/thumb/{address}"
alt={address}
on:load={() => (imageLoaded = address)}
on:error={() => (imageLoaded = address)}
/>
{:else}
<!-- svelte-ignore a11y-media-has-caption -->
<video
controls
preload="auto"
src="api/raw/{address}"
poster="api/thumb/{address}"
/>
{/if}
{/if}
{#if image}
<a target="_blank" href="api/raw/{address}?inline=1">
{#if imageLoaded != address}
<Spinner />
{/if}
<img
src="api/thumb/{address}"
alt={address}
on:load={() => (imageLoaded = address)}
on:error={() => (handled = false)}
/>
</a>
{/if}
{#if pdf}
<iframe
src="api/raw/{address}?inline"
title="PDF document of {address}"
/>
{/if}
{#if model}
<ModelViewer src="api/raw/{address}" />
{/if}
</div>
{/if}
<style scoped lang="scss">
.preview {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
audio,
video,
img,
.text {
width: 100%;
max-height: 25em;
}
iframe {
width: 100%;
min-height: 25em;
}
.text {
display: flex;
margin-bottom: 1rem;
}
video {
background: rgba(128, 128, 128, 128);
}
</style>