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.
38 lines
2.1 KiB
Vue
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>
|