initial commit - LeDiscord plateforme des copains
This commit is contained in:
178
frontend/src/components/VideoPlayer.vue
Normal file
178
frontend/src/components/VideoPlayer.vue
Normal file
@@ -0,0 +1,178 @@
|
||||
<template>
|
||||
<div class="video-player-container">
|
||||
<div class="relative">
|
||||
<!-- Video.js Player -->
|
||||
<video
|
||||
ref="videoPlayer"
|
||||
class="video-js vjs-default-skin vjs-big-play-centered w-full rounded-lg"
|
||||
controls
|
||||
preload="auto"
|
||||
:poster="posterUrl"
|
||||
data-setup="{}"
|
||||
>
|
||||
<source :src="videoUrl" type="video/mp4" />
|
||||
<p class="vjs-no-js">
|
||||
Pour voir cette vidéo, activez JavaScript et considérez passer à un navigateur web qui
|
||||
<a href="https://videojs.com/html5-video-support/" target="_blank">supporte la vidéo HTML5</a>.
|
||||
</p>
|
||||
</video>
|
||||
</div>
|
||||
|
||||
<!-- Video Stats -->
|
||||
<div class="mt-4 flex items-center justify-between text-sm text-gray-600">
|
||||
<div class="flex items-center space-x-4">
|
||||
<span class="flex items-center">
|
||||
<Eye class="w-4 h-4 mr-1" />
|
||||
{{ viewsCount }} vue{{ viewsCount > 1 ? 's' : '' }}
|
||||
</span>
|
||||
<span class="flex items-center">
|
||||
<Clock class="w-4 h-4 mr-1" />
|
||||
{{ formatDuration(duration) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-2">
|
||||
<button
|
||||
@click="toggleLike"
|
||||
class="flex items-center space-x-1 px-3 py-1 rounded-full transition-colors"
|
||||
:class="isLiked ? 'bg-red-100 text-red-600' : 'bg-gray-100 text-gray-600 hover:bg-gray-200'"
|
||||
>
|
||||
<Heart :class="isLiked ? 'fill-current' : ''" class="w-4 h-4" />
|
||||
<span>{{ likesCount }}</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
@click="toggleComments"
|
||||
class="flex items-center space-x-1 px-3 py-1 rounded-full bg-gray-100 text-gray-600 hover:bg-gray-200 transition-colors"
|
||||
>
|
||||
<MessageSquare class="w-4 h-4" />
|
||||
<span>{{ commentsCount }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted, onBeforeUnmount, watch, computed } from 'vue'
|
||||
import videojs from 'video.js'
|
||||
import 'video.js/dist/video-js.css'
|
||||
import { Eye, Clock, Heart, MessageSquare } from 'lucide-vue-next'
|
||||
import { getMediaUrl } from '@/utils/axios'
|
||||
|
||||
const props = defineProps({
|
||||
src: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
poster: {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
viewsCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
likesCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
commentsCount: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
isLiked: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['like', 'toggle-comments'])
|
||||
|
||||
const videoPlayer = ref(null)
|
||||
const player = ref(null)
|
||||
|
||||
// Computed properties pour les URLs
|
||||
const videoUrl = computed(() => getMediaUrl(props.src))
|
||||
const posterUrl = computed(() => getMediaUrl(props.poster))
|
||||
|
||||
function formatDuration(seconds) {
|
||||
if (!seconds) return '--:--'
|
||||
|
||||
const minutes = Math.floor(seconds / 60)
|
||||
const remainingSeconds = seconds % 60
|
||||
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
|
||||
}
|
||||
|
||||
function toggleLike() {
|
||||
emit('like')
|
||||
}
|
||||
|
||||
function toggleComments() {
|
||||
emit('toggle-comments')
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (videoPlayer.value) {
|
||||
player.value = videojs(videoPlayer.value, {
|
||||
controls: true,
|
||||
fluid: true,
|
||||
responsive: true,
|
||||
playbackRates: [0.5, 0.75, 1, 1.25, 1.5, 2],
|
||||
controlBar: {
|
||||
children: [
|
||||
'playToggle',
|
||||
'volumePanel',
|
||||
'currentTimeDisplay',
|
||||
'timeDivider',
|
||||
'durationDisplay',
|
||||
'progressControl',
|
||||
'playbackRateMenuButton',
|
||||
'fullscreenToggle'
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
// Error handling
|
||||
player.value.on('error', (error) => {
|
||||
console.error('Video.js error:', error)
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
if (player.value) {
|
||||
player.value.dispose()
|
||||
}
|
||||
})
|
||||
|
||||
// Watch for src changes to reload video
|
||||
watch(() => props.src, () => {
|
||||
if (player.value && videoUrl.value) {
|
||||
player.value.src({ src: videoUrl.value, type: 'video/mp4' })
|
||||
player.value.load()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.video-js {
|
||||
aspect-ratio: 16/9;
|
||||
}
|
||||
|
||||
.video-js .vjs-big-play-button {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user