@gcorevideo/player 2.22.4 → 2.22.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/assets/level-selector/button.ejs +1 -1
  2. package/assets/level-selector/list.ejs +10 -4
  3. package/assets/level-selector/style.scss +8 -3
  4. package/assets/media-control/media-control.ejs +1 -2
  5. package/dist/core.js +2 -2
  6. package/dist/index.css +916 -912
  7. package/dist/index.js +452 -413
  8. package/dist/plugins/index.css +668 -664
  9. package/dist/plugins/index.js +514 -474
  10. package/lib/index.plugins.d.ts +2 -1
  11. package/lib/index.plugins.d.ts.map +1 -1
  12. package/lib/index.plugins.js +2 -1
  13. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  14. package/lib/playback/dash-playback/DashPlayback.js +1 -1
  15. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  16. package/lib/plugins/bottom-gear/BottomGear.js +2 -2
  17. package/lib/plugins/level-selector/LevelSelector.d.ts +6 -5
  18. package/lib/plugins/level-selector/LevelSelector.d.ts.map +1 -1
  19. package/lib/plugins/level-selector/LevelSelector.js +11 -8
  20. package/lib/plugins/level-selector/QualityLevels.d.ts +112 -0
  21. package/lib/plugins/level-selector/QualityLevels.d.ts.map +1 -0
  22. package/lib/plugins/level-selector/QualityLevels.js +280 -0
  23. package/lib/plugins/media-control/MediaControl.d.ts +37 -6
  24. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  25. package/lib/plugins/media-control/MediaControl.js +54 -36
  26. package/lib/plugins/playback-rate/PlaybackRate.d.ts +5 -4
  27. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  28. package/lib/plugins/playback-rate/PlaybackRate.js +46 -24
  29. package/lib/plugins/subtitles/ClosedCaptions.js +1 -1
  30. package/lib/plugins/utils/fullscreen.d.ts +4 -0
  31. package/lib/plugins/utils/fullscreen.d.ts.map +1 -0
  32. package/lib/plugins/utils/fullscreen.js +30 -0
  33. package/lib/plugins/utils.d.ts +0 -1
  34. package/lib/plugins/utils.d.ts.map +1 -1
  35. package/lib/plugins/utils.js +0 -28
  36. package/lib/plugins/vast-ads/VastAds.d.ts +1 -0
  37. package/lib/plugins/vast-ads/VastAds.d.ts.map +1 -1
  38. package/lib/plugins/vast-ads/VastAds.js +6 -3
  39. package/lib/utils/fullscreen.d.ts +3 -0
  40. package/lib/utils/fullscreen.d.ts.map +1 -0
  41. package/lib/utils/fullscreen.js +2 -0
  42. package/package.json +1 -1
  43. package/src/index.plugins.ts +2 -1
  44. package/src/playback/dash-playback/DashPlayback.ts +1 -4
  45. package/src/plugins/bottom-gear/BottomGear.ts +2 -2
  46. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +15 -3
  47. package/src/plugins/level-selector/{LevelSelector.ts → QualityLevels.ts} +19 -13
  48. package/src/plugins/level-selector/__tests__/{LevelSelector.test.ts → QualityLevels.test.ts} +20 -6
  49. package/src/plugins/level-selector/__tests__/__snapshots__/{LevelSelector.test.ts.snap → QualityLevels.test.ts.snap} +58 -25
  50. package/src/plugins/media-control/MediaControl.ts +111 -62
  51. package/src/plugins/media-control/__tests__/MediaControl.test.ts +118 -8
  52. package/src/plugins/media-control/__tests__/__snapshots__/MediaControl.test.ts.snap +149 -5
  53. package/src/plugins/playback-rate/PlaybackRate.ts +48 -26
  54. package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +125 -55
  55. package/src/plugins/playback-rate/__tests__/__snapshots__/PlaybackRate.test.ts.snap +1 -1
  56. package/src/plugins/subtitles/ClosedCaptions.ts +1 -1
  57. package/src/plugins/utils/fullscreen.ts +34 -0
  58. package/src/plugins/utils.ts +0 -31
  59. package/src/plugins/vast-ads/VastAds.ts +8 -4
  60. package/tsconfig.tsbuildinfo +1 -1
@@ -10278,7 +10278,6 @@ class BottomGear extends UICorePlugin {
10278
10278
  .find('#gear-sub-menu-wrapper')
10279
10279
  .hide();
10280
10280
  // TODO make non-clickable when there are no items
10281
- mediaControl.putElement('gear', this.$el);
10282
10281
  setTimeout(() => {
10283
10282
  this.trigger(GearEvents.RENDERED);
10284
10283
  }, 0);
@@ -10306,7 +10305,8 @@ class BottomGear extends UICorePlugin {
10306
10305
  this.listenTo(mediaControl, Events.MEDIACONTROL_HIDE, this.hide);
10307
10306
  }
10308
10307
  onMediaControlRendered() {
10309
- this.render();
10308
+ const mediaControl = this.core.getPlugin('media_control');
10309
+ mediaControl.putElement('gear', this.$el);
10310
10310
  }
10311
10311
  }
10312
10312
 
@@ -13153,31 +13153,6 @@ function strtimeToMiliseconds(str) {
13153
13153
  }
13154
13154
  return (h + m + s);
13155
13155
  }
