viewer: animate lp icon
Signed-off-by: Varun Patil <radialapps@gmail.com>pull/900/head
parent
c6f5ed5b05
commit
5ccba14519
|
@ -24,7 +24,7 @@
|
|||
<VideoIcon :size="22" />
|
||||
</div>
|
||||
<div class="livephoto" v-if="data.liveid" @mouseenter.passive="playVideo" @mouseleave.passive="stopVideo">
|
||||
<LivePhotoIcon :size="22" :spin="liveWaiting" :playing="livePlaying" />
|
||||
<LivePhotoIcon :size="22" :spin="liveState.waiting" :playing="liveState.playing" />
|
||||
</div>
|
||||
<RawIcon class="raw" v-if="isRaw" :size="28" />
|
||||
</div>
|
||||
|
@ -119,9 +119,11 @@ export default defineComponent({
|
|||
|
||||
data: () => ({
|
||||
touchTimer: 0,
|
||||
livePlayTimer: 0,
|
||||
liveWaiting: false,
|
||||
livePlaying: false,
|
||||
liveState: {
|
||||
playTimer: 0,
|
||||
playing: false,
|
||||
waiting: false,
|
||||
},
|
||||
faceSrc: null as string | null,
|
||||
}),
|
||||
|
||||
|
@ -140,17 +142,14 @@ export default defineComponent({
|
|||
// Setup video hooks
|
||||
const video = this.refs.video;
|
||||
if (video) {
|
||||
utils.setupLivePhotoHooks(video);
|
||||
video.addEventListener('playing', () => (this.livePlaying = true));
|
||||
video.addEventListener('pause', () => (this.livePlaying = false));
|
||||
video.addEventListener('ended', () => (this.livePlaying = false));
|
||||
utils.setupLivePhotoHooks(video, this.liveState);
|
||||
}
|
||||
},
|
||||
|
||||
/** Clear timers */
|
||||
beforeDestroy() {
|
||||
clearTimeout(this.touchTimer);
|
||||
clearTimeout(this.livePlayTimer);
|
||||
clearTimeout(this.liveState.playTimer);
|
||||
|
||||
// Clean up blob url if face rect was created
|
||||
if (this.faceSrc) {
|
||||
|
@ -277,11 +276,11 @@ export default defineComponent({
|
|||
|
||||
/** Start preview video */
|
||||
playVideo() {
|
||||
this.liveWaiting = true;
|
||||
this.liveState.waiting = true;
|
||||
|
||||
utils.setRenewingTimeout(
|
||||
this,
|
||||
'livePlayTimer',
|
||||
this.liveState,
|
||||
'playTimer',
|
||||
async () => {
|
||||
const video = this.refs.video;
|
||||
if (!video || this.data.flag & this.c.FLAG_SELECTED) return;
|
||||
|
@ -292,7 +291,7 @@ export default defineComponent({
|
|||
} catch (e) {
|
||||
// ignore, pause was probably called too soon
|
||||
} finally {
|
||||
this.liveWaiting = false;
|
||||
this.liveState.waiting = false;
|
||||
}
|
||||
},
|
||||
400,
|
||||
|
@ -302,10 +301,9 @@ export default defineComponent({
|
|||
/** Stop preview video */
|
||||
stopVideo() {
|
||||
this.refs.video?.pause();
|
||||
window.clearTimeout(this.livePlayTimer);
|
||||
this.livePlayTimer = 0;
|
||||
this.liveWaiting = false;
|
||||
this.livePlaying = false;
|
||||
window.clearTimeout(this.liveState.playTimer);
|
||||
this.liveState.playTimer = 0;
|
||||
this.liveState.waiting = false;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
|
|
@ -20,6 +20,7 @@ class LivePhotoContentSetup {
|
|||
constructor(
|
||||
lightbox: PhotoSwipe,
|
||||
private psImage: PsImage,
|
||||
private liveState: { playing: boolean; waiting: boolean },
|
||||
) {
|
||||
lightbox.on('contentLoad', this.onContentLoad.bind(this));
|
||||
lightbox.on('contentActivate', this.onContentActivate.bind(this));
|
||||
|
@ -32,10 +33,13 @@ class LivePhotoContentSetup {
|
|||
if (!video) return;
|
||||
|
||||
try {
|
||||
this.liveState.waiting = true;
|
||||
video.currentTime = 0;
|
||||
await video.play();
|
||||
} catch (e) {
|
||||
// ignore, pause was probably called too soon
|
||||
} finally {
|
||||
this.liveState.waiting = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +64,7 @@ class LivePhotoContentSetup {
|
|||
div.appendChild(video);
|
||||
content.element = div;
|
||||
|
||||
utils.setupLivePhotoHooks(video);
|
||||
utils.setupLivePhotoHooks(video, this.liveState);
|
||||
|
||||
const img = this.psImage.getXImgElem(content, () => content.onLoaded());
|
||||
div.appendChild(img);
|
||||
|
|
|
@ -55,7 +55,9 @@
|
|||
:close-after-click="true"
|
||||
>
|
||||
{{ t('memories', 'Play Live Photo') }}
|
||||
<template #icon> <LivePhotoIcon :size="24" /> </template>
|
||||
<template #icon>
|
||||
<LivePhotoIcon :size="24" :playing="liveState.playing" :spin="liveState.waiting" />
|
||||
</template>
|
||||
</NcActionButton>
|
||||
<NcActionButton
|
||||
v-if="!routeIsPublic && !isLocal"
|
||||
|
@ -194,6 +196,7 @@ import PsLivePhoto from './PsLivePhoto';
|
|||
import type { IImageInfo, IPhoto, TimelineState } from '@typings';
|
||||
import type { PsContent } from './types';
|
||||
|
||||
import LivePhotoIcon from '@components/icons/LivePhoto.vue';
|
||||
import ShareIcon from 'vue-material-design-icons/ShareVariant.vue';
|
||||
import DeleteIcon from 'vue-material-design-icons/TrashCanOutline.vue';
|
||||
import StarIcon from 'vue-material-design-icons/Star.vue';
|
||||
|
@ -205,7 +208,6 @@ import TuneIcon from 'vue-material-design-icons/Tune.vue';
|
|||
import SlideshowIcon from 'vue-material-design-icons/PlayBox.vue';
|
||||
import EditFileIcon from 'vue-material-design-icons/FileEdit.vue';
|
||||
import AlbumRemoveIcon from 'vue-material-design-icons/BookRemove.vue';
|
||||
import LivePhotoIcon from 'vue-material-design-icons/MotionPlayOutline.vue';
|
||||
import AlbumIcon from 'vue-material-design-icons/ImageAlbum.vue';
|
||||
|
||||
const SLIDESHOW_MS = 5000;
|
||||
|
@ -220,6 +222,7 @@ export default defineComponent({
|
|||
NcActions,
|
||||
NcActionButton,
|
||||
ImageEditor,
|
||||
LivePhotoIcon,
|
||||
ShareIcon,
|
||||
DeleteIcon,
|
||||
StarIcon,
|
||||
|
@ -231,7 +234,6 @@ export default defineComponent({
|
|||
SlideshowIcon,
|
||||
EditFileIcon,
|
||||
AlbumRemoveIcon,
|
||||
LivePhotoIcon,
|
||||
AlbumIcon,
|
||||
},
|
||||
|
||||
|
@ -260,6 +262,13 @@ export default defineComponent({
|
|||
psImage: null as PsImage | null,
|
||||
psLivePhoto: null as PsLivePhoto | null,
|
||||
|
||||
/** Live photo state */
|
||||
liveState: {
|
||||
playing: false,
|
||||
waiting: false,
|
||||
},
|
||||
|
||||
/** List globals */
|
||||
list: [] as IPhoto[],
|
||||
globalCount: 0,
|
||||
globalAnchor: -1,
|
||||
|
@ -590,15 +599,15 @@ export default defineComponent({
|
|||
});
|
||||
|
||||
// Video support
|
||||
this.psVideo = new PsVideo(<PhotoSwipe>this.photoswipe, {
|
||||
this.psVideo = new PsVideo(<any>this.photoswipe, {
|
||||
preventDragOffset: 40,
|
||||
});
|
||||
|
||||
// Image support
|
||||
this.psImage = new PsImage(<PhotoSwipe>this.photoswipe);
|
||||
this.psImage = new PsImage(<any>this.photoswipe);
|
||||
|
||||
// Live Photo support
|
||||
this.psLivePhoto = new PsLivePhoto(<PhotoSwipe>this.photoswipe, <PsImage>this.psImage);
|
||||
this.psLivePhoto = new PsLivePhoto(<any>this.photoswipe, <any>this.psImage, this.liveState);
|
||||
|
||||
// Patch the close button to stop the slideshow
|
||||
const _close = this.photoswipe.close.bind(this.photoswipe);
|
||||
|
|
|
@ -162,13 +162,23 @@ export function getLivePhotoVideoUrl(p: IPhoto, transcode: boolean) {
|
|||
/**
|
||||
* Set up hooks to set classes on parent element for Live Photo
|
||||
* @param video Video element
|
||||
* @param parent State object to update (reactivity)
|
||||
*/
|
||||
export function setupLivePhotoHooks(video: HTMLVideoElement) {
|
||||
export function setupLivePhotoHooks(video: HTMLVideoElement, state: { playing: boolean }) {
|
||||
const div = video.closest('.memories-livephoto') as HTMLDivElement;
|
||||
|
||||
// Playing state
|
||||
video.addEventListener('playing', () => (state.playing = true));
|
||||
video.addEventListener('play', () => div.classList.add('playing'));
|
||||
video.addEventListener('canplay', () => div.classList.add('canplay'));
|
||||
video.addEventListener('ended', () => div.classList.remove('playing'));
|
||||
video.addEventListener('pause', () => div.classList.remove('playing'));
|
||||
|
||||
// Ended or pausing state
|
||||
const ended = () => {
|
||||
state.playing = false;
|
||||
div.classList.remove('playing');
|
||||
};
|
||||
video.addEventListener('ended', ended);
|
||||
video.addEventListener('pause', ended);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue