Files
FabledCurator/frontend/src/components/modal/VideoCanvas.vue
T
bvandeusen 0faeebf3aa feat(fc2a): add ImageCanvas (pan/zoom) and VideoCanvas (with format gate)
ImageCanvas mounts an <img> wrapped in the usePanZoom composable —
spreading its handlers onto the container element. Zoom resets when src
changes so prev/next nav doesn't carry zoom state into the next image.

VideoCanvas plays MP4/WebM/Ogg/MOV natively. Non-playable formats render
a friendly explainer with a download fallback, naming the actual MIME so
operators know what they're dealing with, and pointing forward at FC-2e
where transcoding lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 12:33:41 -04:00

60 lines
1.6 KiB
Vue

<template>
<div class="fc-canvas fc-canvas--video">
<video
v-if="playable" :src="src" controls playsinline preload="metadata"
class="fc-canvas__video"
/>
<div v-else class="fc-canvas__unsupported">
<v-icon size="56" icon="mdi-video-off-outline" />
<h3 class="fc-canvas__unsupported-title">Format not browser-playable</h3>
<p>
This video isn't in a format the browser can play natively
(<code>{{ mime }}</code>). Transcoding to MP4 lands in FC-2e —
until then, you can download the original.
</p>
<v-btn :href="src" download variant="tonal" rounded="pill">
<v-icon start>mdi-download</v-icon>
Download original
</v-btn>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps({ src: String, mime: String })
const BROWSER_PLAYABLE = new Set([
'video/mp4', 'video/webm', 'video/ogg', 'video/quicktime'
])
const playable = computed(() => BROWSER_PLAYABLE.has(props.mime))
</script>
<style scoped>
.fc-canvas {
flex: 1;
background: rgb(var(--v-theme-background));
display: flex; align-items: center; justify-content: center;
}
.fc-canvas__video { max-width: 100%; max-height: 100%; }
.fc-canvas__unsupported {
text-align: center;
max-width: 520px;
padding: 32px;
color: rgb(var(--v-theme-on-surface));
}
.fc-canvas__unsupported-title {
font-family: 'Fraunces', Georgia, serif;
font-size: 22px;
font-weight: 500;
margin: 12px 0 8px;
}
code {
background: rgb(var(--v-theme-surface-light));
padding: 1px 6px;
border-radius: 4px;
font-family: 'JetBrains Mono', monospace;
}
</style>