13156
- // TODO refactor
13157
- function isFullscreen(el) {
13158
- const video = el.nodeName === "video" ? el : el.querySelector('video');
13159
- if (!video) {
13160
- return false;
13161
- }
13162
- if (Browser.isiOS) {
13163
- return FullscreenIOS.isFullscreen(video);
13164
- }
13165
- return !!(document.fullscreenElement);
13166
- }
13167
- const FullscreenIOS = {
13168
- isFullscreen: function (el) {
13169
- try {
13170
- // @ts-ignore
13171
- if (el.webkitDisplayingFullscreen !== undefined) {
13172
- // @ts-ignore
13173
- return !!(el.webkitDisplayingFullscreen);
13174
- }
13175
- }
13176
- catch (e) {
13177
- }
13178
- return false;
13179
- }
13180
- };
13181
13156
  function getPageX(event) {
13182
13157
  if (event.pageX) {
13183
13158
  return event.pageX;
@@ -13345,7 +13320,7 @@ class ClipsPlugin extends UICorePlugin {
13345
13320
 
13346
13321
  const templateHtml$1 = "<ul class=\"context-menu-list\">\n <% if(options) { %>\n <% for (var i = 0; i < options.length; i++) { %>\n <li class=\"context-menu-list-item <%= options[i].class %>\"\n data-<%= options[i].name %>><%= options[i].label %></li>\n <% } %>\n <% } %>\n</ul>\n";
13347
13322
 
13348
- var version$1 = "2.22.4";
13323
+ var version$1 = "2.22.7";
13349
13324
 
13350
13325
  var packages = {
13351
13326
  "node_modules/@clappr/core": {
@@ -13927,397 +13902,125 @@ class GoogleAnalytics extends ContainerPlugin {
13927
13902
  }
13928
13903
  }
13929
13904
 
13930
- const buttonHtml$2 = "<button class='gplayer-lite-btn gcore-skin-text-color gear-option'>\n <span class=\"gear-option_hd-icon<%= isHd ? '' : ' hidden' %>\"><%= hdIcon %></span>\n <span><%= i18n.t('quality') %></span>\n <span class=\"gear-option_arrow-right-icon\"><%= arrowRightIcon %></span>\n <span class='gear-option_value'><%= currentText %></span>\n</button>\n";
13931
-
13932
- const listHtml$1 = "<button class=\"gplayer-lite-btn go-back gcore-skin-text-color\" id=\"level-selector-back-button\">\n <span class=\"arrow-left-icon\"><%= arrowLeftIcon %></span>\n <%= i18n.t('quality') %>\n</button>\n<ul class=\"gear-sub-menu\" id=\"level-selector-menu\">\n <% if (!removeAuto) { %>\n <li>\n <a href=\"#\" class='gear-sub-menu_btn gcore-skin-text-color' data-id=\"-1\" id=\"level_selector_auto\">\n <span class=\"check-icon\"><%= checkIcon %></span>\n <%= i18n.t('auto') %>\n </a>\n </li>\n <% } %>\n <% for (const item of levels.slice().reverse()) { %>\n <li class=\"<%= maxLevel >= 0 && item.level > maxLevel ? 'disabled ' : ''%><%=item.level === current ? 'current ' : ''%>\">\n <a href=\"#\"\n class=\"gear-sub-menu_btn gcore-skin-text-color<%= item.level === current ? ' gcore-skin-active' : '' %>\"\n data-id=\"<%= item.level %>\"\n id=\"level_selector_<%= item.width > item.height ? item.height : item.width %>\"\n >\n <span class=\"check-icon\"><%= checkIcon %></span>\n <%= labels[item.level] %>\n </a>\n </li>\n <% } %>\n</ul>\n";
13933
-
13934
- const hdIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14.9562 8.22232H13.9961V15.1873H14.9562C15.8914 15.1873 16.766 14.8253 17.4195 14.1676C18.0786 13.5037 18.4415 12.6281 18.4415 11.7026C18.4415 9.7837 16.8781 8.22253 14.9561 8.22253L14.9562 8.22232Z\"\n fill=\"#C9C9C9\"/>\n <path\n d=\"M22.0801 4H1.91994C0.859222 4 0 4.86406 0 5.91994V17.4878C0 18.5437 0.859222 19.4078 1.91994 19.4078H22.0801C23.1408 19.4078 24 18.5437 24 17.4878V5.91994C24 4.86406 23.1408 4 22.0801 4ZM10.3975 15.3473C10.3975 15.6124 10.1827 15.8272 9.91754 15.8272C9.65216 15.8272 9.43761 15.6122 9.43761 15.3473V12.0239H5.55956V15.3473C5.55956 15.6124 5.34481 15.8272 5.07963 15.8272C4.81425 15.8272 4.5997 15.6122 4.5997 15.3473L4.59949 7.74042C4.59949 7.47524 4.81425 7.26049 5.07943 7.26049C5.34481 7.26049 5.55936 7.47544 5.55936 7.74042V11.0636H9.43741V7.74042C9.43741 7.47524 9.65216 7.26049 9.91734 7.26049C10.1827 7.26049 10.3973 7.47544 10.3973 7.74042L10.3975 15.3473ZM18.1005 14.8438C17.2652 15.6844 16.1486 16.1472 14.9561 16.1472H13.5161C13.2507 16.1472 13.0361 15.9323 13.0361 15.6673V7.74263C13.0361 7.47745 13.2509 7.26269 13.5161 7.26269H14.9561C17.4072 7.26269 19.4013 9.25438 19.4013 11.7027C19.4013 12.8835 18.9392 13.9991 18.1005 14.844V14.8438Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
13935
-
13936
- const arrowRightIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.70725 20.7073C8.51225 20.9023 8.25625 21.0002 8.00025 21.0002C7.74425 21.0002 7.48825 20.9023 7.29325 20.7073C6.90225 20.3162 6.90225 19.6842 7.29325 19.2932L14.5863 12.0002L7.29325 4.70725C6.90225 4.31625 6.90225 3.68425 7.29325 3.29325C7.68425 2.90225 8.31625 2.90225 8.70725 3.29325L16.7073 11.2933C17.0983 11.6842 17.0983 12.3162 16.7073 12.7072L8.70725 20.7073Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
13937
-
13938
- const arrowLeftIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M16.7073 19.2932C17.0983 19.6842 17.0983 20.3162 16.7073 20.7073C16.5123 20.9023 16.2563 21.0002 16.0003 21.0002C15.7443 21.0002 15.4882 20.9023 15.2933 20.7073L7.29325 12.7072C6.90225 12.3162 6.90225 11.6842 7.29325 11.2933L15.2933 3.29325C15.6842 2.90225 16.3163 2.90225 16.7073 3.29325C17.0983 3.68425 17.0983 4.31625 16.7073 4.70725L9.41425 12.0002L16.7073 19.2932Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
13905
+ function calculateSize(original) {
13906
+ const transformed = {
13907
+ media: {
13908
+ width: 0,
13909
+ height: 0
13910
+ },
13911
+ letterboxing: {
13912
+ horizontal: 0,
13913
+ vertical: 0
13914
+ }
13915
+ };
13916
+ // Freeze viewport height and scale video to fit vertically
13917
+ transformed.media.width = (original.media.width * original.dom.height / original.media.height);
13918
+ transformed.media.height = (original.media.height * transformed.media.width / original.media.width);
13919
+ // If it didnt't fit, freeze viewport width and scale video to fit horizontally
13920
+ if (transformed.media.width > original.dom.width) {
13921
+ transformed.media.height = (original.media.height * original.dom.width / original.media.width);
13922
+ transformed.media.width = (original.media.width * transformed.media.height / original.media.height);
13923
+ }
13924
+ // Calculate paddings for vertical or horizontal letterboxing
13925
+ if (transformed.media.width < original.dom.width) {
13926
+ transformed.letterboxing.horizontal = Math.floor((original.dom.width - transformed.media.width) / 2);
13927
+ }
13928
+ else {
13929
+ if (transformed.media.height < original.dom.height) {
13930
+ transformed.letterboxing.vertical = Math.floor((original.dom.height - transformed.media.height) / 2);
13931
+ }
13932
+ }
13933
+ transformed.media.width = Math.floor(transformed.media.width);
13934
+ transformed.media.height = Math.floor(transformed.media.height);
13935
+ return transformed;
13936
+ }
13939
13937
 
13940
- const checkIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M20.5793 4.19296C20.1216 3.86696 19.4777 3.96396 19.1424 4.40896L9.37295 17.3809L4.81634 12.107C4.45222 11.683 3.80218 11.6289 3.36709 11.9839C2.932 12.3389 2.87543 12.97 3.2416 13.393L8.64165 19.643C8.83708 19.869 9.12506 20 9.42849 20C9.4398 20 9.45114 20 9.46246 19.999C9.77926 19.989 10.0724 19.838 10.2586 19.59L20.8015 5.58996C21.1368 5.14496 21.0371 4.51896 20.5793 4.19296Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
13938
+ const logoHTML = "<div class=\"clappr-logo control-need-disable\">\n <img class=\"clappr-logo-img\"/>\n</div>\n";
13941
13939
 
13942
- const T$a = 'plugins.level_selector';
13943
- const VERSION$4 = '2.19.4';
13944
13940
  /**
13945
- * `PLUGIN` that provides a UI to select the desired quality level of the playback.
13941
+ * `PLUGIN` that adds custom logo to the player.
13946
13942
  * @beta
13947
- *
13948
- * @remarks
13949
- * Depends on:
13950
- *
13951
- * - {@link MediaControl}
13952
- *
13953
- * - {@link BottomGear}
13954
- *
13955
- * The plugin is rendered as an item in the gear menu, which, when clicked, shows a list of quality levels to choose from.
13956
- *
13957
- * Configuration options - {@link LevelSelectorPluginSettings}
13958
- *
13959
- * @example
13960
- * ```ts
13961
- * new Player({
13962
- * levelSelector: {
13963
- * restrictResolution: 360,
13964
- * labels: { 360: 'SD', 720: 'HD' },
13965
- * },
13966
- * })
13967
- * ```
13968
13943
  */
13969
- class LevelSelector extends UICorePlugin {
13970
- levels = [];
13971
- levelLabels = [];
13972
- removeAuto = false;
13973
- isHd = false;
13974
- currentText = '';
13975
- selectedLevelId = -1;
13976
- static buttonTemplate = tmpl(buttonHtml$2);
13977
- static listTemplate = tmpl(listHtml$1);
13978
- /**
13979
- * @internal
13980
- */
13944
+ class Logo extends UIContainerPlugin {
13945
+ hasStartedPlaying = false;
13946
+ $logoContainer = null;
13981
13947
  get name() {
13982
- return 'level_selector';
13948
+ return 'logo';
13983
13949
  }
13984
- /**
13985
- * @internal
13986
- */
13987
13950
  get supportedVersion() {
13988
13951
  return { min: CLAPPR_VERSION };
13989
13952
  }
13990
- /**
13991
- * @internal
13992
- */
13993
- static get version() {
13994
- return VERSION$4;
13953
+ get template() {
13954
+ return tmpl(logoHTML);
13995
13955
  }
13996
- /**
13997
- * @internal
13998
- */
13999
13956
  get attributes() {
14000
13957
  return {
14001
- class: 'level-selector',
14002
- 'data-level-selector': '',
13958
+ 'class': 'player-logo',
13959
+ 'data-logo': ''
14003
13960
  };
14004
13961
  }
14005
- get events() {
14006
- return {
14007
- 'click .gear-sub-menu_btn': 'onSelect',
14008
- 'click .go-back': 'goBack',
14009
- };
13962
+ get shouldRender() {
13963
+ return !!this.options.logo && !!this.options.logo.path;
14010
13964
  }
14011
- /**
14012
- * @internal
14013
- */
14014
13965
  bindEvents() {
14015
- this.listenToOnce(this.core, Events.CORE_READY, this.onCoreReady);
14016
- this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChange);
13966
+ window.addEventListener('resize', this.setPosition);
13967
+ this.listenTo(this.container, Events.CONTAINER_RESIZE, this.setPosition);
13968
+ this.listenTo(this.container, Events.CONTAINER_STOP, this.onStop);
13969
+ this.listenTo(this.container, Events.CONTAINER_PLAY, this.onPlay);
13970
+ this.listenTo(this.container, Events.CONTAINER_LOADEDMETADATA, this.setPosition);
14017
13971
  }
14018
- onCoreReady() {
14019
- const gear = this.core.getPlugin('bottom_gear');
14020
- assert(gear, 'bottom_gear plugin is required');
14021
- this.currentText = this.core.i18n.t('auto');
14022
- this.listenTo(gear, GearEvents.RENDERED, this.onGearRendered);
13972
+ stopListening() {
13973
+ window.removeEventListener('resize', this.setPosition);
13974
+ // @ts-ignore
13975
+ return super.stopListening();
14023
13976
  }
14024
- onGearRendered() {
14025
- this.render();
13977
+ onPlay() {
13978
+ this.hasStartedPlaying = true;
13979
+ this.setPosition();
14026
13980
  }
14027
- onActiveContainerChange() {
14028
- this.removeAuto = false;
14029
- this.isHd = false;
14030
- const activePlayback = this.core.activePlayback;
14031
- this.listenTo(activePlayback, Events.PLAYBACK_LEVELS_AVAILABLE, this.onLevelsAvailable);
14032
- this.listenTo(activePlayback, Events.PLAYBACK_LEVEL_SWITCH_START, this.onLevelSwitchStart);
14033
- this.listenTo(activePlayback, Events.PLAYBACK_LEVEL_SWITCH_END, this.onLevelSwitchEnd);
14034
- this.listenTo(activePlayback, Events.PLAYBACK_BITRATE, this.onBitrate);
14035
- this.listenTo(activePlayback, Events.PLAYBACK_STOP, this.onStop);
14036
- this.listenTo(activePlayback, Events.PLAYBACK_HIGHDEFINITIONUPDATE, (isHd) => {
14037
- this.isHd = isHd;
14038
- this.updateHd();
14039
- });
14040
- if (activePlayback.levels?.length > 0) {
14041
- this.onLevelsAvailable(activePlayback.levels);
14042
- }
13981
+ onStop() {
13982
+ this.hasStartedPlaying = false;
13983
+ this.update();
14043
13984
  }
14044
- updateHd() {
14045
- if (this.isHd) {
14046
- this.$el.find('.gear-option_hd-icon').removeClass('hidden');
13985
+ update() {
13986
+ if (!this.shouldRender) {
13987
+ return;
13988
+ }
13989
+ if (!this.hasStartedPlaying) {
13990
+ this.$el.hide();
14047
13991
  }
14048
13992
  else {
14049
- this.$el.find('.gear-option_hd-icon').addClass('hidden');
13993
+ this.$el.show();
14050
13994
  }
14051
13995
  }
14052
- onStop() {
14053
- this.listenToOnce(this.core.activePlayback, Events.PLAYBACK_PLAY, () => {
14054
- if (this.core.activePlayback.getPlaybackType() === 'live') {
14055
- if (this.selectedLevelId !== -1) {
14056
- this.core.activePlayback.currentLevel = this.selectedLevelId;
14057
- }
14058
- }
14059
- });
14060
- }
14061
- shouldRender() {
14062
- const activePlayback = this.core.activePlayback;
14063
- if (!activePlayback) {
14064
- return false;
14065
- }
14066
- const supportsCurrentLevel = 'currentLevel' in activePlayback;
14067
- if (!supportsCurrentLevel) {
14068
- return false;
13996
+ constructor(container) {
13997
+ super(container);
13998
+ this.setPosition = this.setPosition.bind(this);
13999
+ this.hasStartedPlaying = false;
14000
+ if (!this.options.logo) {
14001
+ this.disable();
14002
+ return;
14069
14003
  }
14070
- // Only care if we have at least 2 to choose from
14071
- return !!(this.levels && this.levels.length > 1);
14004
+ this.render();
14072
14005
  }
14073
- /**
14074
- * @internal
14075
- */
14076
14006
  render() {
14077
- if (!this.shouldRender()) {
14007
+ if (!this.shouldRender) {
14078
14008
  return this;
14079
14009
  }
14080
- this.renderDropdown();
14081
- this.updateButton();
14010
+ this.$el.html(this.template());
14011
+ this.setLogoImgAttrs();
14012
+ this.container.$el.append(this.$el.get(0));
14013
+ this.update();
14082
14014
  return this;
14083
14015
  }
14084
- renderDropdown() {
14085
- this.$el.html(LevelSelector.listTemplate({
14086
- arrowLeftIcon,
14087
- checkIcon,
14088
- current: this.selectedLevelId,
14089
- labels: this.levelLabels,
14090
- levels: this.levels,
14091
- maxLevel: this.maxLevel,
14092
- removeAuto: this.removeAuto,
14093
- i18n: this.core.i18n,
14094
- }));
14095
- }
14096
- updateButton() {
14097
- this.core.getPlugin('bottom_gear')
14098
- ?.addItem('quality', this.$el)
14099
- .html(LevelSelector.buttonTemplate({
14100
- arrowRightIcon,
14101
- currentText: this.currentText,
14102
- isHd: this.isHd,
14103
- hdIcon,
14104
- i18n: this.core.i18n,
14105
- }));
14106
- }
14107
- get maxLevel() {
14108
- const maxRes = this.core.options.levelSelector?.restrictResolution;
14109
- return maxRes
14110
- ? this.levels.find((level) => (level.height > level.width ? level.width : level.height) ===
14111
- maxRes)?.level ?? -1
14112
- : -1;
14113
- }
14114
- onLevelsAvailable(levels) {
14115
- const maxResolution = this.core.options.levelSelector?.restrictResolution;
14116
- this.levels = levels;
14117
- this.makeLevelsLabels();
14118
- if (maxResolution) {
14119
- this.removeAuto = true;
14120
- const initialLevel = levels
14121
- .filter((level) => (level.width > level.height ? level.height : level.width) <=
14122
- maxResolution)
14123
- .pop();
14124
- this.setLevel(initialLevel?.level ?? 0);
14125
- }
14126
- this.render();
14127
- }
14128
- makeLevelsLabels() {
14129
- const labels = this.core.options.levelSelector?.labels ?? {};
14130
- this.levelLabels = [];
14131
- for (const level of this.levels) {
14132
- const ll = level.width > level.height ? level.height : level.width;
14133
- const label = labels[ll] || `${ll}p`;
14134
- this.levelLabels.push(label);
14135
- }
14136
- }
14137
- onSelect(event) {
14138
- const selectedLevel = parseInt(event.currentTarget?.dataset?.id ?? '-1', 10);
14139
- this.setLevel(selectedLevel);
14140
- event.stopPropagation();
14141
- event.preventDefault();
14142
- return false;
14143
- }
14144
- goBack() {
14145
- this.core.getPlugin('bottom_gear').refresh();
14146
- }
14147
- setLevel(index) {
14148
- this.selectedLevelId = index;
14149
- this.core.activePlayback.currentLevel = this.selectedLevelId;
14150
- this.highlightCurrentLevel();
14151
- }
14152
- allLevelElements() {
14153
- return this.$('#level-selector-menu li');
14154
- }
14155
- levelElement(id = -1) {
14156
- return this.$(`#level-selector-menu a[data-id="${id}"]`).parent();
14157
- }
14158
- onLevelSwitchStart() {
14159
- this.levelElement(this.selectedLevelId).addClass('changing');
14160
- }
14161
- onLevelSwitchEnd() {
14162
- this.levelElement(this.selectedLevelId).removeClass('changing');
14163
- }
14164
- updateText(level) {
14165
- this.currentText = this.getLevelLabel(level);
14166
- this.updateButton();
14167
- }
14168
- getLevelLabel(id) {
14169
- if (id < 0) {
14170
- return this.core.i18n.t('auto');
14171
- }
14172
- const index = this.levels.findIndex((l) => l.level === id);
14173
- if (index < 0) {
14174
- return this.core.i18n.t('auto');
14175
- }
14176
- return this.levelLabels[index] ?? formatLevelLabel(this.levels[index]);
14177
- }
14178
- onBitrate(info) {
14179
- this.highlightCurrentLevel();
14180
- }
14181
- highlightCurrentLevel() {
14182
- trace(`${T$a} highlightCurrentLevel`, {
14183
- selectedLevelId: this.selectedLevelId,
14184
- });
14185
- this.allLevelElements()
14186
- .removeClass('current')
14187
- .find('a')
14188
- .removeClass('gcore-skin-active');
14189
- const currentLevelElement = this.levelElement(this.selectedLevelId);
14190
- currentLevelElement
14191
- .addClass('current')
14192
- .find('a')
14193
- .addClass('gcore-skin-active');
14194
- this.updateText(this.selectedLevelId);
14195
- }
14196
- }
14197
- function formatLevelLabel(level) {
14198
- const h = level.width > level.height ? level.height : level.width;
14199
- return `${h}p`;
14200
- }
14201
-
14202
- function calculateSize(original) {
14203
- const transformed = {
14204
- media: {
14205
- width: 0,
14206
- height: 0
14207
- },
14208
- letterboxing: {
14209
- horizontal: 0,
14210
- vertical: 0
14211
- }
14212
- };
14213
- // Freeze viewport height and scale video to fit vertically
14214
- transformed.media.width = (original.media.width * original.dom.height / original.media.height);
14215
- transformed.media.height = (original.media.height * transformed.media.width / original.media.width);
14216
- // If it didnt't fit, freeze viewport width and scale video to fit horizontally
14217
- if (transformed.media.width > original.dom.width) {
14218
- transformed.media.height = (original.media.height * original.dom.width / original.media.width);
14219
- transformed.media.width = (original.media.width * transformed.media.height / original.media.height);
14220
- }
14221
- // Calculate paddings for vertical or horizontal letterboxing
14222
- if (transformed.media.width < original.dom.width) {
14223
- transformed.letterboxing.horizontal = Math.floor((original.dom.width - transformed.media.width) / 2);
14224
- }
14225
- else {
14226
- if (transformed.media.height < original.dom.height) {
14227
- transformed.letterboxing.vertical = Math.floor((original.dom.height - transformed.media.height) / 2);
14228
- }
14229
- }
14230
- transformed.media.width = Math.floor(transformed.media.width);
14231
- transformed.media.height = Math.floor(transformed.media.height);
14232
- return transformed;
14233
- }
14234
-
14235
- const logoHTML = "<div class=\"clappr-logo control-need-disable\">\n <img class=\"clappr-logo-img\"/>\n</div>\n";
14236
-
14237
- /**
14238
- * `PLUGIN` that adds custom logo to the player.
14239
- * @beta
14240
- */
14241
- class Logo extends UIContainerPlugin {
14242
- hasStartedPlaying = false;
14243
- $logoContainer = null;
14244
- get name() {
14245
- return 'logo';
14246
- }
14247
- get supportedVersion() {
14248
- return { min: CLAPPR_VERSION };
14249
- }
14250
- get template() {
14251
- return tmpl(logoHTML);
14252
- }
14253
- get attributes() {
14254
- return {
14255
- 'class': 'player-logo',
14256
- 'data-logo': ''
14257
- };
14258
- }
14259
- get shouldRender() {
14260
- return !!this.options.logo && !!this.options.logo.path;
14261
- }
14262
- bindEvents() {
14263
- window.addEventListener('resize', this.setPosition);
14264
- this.listenTo(this.container, Events.CONTAINER_RESIZE, this.setPosition);
14265
- this.listenTo(this.container, Events.CONTAINER_STOP, this.onStop);
14266
- this.listenTo(this.container, Events.CONTAINER_PLAY, this.onPlay);
14267
- this.listenTo(this.container, Events.CONTAINER_LOADEDMETADATA, this.setPosition);
14268
- }
14269
- stopListening() {
14270
- window.removeEventListener('resize', this.setPosition);
14271
- // @ts-ignore
14272
- return super.stopListening();
14273
- }
14274
- onPlay() {
14275
- this.hasStartedPlaying = true;
14276
- this.setPosition();
14277
- }
14278
- onStop() {
14279
- this.hasStartedPlaying = false;
14280
- this.update();
14281
- }
14282
- update() {
14283
- if (!this.shouldRender) {
14284
- return;
14285
- }
14286
- if (!this.hasStartedPlaying) {
14287
- this.$el.hide();
14288
- }
14289
- else {
14290
- this.$el.show();
14291
- }
14292
- }
14293
- constructor(container) {
14294
- super(container);
14295
- this.setPosition = this.setPosition.bind(this);
14296
- this.hasStartedPlaying = false;
14297
- if (!this.options.logo) {
14298
- this.disable();
14299
- return;
14300
- }
14301
- this.render();
14302
- }
14303
- render() {
14304
- if (!this.shouldRender) {
14305
- return this;
14306
- }
14307
- this.$el.html(this.template());
14308
- this.setLogoImgAttrs();
14309
- this.container.$el.append(this.$el.get(0));
14310
- this.update();
14311
- return this;
14312
- }
14313
- setLogoImgAttrs() {
14314
- const { logo: { path: imgUrl, width = 60, height = 60 } } = this.options;
14315
- this.$logoContainer = this.$el.find('.clappr-logo');
14316
- const $logo = this.$logoContainer.find('.clappr-logo-img');
14317
- $logo.attr({
14318
- 'src': `${imgUrl}`,
14319
- 'style': `width: ${width}px;height: ${height}px;`
14320
- });
14016
+ setLogoImgAttrs() {
14017
+ const { logo: { path: imgUrl, width = 60, height = 60 } } = this.options;
14018
+ this.$logoContainer = this.$el.find('.clappr-logo');
14019
+ const $logo = this.$logoContainer.find('.clappr-logo-img');
14020
+ $logo.attr({
14021
+ 'src': `${imgUrl}`,
14022
+ 'style': `width: ${width}px;height: ${height}px;`
14023
+ });
14321
14024
  }
14322
14025
  setLogoWidth(size) {
14323
14026
  let { logo: { width = 60, height = 60, objectFit = 'contain' } } = this.options;
@@ -14606,7 +14309,35 @@ function keyName(keyCode) {
14606
14309
  return KEY_NAMES_BY_CODE[keyCode] || '';
14607
14310
  }
14608
14311
 
14609
- const mediaControlHTML = "<div class=\"media-control-background\" data-background></div>\n\n<div class=\"media-control-layer gcore-skin-bg-color\" data-controls>\n <% var renderBar = function(name) { %>\n <div class=\"bar-container\" data-<%= name %>>\n <div class=\"bar-background\" data-<%= name %>>\n <div class=\"bar-fill-1\" data-<%= name %>></div>\n <div class=\"bar-fill-2 gcore-skin-main-color\" data-<%= name %>></div>\n <div class=\"bar-hover\" data-<%= name %>></div>\n </div>\n </div>\n <div class=\"bar-scrubber\" data-<%= name %>>\n <div class=\"bar-scrubber-icon gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n <% }; %>\n <% var renderSegmentedBar = function(name, segments) {\n segments = segments || 10; %>\n <div class=\"bar-container\" data-<%= name %>>\n <div class=\"bar-background\" data-<%= name %>>\n <div class=\"bar-fill-1 gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n <div class=\"bar-scrubber\" data-<%= name %>>\n <div class=\"bar-scrubber-icon gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n </div>\n <% }; %>\n <% var renderDrawer = function(name, renderContent) { %>\n <div class=\"drawer-container\" data-<%= name %>>\n <div class=\"drawer-icon-container\" data-<%= name %>>\n <div class=\"drawer-icon media-control-icon gcore-skin-button-color\" data-<%= name %>></div>\n <span class=\"drawer-text\" data-<%= name %>></span>\n </div>\n <% renderContent(name); %>\n </div>\n <% }; %>\n <% var renderIndicator = function(name) { %>\n <div class=\"media-control-indicator gcore-skin-text-color\" data-<%= name %>></div>\n <% }; %>\n <% var renderQuality = function(name) { %>\n <div class=\"media-control-quality\" data-<%= name %>></div>\n <% }; %>\n <% var renderNerd = function(name) { %>\n <div class=\"media-control-nerd\" data-<%= name %>></div>\n <% }; %>\n <% var renderMultiCamera = function(name) { %>\n <div class=\"media-control-multicamera\" data-<%= name %>></div>\n <% }; %>\n <% var renderClipsText = function(name) { %>\n\n <div class=\"media-clip-container gcore-skin-text-color\" data-<%= name %>>\n <div class=\"media-clip-point gcore-skin-text-color\" data-<%= name %>>•</div>\n <div class=\"media-clip-text gcore-skin-text-color\" data-<%= name %>></div>\n </div>\n <% }; %>\n <% var renderVR = function(name) { %>\n <div class=\"media-control-vr\" data-<%= name %>></div>\n <% }; %>\n <% var renderButton = function(name) { %>\n <button type=\"button\" class=\"media-control-button media-control-icon gcore-skin-button-color\" data-<%= name %>\n aria-label=\"<%= name %>\"></button>\n <% }; %>\n\n <% var templates = {\n bar: renderBar,\n segmentedBar: renderSegmentedBar,\n };\n var render = function (settingsList) {\n settingsList.forEach(function (setting) {\n\n if (setting === \"seekbar\") {\n renderBar(setting);\n } else if (setting === \"volume\") {\n renderDrawer(setting, settings.volumeBarTemplate ? templates[settings.volumeBarTemplate] : function (name) {\n return renderSegmentedBar(name);\n });\n } else if (setting === \"duration\" || setting === \"position\") {\n renderIndicator(setting);\n } else if (setting === \"quality\") {\n renderQuality(setting)\n } else if (setting === \"nerd\") {\n renderNerd(setting)\n } else if (setting === \"multicamera\") {\n renderMultiCamera(setting)\n } else if (setting === \"vr\") {\n renderVR(setting)\n } else if (setting === \"clipsText\") {\n renderClipsText(setting)\n } else if ([\"playpause\", \"playstop\", \"fullscreen\"].includes(setting)) {\n renderButton(setting);\n }\n });\n }; %>\n <% if (settings.left && settings.left.length) { %>\n <div class=\"media-control-left-panel\" data-media-control>\n <% render(settings.left); %>\n </div>\n <% } %>\n <% if (settings.default && settings.default.length) { %>\n <div class=\"media-control-center-panel\" data-media-control>\n <% render(settings.default); %>\n </div>\n <% } %>\n <% if (settings.right && settings.right.length) { %>\n <div class=\"media-control-right-panel\" data-media-control>\n <% render(settings.right); %>\n </div>\n <% } %>\n</div>\n";
14312
+ const fullscreenEnabled = Utils.Fullscreen.fullscreenEnabled;
14313
+ function isFullscreen(el) {
14314
+ const video = el.nodeName === 'video'
14315
+ ? el
14316
+ : el.querySelector('video');
14317
+ if (!video) {
14318
+ return false;
14319
+ }
14320
+ if (Browser.isiOS) {
14321
+ return FullscreenIOS.isFullscreen(video);
14322
+ }
14323
+ return !!document.fullscreenElement;
14324
+ }
14325
+ const FullscreenIOS = {
14326
+ isFullscreen: function (el) {
14327
+ try {
14328
+ // @ts-ignore
14329
+ if (el.webkitDisplayingFullscreen !== undefined) {
14330
+ // @ts-ignore
14331
+ return !!el.webkitDisplayingFullscreen;
14332
+ }
14333
+ }
14334
+ catch (e) {
14335
+ }
14336
+ return false;
14337
+ },
14338
+ };
14339
+
14340
+ const mediaControlHTML = "<div class=\"media-control-background\" data-background></div>\n\n<div class=\"media-control-layer gcore-skin-bg-color\" data-controls>\n <% var renderBar = function(name) { %>\n <div class=\"bar-container\" data-<%= name %>>\n <div class=\"bar-background\" data-<%= name %>>\n <div class=\"bar-fill-1\" data-<%= name %>></div>\n <div class=\"bar-fill-2 gcore-skin-main-color\" data-<%= name %>></div>\n <div class=\"bar-hover\" data-<%= name %>></div>\n </div>\n </div>\n <div class=\"bar-scrubber\" data-<%= name %>>\n <div class=\"bar-scrubber-icon gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n <% }; %>\n <% var renderSegmentedBar = function(name, segments) {\n segments = segments || 10; %>\n <div class=\"bar-container\" data-<%= name %>>\n <div class=\"bar-background\" data-<%= name %>>\n <div class=\"bar-fill-1 gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n <div class=\"bar-scrubber\" data-<%= name %>>\n <div class=\"bar-scrubber-icon gcore-skin-main-color\" data-<%= name %>></div>\n </div>\n </div>\n <% }; %>\n <% var renderDrawer = function(name, renderContent) { %>\n <div class=\"drawer-container\" data-<%= name %>>\n <div class=\"drawer-icon-container\" data-<%= name %>>\n <div class=\"drawer-icon media-control-icon gcore-skin-button-color\" data-<%= name %>></div>\n <span class=\"drawer-text\" data-<%= name %>></span>\n </div>\n <% renderContent(name); %>\n </div>\n <% }; %>\n <% var renderIndicator = function(name) { %>\n <div class=\"media-control-indicator gcore-skin-text-color\" data-<%= name %>></div>\n <% }; %>\n <% var renderQuality = function(name) { %>\n <div class=\"media-control-quality\" data-<%= name %>></div>\n <% }; %>\n <% var renderNerd = function(name) { %>\n <div class=\"media-control-nerd\" data-<%= name %>></div>\n <% }; %>\n <% var renderMultiCamera = function(name) { %>\n <div class=\"media-control-multicamera\" data-<%= name %>></div>\n <% }; %>\n <% var renderClipsText = function(name) { %>\n <div class=\"media-clip-container gcore-skin-text-color\" data-<%= name %>>\n <div class=\"media-clip-point gcore-skin-text-color\" data-<%= name %>>•</div>\n <div class=\"media-clip-text gcore-skin-text-color\" data-<%= name %>></div>\n </div>\n <% }; %>\n <% var renderVR = function(name) { %>\n <div class=\"media-control-vr\" data-<%= name %>></div>\n <% }; %>\n <% var renderButton = function(name) { %>\n <button type=\"button\" class=\"media-control-button media-control-icon gcore-skin-button-color\" data-<%= name %>\n aria-label=\"<%= name %>\"></button>\n <% }; %>\n\n <% var templates = {\n bar: renderBar,\n segmentedBar: renderSegmentedBar,\n };\n var render = function (settingsList) {\n settingsList.forEach(function (setting) {\n\n if (setting === \"seekbar\") {\n renderBar(setting);\n } else if (setting === \"volume\") {\n renderDrawer(setting, settings.volumeBarTemplate ? templates[settings.volumeBarTemplate] : function (name) {\n return renderSegmentedBar(name);\n });\n } else if (setting === \"duration\" || setting === \"position\") {\n renderIndicator(setting);\n } else if (setting === \"quality\") {\n renderQuality(setting)\n } else if (setting === \"nerd\") {\n renderNerd(setting)\n } else if (setting === \"multicamera\") {\n renderMultiCamera(setting)\n } else if (setting === \"vr\") {\n renderVR(setting)\n } else if (setting === \"clipsText\") {\n renderClipsText(setting)\n } else if ([\"playpause\", \"playstop\", \"fullscreen\"].includes(setting)) {\n renderButton(setting);\n }\n });\n }; %>\n <% if (settings.left && settings.left.length) { %>\n <div class=\"media-control-left-panel\" data-media-control>\n <% render(settings.left); %>\n </div>\n <% } %>\n <% if (settings.default && settings.default.length) { %>\n <div class=\"media-control-center-panel\" data-media-control>\n <% render(settings.default); %>\n </div>\n <% } %>\n <% if (settings.right && settings.right.length) { %>\n <div class=\"media-control-right-panel\" data-media-control>\n <% render(settings.right); %>\n </div>\n <% } %>\n</div>\n";
14610
14341
 
14611
14342
  const volumeMaxIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14.187 7.71405C13.759 8.06405 13.697 8.69307 14.046 9.12107C14.662 9.87207 15 10.8941 15 11.9961C15 13.0991 14.662 14.1201 14.046 14.8711C13.697 15.2991 13.759 15.9291 14.187 16.2781C14.373 16.4311 14.597 16.5051 14.82 16.5051C15.109 16.5051 15.396 16.3801 15.594 16.1391C16.501 15.0301 17 13.5601 17 11.9961C17 10.4331 16.501 8.96207 15.594 7.85407C15.245 7.42707 14.614 7.36405 14.187 7.71405ZM19.772 5.14408C19.443 4.70008 18.816 4.60907 18.374 4.94007C17.931 5.27007 17.839 5.89605 18.169 6.33905C19.367 7.94705 20 9.90307 20 11.9961C20 14.0891 19.367 16.0451 18.169 17.6531C17.839 18.0971 17.931 18.7231 18.374 19.0531C18.553 19.1871 18.762 19.2511 18.97 19.2511C19.275 19.2511 19.576 19.1121 19.772 18.8491C21.23 16.8921 22 14.5231 22 11.9961C22 9.47007 21.23 7.10108 19.772 5.14408ZM12 3.85108V20.1421C12 20.4881 11.793 20.7971 11.473 20.9291C11.368 20.9721 11.258 20.9921 11.149 20.9921C10.926 20.9921 10.708 20.9031 10.544 20.7371L6.317 16.4431C6.038 16.1591 5.648 15.9961 5.249 15.9961H3.5C2.673 15.9961 2 15.3231 2 14.4961V9.49607C2 8.66907 2.673 7.99607 3.5 7.99607H5.249C5.648 7.99607 6.038 7.83308 6.317 7.54908L10.544 3.25507C10.787 3.00807 11.151 2.93206 11.473 3.06406C11.793 3.19506 12 3.50408 12 3.85108Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
14612
14343
 
@@ -14620,21 +14351,24 @@ const fullscreenOnIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"
14620
14351
  // Use of this source code is governed by a BSD-style
14621
14352
  // license that can be found in the {@link https://github.com/clappr/clappr-plugins/blob/master/LICENSE | LICENSE}.
14622
14353
  const DEFAULT_SETTINGS = {
14623
- left: [],
14624
14354
  right: [
14355
+ 'audiotracks',
14356
+ 'cc',
14357
+ // 'dvr',
14358
+ // 'duration',
14625
14359
  'fullscreen',
14626
- 'pip',
14627
14360
  'gear',
14628
- 'cc',
14629
14361
  'multicamera',
14630
- // 'playbackrate',
14362
+ 'pip',
14631
14363
  'vr',
14632
- 'audiotracks',
14633
- ],
14364
+ ]};
14365
+ const INITIAL_SETTINGS = {
14366
+ left: [],
14367
+ right: [],
14634
14368
  default: [],
14635
- seekEnabled: true,
14369
+ seekEnabled: false,
14636
14370
  };
14637
- const T$9 = 'plugins.media_control';
14371
+ const T$a = 'plugins.media_control';
14638
14372
  const LEFT_ORDER = [
14639
14373
  'playpause',
14640
14374
  'playstop',
@@ -14655,11 +14389,17 @@ function orderByOrderPattern(arr, order) {
14655
14389
  * @beta
14656
14390
  * @remarks
14657
14391
  * The methods exposed are to be used by the other plugins that extend the media control UI.
14392
+ *
14393
+ * Configuration options:
14394
+ *
14395
+ * - `mediaControl`: {@link MediaControlSettings} - specifies the allowed media control elements in each area
14396
+ *
14397
+ * - `persistConfig`: boolean - `common` option, makes the plugin persist the media control settings
14398
+ *
14399
+ * - `chromeless`: boolean
14658
14400
  */
14659
14401
  class MediaControl extends UICorePlugin {
14660
14402
  // private advertisementPlaying = false
14661
- customAreaElements = {};
14662
- customAreaHandler;
14663
14403
  buttonsColor = null;
14664
14404
  currentDurationValue = 0;
14665
14405
  currentPositionValue = 0;
@@ -14670,7 +14410,7 @@ class MediaControl extends UICorePlugin {
14670
14410
  displayedSeekBarPercentage = null;
14671
14411
  draggingSeekBar = false;
14672
14412
  draggingVolumeBar = false;
14673
- fullScreenOnVideoTagSupported = null;
14413
+ fullScreenOnVideoTagSupported = false;
14674
14414
  hideId = null;
14675
14415
  hideVolumeId = null;
14676
14416
  intendedVolume = 100;
@@ -14678,9 +14418,10 @@ class MediaControl extends UICorePlugin {
14678
14418
  kibo;
14679
14419
  lastMouseX = 0;
14680
14420
  lastMouseY = 0;
14421
+ needsUpdate = false;
14681
14422
  persistConfig;
14682
14423
  rendered = false;
14683
- settings = DEFAULT_SETTINGS;
14424
+ settings = INITIAL_SETTINGS;
14684
14425
  userDisabled = false;
14685
14426
  userKeepVisible = false;
14686
14427
  verticalVolume = false;
@@ -14691,7 +14432,6 @@ class MediaControl extends UICorePlugin {
14691
14432
  $multiCameraSelector = null;
14692
14433
  $playPauseToggle = null;
14693
14434
  $playStopToggle = null;
14694
- $playbackRate = null;
14695
14435
  $position = null;
14696
14436
  $seekBarContainer = null;
14697
14437
  $seekBarHover = null;
@@ -14903,7 +14643,8 @@ class MediaControl extends UICorePlugin {
14903
14643
  const video = this.core.activePlayback?.el;
14904
14644
  // video.webkitSupportsFullscreen is deprecated but iOS appears to only use this
14905
14645
  // see https://github.com/clappr/clappr/issues/1127
14906
- if (!Fullscreen.fullscreenEnabled() && video.webkitSupportsFullscreen) {
14646
+ if (!fullscreenEnabled() && video.webkitSupportsFullscreen) {
14647
+ // TODO sort out, use single utility function
14907
14648
  this.fullScreenOnVideoTagSupported = true;
14908
14649
  }
14909
14650
  this.updateSettings();
@@ -15134,22 +14875,21 @@ class MediaControl extends UICorePlugin {
15134
14875
  }
15135
14876
  }
15136
14877
  onActiveContainerChanged() {
15137
- this.fullScreenOnVideoTagSupported = null;
14878
+ this.fullScreenOnVideoTagSupported = false;
15138
14879
  // set the new container to match the volume of the last one
15139
14880
  this.setInitialVolume();
15140
14881
  this.changeTogglePlay();
15141
14882
  this.bindContainerEvents();
14883
+ // TODO remove?
15142
14884
  this.updateSettings();
15143
- // TODO remove
15144
- this.core.activeContainer.trigger(Events.CONTAINER_PLAYBACKDVRSTATECHANGED, this.core.activeContainer.isDvrInUse());
15145
- // TODO test
14885
+ // TODO test, figure out if this is needed
15146
14886
  if (this.core.activeContainer.mediaControlDisabled) {
15147
14887
  this.disable();
15148
14888
  }
15149
14889
  else {
15150
14890
  this.enable();
15151
14891
  }
15152
- this.trigger(Events.MEDIACONTROL_CONTAINERCHANGED); // TODO check
14892
+ this.trigger(Events.MEDIACONTROL_CONTAINERCHANGED); // TODO figure out
15153
14893
  if (this.core.activeContainer.$el) {
15154
14894
  this.core.activeContainer.$el.addClass('container-skin-1');
15155
14895
  }
@@ -15320,6 +15060,7 @@ class MediaControl extends UICorePlugin {
15320
15060
  }
15321
15061
  }
15322
15062
  updateSettings() {
15063
+ trace(`${T$a} updateSettings`, { settings: this.settings });
15323
15064
  const newSettings = $.extend(true, {
15324
15065
  left: [],
15325
15066
  default: [],
@@ -15332,10 +15073,14 @@ class MediaControl extends UICorePlugin {
15332
15073
  newSettings.left.push('dvr');
15333
15074
  }
15334
15075
  // actual order of the items appear rendered is controlled by CSS
15335
- newSettings.right = DEFAULT_SETTINGS.right;
15076
+ newSettings.right = DEFAULT_SETTINGS.right; // TODO get from the options
15336
15077
  if ((!this.fullScreenOnVideoTagSupported &&
15337
- !Fullscreen.fullscreenEnabled()) ||
15078
+ !fullscreenEnabled()) ||
15338
15079
  this.options.fullscreenDisable) {
15080
+ trace(`${T$a} updateSettings removing fullscreen`, {
15081
+ supported: this.fullScreenOnVideoTagSupported,
15082
+ optionsDisable: this.options.fullscreenDisable,
15083
+ });
15339
15084
  // remove fullscreen from settings if it is not available
15340
15085
  removeArrayItem(newSettings.default, 'fullscreen');
15341
15086
  removeArrayItem(newSettings.left, 'fullscreen');
@@ -15350,6 +15095,7 @@ class MediaControl extends UICorePlugin {
15350
15095
  const settingsChanged = serializeSettings(this.settings) !== serializeSettings(newSettings);
15351
15096
  if (settingsChanged) {
15352
15097
  this.settings = newSettings;
15098
+ this.needsUpdate = true;
15353
15099
  this.render();
15354
15100
  }
15355
15101
  }
@@ -15374,7 +15120,6 @@ class MediaControl extends UICorePlugin {
15374
15120
  this.$volumeBarBackground = this.$el.find('.bar-background[data-volume]');
15375
15121
  this.$volumeBarFill = this.$el.find('.bar-fill-1[data-volume]');
15376
15122
  this.$volumeBarScrubber = this.$el.find('.bar-scrubber[data-volume]');
15377
- this.$playbackRate = this.$el.find('.media-control-playbackrate[data-playbackrate]');
15378
15123
  this.$multiCameraSelector = this.$el.find('.media-control-multicamera[data-multicamera]');
15379
15124
  this.$clipText = this.$el.find('.media-clip-text[data-clipstext]'); // TODO
15380
15125
  this.$clipTextContainer = this.$el.find('.media-clip-container[data-clipstext]');
@@ -15406,8 +15151,6 @@ class MediaControl extends UICorePlugin {
15406
15151
  return null;
15407
15152
  case 'clipText':
15408
15153
  return this.$clipText;
15409
- case 'playbackRate':
15410
- return this.$playbackRate;
15411
15154
  case 'seekBarContainer':
15412
15155
  return this.$seekBarContainer;
15413
15156
  }
@@ -15430,13 +15173,6 @@ class MediaControl extends UICorePlugin {
15430
15173
  return;
15431
15174
  }
15432
15175
  }
15433
- handleCustomArea(handler) {
15434
- this.customAreaHandler = handler;
15435
- Object.entries(this.customAreaElements).forEach(([name, element]) => {
15436
- handler(name, element);
15437
- });
15438
- this.customAreaElements = {};
15439
- }
15440
15176
  /**
15441
15177
  * Toggle the visibility of a media control element
15442
15178
  * @param name - The name of the media control element
@@ -15534,8 +15270,8 @@ class MediaControl extends UICorePlugin {
15534
15270
  keys.forEach((i) => {
15535
15271
  this.bindKeyAndShow(i, () => {
15536
15272
  this.settings.seekEnabled &&
15537
- this.container &&
15538
- this.container.seekPercentage(Number(i) * 10);
15273
+ this.core.activeContainer &&
15274
+ this.core.activeContainer.seekPercentage(Number(i) * 10);
15539
15275
  return false;
15540
15276
  });
15541
15277
  });
@@ -15601,9 +15337,12 @@ class MediaControl extends UICorePlugin {
15601
15337
  * @internal
15602
15338
  */
15603
15339
  render() {
15340
+ trace(`${T$a} render`, { needsUpdate: this.needsUpdate });
15341
+ if (!this.needsUpdate) {
15342
+ return this;
15343
+ }
15604
15344
  const timeout = this.options.hideMediaControlDelay || 2000;
15605
- const html = MediaControl.template({ settings: this.settings ?? {} });
15606
- this.$el.html(html);
15345
+ this.$el.html(MediaControl.template({ settings: this.settings }));
15607
15346
  // const style = Styler.getStyleFor(mediaControlStyle, { baseUrl: this.options.baseUrl });
15608
15347
  // this.$el.append(style[0]);
15609
15348
  this.createCachedElements();
@@ -15649,7 +15388,8 @@ class MediaControl extends UICorePlugin {
15649
15388
  this.core.$el.append(this.el);
15650
15389
  this.rendered = true;
15651
15390
  this.updateVolumeUI();
15652
- // TODO setTimeout
15391
+ this.needsUpdate = false;
15392
+ // TODO setTimeout?
15653
15393
  this.trigger(Events.MEDIACONTROL_RENDERED);
15654
15394
  return this;
15655
15395
  }
@@ -15715,6 +15455,7 @@ class MediaControl extends UICorePlugin {
15715
15455
  element.el.css({ 'pointer-events': 'none' });
15716
15456
  });
15717
15457
  }
15458
+ // TODO drop
15718
15459
  isSeekEnabledForHtml5Playback() {
15719
15460
  if (this.core.getPlaybackType() === Playback.LIVE) {
15720
15461
  return this.options.dvrEnabled;
@@ -15722,7 +15463,7 @@ class MediaControl extends UICorePlugin {
15722
15463
  return isFinite(this.core.activePlayback.getDuration());
15723
15464
  }
15724
15465
  getElementLocation(name) {
15725
- trace(`${T$9} getElementLocation`, {
15466
+ trace(`${T$a} getElementLocation`, {
15726
15467
  right: this.settings.right,
15727
15468
  left: this.settings.left,
15728
15469
  default: this.settings.default,
@@ -15768,8 +15509,8 @@ const streamsMomentoIcon = "<svg id=\"Слой_1\" data-name=\"Слой 1\" xmln
15768
15509
 
15769
15510
  const streamsWhiteNightsIcon = "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" width=\"50\" height=\"50\" viewBox=\"0 0 50 50\">\n <defs>\n <clipPath id=\"clip-Icon\">\n <rect width=\"50\" height=\"50\"/>\n </clipPath>\n </defs>\n <g id=\"Icon\" clip-path=\"url(#clip-Icon)\">\n <g id=\"icon2\" transform=\"translate(-0.041 0)\">\n <path id=\"Контур_77\" data-name=\"Контур 77\" d=\"M6.493,13v8.266h6.275V19.74H8.31V17.714h4.006V16.3H8.31V14.53h4.365V13Zm7.5,0v8.266h1.7V15.732h.023l3.438,5.534h1.818V13h-1.7v5.545h-.023L15.8,13Z\" fill=\"#fff\"/>\n <path id=\"Контур_76\" data-name=\"Контур 76\" d=\"M29.949,29.1V26.774H31.94a1.4,1.4,0,0,1,.938.272,1.1,1.1,0,0,1,.313.874,1.155,1.155,0,0,1-.313.9,1.375,1.375,0,0,1-.938.278ZM28.132,25.36v8.266h1.817V30.4h1.818a1.353,1.353,0,0,1,.984.3,1.637,1.637,0,0,1,.394.949c.046.333.079.681.1,1.042a3.2,3.2,0,0,0,.185.938h1.819a1.218,1.218,0,0,1-.191-.423,3.611,3.611,0,0,1-.093-.527c-.019-.185-.033-.367-.041-.544s-.016-.332-.023-.463a5.052,5.052,0,0,0-.087-.625,2.109,2.109,0,0,0-.2-.573,1.586,1.586,0,0,0-.359-.451,1.414,1.414,0,0,0-.556-.284v-.023a1.926,1.926,0,0,0,1-.81,2.494,2.494,0,0,0,.307-1.262,2.308,2.308,0,0,0-.165-.88,2.128,2.128,0,0,0-.486-.724,2.3,2.3,0,0,0-.764-.492,2.67,2.67,0,0,0-1-.179ZM43.506,30.5V25.36H41.689V30.5a2.065,2.065,0,0,1-.37,1.36,1.7,1.7,0,0,1-1.343.434,2.086,2.086,0,0,1-.886-.156,1.283,1.283,0,0,1-.758-.978,3.748,3.748,0,0,1-.058-.66V25.36H36.456V30.5a3.16,3.16,0,0,0,.92,2.5,3.807,3.807,0,0,0,2.6.81,3.82,3.82,0,0,0,2.593-.816,3.132,3.132,0,0,0,.937-2.492Z\" fill=\"#fff\"/>\n <path id=\"Контур_80\" data-name=\"Контур 80\" d=\"M22.646,31.2H4.689a4.505,4.505,0,0,1-4.5-4.5V8.5A4.505,4.505,0,0,1,4.689,4h18.2a4.505,4.505,0,0,1,4.5,4.5v8.445l-.893.1a3.184,3.184,0,0,0-2.846,3.177V30.5l-.465.7ZM4.689,6a2.5,2.5,0,0,0-2.5,2.5V26.7a2.5,2.5,0,0,0,2.5,2.5H21.65V20.22a5.18,5.18,0,0,1,3.739-4.992V8.5a2.5,2.5,0,0,0-2.5-2.5Z\" fill=\"#fff\"/>\n <path id=\"Контур_81\" data-name=\"Контур 81\" d=\"M30.127,47.884a1,1,0,0,1-1-1V43.267H26.846a5.206,5.206,0,0,1-5.2-5.2V20.222a5.206,5.206,0,0,1,5.2-5.2H44.692a5.206,5.206,0,0,1,5.2,5.2V38.068a5.206,5.206,0,0,1-5.2,5.2H35.058l-4.216,4.316A1,1,0,0,1,30.127,47.884ZM26.846,17.022a3.2,3.2,0,0,0-3.2,3.2V38.067a3.2,3.2,0,0,0,3.2,3.2h3.281a1,1,0,0,1,1,1v2.162l2.8-2.86a1,1,0,0,1,.715-.3H44.692a3.2,3.2,0,0,0,3.2-3.2V20.222a3.2,3.2,0,0,0-3.2-3.2Z\" fill=\"#fff\"/>\n </g>\n </g>\n</svg>\n";
15770
15511
 
15771
- const VERSION$3 = '0.0.1';
15772
- const T$8 = 'plugins.multicamera';
15512
+ const VERSION$4 = '0.0.1';
15513
+ const T$9 = 'plugins.multicamera';
15773
15514
  /**
15774
15515
  * `PLUGIN` that adds support for loading multiple streams and switching between them using the media control UI.
15775
15516
  * @beta
@@ -15787,7 +15528,7 @@ class MultiCamera extends UICorePlugin {
15787
15528
  return { min: CLAPPR_VERSION };
15788
15529
  }
15789
15530
  static get version() {
15790
- return VERSION$3;
15531
+ return VERSION$4;
15791
15532
  }
15792
15533
  get template() {
15793
15534
  return tmpl(pluginHtml$3);
@@ -16041,7 +15782,7 @@ class MultiCamera extends UICorePlugin {
16041
15782
  // TODO figure out what this does
16042
15783
  playbackOptions.recycleVideo = Browser.isMobile;
16043
15784
  this.currentCamera = this.findElementById(id) ?? null;
16044
- trace(`${T$8} changeById`, { currentCamera: this.currentCamera, multicamera: this.multicamera });
15785
+ trace(`${T$9} changeById`, { currentCamera: this.currentCamera, multicamera: this.multicamera });
16045
15786
  if (!this.currentCamera) {
16046
15787
  return;
16047
15788
  }
@@ -16057,7 +15798,7 @@ class MultiCamera extends UICorePlugin {
16057
15798
  // TODO remove?
16058
15799
  // for html5 playback:
16059
15800
  this.options.dvrEnabled = this.currentCamera.dvr;
16060
- trace(`${T$8} changeById`, { currentCamera: this.currentCamera });
15801
+ trace(`${T$9} changeById`, { currentCamera: this.currentCamera });
16061
15802
  // TODO
16062
15803
  this.core.configure({
16063
15804
  playback: playbackOptions,
@@ -16112,10 +15853,10 @@ class MultiCamera extends UICorePlugin {
16112
15853
 
16113
15854
  const pipIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M21.05 3.00001C21.302 3.00001 21.5435 3.10003 21.7217 3.27833C21.9 3.45646 22 3.69802 22 3.95003V10.6H20.1V4.90003H4.90001V18.2H10.6V20.1H3.95001C3.69802 20.1 3.45647 20 3.27832 19.8217C3.10002 19.6436 3 19.402 3 19.15V3.95001C3 3.69802 3.10002 3.45647 3.27832 3.27832C3.45644 3.10002 3.69801 3 3.95001 3L21.05 3.00001ZM21.05 12.5C21.302 12.5 21.5435 12.6 21.7217 12.7783C21.9 12.9565 22 13.198 22 13.45V19.15C22 19.402 21.9 19.6436 21.7217 19.8217C21.5436 20 21.302 20.1 21.05 20.1H13.45C13.198 20.1 12.9564 20 12.7783 19.8217C12.6 19.6436 12.5 19.402 12.5 19.15V13.45C12.5 13.198 12.6 12.9565 12.7783 12.7783C12.9564 12.6 13.198 12.5 13.45 12.5H21.05ZM7.47178 6.12823L9.60928 8.26572L11.5501 6.32492V11.5499H6.32509L8.26589 9.60911L6.12839 7.47161L7.47178 6.12823Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
16114
15855
 
16115
- const buttonHtml$1 = "<button class=\"gplayer-lite-btn gcore-skin-button-color\">\n <%= pipIcon %>\n</button>\n";
15856
+ const buttonHtml$2 = "<button class=\"gplayer-lite-btn gcore-skin-button-color\">\n <%= pipIcon %>\n</button>\n";
16116
15857
 
16117
- const VERSION$2 = '0.0.1';
16118
- const T$7 = `plugins.pip`;
15858
+ const VERSION$3 = '0.0.1';
15859
+ const T$8 = `plugins.pip`;
16119
15860
  /**
16120
15861
  * `PLUGIN` that enables picture in picture mode.
16121
15862
  * @beta
@@ -16143,9 +15884,9 @@ class PictureInPicture extends UICorePlugin {
16143
15884
  * @internal
16144
15885
  */
16145
15886
  static get version() {
16146
- return VERSION$2;
15887
+ return VERSION$3;
16147
15888
  }
16148
- static buttonTemplate = tmpl(buttonHtml$1);
15889
+ static buttonTemplate = tmpl(buttonHtml$2);
16149
15890
  /**
16150
15891
  * @internal
16151
15892
  */
@@ -16198,7 +15939,7 @@ class PictureInPicture extends UICorePlugin {
16198
15939
  }
16199
15940
  }
16200
15941
  requestPictureInPicture() {
16201
- trace(`${T$7} requestPictureInPicture`, {
15942
+ trace(`${T$8} requestPictureInPicture`, {
16202
15943
  videoElement: !!this.videoElement,
16203
15944
  });
16204
15945
  this.videoElement.requestPictureInPicture();
@@ -16208,12 +15949,18 @@ class PictureInPicture extends UICorePlugin {
16208
15949
  }
16209
15950
  }
16210
15951
 
16211
- const buttonHtml = "<button class='gplayer-lite-btn gcore-skin-text-color gear-option' id=\"playback-rate-button\">\n <span class=\"gear-option_speed-icon\"><%= speedIcon %></span>\n <span class=\"gear-option_label\"><%= i18n.t('playback_rate') %></span>\n <span class=\"gear-option_arrow-right-icon\"><%= arrowRightIcon %></span>\n <span class='gear-option_value'><%= title %></span>\n</button>\n";
15952
+ const buttonHtml$1 = "<button class='gplayer-lite-btn gcore-skin-text-color gear-option' id=\"playback-rate-button\">\n <span class=\"gear-option_speed-icon\"><%= speedIcon %></span>\n <span class=\"gear-option_label\"><%= i18n.t('playback_rate') %></span>\n <span class=\"gear-option_arrow-right-icon\"><%= arrowRightIcon %></span>\n <span class='gear-option_value'><%= title %></span>\n</button>\n";
16212
15953
 
16213
- const listHtml = "<button class=\"gplayer-lite-btn go-back gcore-skin-text-color\" id=\"playback-rate-back-button\">\n <span class=\"arrow-left-icon\"><%= arrowLeftIcon %></span>\n <%= i18n.t('playback_rate') %>\n</button>\n<ul class=\"gear-sub-menu\" id=\"playback-rate-menu\">\n <% for (const item of playbackRates) { %>\n <li<%= item.value === current ? ' class=\"current\"' : '' %>>\n <a href=\"#\" class=\"gear-sub-menu_btn gcore-skin-text-color<%= item.value === current ? ' gcore-skin-active' : '' %>\" data-rate=\"<%= item.value %>\">\n <span class=\"check-icon\"><%= checkIcon %></span>\n <%= item.label %>\n </a>\n </li>\n <% } %>\n</ul>";
15954
+ const listHtml$1 = "<button class=\"gplayer-lite-btn go-back gcore-skin-text-color\" id=\"playback-rate-back-button\">\n <span class=\"arrow-left-icon\"><%= arrowLeftIcon %></span>\n <%= i18n.t('playback_rate') %>\n</button>\n<ul class=\"gear-sub-menu\" id=\"playback-rate-menu\">\n <% for (const item of playbackRates) { %>\n <li<%= item.value === current ? ' class=\"current\"' : '' %>>\n <a href=\"#\" class=\"gear-sub-menu_btn gcore-skin-text-color<%= item.value === current ? ' gcore-skin-active' : '' %>\" data-rate=\"<%= item.value %>\">\n <span class=\"check-icon\"><%= checkIcon %></span>\n <%= item.label %>\n </a>\n </li>\n <% } %>\n</ul>";
16214
15955
 
16215
15956
  const speedIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M11.9854 23.9999C11.4272 23.9999 10.9571 23.5293 10.9571 22.9704C10.9571 22.4115 11.4272 21.9409 11.9854 21.9409C17.4492 21.9409 21.9143 17.4704 21.9143 11.9999C21.9143 6.52948 17.4492 2.05899 11.9854 2.05899C11.4272 2.05899 10.9571 1.58836 10.9571 1.02949C10.9571 0.470625 11.4272 0 11.9854 0C18.5949 0 24 5.38224 24 12.0291C24 18.6766 18.5949 24 11.9854 24V23.9999ZM10.2227 17.853L17.4785 13.4413C18.0072 13.1178 18.301 12.5885 18.301 11.9707C18.301 11.353 17.9779 10.8237 17.4785 10.5002L10.2227 6.08852C9.69405 5.76499 9.01826 5.76499 8.4896 6.05919C7.96094 6.35338 7.60828 6.94157 7.60828 7.5591V16.3824C7.60828 17.0002 7.93142 17.5883 8.4896 17.8824C8.75393 18.0294 9.04779 18.1177 9.34139 18.1177C9.63523 18.1177 9.95838 18.0294 10.2227 17.853V17.853ZM15.9216 11.9707L9.66457 15.7647V8.17661L15.9216 11.9707ZM8.22516 22.3529C8.4602 21.8236 8.25447 21.2058 7.7258 20.9705C7.19714 20.7353 6.69755 20.4413 6.2277 20.0882C5.75764 19.7646 5.11137 19.8822 4.78824 20.3235C4.46509 20.7941 4.58251 21.4412 5.02327 21.7647C5.58146 22.1764 6.19819 22.5293 6.81519 22.8235C6.96211 22.8824 7.10903 22.9117 7.25574 22.9117C7.66699 22.941 8.04893 22.7057 8.22513 22.3528L8.22516 22.3529ZM3.58381 19.0882C4.05387 18.7647 4.17127 18.1177 3.84814 17.647C3.52502 17.1764 3.23115 16.6765 2.99635 16.1471C2.76132 15.6178 2.14456 15.4118 1.6157 15.6472C1.08704 15.8825 0.881306 16.5 1.11634 17.0295C1.41018 17.6472 1.7626 18.2648 2.14459 18.8236C2.35032 19.1178 2.67325 19.2646 2.99638 19.2646C3.20191 19.2942 3.40763 19.2353 3.58384 19.0882L3.58381 19.0882ZM1.14563 13.9707C1.70382 13.9118 2.14435 13.4118 2.08576 12.853C2.05645 12.5588 2.05645 12.2648 2.05645 11.9706C2.05645 11.6764 2.05645 11.4117 2.08576 11.1178C2.14456 10.5589 1.70381 10.059 1.14563 10.0001C0.587439 9.94122 0.0881057 10.3825 0.0293019 10.9414C1.96979e-07 11.2942 0 11.6178 0 11.9709C0 12.3237 0.0293018 12.6768 0.0588091 13.0297C0.117618 13.5589 0.558169 13.9709 1.08706 13.9709C1.08686 13.9707 1.11636 13.9707 1.14567 13.9707L1.14563 13.9707ZM2.96687 7.79432C3.2019 7.26502 3.49553 6.76482 3.81866 6.2944C4.1418 5.82377 4.02439 5.17672 3.55432 4.8532C3.08427 4.52967 2.438 4.64722 2.11486 5.11786C1.73292 5.67672 1.38047 6.2942 1.08661 6.91193C0.851579 7.44123 1.08661 8.05897 1.58597 8.29426C1.73289 8.35314 1.87981 8.38247 2.02652 8.38247C2.40888 8.41181 2.7906 8.1767 2.96686 7.7943L2.96687 7.79432ZM6.22757 3.85328C6.69762 3.52974 7.19696 3.23554 7.69635 2.97089C8.22501 2.73558 8.43074 2.11807 8.19571 1.58857C7.96068 1.05927 7.34392 0.85329 6.81505 1.08861C6.19806 1.3828 5.58128 1.73565 5.02314 2.14741C4.55308 2.47094 4.43568 3.11797 4.78811 3.5886C4.99384 3.8828 5.31676 4.02969 5.6399 4.02969C5.84583 4.05902 6.05135 4.00014 6.22757 3.85325V3.85328Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
16216
15957
 
15958
+ const arrowRightIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8.70725 20.7073C8.51225 20.9023 8.25625 21.0002 8.00025 21.0002C7.74425 21.0002 7.48825 20.9023 7.29325 20.7073C6.90225 20.3162 6.90225 19.6842 7.29325 19.2932L14.5863 12.0002L7.29325 4.70725C6.90225 4.31625 6.90225 3.68425 7.29325 3.29325C7.68425 2.90225 8.31625 2.90225 8.70725 3.29325L16.7073 11.2933C17.0983 11.6842 17.0983 12.3162 16.7073 12.7072L8.70725 20.7073Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
15959
+
15960
+ const arrowLeftIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M16.7073 19.2932C17.0983 19.6842 17.0983 20.3162 16.7073 20.7073C16.5123 20.9023 16.2563 21.0002 16.0003 21.0002C15.7443 21.0002 15.4882 20.9023 15.2933 20.7073L7.29325 12.7072C6.90225 12.3162 6.90225 11.6842 7.29325 11.2933L15.2933 3.29325C15.6842 2.90225 16.3163 2.90225 16.7073 3.29325C17.0983 3.68425 17.0983 4.31625 16.7073 4.70725L9.41425 12.0002L16.7073 19.2932Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
15961
+
15962
+ const checkIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path fill-rule=\"evenodd\" clip-rule=\"evenodd\"\n d=\"M20.5793 4.19296C20.1216 3.86696 19.4777 3.96396 19.1424 4.40896L9.37295 17.3809L4.81634 12.107C4.45222 11.683 3.80218 11.6289 3.36709 11.9839C2.932 12.3389 2.87543 12.97 3.2416 13.393L8.64165 19.643C8.83708 19.869 9.12506 20 9.42849 20C9.4398 20 9.45114 20 9.46246 19.999C9.77926 19.989 10.0724 19.838 10.2586 19.59L20.8015 5.58996C21.1368 5.14496 21.0371 4.51896 20.5793 4.19296Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
15963
+
16217
15964
  var PlaybackEvents;
16218
15965
  (function (PlaybackEvents) {
16219
15966
  /**
@@ -16234,7 +15981,7 @@ const DEFAULT_PLAYBACK_RATES = [
16234
15981
  { value: 2.0, label: '2x' },
16235
15982
  ];
16236
15983
  const DEFAULT_PLAYBACK_RATE = 1;
16237
- const T$6 = 'plugins.playback_rate';
15984
+ const T$7 = 'plugins.playback_rate';
16238
15985
  /**
16239
15986
  * `PLUGIN` that allows changing the playback speed of the video.
16240
15987
  * @beta
@@ -16262,12 +16009,11 @@ const T$6 = 'plugins.playback_rate';
16262
16009
  * { value: 1, label: '1x' },
16263
16010
  * ],
16264
16011
  * defaultValue: 1,
16265
- * } as PlaybackRateSettings,
16012
+ * },
16266
16013
  * })
16267
16014
  * ```
16268
16015
  */
16269
16016
  class PlaybackRate extends UICorePlugin {
16270
- playbackRates = DEFAULT_PLAYBACK_RATES;
16271
16017
  // Saved when an ad starts to restore after it finishes
16272
16018
  // private prevSelectedRate: string | undefined
16273
16019
  selectedRate = DEFAULT_PLAYBACK_RATE;
@@ -16283,14 +16029,16 @@ class PlaybackRate extends UICorePlugin {
16283
16029
  get supportedVersion() {
16284
16030
  return { min: CLAPPR_VERSION };
16285
16031
  }
16286
- static buttonTemplate = tmpl(buttonHtml);
16287
- static listTemplate = tmpl(listHtml);
16032
+ static buttonTemplate = tmpl(buttonHtml$1);
16033
+ static listTemplate = tmpl(listHtml$1);
16288
16034
  constructor(core) {
16289
16035
  super(core);
16290
- this.playbackRates =
16291
- core.options.playbackRate?.options || DEFAULT_PLAYBACK_RATES;
16292
- this.selectedRate =
16293
- core.options.playbackRate?.defaultValue || DEFAULT_PLAYBACK_RATE;
16036
+ if (this.core.options.playbackRate?.defaultValue) {
16037
+ this.setSelectedRate(this.core.options.playbackRate.defaultValue);
16038
+ }
16039
+ }
16040
+ get playbackRates() {
16041
+ return this.core.options.playbackRate?.options || DEFAULT_PLAYBACK_RATES;
16294
16042
  }
16295
16043
  /**
16296
16044
  * @internal
@@ -16334,9 +16082,15 @@ class PlaybackRate extends UICorePlugin {
16334
16082
  this.render();
16335
16083
  }
16336
16084
  onGearRendered() {
16337
- this.addGearItem();
16085
+ this.mount();
16338
16086
  }
16339
- addGearItem() {
16087
+ mount() {
16088
+ trace(`${T$7} mount`, {
16089
+ shouldMount: this.shouldMount(),
16090
+ });
16091
+ if (!this.shouldMount()) {
16092
+ return;
16093
+ }
16340
16094
  this.core
16341
16095
  .getPlugin('bottom_gear')
16342
16096
  ?.addItem('rate', this.$el)
@@ -16362,12 +16116,12 @@ class PlaybackRate extends UICorePlugin {
16362
16116
  this.core.activePlayback?.setPlaybackRate(this.selectedRate);
16363
16117
  }
16364
16118
  else {
16365
- trace(`${T$6} onPlaybackRateChange not steering to the selected rate, it is seemingly a catchup algorithm working`, {
16119
+ trace(`${T$7} onPlaybackRateChange not steering to the selected rate, it is seemingly a catchup algorithm working`, {
16366
16120
  selectedRate: this.selectedRate,
16367
16121
  });
16368
16122
  }
16369
16123
  }
16370
- shouldRender() {
16124
+ shouldMount() {
16371
16125
  if (!this.core.activePlayback) {
16372
16126
  return false;
16373
16127
  }
@@ -16381,12 +16135,9 @@ class PlaybackRate extends UICorePlugin {
16381
16135
  * @internal
16382
16136
  */
16383
16137
  render() {
16384
- trace(`${T$6} render`, {
16385
- shouldRender: this.shouldRender(),
16138
+ trace(`${T$7} render`, {
16139
+ shouldMount: this.shouldMount(),
16386
16140
  });
16387
- if (!this.shouldRender()) {
16388
- return this;
16389
- }
16390
16141
  this.$el.html(PlaybackRate.listTemplate({
16391
16142
  arrowLeftIcon,
16392
16143
  checkIcon,
@@ -16394,7 +16145,7 @@ class PlaybackRate extends UICorePlugin {
16394
16145
  i18n: this.core.i18n,
16395
16146
  playbackRates: this.playbackRates,
16396
16147
  }));
16397
- this.addGearItem();
16148
+ this.mount();
16398
16149
  return this;
16399
16150
  }
16400
16151
  // private onStartAd() {
@@ -16417,11 +16168,21 @@ class PlaybackRate extends UICorePlugin {
16417
16168
  this.resetPlaybackRate();
16418
16169
  }
16419
16170
  else {
16420
- this.setSelectedRate(this.selectedRate);
16171
+ this.syncRate();
16421
16172
  }
16422
16173
  }
16174
+ syncRate() {
16175
+ trace(`${T$7} syncRate`, {
16176
+ selectedRate: this.selectedRate,
16177
+ });
16178
+ this.core.activePlayback?.setPlaybackRate(this.selectedRate);
16179
+ }
16423
16180
  resetPlaybackRate() {
16424
- this.setSelectedRate(DEFAULT_PLAYBACK_RATE);
16181
+ trace(`${T$7} resetPlaybackRate`, {
16182
+ selectedRate: this.selectedRate,
16183
+ });
16184
+ this.core.activePlayback?.setPlaybackRate(DEFAULT_PLAYBACK_RATE);
16185
+ this.selectedRate = DEFAULT_PLAYBACK_RATE;
16425
16186
  }
16426
16187
  onStop() { }
16427
16188
  onSelect(event) {
@@ -16429,8 +16190,6 @@ class PlaybackRate extends UICorePlugin {
16429
16190
  const rate = parseFloat(event.currentTarget.dataset.rate || '');
16430
16191
  if (rate) {
16431
16192
  this.setSelectedRate(rate);
16432
- this.highlightCurrentRate();
16433
- this.updateGearOptionLabel();
16434
16193
  }
16435
16194
  return false;
16436
16195
  }
@@ -16440,14 +16199,23 @@ class PlaybackRate extends UICorePlugin {
16440
16199
  }, 0);
16441
16200
  }
16442
16201
  setSelectedRate(rate) {
16443
- this.core.activePlayback?.setPlaybackRate(rate);
16202
+ if (rate === this.selectedRate) {
16203
+ return;
16204
+ }
16444
16205
  this.selectedRate = rate;
16206
+ this.syncRate();
16207
+ this.highlightCurrentRate();
16208
+ this.updateGearOptionLabel();
16445
16209
  }
16446
16210
  getTitle() {
16447
- return (this.playbackRates.find((r) => r.value === this.selectedRate)?.label ||
16448
- `x${this.selectedRate}`);
16211
+ const rate = this.selectedRate;
16212
+ return (this.playbackRates.find((r) => r.value === rate)?.label ||
16213
+ `x${rate}`);
16449
16214
  }
16450
16215
  highlightCurrentRate() {
16216
+ trace(`${T$7} highlightCurrentRate`, {
16217
+ selectedRate: this.selectedRate,
16218
+ });
16451
16219
  this.allRateElements().removeClass('current');
16452
16220
  this.allRateElements().find('a').removeClass('gcore-skin-active');
16453
16221
  this.rateElement(this.selectedRate)
@@ -16456,7 +16224,10 @@ class PlaybackRate extends UICorePlugin {
16456
16224
  .addClass('gcore-skin-active');
16457
16225
  }
16458
16226
  updateGearOptionLabel() {
16459
- this.addGearItem();
16227
+ trace(`${T$7} updateGearOptionLabel`, {
16228
+ selectedRate: this.selectedRate,
16229
+ });
16230
+ this.mount();
16460
16231
  }
16461
16232
  }
16462
16233
 
@@ -16465,7 +16236,7 @@ const posterHTML = "<div class=\"play-wrapper\" data-poster></div>\n";
16465
16236
  //Copyright 2014 Globo.com Player authors. All rights reserved.
16466
16237
  // Use of this source code is governed by a BSD-style
16467
16238
  // license that can be found in the LICENSE file.
16468
- const T$5 = 'plugins.poster';
16239
+ const T$6 = 'plugins.poster';
16469
16240
  /**
16470
16241
  * `PLUGIN` that displays a poster image in the background and a big play button on top when playback is stopped
16471
16242
  * @beta
@@ -16576,7 +16347,7 @@ class Poster extends UIContainerPlugin {
16576
16347
  super.disable();
16577
16348
  }
16578
16349
  onError(error) {
16579
- trace(`${T$5} onError`, {
16350
+ trace(`${T$6} onError`, {
16580
16351
  enabled: this.enabled,
16581
16352
  });
16582
16353
  this.hasFatalError = error.level === PlayerError.Levels.FATAL;
@@ -16597,7 +16368,7 @@ class Poster extends UIContainerPlugin {
16597
16368
  this.update();
16598
16369
  }
16599
16370
  onStop() {
16600
- trace(`${T$5} onStop`, {
16371
+ trace(`${T$6} onStop`, {
16601
16372
  enabled: this.enabled,
16602
16373
  });
16603
16374
  this.hasStartedPlaying = false;
@@ -16605,7 +16376,7 @@ class Poster extends UIContainerPlugin {
16605
16376
  this.update();
16606
16377
  }
16607
16378
  updatePlayButton(show) {
16608
- trace(`${T$5} updatePlayButton`, {
16379
+ trace(`${T$6} updatePlayButton`, {
16609
16380
  chromeless: this.options.chromeless,
16610
16381
  allowUserInteraction: this.options.allowUserInteraction,
16611
16382
  });
@@ -16633,7 +16404,7 @@ class Poster extends UIContainerPlugin {
16633
16404
  this.$el.removeClass('clickable');
16634
16405
  }
16635
16406
  clicked() {
16636
- trace(`${T$5} clicked`, {
16407
+ trace(`${T$6} clicked`, {
16637
16408
  hasStartedPlaying: this.hasStartedPlaying,
16638
16409
  chromeless: this.options.chromeless,
16639
16410
  allowUserInteraction: this.options.allowUserInteraction,
@@ -16654,7 +16425,7 @@ class Poster extends UIContainerPlugin {
16654
16425
  return !this.container.playback.isAudioOnly;
16655
16426
  }
16656
16427
  update() {
16657
- trace(`${T$5} update`, {
16428
+ trace(`${T$6} update`, {
16658
16429
  shouldRender: this.shouldRender,
16659
16430
  });
16660
16431
  if (!this.shouldRender) {
@@ -16667,7 +16438,7 @@ class Poster extends UIContainerPlugin {
16667
16438
  this.updatePoster();
16668
16439
  }
16669
16440
  updatePoster() {
16670
- trace(`${T$5} updatePoster`, {
16441
+ trace(`${T$6} updatePoster`, {
16671
16442
  hasStartedPlaying: this.hasStartedPlaying,
16672
16443
  });
16673
16444
  if (!this.hasStartedPlaying) {
@@ -16682,7 +16453,7 @@ class Poster extends UIContainerPlugin {
16682
16453
  this.$el.show();
16683
16454
  }
16684
16455
  hidePoster() {
16685
- trace(`${T$5} hidePoster`, {
16456
+ trace(`${T$6} hidePoster`, {
16686
16457
  shouldHideOnPlay: this.shouldHideOnPlay(),
16687
16458
  });
16688
16459
  if (!this.options.disableMediaControl) {
@@ -16732,6 +16503,275 @@ class Poster extends UIContainerPlugin {
16732
16503
  }
16733
16504
  }
16734
16505
 
16506
+ const buttonHtml = "<button class='gplayer-lite-btn gcore-skin-text-color gear-option' aria-haspopup=\"menu\">\n <span class=\"gear-option_hd-icon<%= isHd ? '' : ' hidden' %>\"><%= hdIcon %></span>\n <span><%= i18n.t('quality') %></span>\n <span class=\"gear-option_arrow-right-icon\"><%= arrowRightIcon %></span>\n <span class='gear-option_value'><%= currentText %></span>\n</button>\n";
16507
+
16508
+ const listHtml = "<button class=\"gplayer-lite-btn go-back gcore-skin-text-color\" id=\"level-selector-back-button\">\n <span class=\"arrow-left-icon\"><%= arrowLeftIcon %></span>\n <%= i18n.t('quality') %>\n</button>\n<ul class=\"gear-sub-menu quality-levels\" id=\"level-selector-menu\" role=\"menu\">\n <% if (!removeAuto) { %>\n <li>\n <a href=\"#\" class='gear-sub-menu_btn gcore-skin-text-color' data-id=\"-1\" id=\"level_selector_auto\">\n <span class=\"check-icon\"><%= checkIcon %></span>\n <%= i18n.t('auto') %>\n </a>\n </li>\n <% } %>\n <% for (const item of levels.slice().reverse()) {\n var disabled = maxLevel >= 0 && item.level > maxLevel\n var checked = item.level === current\n %>\n <li class=\"<%= disabled ? ' disabled' : ''%><%=checked ? ' current' : ''%>\">\n <a href=\"#\"\n class=\"gear-sub-menu_btn gcore-skin-text-color<%= checked ? ' gcore-skin-active' : '' %>\"\n data-id=\"<%= item.level %>\"\n data-disabled=\"<%= disabled %>\"\n data-checked=\"<%= checked %>\"\n role=\"menuitemradio\"\n id=\"level_selector_<%= item.width > item.height ? item.height : item.width %>\"\n >\n <span class=\"check-icon\"><%= checkIcon %></span>\n <%= labels[item.level] %>\n </a>\n </li>\n <% } %>\n</ul>\n";
16509
+
16510
+ const hdIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M14.9562 8.22232H13.9961V15.1873H14.9562C15.8914 15.1873 16.766 14.8253 17.4195 14.1676C18.0786 13.5037 18.4415 12.6281 18.4415 11.7026C18.4415 9.7837 16.8781 8.22253 14.9561 8.22253L14.9562 8.22232Z\"\n fill=\"#C9C9C9\"/>\n <path\n d=\"M22.0801 4H1.91994C0.859222 4 0 4.86406 0 5.91994V17.4878C0 18.5437 0.859222 19.4078 1.91994 19.4078H22.0801C23.1408 19.4078 24 18.5437 24 17.4878V5.91994C24 4.86406 23.1408 4 22.0801 4ZM10.3975 15.3473C10.3975 15.6124 10.1827 15.8272 9.91754 15.8272C9.65216 15.8272 9.43761 15.6122 9.43761 15.3473V12.0239H5.55956V15.3473C5.55956 15.6124 5.34481 15.8272 5.07963 15.8272C4.81425 15.8272 4.5997 15.6122 4.5997 15.3473L4.59949 7.74042C4.59949 7.47524 4.81425 7.26049 5.07943 7.26049C5.34481 7.26049 5.55936 7.47544 5.55936 7.74042V11.0636H9.43741V7.74042C9.43741 7.47524 9.65216 7.26049 9.91734 7.26049C10.1827 7.26049 10.3973 7.47544 10.3973 7.74042L10.3975 15.3473ZM18.1005 14.8438C17.2652 15.6844 16.1486 16.1472 14.9561 16.1472H13.5161C13.2507 16.1472 13.0361 15.9323 13.0361 15.6673V7.74263C13.0361 7.47745 13.2509 7.26269 13.5161 7.26269H14.9561C17.4072 7.26269 19.4013 9.25438 19.4013 11.7027C19.4013 12.8835 18.9392 13.9991 18.1005 14.844V14.8438Z\"\n fill=\"#C9C9C9\"/>\n</svg>\n";
16511
+
16512
+ const T$5 = 'plugins.quality_levels';
16513
+ const VERSION$2 = 'v2.22.5';
16514
+ /**
16515
+ * `PLUGIN` that provides a UI to select the desired quality level of the playback.
16516
+ * @beta
16517
+ *
16518
+ * @remarks
16519
+ * Depends on:
16520
+ *
16521
+ * - {@link MediaControl}
16522
+ *
16523
+ * - {@link BottomGear}
16524
+ *
16525
+ * The plugin is rendered as an item in the gear menu, which, when clicked, shows a list of quality levels to choose from.
16526
+ *
16527
+ * Configuration options - {@link QualityLevelsPluginSettings}
16528
+ *
16529
+ * @example
16530
+ * ```ts
16531
+ * new Player({
16532
+ * qualityLevels: {
16533
+ * restrictResolution: 360,
16534
+ * labels: { 360: 'SD', 720: 'HD' },
16535
+ * },
16536
+ * })
16537
+ * ```
16538
+ */
16539
+ class QualityLevels extends UICorePlugin {
16540
+ levels = [];
16541
+ levelLabels = [];
16542
+ removeAuto = false;
16543
+ isHd = false;
16544
+ currentText = '';
16545
+ selectedLevelId = -1;
16546
+ static buttonTemplate = tmpl(buttonHtml);
16547
+ static listTemplate = tmpl(listHtml);
16548
+ /**
16549
+ * @internal
16550
+ */
16551
+ get name() {
16552
+ return 'level_selector';
16553
+ }
16554
+ /**
16555
+ * @internal
16556
+ */
16557
+ get supportedVersion() {
16558
+ return { min: CLAPPR_VERSION };
16559
+ }
16560
+ /**
16561
+ * @internal
16562
+ */
16563
+ static get version() {
16564
+ return VERSION$2;
16565
+ }
16566
+ /**
16567
+ * @internal
16568
+ */
16569
+ get attributes() {
16570
+ return {
16571
+ class: 'level-selector',
16572
+ 'data-level-selector': '',
16573
+ };
16574
+ }
16575
+ get events() {
16576
+ return {
16577
+ 'click .gear-sub-menu_btn': 'onSelect',
16578
+ 'click .go-back': 'goBack',
16579
+ };
16580
+ }
16581
+ /**
16582
+ * @internal
16583
+ */
16584
+ bindEvents() {
16585
+ this.listenToOnce(this.core, Events.CORE_READY, this.onCoreReady);
16586
+ this.listenTo(this.core, Events.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChange);
16587
+ }
16588
+ onCoreReady() {
16589
+ const gear = this.core.getPlugin('bottom_gear');
16590
+ assert(gear, 'bottom_gear plugin is required');
16591
+ this.currentText = this.core.i18n.t('auto');
16592
+ this.listenTo(gear, GearEvents.RENDERED, this.onGearRendered);
16593
+ }
16594
+ onGearRendered() {
16595
+ this.render();
16596
+ }
16597
+ onActiveContainerChange() {
16598
+ this.removeAuto = false;
16599
+ this.isHd = false;
16600
+ const activePlayback = this.core.activePlayback;
16601
+ this.listenTo(activePlayback, Events.PLAYBACK_LEVELS_AVAILABLE, this.onLevelsAvailable);
16602
+ this.listenTo(activePlayback, Events.PLAYBACK_LEVEL_SWITCH_START, this.onLevelSwitchStart);
16603
+ this.listenTo(activePlayback, Events.PLAYBACK_LEVEL_SWITCH_END, this.onLevelSwitchEnd);
16604
+ this.listenTo(activePlayback, Events.PLAYBACK_BITRATE, this.onBitrate);
16605
+ this.listenTo(activePlayback, Events.PLAYBACK_STOP, this.onStop);
16606
+ this.listenTo(activePlayback, Events.PLAYBACK_HIGHDEFINITIONUPDATE, (isHd) => {
16607
+ this.isHd = isHd;
16608
+ this.updateHd();
16609
+ });
16610
+ if (activePlayback.levels?.length > 0) {
16611
+ this.onLevelsAvailable(activePlayback.levels);
16612
+ }
16613
+ }
16614
+ updateHd() {
16615
+ if (this.isHd) {
16616
+ this.$el.find('.gear-option_hd-icon').removeClass('hidden');
16617
+ }
16618
+ else {
16619
+ this.$el.find('.gear-option_hd-icon').addClass('hidden');
16620
+ }
16621
+ }
16622
+ onStop() {
16623
+ this.listenToOnce(this.core.activePlayback, Events.PLAYBACK_PLAY, () => {
16624
+ if (this.core.activePlayback.getPlaybackType() === 'live') {
16625
+ if (this.selectedLevelId !== -1) {
16626
+ this.core.activePlayback.currentLevel = this.selectedLevelId;
16627
+ }
16628
+ }
16629
+ });
16630
+ }
16631
+ shouldRender() {
16632
+ const activePlayback = this.core.activePlayback;
16633
+ if (!activePlayback) {
16634
+ return false;
16635
+ }
16636
+ const supportsCurrentLevel = 'currentLevel' in activePlayback;
16637
+ if (!supportsCurrentLevel) {
16638
+ return false;
16639
+ }
16640
+ // Only care if we have at least 2 to choose from
16641
+ return !!(this.levels && this.levels.length > 1);
16642
+ }
16643
+ /**
16644
+ * @internal
16645
+ */
16646
+ render() {
16647
+ if (!this.shouldRender()) {
16648
+ return this;
16649
+ }
16650
+ this.renderDropdown();
16651
+ this.updateButton();
16652
+ return this;
16653
+ }
16654
+ renderDropdown() {
16655
+ this.$el.html(QualityLevels.listTemplate({
16656
+ arrowLeftIcon,
16657
+ checkIcon,
16658
+ current: this.selectedLevelId,
16659
+ labels: this.levelLabels,
16660
+ levels: this.levels,
16661
+ maxLevel: this.maxLevel,
16662
+ removeAuto: this.removeAuto,
16663
+ i18n: this.core.i18n,
16664
+ }));
16665
+ }
16666
+ updateButton() {
16667
+ this.core.getPlugin('bottom_gear')
16668
+ ?.addItem('quality', this.$el)
16669
+ .html(QualityLevels.buttonTemplate({
16670
+ arrowRightIcon,
16671
+ currentText: this.currentText,
16672
+ isHd: this.isHd,
16673
+ hdIcon,
16674
+ i18n: this.core.i18n,
16675
+ }));
16676
+ }
16677
+ get pluginOptions() {
16678
+ return (this.core.options.qualityLevels || this.core.options.levelSelector || {});
16679
+ }
16680
+ get maxLevel() {
16681
+ const maxRes = this.pluginOptions.restrictResolution;
16682
+ return maxRes
16683
+ ? this.levels.find((level) => (level.height > level.width ? level.width : level.height) ===
16684
+ maxRes)?.level ?? -1
16685
+ : -1;
16686
+ }
16687
+ onLevelsAvailable(levels) {
16688
+ const maxResolution = this.pluginOptions.restrictResolution;
16689
+ this.levels = levels;
16690
+ this.makeLevelsLabels();
16691
+ if (maxResolution) {
16692
+ this.removeAuto = true;
16693
+ const initialLevel = levels
16694
+ .filter((level) => (level.width > level.height ? level.height : level.width) <=
16695
+ maxResolution)
16696
+ .pop();
16697
+ this.setLevel(initialLevel?.level ?? 0);
16698
+ }
16699
+ this.render();
16700
+ }
16701
+ makeLevelsLabels() {
16702
+ const labels = this.pluginOptions.labels ?? {};
16703
+ this.levelLabels = [];
16704
+ for (const level of this.levels) {
16705
+ const ll = level.width > level.height ? level.height : level.width;
16706
+ const label = labels[ll] || `${ll}p`;
16707
+ this.levelLabels.push(label);
16708
+ }
16709
+ }
16710
+ onSelect(event) {
16711
+ const selectedLevel = parseInt(event.currentTarget?.dataset?.id ?? '-1', 10);
16712
+ this.setLevel(selectedLevel);
16713
+ event.stopPropagation();
16714
+ event.preventDefault();
16715
+ return false;
16716
+ }
16717
+ goBack() {
16718
+ this.core.getPlugin('bottom_gear').refresh();
16719
+ }
16720
+ setLevel(index) {
16721
+ this.selectedLevelId = index;
16722
+ this.core.activePlayback.currentLevel = this.selectedLevelId;
16723
+ this.highlightCurrentLevel();
16724
+ }
16725
+ allLevelElements() {
16726
+ return this.$('#level-selector-menu li');
16727
+ }
16728
+ levelElement(id = -1) {
16729
+ return this.$(`#level-selector-menu a[data-id="${id}"]`).parent();
16730
+ }
16731
+ onLevelSwitchStart() {
16732
+ this.levelElement(this.selectedLevelId).addClass('changing');
16733
+ }
16734
+ onLevelSwitchEnd() {
16735
+ this.levelElement(this.selectedLevelId).removeClass('changing');
16736
+ }
16737
+ updateText(level) {
16738
+ this.currentText = this.getLevelLabel(level);
16739
+ this.updateButton();
16740
+ }
16741
+ getLevelLabel(id) {
16742
+ if (id < 0) {
16743
+ return this.core.i18n.t('auto');
16744
+ }
16745
+ const index = this.levels.findIndex((l) => l.level === id);
16746
+ if (index < 0) {
16747
+ return this.core.i18n.t('auto');
16748
+ }
16749
+ return this.levelLabels[index] ?? formatLevelLabel(this.levels[index]);
16750
+ }
16751
+ onBitrate(info) {
16752
+ this.highlightCurrentLevel();
16753
+ }
16754
+ highlightCurrentLevel() {
16755
+ trace(`${T$5} highlightCurrentLevel`, {
16756
+ selectedLevelId: this.selectedLevelId,
16757
+ });
16758
+ this.allLevelElements()
16759
+ .removeClass('current')
16760
+ .find('a')
16761
+ .removeClass('gcore-skin-active');
16762
+ const currentLevelElement = this.levelElement(this.selectedLevelId);
16763
+ currentLevelElement
16764
+ .addClass('current')
16765
+ .find('a')
16766
+ .addClass('gcore-skin-active');
16767
+ this.updateText(this.selectedLevelId);
16768
+ }
16769
+ }
16770
+ function formatLevelLabel(level) {
16771
+ const h = level.width > level.height ? level.height : level.width;
16772
+ return `${h}p`;
16773
+ }
16774
+
16735
16775
  const seekTimeHTML = "<span data-seek-time></span>\n<span data-duration></span>\n";
16736
16776
 
16737
16777
  // Copyright 2014 Globo.com Player authors. All rights reserved.
@@ -18691,4 +18731,4 @@ class VolumeFade extends UICorePlugin {
18691
18731
  }
18692
18732
  }
18693
18733
 
18694
- export { AudioTracks as AudioSelector, AudioTracks, BigMuteButton, BottomGear, ClapprNerdStats, ClapprStats, ClickToPause, ClipsPlugin, ClosedCaptions, ContextMenu, DvrControls, ErrorScreen, Favicon, GearEvents, GoogleAnalytics, LevelSelector, Logo, MediaControl, MultiCamera, PictureInPicture, PlaybackRate, Poster, SeekTime, Share, SkipTime, SourceController, SpinnerThreeBounce as Spinner, SpinnerEvents, SpinnerThreeBounce, ClosedCaptions as Subtitles, Telemetry, TelemetryEvent, Thumbnails, VolumeFade, VolumeFadeEvents };
18734
+ export { AudioTracks as AudioSelector, AudioTracks, BigMuteButton, BottomGear, ClapprNerdStats, ClapprStats, ClickToPause, ClipsPlugin, ClosedCaptions, ContextMenu, DvrControls, ErrorScreen, Favicon, GearEvents, GoogleAnalytics, QualityLevels as LevelSelector, Logo, MediaControl, MultiCamera, PictureInPicture, PlaybackRate, Poster, QualityLevels, SeekTime, Share, SkipTime, SourceController, SpinnerThreeBounce as Spinner, SpinnerEvents, SpinnerThreeBounce, ClosedCaptions as Subtitles, Telemetry, TelemetryEvent, Thumbnails, VolumeFade, VolumeFadeEvents };