Skip to content

Commit

Permalink
feat(esl-media): observation for togglebale container state
Browse files Browse the repository at this point in the history
  • Loading branch information
fshovchko committed Nov 11, 2024
1 parent 6da1e38 commit e66c384
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 10 deletions.
8 changes: 2 additions & 6 deletions src/modules/esl-media/core/esl-media-iobserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,7 @@ function handleViewport(entry: IntersectionObserverEntry): void {
}

// Videos that playing and out of min ratio RATIO_TO_STOP should be stopped
if (video.active && entry.intersectionRatio <= RATIO_TO_STOP) {
video.pause();
}
if (entry.intersectionRatio <= RATIO_TO_STOP) video.$$attr('in-viewport', false);
// Play should start only for inactive and background(muted) videos that are visible more than on RATIO_TO_PLAY
if (!video.active && video.autoplay && entry.intersectionRatio >= RATIO_TO_PLAY) {
video.play();
}
if (entry.intersectionRatio >= RATIO_TO_PLAY) video.$$attr('in-viewport', true);
}
42 changes: 39 additions & 3 deletions src/modules/esl-media/core/esl-media.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {ESLBaseElement} from '../../esl-base-element/core';
import {ExportNs} from '../../esl-utils/environment/export-ns';
import {isElement} from '../../esl-utils/dom/api';
import {isSafeContains} from '../../esl-utils/dom/traversing';
import {CSSClassUtils} from '../../esl-utils/dom/class';
import {SPACE, PAUSE} from '../../esl-utils/dom/keys';
import {prop, attr, boolAttr, listen} from '../../esl-utils/decorators';
Expand Down Expand Up @@ -43,6 +43,7 @@ export class ESLMedia extends ESLBaseElement {
'fill-mode',
'aspect-ratio',
'play-in-viewport',
'in-viewport',
'muted',
'loop',
'controls',
Expand Down Expand Up @@ -99,6 +100,8 @@ export class ESLMedia extends ESLBaseElement {
@boolAttr() public playsinline: boolean;
/** Allows play resource only in viewport area */
@boolAttr() public playInViewport: boolean;
/** Viewport intersection marker */
@boolAttr({readonly: true}) public inViewport: boolean;
/** Allows to start viewing a resource from a specific time offset. */
@attr({parser: parseInt}) public startTime: number;

Expand Down Expand Up @@ -176,6 +179,7 @@ export class ESLMedia extends ESLBaseElement {

protected override attributeChangedCallback(attrName: string, oldVal: string, newVal: string): void {
if (!this.connected || oldVal === newVal) return;
// eslint-disable-next-line sonarjs/max-switch-cases
switch (attrName) {
case 'disabled':
case 'media-id':
Expand Down Expand Up @@ -205,6 +209,9 @@ export class ESLMedia extends ESLBaseElement {
this.$$on(this._onConditionChange);
this.deferredReinitialize();
break;
case 'in-viewport':
this.inViewport ? this.play() : this.pause();
break;
}
}

Expand All @@ -213,6 +220,14 @@ export class ESLMedia extends ESLBaseElement {
return this.conditionQuery.matches;
}

protected canPlay(): boolean {
return !this.playInViewport || (!this.active && this.autoplay && this.inViewport);
}

protected canPause(): boolean {
return this.active;
}

private reinitInstance(): void {
console.debug('[ESL] Media reinitialize ', this);
this._provider && this._provider.unbind();
Expand Down Expand Up @@ -259,12 +274,13 @@ export class ESLMedia extends ESLBaseElement {
this.deferredReinitialize.cancel();
this.reinitInstance();
}
if (!this.canActivate()) return null;
if (!this.canActivate() || !this.canPlay()) return null;
return this._provider && this._provider.safePlay();
}

/** Pause playing media */
public pause(): Promise<void> | null {
if (!this.canPause()) return null;
return this._provider && this._provider.safePause();
}

Expand Down Expand Up @@ -352,7 +368,7 @@ export class ESLMedia extends ESLBaseElement {
})
protected _onRefresh(e: Event): void {
const {target} = e;
if (isElement(target) && target.contains(this)) this._onResize();
if (isSafeContains(target as Node, this)) this._onResize();
}

@listen({
Expand All @@ -371,6 +387,26 @@ export class ESLMedia extends ESLBaseElement {
this.deferredReinitialize();
}

@listen({
event: 'esl:show',
target: window
})
protected _onContainerShow(e: Event): void {
const {target} = e;
if (!isSafeContains(target as Node, this)) return;
this.play();
}

@listen({
event: 'esl:hide',
target: window
})
protected _onContainerHide(e: Event): void {
const {target} = e;
if (!isSafeContains(target as Node, this)) return;
this.pause();
}

@listen('keydown')
protected _onKeydown(e: KeyboardEvent): void {
if (e.target !== this) return;
Expand Down
8 changes: 7 additions & 1 deletion src/modules/esl-utils/dom/traversing.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {isElement} from './api';
import type {Predicate} from '../misc/functions';

/** Checks if element matches passed selector or exact predicate function */
Expand All @@ -7,14 +8,19 @@ export const isMatches = (el: Element, matcher?: string | ((el: Element) => bool
return typeof matcher === 'undefined';
};

/** Safely checks if the target element is within the container element */
export const isSafeContains = (container: Node | null | undefined, element: Node | null | undefined): boolean => {
return isElement(element) && isElement(container) && container.contains(element);
};

/** Checks that `nodeA` and `nodeB` are from the same tree path */
export function isRelativeNode(nodeA: null | undefined, nodeB: Node | null | undefined): false;
/** Checks that `nodeA` and `nodeB` are from the same tree path */
export function isRelativeNode(nodeA: Node | null | undefined, nodeB: null | undefined): false;
/** Checks that `nodeA` and `nodeB` are from the same tree path */
export function isRelativeNode(nodeA: Node | null | undefined, nodeB: Node | null | undefined): boolean;
export function isRelativeNode(nodeA: Node | null | undefined, nodeB: Node | null | undefined): boolean {
return !!(nodeA && nodeB) && (nodeA.contains(nodeB) || nodeB.contains(nodeA));
return isSafeContains(nodeA, nodeB) || isSafeContains(nodeB, nodeA);
}

type IteratorFn = (el: Element) => Element | null;
Expand Down

0 comments on commit e66c384

Please sign in to comment.