Skip to content

Commit

Permalink
video: Embedded player on popover
Browse files Browse the repository at this point in the history
  • Loading branch information
ArturoManzoli committed Mar 26, 2024
1 parent d0196d7 commit 64943fe
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 67 deletions.
Binary file modified bun.lockb
Binary file not shown.
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
"sweetalert2": "^11.7.1",
"tailwind-scrollbar-hide": "^1.1.7",
"uuid": "^8.3.2",
"video.js": "^8.10.0",
"vue": "^3.3.4",
"vue-draggable-plus": "^0.2.0-beta.2",
"vue-router": "^4.0.14",
Expand Down
Binary file added src/assets/temp/test_video.webm
Binary file not shown.
99 changes: 48 additions & 51 deletions src/components/VideoPlayer.vue
Original file line number Diff line number Diff line change
@@ -1,41 +1,22 @@
<template>
<div v-if="openDialog" class="modal">
<div class="overlay" @click="closeDialog"></div>
<div class="overlay" @click="closeDialog">
<span class="close-icon mdi mdi-close" @click.stop="closeDialog"></span>
</div>
<div class="modal-content">
<video-player
class="video-player vjs-big-play-centered"
:src="videoFile"
poster="/images/poster/oceans.png"
crossorigin="anonymous"
playsinline
controls
:volume="0.6"
:height="640"
:playback-rates="[0.7, 1.0, 1.5, 2.0]"
@mounted="handleMounted"
@ready="handleEvent"
@play="handleEvent"
@pause="handleEvent"
@ended="handleEvent"
@loadeddata="handleEvent"
@waiting="handleEvent"
@playing="handleEvent"
@canplay="handleEvent"
@canplaythrough="handleEvent"
@timeupdate="(event) => handleEvent(player?.currentTime())"
/>
<video id="my-video" class="video-js" controls preload="auto" width="1000px" data-setup="{}">
<source :src="videoFileUrl" type="video/webm" />
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
</p>
</video>
</div>
</div>
</template>

