172 lines
3.4 KiB
Vue
172 lines
3.4 KiB
Vue
<template>
|
|
<div ref="videoContainer" :class="{'video': true, 'video-mobile': mobile}">
|
|
<div ref="thumbnailContainer" :class="{'thumbnail-container': true, 'thumbnail-mobile': mobile}">
|
|
<img v-if="video" class="thumbnail" :src="video.thumbnail" alt="Video Thumbnail" />
|
|
<div v-else class="thumbnail-placeholder"></div>
|
|
<p v-if="video && typeof video.duration === 'number' && video.duration != 0 && !mobile" class="duration">{{ getVideoDuration(video.duration) }}</p>
|
|
<p v-else-if="video && video.duration === 0 && !mobile" class="duration align"><Icon font-size="10px" color="red" icon="fa-solid fa-circle"></Icon> LIVE</p>
|
|
<span v-else></span>
|
|
<slot></slot>
|
|
</div>
|
|
<div :class="{'info-mobile': mobile, 'info': !mobile}">
|
|
<Marquee v-if="video && mobile"><p>{{ video.title }}</p></Marquee>
|
|
<p v-else-if="video" class="title">{{ video.title }}</p>
|
|
<p v-else class="title">Aucun titre jouée</p>
|
|
|
|
<p v-if="video" class="author">{{ video.author }}</p>
|
|
<p v-else class="author">Aucun auteur</p>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<script setup>
|
|
import { getVideoDuration } from '@/utils/TimeConverter';
|
|
import { ref } from 'vue';
|
|
import Marquee from './Marquee.vue';
|
|
|
|
const props = defineProps({
|
|
video: {
|
|
required: true,
|
|
default: null
|
|
},
|
|
mobile: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
});
|
|
|
|
const thumbnailContainer = ref(null);
|
|
const videoContainer = ref(null);
|
|
|
|
function getThumbnailContainer() {
|
|
return thumbnailContainer.value;
|
|
}
|
|
|
|
function getVideoContainer() {
|
|
return videoContainer.value;
|
|
}
|
|
|
|
|
|
|
|
defineExpose({
|
|
getThumbnailContainer,
|
|
getVideoContainer,
|
|
});
|
|
</script>
|
|
<style scoped>
|
|
.align {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 3px;
|
|
}
|
|
|
|
.thumbnail {
|
|
width: 100%;
|
|
height: auto;
|
|
border-radius: 10px;
|
|
user-select: none;
|
|
aspect-ratio: 16/9;
|
|
object-fit: cover;
|
|
background-color: var(--tertiary);
|
|
}
|
|
|
|
.thumbnail-container {
|
|
position: relative;
|
|
display: flex;
|
|
width: 100%;
|
|
|
|
}
|
|
|
|
.thumbnail-mobile {
|
|
width: 100% !important;
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
max-width: 350px;
|
|
}
|
|
|
|
.thumbnail-placeholder {
|
|
flex: 1;
|
|
height: auto;
|
|
border-radius: 10px;
|
|
user-select: none;
|
|
aspect-ratio: 16/9;
|
|
object-fit: cover;
|
|
background-color: var(--quaternary);
|
|
|
|
}
|
|
|
|
.duration {
|
|
position: absolute;
|
|
bottom: 0px;
|
|
right: 0px;
|
|
background-color: rgba(0, 0, 0, 0.5);
|
|
color: white;
|
|
padding: 2px 5px;
|
|
border-radius: 15px;
|
|
font-size: 0.8em;
|
|
margin: 3% 0.5% 3% 3%;
|
|
}
|
|
|
|
.info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
flex: 1;
|
|
gap: 5px;
|
|
overflow-wrap: break-word;
|
|
word-break: break-word;
|
|
white-space: normal;
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
.info p {
|
|
margin: 0;
|
|
font-size: 0.9em;
|
|
}
|
|
|
|
.title {
|
|
|
|
font-weight: bold;
|
|
margin: 5px 0 0 0;
|
|
}
|
|
|
|
.author {
|
|
color: var(--text-secondary);
|
|
}
|
|
|
|
.video {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
justify-content: space-between;
|
|
gap: 5px;
|
|
}
|
|
|
|
.video-mobile {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: start !important;
|
|
cursor: pointer;
|
|
justify-content: space-between;
|
|
gap: 10px;
|
|
margin-left: 10px;
|
|
margin-right: 10px;
|
|
width: 100%;
|
|
}
|
|
|
|
.info-mobile {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 5px;
|
|
width: 100%;
|
|
}
|
|
|
|
.info-mobile p {
|
|
margin: 0;
|
|
font-size: 1.3em;
|
|
}
|
|
|
|
|
|
|
|
</style> |