Skip to content

Instantly share code, notes, and snippets.

@martinherweg
Created July 28, 2020 13:31
Show Gist options
  • Save martinherweg/3297e02867eff18902ab0c5dcfcc5587 to your computer and use it in GitHub Desktop.
Save martinherweg/3297e02867eff18902ab0c5dcfcc5587 to your computer and use it in GitHub Desktop.
/* eslint-disable */
import Vue from "vue";
import VueCompositionAPI, {
computed,
onBeforeMount,
reactive,
toRefs,
} from "@vue/composition-api";
import { useVideoPlayer } from "../../../helpers/videoPlayer/videoPlayerFunctions";
Vue.use(VueCompositionAPI);
const state = reactive({
activeVideo: {},
videos: [],
})
// eslint-disable-next-line
export function useVideoGallery(videos = []) {
state.videos = videos;
const { toggleVideo } = useVideoPlayer()
function setActiveVideo(video, { startVideo = false } = {}) {
state.activeVideo = video;
if (startVideo) {
Vue.nextTick(() => toggleVideo());
}
}
onBeforeMount(() => {
setActiveVideo(state.videos[0]);
});
const upNext = computed(() => {
const lastVideo = state.videos[state.videos.length - 1];
if (lastVideo?.id === state.activeVideo?.id) {
return state.videos[0];
}
return state.videos.find((video) => video.id === state.activeVideo?.id + 1);
});
return {
...toRefs(state),
setActiveVideo,
upNext,
};
}
<template>
<div class="video-gallery__full">
<div
class="video-gallery-container"
:class="{
'video-gallery-container--playing': videoIsPlaying,
'video-gallery-container--stopped': !videoIsPlaying,
'video-gallery-container--ended': videoHasFinished,
}"
@click="toggleVideo"
>
<video-wrapper>
<RawIcon
v-show="!videoIsPlaying && !videoHasFinished"
:icon="icons.playButton"
/>
<template v-if="hasUpNext">
<button v-show="videoHasFinished" class="video-gallery-next">
<div
class="video-gallery-next__wrapper"
@click="setActiveVideo(upNext, { startVideo: true })"
>
<h4 class="video-gallery-next__title">Up next</h4>
<div class="video-gallery-next__thumb">
<video-wrapper>
<img
width="384"
height="217"
class="lazyload"
:data-src="upNext.thumbnail.src"
:data-srcset="upNext.thumbnail.srcset"
alt=""
/>
</video-wrapper>
</div>
</div>
</button>
</template>
<video-player
:key="activeVideo.id"
ref="videoPlayer"
:src="activeVideo.src"
:video-is-playing="videoIsPlaying"
/>
</video-wrapper>
</div>
</div>
</template>
<script>
import { computed, ref } from "@vue/composition-api";
import VideoWrapper from "../../helpers/videoWrapper/VideoWrapper.vue";
import VideoPlayer from "../../helpers/videoPlayer/videoPlayer.vue";
import RawIcon from "../../helpers/RawIcon.vue";
import { useVideoGallery } from "./use/useVideoGallery";
import { useVideoPlayer } from "../../helpers/videoPlayer/videoPlayerFunctions";
export default {
name: "VideoGalleryFull",
components: { VideoPlayer, RawIcon, VideoWrapper },
props: {
activeVideo: {
type: Object,
required: true,
},
upNext: {
type: Object,
required: true,
},
translations: {
type: Object,
default: () => ({
upNext: "Up Next",
}),
required: true,
},
icons: {
type: Object,
default: () => ({ playButton: "" }),
required: true,
},
},
setup() {
const videoPlayer = ref(0);
const { videoIsPlaying, videoHasFinished, toggleVideo } = useVideoPlayer(
videoPlayer
);
const { setActiveVideo, upNext } = useVideoGallery();
const hasUpNext = computed(() => {
return upNext && Object.keys(upNext).length > 0;
});
return {
toggleVideo,
setActiveVideo,
videoIsPlaying,
videoHasFinished,
hasUpNext,
upNext,
};
},
};
</script>
<template>
<div class="video-gallery">
<video-gallery-full
:active-video="activeVideo"
:up-next="upNext"
:icons="icons"
:translations="translations"
/>
<video-gallery-list
v-if="showGalleryList"
:videos="videos"
:active-video="activeVideo"
:set-active-video="setActiveVideo"
:icons="icons"
/>
</div>
</template>
<script>
/* eslint-disable */
import { computed, onMounted } from "@vue/composition-api";
import VideoGalleryFull from "./videoGallery--full.vue";
import VideoGalleryList from "./videoGallery--list.vue";
import { useVideoGallery } from "./use/useVideoGallery";
export default {
name: "VideoGallery",
components: { VideoGalleryList, VideoGalleryFull },
props: {
videos: {
type: Array,
required: true,
},
icons: {
type: Object,
required: true,
},
translations: {
type: Object,
required: true,
},
},
setup(props) {
const showGalleryList = computed(() => props.videos.length > 1);
onMounted(() => {
const { activeVideo, upNext, setActiveVideo } = useVideoGallery(props.videos);
})
return {
showGalleryList,
activeVideo,
upNext,
setActiveVideo
};
},
};
</script>
import Vue from "vue";
import VueCompositionAPI, {
onBeforeUnmount,
onMounted,
reactive,
toRefs,
} from "@vue/composition-api";
Vue.use(VueCompositionAPI);
// eslint-disable-next-line
export function useVideoPlayer(fullVideoRef) {
let fullVideo = null;
const videoState = reactive({
videoIsPlaying: false,
videoHasFinished: false,
});
function setVideoIsPlaying(playState) {
videoState.videoIsPlaying = playState;
if (fullVideo && playState) {
fullVideo.play();
}
}
function setVideoHasFinished(finishState) {
videoState.videoHasFinished = finishState;
if (finishState) {
setVideoIsPlaying(false);
}
}
function toggleVideo() {
setVideoIsPlaying(true);
setVideoHasFinished(false);
}
const handleVideoPlay = function () {
setVideoIsPlaying(true);
};
const handleVideoPause = function () {
setVideoIsPlaying(false);
};
const handleVideoFinished = function () {
setVideoHasFinished(true);
};
onMounted(() => {
if (fullVideoRef) {
fullVideo = fullVideoRef.value.$el;
console.log(fullVideo);
}
fullVideo.addEventListener("playing", handleVideoPlay);
fullVideo.addEventListener("pause", handleVideoPause);
fullVideo.addEventListener("ended", handleVideoFinished);
});
onBeforeUnmount(() => {
if (!fullVideo || fullVideo === null) {
return;
}
fullVideo.removeEventListener("playing", handleVideoPlay);
fullVideo.removeEventListener("pause", handleVideoPause);
fullVideo.removeEventListener("ended", handleVideoFinished);
});
return {
...toRefs(videoState),
fullVideo,
toggleVideo,
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment