UNPKG

playable

Version:

Video player based on HTML5Video

189 lines (153 loc) 4.31 kB
import { VideoEvent, UIEvent, LiveState } from '../../../constants'; import KeyboardInterceptor, { KEYCODES, } from '../../../utils/keyboard-interceptor'; import LiveIndicatorView from './live-indicator.view'; import { ITooltipService } from '../core/tooltip/types'; import { IEventEmitter } from '../../event-emitter/types'; import { ITextMap } from '../../text-map/types'; import { IPlaybackEngine } from '../../playback-engine/types'; import { ILiveIndicator } from './types'; export default class LiveIndicator implements ILiveIndicator { static moduleName = 'liveIndicator'; static View = LiveIndicatorView; static dependencies = ['engine', 'eventEmitter', 'textMap', 'tooltipService']; private _engine: IPlaybackEngine; private _eventEmitter: IEventEmitter; private _textMap: ITextMap; private _tooltipService: ITooltipService; private _interceptor: KeyboardInterceptor; private _isHidden: boolean = true; private _isActive: boolean = false; private _isEnded: boolean = false; private _unbindEvents: () => void; view: LiveIndicatorView; constructor({ engine, eventEmitter, textMap, tooltipService, }: { engine: IPlaybackEngine; eventEmitter: IEventEmitter; textMap: ITextMap; tooltipService: ITooltipService; }) { this._engine = engine; this._eventEmitter = eventEmitter; this._textMap = textMap; this._tooltipService = tooltipService; this._bindCallbacks(); this._initUI(); this._bindEvents(); this._initInterceptor(); } getElement() { return this.view.getElement(); } private _initInterceptor() { this._interceptor = new KeyboardInterceptor(this.getElement(), { [KEYCODES.SPACE_BAR]: e => { e.stopPropagation(); this._eventEmitter.emitAsync(UIEvent.KEYBOARD_KEYDOWN_INTERCEPTED); this._syncWithLive(); }, [KEYCODES.ENTER]: e => { e.stopPropagation(); this._eventEmitter.emitAsync(UIEvent.KEYBOARD_KEYDOWN_INTERCEPTED); this._syncWithLive(); }, }); } get isHidden(): boolean { return this._isHidden; } get isActive(): boolean { return this._isActive; } show() { this._toggle(true); } hide() { this._toggle(false); } private _initUI() { this.view = new LiveIndicator.View({ callbacks: { onClick: this._syncWithLive, }, textMap: this._textMap, tooltipService: this._tooltipService, }); } private _bindCallbacks() { this._syncWithLive = this._syncWithLive.bind(this); } private _bindEvents() { this._unbindEvents = this._eventEmitter.bindEvents( [ [VideoEvent.LIVE_STATE_CHANGED, this._processStateChange], [ UIEvent.PROGRESS_SYNC_BUTTON_MOUSE_ENTER, () => { this.view.toggleActive(true); }, ], [ UIEvent.PROGRESS_SYNC_BUTTON_MOUSE_LEAVE, () => { // NOTE: restore state before mouse enter this.view.toggleActive(this._isActive); }, ], ], this, ); } private _processStateChange({ nextState }: { nextState: LiveState }) { switch (nextState) { case LiveState.NONE: this._toggle(false); this._toggleActive(false); this._toggleEnded(false); break; case LiveState.INITIAL: this._toggle(true); break; case LiveState.SYNC: this._toggleActive(true); break; case LiveState.NOT_SYNC: this._toggleActive(false); break; case LiveState.ENDED: this._toggleActive(false); this._toggleEnded(true); break; default: break; } } private _syncWithLive() { if (!this._isEnded) { this._engine.syncWithLive(); } } private _toggle(shouldShow: boolean) { this._isHidden = !shouldShow; this.view.toggle(shouldShow); } private _toggleActive(shouldActivate: boolean) { this._isActive = shouldActivate; this.view.toggleActive(shouldActivate); } private _toggleEnded(isEnded: boolean) { this._isEnded = isEnded; this.view.toggleEnded(isEnded); } destroy() { this._unbindEvents(); this._interceptor.destroy(); this.view.destroy(); } }