Skip to content

Commit

Permalink
Merge pull request #289 from dermotduffy/visibility
Browse files Browse the repository at this point in the history
Automatically pause/unload media on document visibility changes
  • Loading branch information
dermotduffy authored Jan 28, 2022
2 parents 748b4fc + 87aaa25 commit 9db5213
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 25 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ live:
| - | - | - | - |
| `preload` | `false` | :heavy_multiplication_x: | Whether or not to preload the live view. Preloading causes the live view to render in the background regardless of what view is actually shown, so it's instantly available when requested. This consumes additional network/CPU resources continually. |
| `lazy_load` | `true` | :heavy_multiplication_x: | Whether or not to lazily load cameras in the camera carousel. Setting this will `false` will cause all cameras to load simultaneously when the `live` carousel is opened (or cause all cameras to load continually if both `lazy_load` and `preload` are `true`). This will result in a smoother carousel experience at a cost of (potentially) a substantial amount of continually streamed data. |
| `lazy_unload` | `false` | :heavy_multiplication_x: | Whether or not to lazily **un**load cameras in the camera carousel, or just leave the camera paused. Setting this to `true` will cause cameras to be entirely unloaded when they are no longer visible. This will cause a reloading delay on revisiting that camera in the carousel but will save the streaming network resources that are otherwise consumed. |
| `lazy_unload` | `false` | :heavy_multiplication_x: | Whether or not to lazily **un**load cameras in the camera carousel, or just leave the camera paused. Setting this to `true` will cause cameras to be entirely unloaded when they are no longer visible (either because the carousel has scrolled past them, or because the document has been marked hidden/inactive by the browser). This will cause a reloading delay on revisiting that camera in the carousel but will save the streaming network resources that are otherwise consumed. |
| `draggable` | `true` | :heavy_multiplication_x: | Whether or not the live carousel can be dragged left or right, via touch/swipe and mouse dragging. |
| `provider` | `frigate` | :white_check_mark: | The means through which the live camera view is displayed. See [Live Provider](#live-provider) below.|
| `actions` | | :white_check_mark: | Actions to use for the `live` view. See [actions](#actions) below.|
Expand Down
13 changes: 13 additions & 0 deletions src/components/embla-plugins/lazyload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function Lazyload(userOptions?: LazyloadOptionsType): LazyloadType {
if (options.lazyunloadCallback) {
unloadEvents.forEach((evt) => carousel.on(evt, lazyunloadHandler));
}
document.addEventListener('visibilitychange', visibilityHandler);
}

/**
Expand All @@ -51,6 +52,18 @@ export function Lazyload(userOptions?: LazyloadOptionsType): LazyloadType {
if (options.lazyunloadCallback) {
unloadEvents.forEach((evt) => carousel.off(evt, lazyunloadHandler));
}
document.removeEventListener('visibilitychange', visibilityHandler);
}

/**
* Handle document visibility changes.
*/
function visibilityHandler(): void {
if (document.visibilityState == 'hidden' && lazyunloadHandler) {
lazyunloadHandler();
} else if (document.visibilityState == 'visible' && lazyloadHandler) {
lazyloadHandler();
}
}

/**
Expand Down
51 changes: 27 additions & 24 deletions src/components/embla-plugins/media-autoplay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,10 @@ import { EmblaCarouselType, EmblaPluginType } from 'embla-carousel';
import { FrigateCardMediaPlayer } from '../../types.js';

export type MediaAutoPlayPauseOptionsType = {
autoplay?: boolean;
autopause?: boolean;
playerSelector: string;
};

export const defaultOptions: Partial<MediaAutoPlayPauseOptionsType> = {
// Frigate card media autoplays when the media loads, not necessarily when the
// slide is selected.
autoplay: false,
autopause: true,
};
export const defaultOptions: Partial<MediaAutoPlayPauseOptionsType> = {};

export type MediaAutoPlayPauseType = EmblaPluginType<MediaAutoPlayPauseOptionsType> & {
play: () => void;
Expand All @@ -33,29 +26,32 @@ export function MediaAutoPlayPause(
carousel = embla;
slides = carousel.slideNodes();

if (options.autopause) {
carousel.on('destroy', pauseAllHandler);
carousel.on('select', pausePrevious);
}
// Frigate card media autoplays when the media loads not necessarily when the
// slide is selected, so only pause based on carousel events.
carousel.on('destroy', pauseAllHandler);
carousel.on('select', pausePrevious);

if (options.autoplay) {
carousel.on('select', play);
carousel.on('init', play);
}
document.addEventListener('visibilitychange', visibilityHandler);
}

/**
* Destroy the plugin.
*/
function destroy(): void {
if (options.autopause) {
carousel.off('destroy', pauseAllHandler);
carousel.off('select', pausePrevious);
}
carousel.off('destroy', pauseAllHandler);
carousel.off('select', pausePrevious);

document.removeEventListener('visibilitychange', visibilityHandler);
}

if (options.autoplay) {
carousel.off('select', play);
carousel.off('init', play);
/**
* Handle document visibility changes.
*/
function visibilityHandler(): void {
if (document.visibilityState == 'hidden') {
pause();
} else if (document.visibilityState == 'visible') {
play();
}
}

Expand All @@ -82,10 +78,17 @@ export function MediaAutoPlayPause(
getPlayer(slides[carousel.selectedScrollSnap()])?.play();
}

/**
* Autopause the current slide.
*/
function pause(): void {
getPlayer(slides[carousel.selectedScrollSnap()])?.pause();
}

/**
* Autopause the previous slide.
*/
function pausePrevious(): void {
function pausePrevious(): void {
getPlayer(slides[carousel.previousScrollSnap()])?.pause();
}

Expand Down

0 comments on commit 9db5213

Please sign in to comment.