UNPKG

playable

Version:

Video player based on HTML5Video

236 lines (195 loc) 6.5 kB
import View from './volume.view'; import KeyboardInterceptor, { KEYCODES, } from '../../../../utils/keyboard-interceptor'; import { AMOUNT_TO_CHANGE_VOLUME } from '../../../keyboard-control/keyboard-control'; import { VideoEvent, UIEvent } from '../../../../constants'; import { IEventEmitter } from '../../../event-emitter/types'; import { ITooltipService } from '../../core/tooltip/types'; import { IVolumeControl, IVolumeViewConfig } from './types'; import { ITextMap } from '../../../text-map/types'; import { IPlaybackEngine } from '../../../playback-engine/types'; import { IThemeService } from '../../core/theme'; export default class VolumeControl implements IVolumeControl { static moduleName = 'volumeControl'; static View = View; static dependencies = [ 'engine', 'eventEmitter', 'textMap', 'tooltipService', 'theme', ]; private _engine: IPlaybackEngine; private _eventEmitter: IEventEmitter; private _textMap: ITextMap; private _tooltipService: ITooltipService; private _theme: IThemeService; private _buttonInterceptor: KeyboardInterceptor; private _inputInterceptor: KeyboardInterceptor; private _unbindEvents: () => void; view: View; isHidden: boolean; constructor({ engine, eventEmitter, textMap, tooltipService, theme, }: { eventEmitter: IEventEmitter; engine: IPlaybackEngine; textMap: ITextMap; tooltipService: ITooltipService; theme: IThemeService; }) { this._engine = engine; this._eventEmitter = eventEmitter; this._textMap = textMap; this._tooltipService = tooltipService; this._theme = theme; this._bindCallbacks(); this._initUI(); this._bindEvents(); this.view.setVolume(this._engine.getVolume()); this.view.setMute(this._engine.isMuted); this._initInterceptor(); } getElement() { return this.view.getElement(); } private _initUI() { const config: IVolumeViewConfig = { callbacks: { onDragStart: this._broadcastDragStart, onDragEnd: this._broadcastDragEnd, onVolumeLevelChangeFromInput: this._getVolumeLevelFromInput, onVolumeLevelChangeFromWheel: this._getVolumeLevelFromWheel, onToggleMuteClick: this._toggleMuteState, }, theme: this._theme, textMap: this._textMap, tooltipService: this._tooltipService, }; this.view = new VolumeControl.View(config); } private _initInterceptor() { this._buttonInterceptor = new KeyboardInterceptor( this.view.getButtonElement(), { [KEYCODES.SPACE_BAR]: e => { e.stopPropagation(); this._eventEmitter.emitAsync(UIEvent.KEYBOARD_KEYDOWN_INTERCEPTED); this._eventEmitter.emitAsync( this._engine.isMuted ? UIEvent.UNMUTE_WITH_KEYBOARD : UIEvent.MUTE_WITH_KEYBOARD, ); }, [KEYCODES.ENTER]: e => { e.stopPropagation(); this._eventEmitter.emitAsync(UIEvent.KEYBOARD_KEYDOWN_INTERCEPTED); this._eventEmitter.emitAsync( this._engine.isMuted ? UIEvent.UNMUTE_WITH_KEYBOARD : UIEvent.MUTE_WITH_KEYBOARD, ); }, }, ); this._inputInterceptor = new KeyboardInterceptor( this.view.getInputElement(), { [KEYCODES.RIGHT_ARROW]: e => { e.stopPropagation(); e.preventDefault(); this._eventEmitter.emitAsync(UIEvent.KEYBOARD_KEYDOWN_INTERCEPTED); this._eventEmitter.emitAsync(UIEvent.INCREASE_VOLUME_WITH_KEYBOARD); this._engine.setMute(false); this._engine.increaseVolume(AMOUNT_TO_CHANGE_VOLUME); }, [KEYCODES.LEFT_ARROW]: e => { e.stopPropagation(); e.preventDefault(); this._eventEmitter.emitAsync(UIEvent.KEYBOARD_KEYDOWN_INTERCEPTED); this._eventEmitter.emitAsync(UIEvent.DECREASE_VOLUME_WITH_KEYBOARD); this._engine.setMute(false); this._engine.decreaseVolume(AMOUNT_TO_CHANGE_VOLUME); }, }, ); } private _destroyInterceptor() { this._buttonInterceptor.destroy(); this._inputInterceptor.destroy(); } private _bindEvents() { this._unbindEvents = this._eventEmitter.bindEvents( [[VideoEvent.SOUND_STATE_CHANGED, this._updateSoundState]], this, ); } private _bindCallbacks() { this._getVolumeLevelFromInput = this._getVolumeLevelFromInput.bind(this); this._toggleMuteState = this._toggleMuteState.bind(this); this._getVolumeLevelFromWheel = this._getVolumeLevelFromWheel.bind(this); this._broadcastDragStart = this._broadcastDragStart.bind(this); this._broadcastDragEnd = this._broadcastDragEnd.bind(this); } private _broadcastDragStart() { this._eventEmitter.emitAsync(UIEvent.CONTROL_DRAG_START); } private _broadcastDragEnd() { this._eventEmitter.emitAsync(UIEvent.CONTROL_DRAG_END); } private _changeVolumeLevel(level: number) { this._engine.setVolume(level); this._eventEmitter.emitAsync(UIEvent.VOLUME_CHANGE, level); if (this._engine.isMuted) { this._toggleMuteState(); } } private _toggleMuteState() { const desiredMuteState = !this._engine.isMuted; this._engine.setMute(desiredMuteState); this._eventEmitter.emitAsync( desiredMuteState ? UIEvent.MUTE_CLICK : UIEvent.UNMUTE_CLICK, ); } private _getVolumeLevelFromWheel(delta: number) { if (!this._engine.isMuted) { const adjustedVolume = this._engine.getVolume() + delta / 10; const validatedVolume = Math.min(100, Math.max(0, adjustedVolume)); this._changeVolumeLevel(validatedVolume); } } private _getVolumeLevelFromInput(level: number) { this._changeVolumeLevel(level); } private _updateSoundState() { this._setVolumeLevel(this._engine.getVolume()); this._setMuteState(this._engine.isMuted); } private _setVolumeLevel(level: number) { this.view.setVolume(level); this.view.setMute(Boolean(!level)); } private _setMuteState(isMuted: boolean) { const volume = this._engine.getVolume(); this.view.setVolume(isMuted ? 0 : volume); this.view.setMute(isMuted || Boolean(!volume)); } hide() { this.isHidden = true; this.view.hide(); } show() { this.isHidden = false; this.view.show(); } destroy() { this._destroyInterceptor(); this._unbindEvents(); this.view.destroy(); } }