wallace-screen-app/components/ScreenPlayer/ScreenPlayer.vue

95 lines
1.8 KiB
Vue

<template>
<view class="player">
<image
v-if="currentItem?.type === 'image'"
:key="currentItem.id"
class="media"
:src="currentItem.url"
mode="aspectFill"
@error="next"
/>
<video
v-else-if="currentItem?.type === 'video'"
:key="currentItem.id"
class="media video"
:src="currentItem.url"
:autoplay="true"
:controls="false"
:show-center-play-btn="false"
:show-play-btn="false"
:enable-progress-gesture="false"
object-fit="cover"
@ended="next"
@error="next"
/>
</view>
</template>
<script setup lang="ts">
import { computed, onBeforeUnmount, ref, watch } from 'vue'
import type { PlaylistItem } from '@/types/terminal'
const props = defineProps<{
items: PlaylistItem[]
}>()
const emit = defineEmits<{
cycleEnd: []
}>()
const currentIndex = ref(0)
let imageTimer: ReturnType<typeof setTimeout> | undefined
const currentItem = computed(() => props.items[currentIndex.value])
const clearImageTimer = () => {
if (!imageTimer) return
clearTimeout(imageTimer)
imageTimer = undefined
}
const scheduleImage = () => {
clearImageTimer()
if (currentItem.value?.type !== 'image') return
imageTimer = setTimeout(next, Math.max(currentItem.value.duration || 8, 1) * 1000)
}
const next = () => {
clearImageTimer()
if (!props.items.length) return
const isLast = currentIndex.value >= props.items.length - 1
currentIndex.value = isLast ? 0 : currentIndex.value + 1
if (isLast) emit('cycleEnd')
scheduleImage()
}
watch(
() => props.items,
() => {
currentIndex.value = 0
scheduleImage()
},
{ immediate: true }
)
onBeforeUnmount(clearImageTimer)
</script>
<style lang="scss" scoped>
.player,
.media {
width: 100vw;
height: 100vh;
}
.player {
background: #111111;
overflow: hidden;
}
.media {
display: block;
}
</style>