Skip to content

Commit

Permalink
Implements enhancement ideas in #2924 and #2925 and fixes #2925 (#2927)
Browse files Browse the repository at this point in the history
  • Loading branch information
sancsin authored Jan 18, 2025
1 parent a8f321f commit bcd7e02
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 13 deletions.
114 changes: 105 additions & 9 deletions resources/js/composables/photo/slideshow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export function useSlideshowFunction(
delay: number,
is_slideshow_active: Ref<boolean>,
slide_show_interval: Ref<number>,
videoElement: Ref<HTMLVideoElement | null>,
getNext: () => void,
getPrevious?: () => void,
) {
Expand All @@ -18,14 +19,13 @@ export function useSlideshowFunction(

function start() {
is_slideshow_active.value = true;
curtainDown();
window.setTimeout(() => curtainUp(), delay); // We wait 500ms for the next photo to be loaded.
window.setTimeout(() => next(), delay + 1000 * slide_show_interval.value); // Set timeout for next iteration.
startSlideShow();
}

function stop() {
clearTimeouts();
curtainUp();
removeVideoElementListeners();
is_slideshow_active.value = false;
}

Expand All @@ -38,6 +38,20 @@ export function useSlideshowFunction(
}
}

function removeVideoElementListeners() {
videoElement.value?.removeEventListener("ended", videoEndedEventListener);
}

function videoEndedEventListener(event: Event) {
curtainDown();
window.setTimeout(() => {
removeVideoElementListeners();
getNext();
}, delay);
window.setTimeout(() => curtainUp(), delay * 2); // We wait 500ms for the next photo to be loaded.
window.setTimeout(() => next(), delay * 2 + 1000 * slide_show_interval.value); // Set timeout for next iteration.
}

function curtainDown() {
document.getElementById("shutter")?.classList?.remove("opacity-0");
}
Expand All @@ -47,33 +61,115 @@ export function useSlideshowFunction(
}

function next(immediate: boolean = false) {
if (!is_slideshow_active.value || immediate) {
removeVideoElementListeners();

/**
* If immediate is true and slideshow is not active then we need to get
* the next photo immediately
*/
if (immediate && is_slideshow_active.value === false) {
getNext();
return;
}

/**
* If immediate is true and slideshow is active then we need get the
* next photo immediately but add a timeout delay for loading the next
* photo i.e. continue the slideshow
*/

//
if (immediate && is_slideshow_active.value === true) {
clearTimeouts();
getNext();
window.setTimeout(() => next(), delay * 2 + 1000 * slide_show_interval.value); // Set timeout for next iteration.
return;
}

/**
* Handle the remaining scenario i.e immediate is false and slideshow is
* active.
*/

/**
* If current photo type is video then handle the slideshow timings
* in such a way that the video finishes before moving on to next photo */

if (videoElement.value && !videoElement.value.ended) {
clearTimeouts();
videoElement.value.addEventListener("ended", videoEndedEventListener);
return;
}
clearTimeouts();
continueNextSlideShow();
}

function startSlideShow() {
curtainDown();
window.setTimeout(() => curtainUp(), delay); // We wait 500ms for the next photo to be loaded.
window.setTimeout(() => next(), delay + 1000 * slide_show_interval.value); // Set timeout for next iteration.
}

function continueNextSlideShow() {
curtainDown(); // takes 500ms
window.setTimeout(() => getNext(), delay); // hence we wait 500ms for curtain to be down
window.setTimeout(() => curtainUp(), delay * 2); // We wait 500ms for the next photo to be loaded.
window.setTimeout(() => next(), delay * 2 + 1000 * slide_show_interval.value); // Set timeout for next iteration.
}

function continuePreviousSlideShow() {
curtainDown(); // takes 500ms
window.setTimeout(() => getPrevious?.(), 500); // hence we wait 500ms for curtain to be down
window.setTimeout(() => curtainUp(), 1000); // We wait 500ms for the next photo to be loaded.
window.setTimeout(() => next(), 1000 * slide_show_interval.value); // Set timeout for next iteration.
}

function previous(immediate: boolean = false) {
removeVideoElementListeners();

if (getPrevious === undefined) {
return;
}

if (!is_slideshow_active.value || immediate) {
/**
* If immediate is true and slideshow is not active then we need to get
* the previous photo immediately
*/
if (immediate && is_slideshow_active.value == false) {
getPrevious();
return;
}

/**
* If immediate is true and slideshow is active then we need get the
* previous photo immediately but add a timeout delay for loading the next
* photo i.e. continue the slideshow
*/

//
if (immediate && is_slideshow_active.value == true) {
clearTimeouts();
getPrevious();
window.setTimeout(() => next(), 1000 * slide_show_interval.value); // Set timeout for next iteration.
return;
}

/**
* Handle the remaining scenario i.e immediate is false and slideshow is
* active.
*/

/**
* If current photo type is video then handle the slideshow timings
* in such a way that the video finishes before moving on to next photo */

if (videoElement.value && !videoElement.value.ended) {
clearTimeouts();
videoElement.value?.addEventListener("ended", videoEndedEventListener);
return;
}
clearTimeouts();
curtainDown(); // takes 500ms
window.setTimeout(() => getPrevious(), 500); // hence we wait 500ms for curtain to be down
window.setTimeout(() => curtainUp(), 1000); // We wait 500ms for the next photo to be loaded.
window.setTimeout(() => next(), 1000 * slide_show_interval.value); // Set timeout for next iteration.
continuePreviousSlideShow();
}

return {
Expand Down
2 changes: 1 addition & 1 deletion resources/js/views/gallery-panels/Frame.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function getNext() {
});
}
const { slideshow, clearTimeouts } = useSlideshowFunction(1000, is_slideshow_active, refreshTimeout, getNext, undefined);
const { slideshow, clearTimeouts } = useSlideshowFunction(1000, is_slideshow_active, refreshTimeout, ref(null), getNext, undefined);
function start() {
AlbumService.frame(props.albumid ?? null).then((response) => {
Expand Down
14 changes: 11 additions & 3 deletions resources/js/views/gallery-panels/Photo.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,14 @@
<!-- <x-gallery.photo.overlay /> -->
</div>
<NextPrevious
v-if="photo.previous_photo_id !== null"
v-if="photo.previous_photo_id !== null && !is_slideshow_active"
:albumId="props.albumid"
:photoId="photo.previous_photo_id"
:is_next="false"
:style="previousStyle"
/>
<NextPrevious
v-if="photo.next_photo_id !== null"
v-if="photo.next_photo_id !== null && !is_slideshow_active"
:albumId="props.albumid"
:photoId="photo.next_photo_id"
:is_next="true"
Expand Down Expand Up @@ -204,7 +204,14 @@ function getPrevious() {
router.push({ name: "photo", params: { albumid: props.albumid, photoid: photo.value?.previous_photo_id ?? "" } });
}
const { slideshow, start, next, previous, stop } = useSlideshowFunction(1000, is_slideshow_active, slideshow_timeout, getNext, getPrevious);
const { slideshow, start, next, previous, stop } = useSlideshowFunction(
1000,
is_slideshow_active,
slideshow_timeout,
videoElement,
getNext,
getPrevious,
);
function load() {
if (togglableStore.isSearchActive) {
Expand Down Expand Up @@ -295,6 +302,7 @@ onKeyStroke("ArrowRight", () => !shouldIgnoreKeystroke() && hasNext() && next(tr
onKeyStroke("o", () => !shouldIgnoreKeystroke() && rotateOverlay());
onKeyStroke(" ", () => !shouldIgnoreKeystroke() && slideshow());
onKeyStroke("f", () => !shouldIgnoreKeystroke() && togglableStore.toggleFullScreen());
onKeyStroke("Escape", () => !shouldIgnoreKeystroke() && is_slideshow_active.value && stop());
// Priviledged operations
onKeyStroke("m", () => !shouldIgnoreKeystroke() && photo.value?.rights.can_edit && toggleMove());
Expand Down

0 comments on commit bcd7e02

Please sign in to comment.