<script lang="ts" setup>
import 'video.js/dist/video-js.css'
import { VideoPlayer } from '@videojs-player/vue'
import videojs from 'video.js'
import { ref, shallowRef, watchEffect } from 'vue'
type VideoJsPlayer = ReturnType<typeof videojs>
import { ref, watchEffect } from 'vue'
const props = defineProps({
videoUrl: String,
Expand All @@ -44,26 +25,16 @@ const props = defineProps({
const emit = defineEmits(['update:openVideoPlayerDialog'])
const player = shallowRef<VideoJsPlayer | null>(null)
const videoFile = ref(props.videoUrl)
const videoFileUrl = ref(props.videoUrl)
const openDialog = ref(props.openVideoPlayerDialog)
const handleMounted = (payload: any): void => {
player.value = payload.player
console.log('Video player mounted', payload)
}
const handleEvent = (log: any): void => {
console.log('Video player event', log)
}
const closeDialog = (): void => {
openDialog.value = false
emit('update:openVideoPlayerDialog', false)
}
watchEffect(() => {
videoFile.value = props.videoUrl
videoFileUrl.value = props.videoUrl
openDialog.value = props.openVideoPlayerDialog
})
</script>
Expand All @@ -73,27 +44,53 @@ watchEffect(() => {
position: fixed;
top: 50%;
left: 50%;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 30px;
z-index: 1000;
backdrop-filter: blur(10px);
}
.overlay {
position: absolute;
position: fixed;
top: 0;
left: 0;
background-color: rgba(255, 255, 255, 0.2);
z-index: 990;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
border-radius: 12px;
}
.close-icon {
position: absolute;
top: 0px;
right: 5px;
cursor: pointer;
color: white;
font-size: 24px;
border-radius: 8px;
}
.modal-content {
z-index: 10;
position: relative;
padding: 20px;
background: white;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: rgba(255, 255, 255, 0.5);
border-radius: 8px;
padding: 5px;
width: 1000px;
height: 565px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
z-index: 1200;
}
video {
height: 580px;
}
</style>
12 changes: 9 additions & 3 deletions src/components/mini-widgets/MiniVideoRecorder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,14 @@
</div>
<div v-if="numberOfVideosOnDB > 0" class="flex justify-center w-8">
<v-divider vertical class="h-6" />
<v-badge color="info" :content="numberOfVideosOnDB" :dot="isOutside || isVideoLibraryDialogOpen"
><v-icon class="w-6 h-6 text-slate-100 ml-3" @click="isVideoLibraryDialogOpen = true">
<v-badge
color="info"
:content="numberOfVideosOnDB"
:dot="isOutside || isVideoLibraryDialogOpen"
class="cursor-pointer"
@click="isVideoLibraryDialogOpen = true"
>
<v-icon class="w-6 h-6 text-slate-100 ml-3" @click="isVideoLibraryDialogOpen = true">
mdi-video-box
</v-icon></v-badge
>
Expand Down Expand Up @@ -76,7 +82,7 @@
</div>
</div>
</v-dialog>
<v-dialog v-model="isVideoLibraryDialogOpen" width="auto">
<v-dialog v-model="isVideoLibraryDialogOpen" width="900px">
<ConfigurationVideoView as-video-library />
</v-dialog>
</template>
Expand Down
56 changes: 44 additions & 12 deletions src/views/ConfigurationVideoView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,46 @@
class="max-w-[90%] bg-slate-100/30 rounded-lg p-3 border"
:class="temporaryDbSize === 0 ? 'mb-10' : 'mb-0'"
>
<template #[`item.filename`]="{ item }">
<span
v-if="item.filename.endsWith('.webm')"
class="cursor-pointer hover:underline"
@click="playVideoOnModal([item.filename])"
>
{{ item.filename }}
</span>
<span v-else>
{{ item.filename }}
</span>
</template>
<template #item.size="{ value }">
{{ formatBytes(value) }}
</template>
<template #item.actions="{ item }">
<span
v-if="selectedFilesNames.isEmpty()"
class="mx-1 transition-all cursor-pointer hover:text-slate-500/50 mdi mdi-trash-can"
class="mx-2 transition-all cursor-pointer hover:text-slate-500/50 mdi mdi-trash-can"
style="font-size: 17px"
@click="discardAndUpdateDB([item.filename])"
/>
<span
v-if="selectedFilesNames.isEmpty()"
class="mx-1 transition-all cursor-pointer hover:text-slate-500/50 mdi mdi-download"
class="mx-0 transition-all cursor-pointer hover:text-slate-500/50 mdi mdi-download"
style="font-size: 17px"
@click="downloadAndUpdateDB([item.filename])"
/>
<span
v-if="selectedFilesNames.isEmpty()"
class="mx-1 ml-2 transition-all mdi mdi-play"
:class="{
'hover:text-slate-500/50': item.filename.endsWith('.webm'),
'cursor-pointer': item.filename.endsWith('.webm'),
'cursor-default': !item.filename.endsWith('.webm'),
}"
:style="{ fontSize: '20px', opacity: item.filename.endsWith('.webm') ? '1' : '0.1' }"
@click="item.filename.endsWith('.webm') && playVideoOnModal([item.filename])"
>
</span>
</template>
<template #footer.prepend>
<Transition name="horizontalFade">
Expand Down Expand Up @@ -139,7 +165,7 @@
</div>
</template>
</BaseConfigurationView>
<VideoPlayer :video-url="videoFile" :open-video-player-dialog="openDialog" />
<VideoPlayer :video-url="videoFile" :open-video-player-dialog="openVideoPlayerDialog" />
</template>

<script setup lang="ts">
Expand All @@ -166,9 +192,13 @@ const props = defineProps<{
asVideoLibrary?: boolean
}>()
/* eslint-enable jsdoc/require-jsdoc */
const availableVideosAndLogs = ref<VideoStorageFile[] | undefined>()
const isVideoLibraryOnly = ref(props.asVideoLibrary)
const videoFile = ref<string | undefined>()
const openDialog = ref<boolean>(false)
const videoFile = ref()
const openVideoPlayerDialog = ref<boolean>(false)
const temporaryDbSize = ref(0)
const selectedFilesNames = ref<string[]>([])
watchEffect(() => {
isVideoLibraryOnly.value = props.asVideoLibrary ?? false
Expand All @@ -180,10 +210,6 @@ interface VideoStorageFile {
filename: string
size: number
}
/* eslint-enable jsdoc/require-jsdoc */
const availableVideosAndLogs = ref<VideoStorageFile[] | undefined>()
const temporaryDbSize = ref(0)
const selectedFilesNames = ref<string[]>([])
onMounted(async () => {
await fetchVideoAndLogsData()
Expand Down Expand Up @@ -224,9 +250,15 @@ const downloadAndUpdateDB = async (filenames: string[]): Promise<void> => {
selectedFilesNames.value = []
}
const playVideoOnModal = (filenames: string[]): void => {
videoFile.value = filenames[0]
openDialog.value = true
async function playVideoOnModal(videoFileName: string[]): Promise<void> {
const videoBlob = await videoStore.videoStoringDB.getItem(videoFileName[0])
if (videoBlob instanceof Blob) {
const tempFileUrl = URL.createObjectURL(videoBlob)
videoFile.value = tempFileUrl
openVideoPlayerDialog.value = true
} else {
console.error('Video data is not a Blob:', videoBlob)
}
}
const clearTemporaryVideoFiles = async (): Promise<void> => {
Expand Down

0 comments on commit 64943fe

Please sign in to comment.