Skip to content

Commit

Permalink
feat: autoplay video in view
Browse files Browse the repository at this point in the history
  • Loading branch information
mdshack committed Aug 4, 2024
1 parent 240d6e9 commit aa7dcdd
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 59 deletions.
136 changes: 78 additions & 58 deletions resources/js/Components/CardShot.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup>
import { onMounted, ref } from 'vue'
import { ChatBubbleLeftRightIcon, EllipsisHorizontalIcon, HandThumbUpIcon } from '@heroicons/vue/24/outline';
import { ChatBubbleLeftRightIcon as ChatSolid, HandThumbUpIcon as HandSolid } from '@heroicons/vue/24/solid';
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { ChatBubbleLeftRightIcon, EllipsisHorizontalIcon, HandThumbUpIcon } from '@heroicons/vue/24/outline'
import { ChatBubbleLeftRightIcon as ChatSolid, HandThumbUpIcon as HandSolid } from '@heroicons/vue/24/solid'
import {
Carousel,
Expand All @@ -17,28 +17,28 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/Components/ui/dropdown-menu'
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/Components/ui/dialog';
import { Button } from '@/Components/ui/button';
import { Button } from '@/Components/ui/button'
import User from '@/Components/User.vue'
import TimeAgo from '@/Components/ui/TimeAgo.vue'
import { Link, router, usePage } from '@inertiajs/vue3';
import axios from 'axios';
import ShotComments from '@/Components/ShotComments.vue';
import MustBeAuthenticatedDialog from '@/Components/MustBeAuthenticatedDialog.vue';
import RequireConfirmationDialog from '@/Components/RequireConfirmationDialog.vue';
import DialogEditShot from '@/Components/DialogEditShot.vue';
import videojs from 'video.js';
import { Link, usePage } from '@inertiajs/vue3'
import axios from 'axios'
import ShotComments from '@/Components/ShotComments.vue'
import MustBeAuthenticatedDialog from '@/Components/MustBeAuthenticatedDialog.vue'
import RequireConfirmationDialog from '@/Components/RequireConfirmationDialog.vue'
import DialogEditShot from '@/Components/DialogEditShot.vue'
import videojs from 'video.js'
import "video.js/dist/video-js.min.css"
const videos = ref([])
const props = defineProps({
shot: Object,
visible: Boolean,
condensed: {
type: Boolean,
default: false,
}
},
})
const emit = defineEmits([
Expand All @@ -49,6 +49,16 @@ const page = usePage()
const currentSlide = ref(0)
watch(() => props.visible, () => {
if(!(currentSlide.value in players.value)) return
if(props.visible) {
players.value[currentSlide.value].play()
} else {
players.value[currentSlide.value].pause()
}
})
const api = ref(null)
const setApi = (value) => {
Expand All @@ -73,24 +83,33 @@ const loadReactions = () => {
})
}
// const players = ref({})
const players = ref({})
onMounted(() => {
loadReactions()
props.shot.uploads
.filter(({type}) => type === 'video')
.forEach((_, i) => {
let element
if(Array.isArray(videos.value)) {
element = videos.value[i]
} else {
element = videos.value
}
videojs(element, {
controls: true
})
props.shot.uploads.forEach((shot, i) => {
if(shot.type !== 'video') return;
let element
if(Array.isArray(videos.value)) {
element = videos.value[i]
} else {
element = videos.value
}
players.value[i] = videojs(element, {
controls: true,
loop: true,
muted: true,
})
})
})
onUnmounted(() => {
for(let player in players.value) {
players.value[player].dispose()
}
})
const commentsOpen = ref(false)
Expand Down Expand Up @@ -154,7 +173,8 @@ const editShotOpen = ref(false)
<video
v-else
ref="videos"
class="video-js vjs-shotshare w-full max-h-[360px]">
class="video-js vjs-shotshare w-full max-h-[360px]"
:data-url="upload.url">
<source :src="upload.url">
</video>
</CarouselItem>
Expand All @@ -173,7 +193,8 @@ const editShotOpen = ref(false)
<video
v-else
ref="videos"
class="video-js vjs-shotshare w-full max-h-[360px]">
class="video-js vjs-shotshare w-full max-h-[360px]"
:data-url="shot.uploads[0]?.url">
<source :src="shot.uploads[0]?.url">
</video>
</template>
Expand Down Expand Up @@ -226,35 +247,34 @@ const editShotOpen = ref(false)
<h5 class="font-semibold p-4 pb-0">Comments</h5>
<ShotComments :shot="shot"/>
</div>
</div>

<div class="!my-0 !py-0">
<RequireConfirmationDialog
v-if="deleteShotOpen"
:open="true"
:action="deleteShot">
<template #title>
Are you sure you wish to delete this shot?
</template>

<template #description>
Deleting shots is a destructive action. You will not be able to recover this image if you delete it.
</template>

<template #reject>
Cancel
</template>

<template #confirm>
Delete Shot
</template>
</RequireConfirmationDialog>

<DialogEditShot
v-if="editShotOpen"
:shot="shot"
@close="editShotOpen = false"
/>
<div class="!my-0 !py-0">
<RequireConfirmationDialog
v-if="deleteShotOpen"
:open="true"
:action="deleteShot">
<template #title>
Are you sure you wish to delete this shot?
</template>

<template #description>
Deleting shots is a destructive action. You will not be able to recover this image if you delete it.
</template>

<template #reject>
Cancel
</template>

<template #confirm>
Delete Shot
</template>
</RequireConfirmationDialog>

<DialogEditShot
v-if="editShotOpen"
:shot="shot"
@close="editShotOpen = false"
/>
</div>
</div>
</template>
<style>
Expand Down
18 changes: 17 additions & 1 deletion resources/js/Components/PaginatedShotList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import CardShot from '@/Components/CardShot.vue';
import { Button } from '@/Components/ui/button';
import { ref, onMounted } from 'vue';
import { router } from '@inertiajs/vue3';
import { vElementVisibility } from '@vueuse/components'
const props = defineProps({
shots: Object,
Expand Down Expand Up @@ -30,10 +31,25 @@ const loadMore = () => {
}
})
}
const visible = ref([])
const onVideoVisible = (isVisible, shot) => {
if(isVisible) {
visible.value.push(shot.id)
} else {
visible.value.splice(visible.value.findIndex(id => id === shot.id), 1)
}
}
</script>
<template>
<div class="space-y-4">
<CardShot v-for="shot in formatted" :shot="shot" :condensed="condensed"/>
<CardShot
v-for="shot in formatted"
v-element-visibility="(e) => onVideoVisible(e, shot)"
:shot="shot"
:condensed="condensed"
:visible="visible.includes(shot.id)"
/>

<div v-if="!formatted?.length" class="flex items-center justify-center text-xl text-muted-foreground">
Nothing to see here
Expand Down

0 comments on commit aa7dcdd

Please sign in to comment.