Files
archipelago 93f0017a4d ui: unify Companion file and video modals with Back and fullscreen
Use MediaLightbox for peer previews and owned files, preserve cached media URLs and payment flows, and keep documents in a modal with an explicit download. Add safe-area chrome, touch controls, same-URL Back history, focus restoration, and PiP blob ownership cleanup.

Focused Vitest: 103 tests across six viewer/PiP/paid-file/PeerFiles modules pass. Browser viewport fixtures are authored but not yet run; strict project types and physical Companion UX remain pending. No native, pairing, version, APK, or release changes.
2026-11-09 16:40:11 -05:00

38 lines
2.1 KiB
Vue

<template>
<main class="fixture-page">
<h1>Files</h1>
<button id="open-image" @click="open(0)">Open photo</button>
<button id="open-video" @click="open(1)">Open movie</button>
<button id="open-document" @click="open(2)">Open document</button>
<a href="#behind-modal">Background link</a>
<p id="download-result">{{ downloaded }}</p>
<MediaLightbox v-if="selected !== null" :items="items" :start-index="selected" :show="true"
:fetch-blob-url="fileUrl" :stream-url="fileUrl" :download-file="download" caption="Owned · unlocked"
@close="selected = null" />
</main>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import MediaLightbox from '../../src/components/cloud/MediaLightbox.vue'
import type { FileBrowserItem } from '../../src/api/filebrowser-client'
const selected = ref<number | null>(null)
const downloaded = ref('')
const items: FileBrowserItem[] = [
{ name: 'Mountain lake on a long summer evening.jpg', path: '/photo', type: 'image/jpeg' },
{ name: 'A film with a long filename.mp4', path: '/movie', type: 'video/mp4' },
{ name: 'Invoice with a long filename.pdf', path: '/document', type: 'application/pdf' },
].map(item => ({ ...item, isDir: false, size: 2048, modified: '', extension: item.name.split('.').pop()! }))
function open(index: number) { selected.value = index }
async function fileUrl(path: string) {
if (path === '/movie') return '/assets/video/video-intro.mp4'
if (path !== '/photo') throw new Error('Documents must not auto-fetch')
return 'data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="1280" height="800"><rect width="1280" height="800" fill="#31576c"/><path d="M0 500 380 100 680 460 900 160 1280 530v270H0" fill="#758d95"/><path d="M0 560h1280v240H0" fill="#193e51"/></svg>')
}
async function download(path: string) { downloaded.value = path }
</script>
<style>
:root { --safe-area-top: 24px; --safe-area-bottom: 20px; }
.fixture-page { min-height: 180vh; padding: 40px 20px; background: #303846; color: white; }
.fixture-page > button, .fixture-page > a { display: block; padding: 16px; margin: 12px 0; background: #506174; }
</style>