playable
Version:
Video player based on HTML5Video
422 lines • 18.3 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.UPDATE_PROGRESS_INTERVAL_DELAY = void 0;
var tslib_1 = require("tslib");
var progress_view_1 = (0, tslib_1.__importDefault)(require("./progress.view"));
var video_data_1 = require("../../../../utils/video-data");
var constants_1 = require("../../../../constants");
var keyboard_control_1 = require("../../../keyboard-control/keyboard-control");
var keyboard_interceptor_1 = (0, tslib_1.__importStar)(require("../../../../utils/keyboard-interceptor"));
var formatTime_1 = (0, tslib_1.__importDefault)(require("../../core/utils/formatTime"));
var player_api_decorator_1 = (0, tslib_1.__importDefault)(require("../../../../core/player-api-decorator"));
exports.UPDATE_PROGRESS_INTERVAL_DELAY = 1000 / 60;
var ProgressControl = /** @class */ (function () {
function ProgressControl(_a) {
var engine = _a.engine, liveStateEngine = _a.liveStateEngine, eventEmitter = _a.eventEmitter, textMap = _a.textMap, tooltipService = _a.tooltipService, theme = _a.theme, previewThumbnail = _a.previewThumbnail, previewFullSize = _a.previewFullSize;
this._engine = engine;
this._liveStateEngine = liveStateEngine;
this._eventEmitter = eventEmitter;
this._textMap = textMap;
this._tooltipService = tooltipService;
this._previewThumbnail = previewThumbnail;
this._previewFullSize = previewFullSize;
this._isUserDragging = false;
this._desiredSeekPosition = 0;
this._theme = theme;
this._timeIndicatorsToAdd = [];
this._showFullScreenPreview = false;
this._bindCallbacks();
this._initUI();
this._bindEvents();
this.view.setPlayed(0);
this.view.setBuffered(0);
this._initInterceptor();
}
ProgressControl.prototype.getElement = function () {
return this.view.getElement();
};
ProgressControl.prototype._bindEvents = function () {
this._unbindEvents = this._eventEmitter.bindEvents([
[constants_1.VideoEvent.STATE_CHANGED, this._processStateChange],
[constants_1.VideoEvent.LIVE_STATE_CHANGED, this._processLiveStateChange],
[constants_1.VideoEvent.CHUNK_LOADED, this._updateBufferIndicator],
[constants_1.VideoEvent.DURATION_UPDATED, this._updateAllIndicators],
[constants_1.UIEvent.RESIZE, this.view.updateOnResize, this.view],
], this);
};
ProgressControl.prototype._initUI = function () {
var config = {
callbacks: {
onSyncWithLiveClick: this._syncWithLive,
onSyncWithLiveMouseEnter: this._onSyncWithLiveMouseEnter,
onSyncWithLiveMouseLeave: this._onSyncWithLiveMouseLeave,
onChangePlayedPercent: this._onChangePlayedPercent,
onSeekToByMouseStart: this._showTooltipAndPreview,
onSeekToByMouseEnd: this._hideTooltip,
onDragStart: this._startProcessingUserDrag,
onDragEnd: this._stopProcessingUserDrag,
},
theme: this._theme,
textMap: this._textMap,
tooltipService: this._tooltipService,
};
this.view = new ProgressControl.View(config);
};
ProgressControl.prototype._initInterceptor = function () {
var _a;
var _this = this;
this._interceptor = new keyboard_interceptor_1.default(this.view.getElement(), (_a = {},
_a[keyboard_interceptor_1.KEYCODES.UP_ARROW] = function (e) {
e.stopPropagation();
e.preventDefault();
_this._eventEmitter.emitAsync(constants_1.UIEvent.KEYBOARD_KEYDOWN_INTERCEPTED);
_this._eventEmitter.emitAsync(constants_1.UIEvent.GO_FORWARD_WITH_KEYBOARD);
_this._engine.seekForward(keyboard_control_1.AMOUNT_TO_SKIP_SECONDS);
},
_a[keyboard_interceptor_1.KEYCODES.DOWN_ARROW] = function (e) {
e.stopPropagation();
e.preventDefault();
_this._eventEmitter.emitAsync(constants_1.UIEvent.KEYBOARD_KEYDOWN_INTERCEPTED);
_this._eventEmitter.emitAsync(constants_1.UIEvent.GO_BACKWARD_WITH_KEYBOARD);
_this._engine.seekBackward(keyboard_control_1.AMOUNT_TO_SKIP_SECONDS);
},
_a[keyboard_interceptor_1.KEYCODES.RIGHT_ARROW] = function (e) {
e.stopPropagation();
e.preventDefault();
_this._eventEmitter.emitAsync(constants_1.UIEvent.KEYBOARD_KEYDOWN_INTERCEPTED);
_this._eventEmitter.emitAsync(constants_1.UIEvent.GO_FORWARD_WITH_KEYBOARD);
_this._engine.seekForward(keyboard_control_1.AMOUNT_TO_SKIP_SECONDS);
},
_a[keyboard_interceptor_1.KEYCODES.LEFT_ARROW] = function (e) {
e.stopPropagation();
e.preventDefault();
_this._eventEmitter.emitAsync(constants_1.UIEvent.KEYBOARD_KEYDOWN_INTERCEPTED);
_this._eventEmitter.emitAsync(constants_1.UIEvent.GO_BACKWARD_WITH_KEYBOARD);
_this._engine.seekBackward(keyboard_control_1.AMOUNT_TO_SKIP_SECONDS);
},
_a));
};
ProgressControl.prototype._destroyInterceptor = function () {
this._interceptor.destroy();
};
ProgressControl.prototype._bindCallbacks = function () {
this._syncWithLive = this._syncWithLive.bind(this);
this._onSyncWithLiveMouseEnter = this._onSyncWithLiveMouseEnter.bind(this);
this._onSyncWithLiveMouseLeave = this._onSyncWithLiveMouseLeave.bind(this);
this._updateAllIndicators = this._updateAllIndicators.bind(this);
this._onChangePlayedPercent = this._onChangePlayedPercent.bind(this);
this._showTooltipAndPreview = this._showTooltipAndPreview.bind(this);
this._hideTooltip = this._hideTooltip.bind(this);
this._startProcessingUserDrag = this._startProcessingUserDrag.bind(this);
this._stopProcessingUserDrag = this._stopProcessingUserDrag.bind(this);
};
ProgressControl.prototype._startIntervalUpdates = function () {
if (this._updateControlInterval) {
this._stopIntervalUpdates();
}
this._updateAllIndicators();
this._updateControlInterval = window.setInterval(this._updateAllIndicators, exports.UPDATE_PROGRESS_INTERVAL_DELAY);
};
ProgressControl.prototype._stopIntervalUpdates = function () {
window.clearInterval(this._updateControlInterval);
this._updateControlInterval = null;
};
ProgressControl.prototype._convertPlayedPercentToTime = function (percent) {
var duration = this._engine.getDuration();
return (duration * percent) / 100;
};
ProgressControl.prototype._onChangePlayedPercent = function (percent) {
var newTime = this._convertPlayedPercentToTime(percent);
if (this._showFullScreenPreview) {
this._desiredSeekPosition = newTime;
this._eventEmitter.emitAsync(constants_1.UIEvent.PROGRESS_USER_PREVIEWING_FRAME, newTime);
}
else {
this._changeCurrentTimeOfVideo(newTime);
}
if (this._isUserDragging) {
this._showTooltipAndPreview(percent);
}
};
ProgressControl.prototype._showTooltipAndPreview = function (percent) {
var duration = this._engine.getDuration();
var seekToTime = this._convertPlayedPercentToTime(percent);
var timeToShow = this._engine.isDynamicContent
? seekToTime - duration
: seekToTime;
this._previewThumbnail.setTime((0, formatTime_1.default)(timeToShow));
this._previewThumbnail.showAt(seekToTime);
this.view.showProgressTimeTooltip(this._previewThumbnail.getElement(), percent);
if (this._isUserDragging && this._showFullScreenPreview) {
this._previewFullSize.showAt(seekToTime);
}
};
ProgressControl.prototype._hideTooltip = function () {
if (!this._isUserDragging) {
this.view.hideProgressTimeTooltip();
}
};
ProgressControl.prototype._startProcessingUserDrag = function () {
if (!this._isUserDragging) {
this._isUserDragging = true;
this._pauseVideoOnDragStart();
this._eventEmitter.emitAsync(constants_1.UIEvent.PROGRESS_DRAG_STARTED);
this._eventEmitter.emitAsync(constants_1.UIEvent.CONTROL_DRAG_START);
}
};
ProgressControl.prototype._stopProcessingUserDrag = function () {
if (this._isUserDragging) {
this._isUserDragging = false;
if (this._showFullScreenPreview) {
this._shouldHidePreviewOnUpdate = true;
}
if (this._showFullScreenPreview) {
this._changeCurrentTimeOfVideo(this._desiredSeekPosition);
}
this._playVideoOnDragEnd();
this.view.hideProgressTimeTooltip();
this._eventEmitter.emitAsync(constants_1.UIEvent.PROGRESS_DRAG_ENDED);
this._eventEmitter.emitAsync(constants_1.UIEvent.CONTROL_DRAG_END);
}
};
ProgressControl.prototype._hidePreview = function () {
this._shouldHidePreviewOnUpdate = false;
this._previewFullSize.hide();
};
ProgressControl.prototype._processStateChange = function (_a) {
var nextState = _a.nextState;
switch (nextState) {
case constants_1.EngineState.SRC_SET:
this._reset();
break;
case constants_1.EngineState.METADATA_LOADED:
this._initTimeIndicators();
if (this._engine.isSeekAvailable) {
this.show();
}
else {
this.hide();
}
break;
case constants_1.EngineState.PLAYING:
if (this._shouldHidePreviewOnUpdate) {
this._hidePreview();
}
if (this._liveStateEngine.state === constants_1.LiveState.SYNC) {
this.view.setPlayed(100);
}
else {
this._startIntervalUpdates();
}
break;
case constants_1.EngineState.PAUSED:
if (this._shouldHidePreviewOnUpdate) {
this._hidePreview();
}
this._stopIntervalUpdates();
break;
case constants_1.EngineState.SEEK_IN_PROGRESS:
this._updateAllIndicators();
break;
default:
break;
}
};
ProgressControl.prototype._processLiveStateChange = function (_a) {
var nextState = _a.nextState;
switch (nextState) {
case constants_1.LiveState.NONE:
this.view.setLiveSyncState(false);
this.view.setUsualMode();
break;
case constants_1.LiveState.INITIAL:
this.view.setLiveMode();
break;
case constants_1.LiveState.SYNC:
this.view.setLiveSyncState(true);
break;
case constants_1.LiveState.NOT_SYNC:
this.view.setLiveSyncState(false);
break;
case constants_1.LiveState.ENDED:
this.view.setLiveSyncState(false);
this.view.hideSyncWithLive();
// ensure progress indicators show latest info
if (this._engine.getCurrentState() === constants_1.EngineState.PLAYING) {
this._startIntervalUpdates();
}
else {
this._updateAllIndicators();
}
break;
default:
break;
}
};
ProgressControl.prototype._changeCurrentTimeOfVideo = function (newTime) {
var duration = this._engine.getDuration();
if (this._engine.isDynamicContent && duration === newTime) {
this._engine.syncWithLive();
}
else {
this._engine.seekTo(newTime);
}
this._eventEmitter.emitAsync(constants_1.UIEvent.PROGRESS_CHANGE, newTime);
};
ProgressControl.prototype._pauseVideoOnDragStart = function () {
var currentState = this._engine.getCurrentState();
if (currentState === constants_1.EngineState.PLAYING ||
currentState === constants_1.EngineState.PLAY_REQUESTED) {
this._shouldPlayAfterDragEnd = true;
this._engine.pause();
}
this._eventEmitter.emitAsync(constants_1.UIEvent.PROGRESS_DRAG_STARTED);
};
ProgressControl.prototype._playVideoOnDragEnd = function () {
if (this._shouldPlayAfterDragEnd) {
this._engine.play();
this._shouldPlayAfterDragEnd = false;
}
};
ProgressControl.prototype._updateBufferIndicator = function () {
var currentTime = this._engine.getCurrentTime();
var buffered = this._engine.getBuffered();
var duration = this._engine.getDuration();
this._setBuffered((0, video_data_1.getOverallBufferedPercent)(buffered, currentTime, duration));
};
ProgressControl.prototype._updatePlayedIndicator = function () {
if (this._liveStateEngine.state === constants_1.LiveState.SYNC) {
// TODO: mb use this.updatePlayed(100) here?
return;
}
var currentTime = this._engine.getCurrentTime();
var duration = this._engine.getDuration();
this._setPlayed((0, video_data_1.getOverallPlayedPercent)(currentTime, duration));
};
ProgressControl.prototype._updateAllIndicators = function () {
this._updatePlayedIndicator();
this._updateBufferIndicator();
};
ProgressControl.prototype._initTimeIndicators = function () {
var _this = this;
this._timeIndicatorsToAdd.forEach(function (time) {
_this._addTimeIndicator(time);
});
this._timeIndicatorsToAdd = [];
};
ProgressControl.prototype._addTimeIndicator = function (time) {
var durationTime = this._engine.getDuration();
if (time > durationTime) {
// TODO: log error for developers
return;
}
this.view.addTimeIndicator((0, video_data_1.getTimePercent)(time, durationTime));
};
ProgressControl.prototype._syncWithLive = function () {
this._engine.syncWithLive();
};
ProgressControl.prototype._onSyncWithLiveMouseEnter = function () {
this._eventEmitter.emitAsync(constants_1.UIEvent.PROGRESS_SYNC_BUTTON_MOUSE_ENTER);
};
ProgressControl.prototype._onSyncWithLiveMouseLeave = function () {
this._eventEmitter.emitAsync(constants_1.UIEvent.PROGRESS_SYNC_BUTTON_MOUSE_LEAVE);
};
ProgressControl.prototype._setPlayed = function (percent) {
this.view.setPlayed(percent);
};
ProgressControl.prototype._setBuffered = function (percent) {
this.view.setBuffered(percent);
};
ProgressControl.prototype._reset = function () {
this._setPlayed(0);
this._setBuffered(0);
this.clearTimeIndicators();
};
/**
* Player will show full screen preview instead of actual seek on video when user drag the progress control
* @example
* player.showPreviewOnProgressDrag();
*/
ProgressControl.prototype.showPreviewOnProgressDrag = function () {
this._showFullScreenPreview = true;
};
/**
* Player will seek on video when user drag the progress control
* @example
* player.seekOnProgressDrag();
*/
ProgressControl.prototype.seekOnProgressDrag = function () {
this._showFullScreenPreview = false;
};
/**
* Add time indicator to progress bar
*/
ProgressControl.prototype.addTimeIndicator = function (time) {
this.addTimeIndicators([time]);
};
/**
* Add time indicators to progress bar
*/
ProgressControl.prototype.addTimeIndicators = function (times) {
var _a;
var _this = this;
if (!this._engine.isMetadataLoaded) {
// NOTE: Add indicator after metadata loaded
(_a = this._timeIndicatorsToAdd).push.apply(_a, times);
return;
}
times.forEach(function (time) {
_this._addTimeIndicator(time);
});
};
/**
* Delete all time indicators from progress bar
*/
ProgressControl.prototype.clearTimeIndicators = function () {
this.view.clearTimeIndicators();
};
ProgressControl.prototype.hide = function () {
this.isHidden = true;
this.view.hide();
};
ProgressControl.prototype.show = function () {
this.isHidden = false;
this.view.show();
};
ProgressControl.prototype.destroy = function () {
this._destroyInterceptor();
this._stopIntervalUpdates();
this._unbindEvents();
this.view.destroy();
};
ProgressControl.moduleName = 'progressControl';
ProgressControl.View = progress_view_1.default;
ProgressControl.dependencies = [
'engine',
'liveStateEngine',
'eventEmitter',
'textMap',
'tooltipService',
'theme',
'previewThumbnail',
'previewFullSize',
];
(0, tslib_1.__decorate)([
(0, player_api_decorator_1.default)()
], ProgressControl.prototype, "showPreviewOnProgressDrag", null);
(0, tslib_1.__decorate)([
(0, player_api_decorator_1.default)()
], ProgressControl.prototype, "seekOnProgressDrag", null);
(0, tslib_1.__decorate)([
(0, player_api_decorator_1.default)()
], ProgressControl.prototype, "addTimeIndicator", null);
(0, tslib_1.__decorate)([
(0, player_api_decorator_1.default)()
], ProgressControl.prototype, "addTimeIndicators", null);
(0, tslib_1.__decorate)([
(0, player_api_decorator_1.default)()
], ProgressControl.prototype, "clearTimeIndicators", null);
return ProgressControl;
}());
exports.default = ProgressControl;
//# sourceMappingURL=progress.js.map