@cassette/core
Version:
A simple, clean, and responsive visual wrapper for the HTML audio tag, built with React.
1,222 lines (986 loc) • 116 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("prop-types"), require("react"));
else if(typeof define === 'function' && define.amd)
define(["prop-types", "react"], factory);
else if(typeof exports === 'object')
exports["cassetteCore"] = factory(require("prop-types"), require("react"));
else
root["cassetteCore"] = factory(root["PropTypes"], root["React"]);
})((typeof self !== "undefined" ? self : this), function(__WEBPACK_EXTERNAL_MODULE__0__, __WEBPACK_EXTERNAL_MODULE__1__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "/dist";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 7);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE__0__;
/***/ }),
/* 1 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE__1__;
/***/ }),
/* 2 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return logError; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "b", function() { return logWarning; });
/* eslint-disable no-console */
var log = console.log.bind(console);
var logError = console.error ? console.error.bind(console) : log;
var logWarning = console.warn ? console.warn.bind(console) : log;
/***/ }),
/* 3 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
/* WEBPACK VAR INJECTION */(function(global) {/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _console__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
var packageVersion = __webpack_require__(6).version;
var _global = typeof window === 'undefined' ? global : window;
_global.__cassette_contexts__ = _global.__cassette_contexts__ || {};
function createSingleGlobalContext(_ref) {
var displayName = _ref.displayName,
_ref$defaultValue = _ref.defaultValue,
defaultValue = _ref$defaultValue === void 0 ? null : _ref$defaultValue,
keysWillUpdate = _ref.keysWillUpdate;
var ExistingContext = _global.__cassette_contexts__[displayName];
if (ExistingContext) {
if (ExistingContext.packageVersion !== packageVersion) {
Object(_console__WEBPACK_IMPORTED_MODULE_1__[/* logWarning */ "b"])("Warning: multiple versions of " + displayName + " from the @cassette/core" + (" package have been loaded. v" + packageVersion + " will be ignored and") + (" v" + ExistingContext.packageVersion + " will be used instead."));
}
return ExistingContext;
} // inspired by:
// https://github.com/philosaf/observed-bits/blob/master/src/index.js
var flags = {};
var i = 0;
for (var _iterator = keysWillUpdate, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref2;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref2 = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref2 = _i.value;
}
var key = _ref2;
flags[key] = 1 << i++;
}
var Context = Object(react__WEBPACK_IMPORTED_MODULE_0__["createContext"])(defaultValue, function getChangedBits(prev, next) {
var mask = 0;
for (var _iterator2 = keysWillUpdate, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref3;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref3 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref3 = _i2.value;
}
var key = _ref3;
if (prev[key] !== next[key]) {
mask |= flags[key];
}
}
return mask;
});
Context.__cassetteGetObservedBits = function (keys) {
var observedBits = 0;
for (var _iterator3 = keys, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
var _ref4;
if (_isArray3) {
if (_i3 >= _iterator3.length) break;
_ref4 = _iterator3[_i3++];
} else {
_i3 = _iterator3.next();
if (_i3.done) break;
_ref4 = _i3.value;
}
var key = _ref4;
observedBits |= flags[key];
}
return observedBits;
};
Context.displayName = displayName;
Context.packageVersion = packageVersion;
_global.__cassette_contexts__[displayName] = Context;
return Context;
}
/* harmony default export */ __webpack_exports__["a"] = (createSingleGlobalContext);
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(5)))
/***/ }),
/* 4 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
module.exports = function (arr, predicate, ctx) {
if (typeof Array.prototype.findIndex === 'function') {
return arr.findIndex(predicate, ctx);
}
if (typeof predicate !== 'function') {
throw new TypeError('predicate must be a function');
}
var list = Object(arr);
var len = list.length;
if (len === 0) {
return -1;
}
for (var i = 0; i < len; i++) {
if (predicate.call(ctx, list[i], i, list)) {
return i;
}
}
return -1;
};
/***/ }),
/* 5 */
/***/ (function(module, exports) {
var g;
// This works in non-strict mode
g = (function() {
return this;
})();
try {
// This works if eval is allowed (see CSP)
g = g || Function("return this")() || (1, eval)("this");
} catch (e) {
// This works if the window reference is available
if (typeof window === "object") g = window;
}
// g can still be undefined, but nothing to do about it...
// We return undefined, instead of nothing here, so it's
// easier to handle this case. if(!global) { ...}
module.exports = g;
/***/ }),
/* 6 */
/***/ (function(module) {
module.exports = {"name":"@cassette/core","version":"2.0.0-beta.4","description":"A simple, clean, and responsive visual wrapper for the HTML audio tag, built with React.","main":"dist/es5/cassette-core.js","scripts":{"build:clean":"rimraf dist","build:webpack":"BUILD_MODE=all webpack --progress","build":"npm run build:clean && npm run build:webpack","prepare":"npm run build","test":"echo \"Error: no test specified\" && exit 1"},"repository":{"type":"git","url":"https://github.com/benwiley4000/cassette.git"},"engines":{"node":">=6.0.0","npm":">=5.0.0"},"keywords":["audio","video","media","ui","react","reactjs","responsive","music","player","html5","component","components"],"author":{"name":"Ben Wiley","email":"therealbenwiley@gmail.com","url":"http://benwiley.org/"},"license":"MIT","peerDependencies":{"react":"^16.3.0"},"devDependencies":{"array-find-index":"^1.0.2","rimraf":"^2.5.4","webpack":"^4.17.1"},"dependencies":{"prop-types":"^15.5.10"},"publishConfig":{"access":"public"},"gitHead":"0b53bfc554d37befcf6340dda3e94019f657e7d0"};
/***/ }),
/* 7 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
var PlayerPropTypes_namespaceObject = {};
__webpack_require__.r(PlayerPropTypes_namespaceObject);
__webpack_require__.d(PlayerPropTypes_namespaceObject, "controlKeyword", function() { return controlKeyword; });
__webpack_require__.d(PlayerPropTypes_namespaceObject, "control", function() { return control; });
__webpack_require__.d(PlayerPropTypes_namespaceObject, "crossOriginAttribute", function() { return crossOriginAttribute; });
__webpack_require__.d(PlayerPropTypes_namespaceObject, "repeatStrategy", function() { return PlayerPropTypes_repeatStrategy; });
__webpack_require__.d(PlayerPropTypes_namespaceObject, "mediaSource", function() { return mediaSource; });
__webpack_require__.d(PlayerPropTypes_namespaceObject, "mediaSessionAction", function() { return mediaSessionAction; });
__webpack_require__.d(PlayerPropTypes_namespaceObject, "mediaSessionArtwork", function() { return mediaSessionArtwork; });
__webpack_require__.d(PlayerPropTypes_namespaceObject, "track", function() { return PlayerPropTypes_track; });
__webpack_require__.d(PlayerPropTypes_namespaceObject, "seekMode", function() { return seekMode; });
// EXTERNAL MODULE: external {"root":"React","commonjs":"react","commonjs2":"react","amd":"react"}
var external_root_React_commonjs_react_commonjs2_react_amd_react_ = __webpack_require__(1);
var external_root_React_commonjs_react_commonjs2_react_amd_react_default = /*#__PURE__*/__webpack_require__.n(external_root_React_commonjs_react_commonjs2_react_amd_react_);
// EXTERNAL MODULE: external {"root":"PropTypes","commonjs":"prop-types","commonjs2":"prop-types","amd":"prop-types"}
var external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_ = __webpack_require__(0);
var external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default = /*#__PURE__*/__webpack_require__.n(external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_);
// EXTERNAL MODULE: ./node_modules/array-find-index/index.js
var array_find_index = __webpack_require__(4);
var array_find_index_default = /*#__PURE__*/__webpack_require__.n(array_find_index);
// EXTERNAL MODULE: ./src/utils/createSingleGlobalContext.js
var createSingleGlobalContext = __webpack_require__(3);
// CONCATENATED MODULE: ./src/PlayerContext.js
// TODO: test to make sure context contents stay in sync with
// enumerated list here
/* harmony default export */ var PlayerContext = (Object(createSingleGlobalContext["a" /* default */])({
displayName: 'PlayerContext',
keysWillUpdate: ['playlist', 'activeTrackIndex', 'trackLoading', 'paused', 'currentTime', 'seekPreviewTime', 'seekInProgress', 'awaitingPlayResume', 'duration', 'bufferedRanges', 'playedRanges', 'seekableRanges', 'volume', 'muted', 'shuffle', 'stalled', 'playbackRate', 'setVolumeInProgress', 'repeatStrategy', 'mediaCannotPlay']
}));
// CONCATENATED MODULE: ./src/GroupContext.js
/* harmony default export */ var GroupContext = (Object(createSingleGlobalContext["a" /* default */])({
displayName: 'GroupContext',
keysWillUpdate: ['groupProps']
}));
// CONCATENATED MODULE: ./src/constants.js
var repeatStrategyOptions = ['none', 'playlist', 'track'];
var MEDIA_ERR_NETWORK = 2;
// EXTERNAL MODULE: ./src/utils/console.js
var console = __webpack_require__(2);
// CONCATENATED MODULE: ./src/PlayerPropTypes.js
function requiredOnlyUnlessHasProp(propType, altPropName) {
var warnedAboutDefiningBoth = false;
function validate(props, propName, componentName) {
if (propName in props) {
if (!warnedAboutDefiningBoth && altPropName in props) {
Object(console["b" /* logWarning */])("Do not define both the '" + propName + "' and '" + altPropName + "' props.");
warnedAboutDefiningBoth = true;
}
for (var _len = arguments.length, rest = new Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
rest[_key - 3] = arguments[_key];
}
return propType.isRequired.apply(propType, [props, propName, componentName].concat(rest));
}
if (!(altPropName in props)) {
return new Error("If the '" + altPropName + "' prop is not defined, '" + propName + "' must be.");
}
}
return validate;
}
var controlKeyword = external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.oneOf(['playpause', 'backskip', 'forwardskip', 'volume', 'mute', 'repeat', 'shuffle', 'progress', 'progressdisplay', 'fullscreen', 'spacer']);
var control = external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.oneOfType([external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.func, controlKeyword]);
var crossOriginAttribute = external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.oneOf(['anonymous', 'use-credentials']);
var PlayerPropTypes_repeatStrategy = external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.oneOf(repeatStrategyOptions);
var mediaSource = external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.shape({
src: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.string.isRequired,
type: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.string.isRequired
});
var mediaSessionAction = external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.oneOf(['play', 'pause', 'previoustrack', 'nexttrack', 'seekbackward', 'seekforward']);
var mediaSessionArtwork = external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.shape({
src: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.string.isRequired,
sizes: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.string,
type: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.string
});
var PlayerPropTypes_track = external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.shape({
url: requiredOnlyUnlessHasProp(external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.string, 'sources'),
sources: requiredOnlyUnlessHasProp(external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.arrayOf(mediaSource.isRequired), 'url'),
title: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.string.isRequired,
artist: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.string,
album: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.string,
artwork: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.arrayOf(mediaSessionArtwork.isRequired),
duration: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.oneOfType([external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.string, external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.number]),
startingTime: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.number,
isUnboundedStream: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.bool,
meta: external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.object
});
var seekMode = external_root_PropTypes_commonjs_prop_types_commonjs2_prop_types_amd_prop_types_default.a.oneOf(['paused', 'immediate', 'onrelease']);
// CONCATENATED MODULE: ./src/factories/createCustomMediaElement.js
var loopchange = 'loopchange';
var srcrequest = 'srcrequest';
function createCustomMediaElement(media) {
new MutationObserver(function () {
media.dispatchEvent(new Event(loopchange));
}).observe(media, {
attributes: true,
attributeFilter: ['loop']
}); // Don't let the media src property get modified directly.
// Instead, when it does get set, dispatch an event to be
// handled in a way that doesn't conflict with the loaded
// playlist.
Object.defineProperty(media, 'src', {
get: function get() {
return media.currentSrc;
},
set: function set(src) {
var e = new Event(srcrequest);
e.srcRequested = src;
media.dispatchEvent(e);
}
});
return media;
}
/* harmony default export */ var factories_createCustomMediaElement = (createCustomMediaElement);
// CONCATENATED MODULE: ./src/utils/ShuffleManager.js
/* ShuffleManager
*
* Manages navigation throughout a list which is:
* - Sourced from another provided list
* - In random order (except to avoid consecutive duplicates)
* - Extended endlessly on-the-fly, as needed
* - Able to have future history overwritten by non-random choices
* - Able to swap source lists and maintain shuffle order for common members
*/
var ShuffleManager =
/*#__PURE__*/
function () {
function ShuffleManager(list, options) {
if (options === void 0) {
options = {};
}
this._list = list;
this._forwardStack = [];
this._backStack = [];
this._currentItem = undefined;
this._allowBackShuffle = Boolean(options.allowBackShuffle);
}
var _proto = ShuffleManager.prototype;
_proto.findNextItem = function findNextItem(currentIndex) {
if (currentIndex !== undefined) {
this.setCurrentIndex(currentIndex);
}
this._currentItem = _findNextItem(this._list, this._forwardStack, this._backStack, this._currentItem, true);
return this._currentItem;
};
_proto.findPreviousItem = function findPreviousItem(currentIndex) {
if (currentIndex !== undefined) {
this.setCurrentIndex(currentIndex);
}
this._currentItem = _findNextItem(this._list, this._backStack, this._forwardStack, this._currentItem, this._allowBackShuffle);
return this._currentItem;
};
_proto.pickNextItem = function pickNextItem(index, currentIndex) {
if (currentIndex !== undefined) {
this.setCurrentIndex(currentIndex);
}
if (this._list[index] === undefined) {
return undefined;
}
if (this._currentItem !== undefined) {
this._backStack.push(this._currentItem);
}
this._forwardStack.length = 0;
this._currentItem = this._list[index];
return this._currentItem;
};
_proto.setList = function setList(list) {
this._list = list;
};
_proto.setOptions = function setOptions(options) {
var _arr = Object.keys(options);
for (var _i = 0; _i < _arr.length; _i++) {
var o = _arr[_i];
switch (o) {
case 'allowBackShuffle':
this["_" + o] = Boolean(options[o]);
break;
default:
break;
}
}
};
_proto.setCurrentIndex = function setCurrentIndex(currentIndex) {
var item = this._list[currentIndex];
if (this._currentItem !== item) {
this.clear();
this._currentItem = item;
}
};
_proto.clear = function clear() {
this._forwardStack.length = 0;
this._backStack.length = 0;
this._currentItem = undefined;
};
return ShuffleManager;
}();
function _goForward(n, forwardStack, backStack, currentItem) {
var item = currentItem;
for (var i = 0; i < n; i++) {
if (!forwardStack.length) {
// rollback before erroring (note stack reversal)
_goForward(i, backStack, forwardStack, item);
throw "Moving " + n + " places was not possible!";
}
backStack.push(item);
item = forwardStack.pop();
}
return item;
}
function _allItemsMatch(list, item) {
if (!list.length) {
return false;
}
for (var i = 0; i < list.length; i++) {
if (item !== list[i]) {
return false;
}
}
return true;
}
function _findNextItem(list, forwardStack, backStack, currentItem, allowMore) {
var item = currentItem;
if (!list.length) {
return undefined;
}
for (var i = 1; i <= forwardStack.length; i++) {
if (list.indexOf(forwardStack[forwardStack.length - i]) !== -1) {
return _goForward(i, forwardStack, backStack, item);
}
}
if (!allowMore) {
return undefined;
}
if (_allItemsMatch(list, item)) {
// we can serve this as our "next" item but we
// won't modify our history since it's the same.
return item;
}
var nextItem;
do {
nextItem = list[Math.floor(Math.random() * list.length)];
} while (item === nextItem || nextItem === undefined); // if we're skipping items that aren't in our current list we may
// have some items in our forwardStack - make sure we move to the front.
item = _goForward(forwardStack.length, forwardStack, backStack, item);
if (item !== undefined) {
backStack.push(item);
}
return nextItem;
}
/* harmony default export */ var utils_ShuffleManager = (ShuffleManager);
// CONCATENATED MODULE: ./src/utils/isPlaylistValid.js
function isPlaylistValid(playlist) {
return Boolean(playlist && playlist.length);
}
/* harmony default export */ var utils_isPlaylistValid = (isPlaylistValid);
// CONCATENATED MODULE: ./src/utils/getTrackSources.js
var blankSources = [{
src: ''
}];
function getTrackSources(playlist, index) {
if (!utils_isPlaylistValid(playlist)) {
return blankSources;
}
var _playlist$index = playlist[index],
sources = _playlist$index.sources,
url = _playlist$index.url;
if (sources) {
return sources.length ? sources : blankSources;
}
return [{
src: url
}];
}
/* harmony default export */ var utils_getTrackSources = (getTrackSources);
// CONCATENATED MODULE: ./src/utils/findTrackIndexByUrl.js
function findTrackIndexByUrl(playlist, url) {
return array_find_index_default()(playlist, function (track) {
if (track.sources) {
return array_find_index_default()(track.sources, function (source) {
return source.src === url;
}) !== -1;
}
return track.url && url === track.url;
});
}
/* harmony default export */ var utils_findTrackIndexByUrl = (findTrackIndexByUrl);
// CONCATENATED MODULE: ./src/utils/snapshot.js
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
var veryLongKey = '__highly_unstable_snapshot_internals_which_will_break_your_app_if_you_use_them_directly__';
var versionKey = '__cassette_snapshot_version__'; // IMPORTANT: new migrations *must* always be added to the end since
// the tracked snapshot version is based on the migration index.
// If there is a crash-inducing bug in an existing migration, it can be patched
// in-place, but it should never be removed from the migrations array.
var migrations = [function (oldSnapshot) {
var _objectSpread2;
var __unstable__ = oldSnapshot.__unstable__,
rest = _objectWithoutPropertiesLoose(oldSnapshot, ["__unstable__"]);
return _objectSpread({}, rest, (_objectSpread2 = {}, _objectSpread2[veryLongKey] = __unstable__, _objectSpread2));
}];
function getStateSnapshot(state) {
var _ref;
var paused = state.paused,
currentTime = state.currentTime,
activeTrackIndex = state.activeTrackIndex,
volume = state.volume,
muted = state.muted,
loop = state.loop,
cycle = state.cycle,
shuffle = state.shuffle,
playbackRate = state.playbackRate,
duration = state.duration,
__playlist__ = state.__playlist__;
return _ref = {}, _ref[versionKey] = migrations.length, _ref[veryLongKey] = {
paused: paused,
// currentTime can't be restored for unbounded live streams
currentTime: duration === Infinity ? 0 : currentTime,
activeTrackIndex: activeTrackIndex,
volume: volume,
muted: muted,
loop: loop,
cycle: cycle,
shuffle: shuffle,
playbackRate: playbackRate,
activeTrackSrc: utils_isPlaylistValid(__playlist__) ? utils_getTrackSources(__playlist__, activeTrackIndex)[0].src : null
}, _ref;
}
function restoreStateFromSnapshot(snapshot, props) {
var migratedSnapshot = migrations.slice(snapshot[versionKey] || 0).reduce(function (oldSnapshot, migration) {
return migration(oldSnapshot);
}, snapshot);
var _migratedSnapshot$ver = migratedSnapshot[veryLongKey],
paused = _migratedSnapshot$ver.paused,
currentTime = _migratedSnapshot$ver.currentTime,
activeTrackIndex = _migratedSnapshot$ver.activeTrackIndex,
volume = _migratedSnapshot$ver.volume,
muted = _migratedSnapshot$ver.muted,
loop = _migratedSnapshot$ver.loop,
cycle = _migratedSnapshot$ver.cycle,
shuffle = _migratedSnapshot$ver.shuffle,
playbackRate = _migratedSnapshot$ver.playbackRate,
activeTrackSrc = _migratedSnapshot$ver.activeTrackSrc;
var restoredStateValues = {};
if (utils_isPlaylistValid(props.playlist) && typeof paused === 'boolean') {
// using awaitingPlay instead of paused triggers an animation
restoredStateValues.awaitingPlay = !paused;
}
if (typeof volume === 'number' && volume >= 0 && volume <= 1) {
restoredStateValues.volume = volume;
}
if (typeof muted === 'boolean') {
restoredStateValues.muted = muted;
}
if (typeof loop === 'boolean') {
restoredStateValues.loop = loop;
}
if (typeof cycle === 'boolean') {
restoredStateValues.cycle = cycle;
}
if (typeof shuffle === 'boolean') {
restoredStateValues.shuffle = shuffle;
}
if (typeof playbackRate === 'number') {
restoredStateValues.playbackRate = playbackRate;
}
var useCurrentTime = false;
if (typeof activeTrackSrc === 'string' && typeof activeTrackIndex === 'number' && activeTrackIndex >= 0) {
// let's try staying on the same track index
var currentSrc = props.playlist[activeTrackIndex] && utils_getTrackSources(props.playlist, activeTrackIndex)[0].src;
if (currentSrc && activeTrackSrc === currentSrc) {
restoredStateValues.activeTrackIndex = activeTrackIndex;
useCurrentTime = true;
} else {
/* if the track we were playing before is in the new playlist,
* update the activeTrackIndex.
*/
var newTrackIndex = utils_findTrackIndexByUrl(props.playlist, activeTrackSrc);
if (newTrackIndex !== -1) {
restoredStateValues.activeTrackIndex = newTrackIndex;
useCurrentTime = true;
}
}
}
if (useCurrentTime && typeof currentTime === 'number' && currentTime >= 0) {
restoredStateValues.currentTime = currentTime;
}
return restoredStateValues;
}
// CONCATENATED MODULE: ./src/utils/getSourceList.js
// collapses playlist into flat list containing
// the first source url for each track
function getSourceList(playlist) {
return (playlist || []).map(function (_, i) {
return utils_getTrackSources(playlist, i)[0].src;
});
}
/* harmony default export */ var utils_getSourceList = (getSourceList);
// CONCATENATED MODULE: ./src/utils/getTimeRangesArray.js
function getTimeRangesArray(timeRangesObj) {
var timeRangesArray = Array(timeRangesObj.length);
for (var i = 0; i < timeRangesObj.length; i++) {
timeRangesArray[i] = {
start: timeRangesObj.start(i),
end: timeRangesObj.end(i)
};
}
return timeRangesArray;
}
/* harmony default export */ var utils_getTimeRangesArray = (getTimeRangesArray);
// CONCATENATED MODULE: ./src/utils/getRepeatStrategy.js
function getRepeatStrategy(loop, cycle) {
if (loop) {
return 'track';
}
if (cycle) {
return 'playlist';
}
return 'none';
}
/* harmony default export */ var utils_getRepeatStrategy = (getRepeatStrategy);
// CONCATENATED MODULE: ./src/utils/convertToNumberWithinIntervalBounds.js
function convertToNumberWithinIntervalBounds(number, min, max) {
min = typeof min === 'number' ? min : -Infinity;
max = typeof max === 'number' ? max : Infinity;
return Math.max(min, Math.min(number, max));
}
/* harmony default export */ var utils_convertToNumberWithinIntervalBounds = (convertToNumberWithinIntervalBounds);
// CONCATENATED MODULE: ./src/utils/getDisplayText.js
function getDisplayText(track) {
if (!track) {
return '';
}
if (track.title && track.artist) {
return track.artist + " - " + track.title;
}
return track.title || track.artist || track.album || '';
}
/* harmony default export */ var utils_getDisplayText = (getDisplayText);
// CONCATENATED MODULE: ./src/utils/parseTimeString.js
function parseTimeString(str) {
var seconds = 0;
var factor = 1;
var times = str.split(':').slice(-3);
while (times.length > 0) {
seconds += factor * parseInt(times.pop(), 10);
factor *= 60;
}
return seconds;
}
/* harmony default export */ var utils_parseTimeString = (parseTimeString);
// CONCATENATED MODULE: ./src/utils/getInitialDuration.js
function getInitialDuration(track) {
var duration = 0;
if (track.duration) {
if (typeof track.duration === 'string') {
duration = utils_parseTimeString(track.duration);
} else {
duration = track.duration;
}
}
return duration;
}
/* harmony default export */ var utils_getInitialDuration = (getInitialDuration);
// CONCATENATED MODULE: ./src/PlayerContextProvider.js
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function PlayerContextProvider_objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
function PlayerContextProvider_objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { PlayerContextProvider_defineProperty(target, key, source[key]); }); } return target; }
function PlayerContextProvider_defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function playErrorHandler(err) {
Object(console["a" /* logError */])(err);
if (err.name === 'NotAllowedError') {
var warningMessage = 'Media playback failed at ' + new Date().toLocaleTimeString() + '! (Perhaps autoplay is disabled in this browser.)';
Object(console["b" /* logWarning */])(warningMessage);
}
} // Existing Media Session API implementations have default handlers
// for play/pause, and may yield unexpected behavior if custom
// play/pause handlers are defined - so let's leave them be.
var supportableMediaSessionActions = ['previoustrack', 'nexttrack', 'seekbackward', 'seekforward'];
var defaultState = {
// indicates whether media player should be paused
paused: true,
// elapsed time for active track, in seconds
currentTime: 0,
// The most recent targeted time, in seconds, for seek preview
seekPreviewTime: 0,
/* true if the user is currently dragging the mouse
* to seek a new track position
*/
seekInProgress: false,
/* true if media was playing when seek previewing began,
* it was paused, and it should be resumed on seek
* complete
*/
awaitingResumeOnSeekComplete: false,
// true if media will play once new track has loaded
awaitingPlayAfterTrackLoad: false,
// the duration in seconds of the loaded track
duration: 0,
// array describing the buffered ranges in the loaded track
bufferedRanges: [],
// array describing the already-played ranges in the loaded track
playedRanges: [],
// array describing the seekable ranges in the loaded track
seekableRanges: [],
// true if the media is currently stalled pending data buffering
stalled: false,
// true if the active track should play on the next componentDidUpdate
shouldRequestPlayOnNextUpdate: false,
/* true if an error occurs while fetching the active track media data
* or if its type is not a supported media format
*/
mediaCannotPlay: false,
// maximum currentTime since the current track has been playing
maxKnownTime: 0
}; // assumes playlist is valid
function getGoToTrackState(_ref) {
var prevState = _ref.prevState,
index = _ref.index,
track = _ref.track,
_ref$shouldPlay = _ref.shouldPlay,
shouldPlay = _ref$shouldPlay === void 0 ? true : _ref$shouldPlay,
_ref$shouldForceLoad = _ref.shouldForceLoad,
shouldForceLoad = _ref$shouldForceLoad === void 0 ? false : _ref$shouldForceLoad,
startingTime = _ref.startingTime;
var isNewTrack = prevState.activeTrackIndex !== index;
var shouldLoadAsNew = Boolean(isNewTrack || shouldForceLoad);
var currentTime = startingTime || track.startingTime || 0;
return {
duration: utils_getInitialDuration(track),
activeTrackIndex: index,
trackLoading: shouldLoadAsNew,
mediaCannotPlay: prevState.mediaCannotPlay && !shouldLoadAsNew,
currentTime: utils_convertToNumberWithinIntervalBounds(currentTime, 0),
loop: shouldLoadAsNew ? false : prevState.loop,
shouldRequestPlayOnNextUpdate: Boolean(shouldPlay),
awaitingPlayAfterTrackLoad: Boolean(shouldPlay),
awaitingForceLoad: Boolean(shouldForceLoad),
maxKnownTime: shouldLoadAsNew ? 0 : prevState.maxKnownTime
};
}
/**
* Wraps an area which shares a common [`playerContext`](#playercontext)
*/
var PlayerContextProvider_PlayerContextProvider =
/*#__PURE__*/
function (_Component) {
_inheritsLoose(PlayerContextProvider, _Component);
function PlayerContextProvider(props) {
var _this;
_this = _Component.call(this, props) || this;
var currentTime = 0;
var activeTrackIndex = utils_convertToNumberWithinIntervalBounds(props.startingTrackIndex, 0);
var playlistIsValid = utils_isPlaylistValid(props.playlist);
if (playlistIsValid && props.playlist[activeTrackIndex]) {
currentTime = props.playlist[activeTrackIndex].startingTime || 0;
}
var initialStateSnapshot = props.initialStateSnapshot;
var restoredStateFromSnapshot = {};
if (initialStateSnapshot) {
try {
restoredStateFromSnapshot = restoreStateFromSnapshot(initialStateSnapshot, props);
var _restoredStateFromSna = restoredStateFromSnapshot,
a = _restoredStateFromSna.activeTrackIndex,
c = _restoredStateFromSna.currentTime;
if (typeof a === 'number') {
activeTrackIndex = a;
}
if (typeof c === 'number') {
currentTime = c;
}
} catch (err) {
Object(console["b" /* logWarning */])(err);
Object(console["b" /* logWarning */])('Loading Cassette state from snapshot failed.');
Object(console["b" /* logWarning */])("Failed snapshot:\n" + JSON.stringify(initialStateSnapshot, null, 2));
}
}
_this.state = PlayerContextProvider_objectSpread({}, defaultState, {
// index matching requested track (whether track has loaded or not)
activeTrackIndex: activeTrackIndex,
// whether we're waiting on loading metadata for the active track
trackLoading: utils_isPlaylistValid(props.playlist),
// the current timestamp on the active track in seconds
currentTime: utils_convertToNumberWithinIntervalBounds(currentTime, 0),
// the latest volume of the media, between 0 and 1.
volume: utils_convertToNumberWithinIntervalBounds(props.defaultVolume, 0, 1),
// true if the media has been muted
muted: props.defaultMuted,
// whether to loop the active track
loop: props.defaultRepeatStrategy === 'track',
// true if playlist should continue at start after completion
cycle: props.defaultRepeatStrategy === 'playlist',
// whether to randomly pick next track from playlist after one finishes
shuffle: props.defaultShuffle,
// Rate at which media should be played. 1.0 is normal speed.
playbackRate: props.defaultPlaybackRate,
// true if user is currently dragging mouse to change the volume
setVolumeInProgress: false,
// initialize shouldRequestPlayOnNextUpdate from autoplay prop
shouldRequestPlayOnNextUpdate: props.autoplay && playlistIsValid,
awaitingForceLoad: false,
// duration might be set on track object
duration: utils_getInitialDuration(playlistIsValid && props.playlist[activeTrackIndex]),
// playlist prop copied to state (for getDerivedStateFromProps)
__playlist__: props.playlist
}, restoredStateFromSnapshot); // volume at last time we were unmuted and not actively setting volume
_this.lastStableVolume = _this.state.volume; // used to keep track of play history when we are shuffling
_this.shuffler = new utils_ShuffleManager(utils_getSourceList(props.playlist), {
allowBackShuffle: props.allowBackShuffle
}); // html media element used for playback
_this.media = null;
_this.videoHostElementList = [];
_this.videoHostOccupiedCallbacks = new Map();
_this.videoHostVacatedCallbacks = new Map(); // bind internal methods
_this.handleTrackPlaybackFailure = _this.handleTrackPlaybackFailure.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handlePlayerOnlineAfterFailure = _this.handlePlayerOnlineAfterFailure.bind(_assertThisInitialized(_assertThisInitialized(_this))); // bind callback methods to pass to descendant elements
_this.togglePause = _this.togglePause.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.selectTrackIndex = _this.selectTrackIndex.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.forwardSkip = _this.forwardSkip.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.backSkip = _this.backSkip.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.seekPreview = _this.seekPreview.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.seekComplete = _this.seekComplete.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.setVolume = _this.setVolume.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.setVolumeComplete = _this.setVolumeComplete.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.toggleMuted = _this.toggleMuted.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.toggleShuffle = _this.toggleShuffle.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.setRepeatStrategy = _this.setRepeatStrategy.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.setPlaybackRate = _this.setPlaybackRate.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.registerVideoHostElement = _this.registerVideoHostElement.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.renderVideoIntoHostElement = _this.renderVideoIntoHostElement.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.unregisterVideoHostElement = _this.unregisterVideoHostElement.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.updateVideoHostElement = _this.updateVideoHostElement.bind(_assertThisInitialized(_assertThisInitialized(_this))); // bind media event handlers
_this.handleMediaPlay = _this.handleMediaPlay.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaPause = _this.handleMediaPause.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaSrcrequest = _this.handleMediaSrcrequest.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaEnded = _this.handleMediaEnded.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaEmptied = _this.handleMediaEmptied.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaStalled = _this.handleMediaStalled.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaCanplaythrough = _this.handleMediaCanplaythrough.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaCanplay = _this.handleMediaCanplay.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaTimeupdate = _this.handleMediaTimeupdate.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaLoadeddata = _this.handleMediaLoadeddata.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaVolumechange = _this.handleMediaVolumechange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaDurationchange = _this.handleMediaDurationchange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaProgress = _this.handleMediaProgress.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaLoopchange = _this.handleMediaLoopchange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
_this.handleMediaRatechange = _this.handleMediaRatechange.bind(_assertThisInitialized(_assertThisInitialized(_this)));
return _this;
}
var _proto = PlayerContextProvider.prototype;
_proto.componentDidMount = function componentDidMount() {
var _this2 = this;
var media = this.media = factories_createCustomMediaElement(this.props.createMediaElement());
var _this$props = this.props,
defaultPlaybackRate = _this$props.defaultPlaybackRate,
crossOrigin = _this$props.crossOrigin,
playlist = _this$props.playlist,
autoplayDelayInSeconds = _this$props.autoplayDelayInSeconds,
mediaElementRef = _this$props.mediaElementRef,
getPosterImageForTrack = _this$props.getPosterImageForTrack,
getMediaTitleAttributeForTrack = _this$props.getMediaTitleAttributeForTrack,
onActiveTrackUpdate = _this$props.onActiveTrackUpdate;
var _this$state = this.state,
volume = _this$state.volume,
muted = _this$state.muted,
playbackRate = _this$state.playbackRate,
loop = _this$state.loop,
activeTrackIndex = _this$state.activeTrackIndex,
shouldRequestPlayOnNextUpdate = _this$state.shouldRequestPlayOnNextUpdate; // initialize media properties
// We used to set currentTime here.. now waiting for loadeddata.
// This avoids an issue where some browsers ignore or delay currentTime
// updates when in the HAVE_NOTHING state.
media.defaultPlaybackRate = defaultPlaybackRate;
if (crossOrigin) {
media.crossOrigin = crossOrigin;
}
media.volume = volume;
media.muted = muted;
media.playbackRate = playbackRate;
media.loop = loop;
media.setAttribute('playsinline', '');
media.setAttribute('webkit-playsinline', '');
media.setAttribute('preload', 'metadata');
media.setAttribute('poster', getPosterImageForTrack(playlist[activeTrackIndex]));
media.setAttribute('title', getMediaTitleAttributeForTrack(playlist[activeTrackIndex])); // add listeners for media events
media.addEventListener('play', this.handleMediaPlay);
media.addEventListener('pause', this.handleMediaPause);
media.addEventListener('ended', this.handleMediaEnded);
media.addEventListener('stalled', this.handleMediaStalled);
media.addEventListener('emptied', this.handleMediaEmptied);
media.addEventListener('canplay', this.handleMediaCanplay);
media.addEventListener('canplaythrough', this.handleMediaCanplaythrough);
media.addEventListener('timeupdate', this.handleMediaTimeupdate);
media.addEventListener('loadeddata', this.handleMediaLoadeddata);
media.addEventListener('volumechange', this.handleMediaVolumechange);
media.addEventListener('durationchange', this.handleMediaDurationchange);
media.addEventListener('progress', this.handleMediaProgress);
media.addEventListener('ratechange', this.handleMediaRatechange);
media.addEventListener('error', this.handleTrackPlaybackFailure); // add listeners for special events
media.addEventListener('srcrequest', this.handleMediaSrcrequest);
media.addEventListener('loopchange', this.handleMediaLoopchange); // set source elements for current track
this.setMediaElementSources(); // initially mount media element in the hidden container (this may change)
this.mediaContainer.appendChild(media);
if (shouldRequestPlayOnNextUpdate) {
this.setState({
shouldRequestPlayOnNextUpdate: false
});
this.delayTimeout = setTimeout(function () {
_this2.togglePause(false);
}, autoplayDelayInSeconds * 1000);
}
if (mediaElementRef) {
mediaElementRef(media);
}
if (onActiveTrackUpdate) {
onActiveTrackUpdate({
track: playlist[activeTrackIndex],
trackIndex: activeTrackIndex,
previousTrack: null,
previousTrackIndex: null
});
}
};
PlayerContextProvider.getDerivedStateFromProps = function getDerivedStateFromProps(nextProps, prevState) {
var newPlaylist = nextProps.playlist;
if (newPlaylist === prevState.__playlist__) {
// reference comparison is equal so we'll
// assume the playlist is unchanged.
return null;
}
var baseNewState = {
__playlist__: newPlaylist
}; // check if the new playlist is invalid
if (!utils_isPlaylistValid(newPlaylist)) {
return PlayerContextProvider_objectSpread({}, defaultState, baseNewState, {
activeTrackIndex: 0,
trackLoading: false
});
} // check if the activeTrackIndex doesn't need to be updated
var prevSources = util