@gcorevideo/player 2.21.1 → 2.21.3

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 (35) hide show
  1. package/assets/media-control/media-control.ejs +0 -5
  2. package/assets/media-control/media-control.scss +44 -54
  3. package/assets/media-control/width370.scss +3 -5
  4. package/assets/subtitles/combobox.ejs +7 -9
  5. package/assets/subtitles/style.scss +8 -15
  6. package/dist/core.js +4 -1
  7. package/dist/index.css +733 -750
  8. package/dist/index.js +135 -159
  9. package/dist/plugins/index.css +1401 -1418
  10. package/dist/plugins/index.js +124 -155
  11. package/lib/playback/BasePlayback.d.ts +1 -0
  12. package/lib/playback/BasePlayback.d.ts.map +1 -1
  13. package/lib/playback/BasePlayback.js +3 -0
  14. package/lib/playback.types.d.ts +5 -0
  15. package/lib/playback.types.d.ts.map +1 -1
  16. package/lib/plugins/bottom-gear/BottomGear.d.ts +1 -1
  17. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  18. package/lib/plugins/bottom-gear/BottomGear.js +2 -1
  19. package/lib/plugins/media-control/MediaControl.d.ts +0 -1
  20. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  21. package/lib/plugins/media-control/MediaControl.js +7 -5
  22. package/lib/plugins/playback-rate/PlaybackRate.d.ts +1 -0
  23. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  24. package/lib/plugins/playback-rate/PlaybackRate.js +1 -0
  25. package/lib/plugins/subtitles/Subtitles.d.ts +21 -19
  26. package/lib/plugins/subtitles/Subtitles.d.ts.map +1 -1
  27. package/lib/plugins/subtitles/Subtitles.js +121 -151
  28. package/package.json +1 -1
  29. package/src/playback/BasePlayback.ts +4 -0
  30. package/src/playback.types.ts +6 -0
  31. package/src/plugins/bottom-gear/BottomGear.ts +3 -1
  32. package/src/plugins/media-control/MediaControl.ts +37 -20
  33. package/src/plugins/playback-rate/PlaybackRate.ts +1 -0
  34. package/src/plugins/subtitles/Subtitles.ts +144 -179
  35. package/tsconfig.tsbuildinfo +1 -1
package/dist/index.js CHANGED
@@ -12628,6 +12628,9 @@ var PlaybackErrorCode;
12628
12628
  * @internal
12629
12629
  */
12630
12630
  class BasePlayback extends HTML5Video$1 {
12631
+ get isHTML5Video() {
12632
+ return true;
12633
+ }
12631
12634
  createError(errorData, options) {
12632
12635
  const i18n = this.i18n ||
12633
12636
  // @ts-ignore
@@ -43296,7 +43299,7 @@ class Player {
43296
43299
  }
43297
43300
  }
43298
43301
 
43299
- var version$1 = "2.21.1";
43302
+ var version$1 = "2.21.3";
43300
43303
 
43301
43304
  var packages = {
43302
43305
  "node_modules/@clappr/core": {
@@ -43918,7 +43921,7 @@ function getPageX(event) {
43918
43921
  return 0;
43919
43922
  }
43920
43923
 
43921
- 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 renderSubtitles = function(name) { %>\n <div class=\"media-control-subtitles\" 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 renderPlaybackRate = function(name) { %>\n <div class=\"media-control-playbackrate\" data-<%= name %>></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 === \"subtitles\") {\n renderSubtitles(setting)\n } else if (setting === \"playbackrate\") {\n renderPlaybackRate(setting)\n } else if (setting === \"vr\") {\n renderVR(setting)\n } else if (setting === \"clipsText\") {\n renderClipsText(setting)\n } else {\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";
43924
+ 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 renderPlaybackRate = function(name) { %>\n <div class=\"media-control-playbackrate\" data-<%= name %>></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 === \"playbackrate\") {\n renderPlaybackRate(setting)\n } else if (setting === \"vr\") {\n renderVR(setting)\n } else if (setting === \"clipsText\") {\n renderClipsText(setting)\n } else {\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";
43922
43925
 
43923
43926
  const playIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <g clip-path=\"url(#clip0_28_1564)\">\n <path d=\"M6 3V20L19.3571 11.5L6 3Z\" fill=\"#C9C9C9\"/>\n </g>\n <defs>\n <clipPath id=\"clip0_28_1564\">\n <rect width=\"24\" height=\"24\" fill=\"white\"/>\n </clipPath>\n </defs>\n</svg>\n";
43924
43927
 
@@ -44013,7 +44016,6 @@ class MediaControl extends UICorePlugin {
44013
44016
  $seekBarLoaded = null;
44014
44017
  $seekBarPosition = null;
44015
44018
  $seekBarScrubber = null;
44016
- $subtitlesSelector = null;
44017
44019
  $volumeBarContainer = null;
44018
44020
  $volumeBarBackground = null;
44019
44021
  $volumeBarFill = null;
@@ -44034,7 +44036,8 @@ class MediaControl extends UICorePlugin {
44034
44036
  return { min: CLAPPR_VERSION };
44035
44037
  }
44036
44038
  get disabled() {
44037
- const playbackIsNOOP = this.core.activeContainer && this.core.activeContainer.getPlaybackType() === Playback.NO_OP;
44039
+ const playbackIsNOOP = this.core.activeContainer &&
44040
+ this.core.activeContainer.getPlaybackType() === Playback.NO_OP;
44038
44041
  return this.userDisabled || playbackIsNOOP;
44039
44042
  }
44040
44043
  /**
@@ -44694,7 +44697,6 @@ class MediaControl extends UICorePlugin {
44694
44697
  this.$volumeBarBackground = this.$el.find('.bar-background[data-volume]');
44695
44698
  this.$volumeBarFill = this.$el.find('.bar-fill-1[data-volume]');
44696
44699
  this.$volumeBarScrubber = this.$el.find('.bar-scrubber[data-volume]');
44697
- this.$subtitlesSelector = this.$el.find('.media-control-subtitles[data-subtitles]');
44698
44700
  this.$playbackRate = this.$el.find('.media-control-playbackrate[data-playbackrate]');
44699
44701
  this.$multiCameraSelector = this.$el.find('.media-control-multicamera[data-multicamera]');
44700
44702
  this.$clipText = this.$el.find('.media-clip-text[data-clipstext]');
@@ -44736,7 +44738,7 @@ class MediaControl extends UICorePlugin {
44736
44738
  case 'seekBarContainer':
44737
44739
  return this.$seekBarContainer;
44738
44740
  case 'subtitlesSelector':
44739
- return this.$subtitlesSelector;
44741
+ return null;
44740
44742
  }
44741
44743
  }
44742
44744
  putElement(name, element) {
@@ -44744,10 +44746,13 @@ class MediaControl extends UICorePlugin {
44744
44746
  case 'audioTracksSelector':
44745
44747
  this.getRightPanel().append(element);
44746
44748
  break;
44749
+ case 'gear':
44750
+ this.getRightPanel().append(element);
44751
+ break;
44747
44752
  case 'pip':
44748
44753
  this.getRightPanel().append(element);
44749
44754
  break;
44750
- case 'gear':
44755
+ case 'subtitlesSelector':
44751
44756
  this.getRightPanel().append(element);
44752
44757
  break;
44753
44758
  }
@@ -45043,6 +45048,7 @@ MediaControl.extend = function (properties) {
45043
45048
 
45044
45049
  const VERSION$5 = '2.19.12';
45045
45050
  const T$d = 'plugins.bottom_gear';
45051
+ // TODO disabled if no items added
45046
45052
  /**
45047
45053
  * `PLUGIN` that adds the gear button with an extra options menu on the right side of the {@link MediaControl | media control} UI
45048
45054
  * @beta
@@ -45051,7 +45057,7 @@ const T$d = 'plugins.bottom_gear';
45051
45057
  *
45052
45058
  * Depends on:
45053
45059
  *
45054
- * - {@link MediaControl | media_control}
45060
+ * - {@link MediaControl}
45055
45061
  */
45056
45062
  class BottomGear extends UICorePlugin {
45057
45063
  isHd = false;
@@ -49731,6 +49737,7 @@ const T$6 = 'plugins.playback_rate';
49731
49737
  * - {@link BottomGear | bottom_gear}
49732
49738
  *
49733
49739
  * It renders a button in the gear menu, which opens a dropdown with the options to change the playback rate.
49740
+ * Note that the playback rate change is supported only for VOD or DVR enabled live streams.
49734
49741
  */
49735
49742
  class PlaybackRate extends UICorePlugin {
49736
49743
  playbackRates = DEFAULT_PLAYBACK_RATES;
@@ -50943,14 +50950,13 @@ const subtitlesOffIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\"
50943
50950
 
50944
50951
  const subtitlesOnIcon = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M16.238 16.1C13.979 16.1 12.578 14.538 12.578 11.997C12.578 9.462 13.973 7.9 16.238 7.9C18.087 7.9 19.5029 9.127 19.6219 10.824H18.032C17.876 9.927 17.168 9.338 16.238 9.338C15.011 9.338 14.249 10.354 14.249 11.997C14.249 13.641 15.011 14.662 16.243 14.662C17.178 14.662 17.881 14.111 18.038 13.251H19.627C19.492 14.938 18.119 16.1 16.238 16.1ZM8.03198 16.1C5.77298 16.1 4.37299 14.538 4.37299 11.997C4.37299 9.462 5.76798 7.9 8.03198 7.9C9.88098 7.9 11.298 9.127 11.416 10.824H9.82697C9.67097 9.927 8.96198 9.338 8.03198 9.338C6.80598 9.338 6.04297 10.354 6.04297 11.997C6.04297 13.641 6.80596 14.662 8.03796 14.662C8.97296 14.662 9.67601 14.111 9.83301 13.251H11.422C11.287 14.938 9.91398 16.1 8.03198 16.1ZM22.5 3H1.5C0.672 3 0 3.671 0 4.5V19.5C0 20.329 0.672 21 1.5 21H22.5C23.329 21 24 20.329 24 19.5V4.5C24 3.671 23.329 3 22.5 3Z\"\n fill=\"#C9C9C9\"/>\n <rect y=\"22\" width=\"24\" height=\"2\" rx=\"1\" fill=\"#F6413B\"/>\n</svg>\n";
50945
50952
 
50946
- const comboboxHTML = "<button data-subtitles-button class='media-control-button media-control-icon gcore-skin-button-color'>\n <span class='subtitle-text'></span>\n</button>\n\n<ul class='gcore-skin-bg-color'>\n <li><a href=\"#\" class='gcore-skin-text-color' data-subtitles-select=\"off\">off</a></li>\n <% for (const track of tracks) { %>\n <% if (track.kind === 'subtitles' || track.kind === 'captions') { %>\n <li>\n <a href=\"#\" class='gcore-skin-text-color' data-subtitles-select=\"<%= track.language %>\">\n <%= track.label %>\n </a>\n </li>\n <% } %>\n <% } %>\n</ul>\n";
50953
+ const comboboxHTML = "<button data-subtitles-button class='media-control-button media-control-icon gcore-skin-button-color'>\n <span class='subtitle-text'></span>\n</button>\n\n<ul class='gcore-skin-bg-color'>\n <% for (const t of tracks) { %>\n <li>\n <a href=\"#\" class='gcore-skin-text-color' data-subtitles-select=\"<%= t.id %>\">\n <%= t.name %>\n </a>\n </li>\n <% } %>\n <li><a href=\"#\" class='gcore-skin-text-color' data-subtitles-select=\"-1\">Off</a></li>\n</ul>\n";
50947
50954
 
50948
50955
  const stringHTML = "<div class=\"subtitle-string\">\n <p></p>\n</div>\n";
50949
50956
 
50950
50957
  const VERSION = '2.19.14';
50951
50958
  const LOCAL_STORAGE_SUBTITLES_ID = 'gplayer.plugins.subtitles.selected';
50952
50959
  const T$2 = 'plugins.subtitles';
50953
- const NO_TRACK = { language: 'off' };
50954
50960
  /**
50955
50961
  * `PLUGIN` that provides a UI to select the subtitles when available.
50956
50962
  * @beta
@@ -50960,10 +50966,7 @@ const NO_TRACK = { language: 'off' };
50960
50966
  *
50961
50967
  * - {@link MediaControl}
50962
50968
  *
50963
- * Configuration options:
50964
- *
50965
- * - subtitles.language - The language of the subtitles to select by default.
50966
- *
50969
+ * Configuration options - {@link SubtitlesPluginSettings}
50967
50970
  * @example
50968
50971
  * ```ts
50969
50972
  * import { Subtitles } from '@gcorevideo/player'
@@ -50979,11 +50982,10 @@ const NO_TRACK = { language: 'off' };
50979
50982
  * ```
50980
50983
  */
50981
50984
  class Subtitles extends UICorePlugin {
50982
- currentLevel = null;
50983
50985
  isPreselectedApplied = false;
50984
50986
  isShowing = false;
50985
- track = { ...NO_TRACK };
50986
- tracks = null;
50987
+ track = null;
50988
+ tracks = [];
50987
50989
  $string = null;
50988
50990
  /**
50989
50991
  * @internal
@@ -51010,7 +51012,7 @@ class Subtitles extends UICorePlugin {
51010
51012
  */
51011
51013
  get attributes() {
51012
51014
  return {
51013
- class: this.name,
51015
+ class: 'media-control-subtitles',
51014
51016
  'data-subtitles': '',
51015
51017
  };
51016
51018
  }
@@ -51019,28 +51021,34 @@ class Subtitles extends UICorePlugin {
51019
51021
  */
51020
51022
  get events() {
51021
51023
  return {
51022
- 'click [data-subtitles-select]': 'onLevelSelect',
51023
- 'click [data-subtitles-button]': 'onShowLevelSelectMenu',
51024
+ 'click [data-subtitles-select]': 'onItemSelect',
51025
+ 'click [data-subtitles-button]': 'toggleMenu',
51024
51026
  };
51025
51027
  }
51026
51028
  get preselectedLanguage() {
51027
- return this.core.options.subtitles?.language ?? 'off';
51029
+ return this.core.options.subtitles?.language ?? '';
51028
51030
  }
51029
51031
  /**
51030
51032
  * @internal
51031
51033
  */
51032
51034
  bindEvents() {
51035
+ this.listenTo(this.core, Events$1.CORE_READY, this.onCoreReady);
51036
+ this.listenTo(this.core, Events$1.CORE_RESIZE, this.playerResize);
51037
+ this.listenTo(this.core, Events$1.CORE_ACTIVE_CONTAINER_CHANGED, this.onContainerChanged);
51038
+ }
51039
+ onCoreReady() {
51040
+ trace(`${T$2} onCoreReady`);
51033
51041
  const mediaControl = this.core.getPlugin('media_control');
51034
51042
  assert(mediaControl, 'media_control plugin is required');
51035
- this.listenTo(this.core, Events$1.CORE_RESIZE, this.playerResize);
51036
- this.listenTo(this.core, Events$1.CORE_ACTIVE_CONTAINER_CHANGED, this.bindPlaybackEvents);
51037
51043
  this.listenTo(mediaControl, Events$1.MEDIACONTROL_RENDERED, this.render);
51038
- this.listenTo(mediaControl, Events$1.MEDIACONTROL_HIDE, this.hideSelectLevelMenu);
51044
+ this.listenTo(mediaControl, Events$1.MEDIACONTROL_HIDE, this.hideMenu);
51039
51045
  }
51040
- bindPlaybackEvents() {
51046
+ onContainerChanged() {
51047
+ trace(`${T$2} onContainerChanged`);
51041
51048
  this.listenTo(this.core.activeContainer, Events$1.CONTAINER_FULLSCREEN, this.playerResize);
51042
- this.listenToOnce(this.core.activePlayback, Events$1.PLAYBACK_PLAY, this.getTracks);
51043
51049
  this.listenTo(this.core.activeContainer, 'container:advertisement:start', this.onStartAd);
51050
+ this.listenTo(this.core.activePlayback, Events$1.PLAYBACK_SUBTITLE_AVAILABLE, this.onSubtitleAvailable);
51051
+ this.listenTo(this.core.activePlayback, Events$1.PLAYBACK_SUBTITLE_CHANGED, this.onSubtitleChanged);
51044
51052
  // fix for iOS
51045
51053
  const video = this.core.activePlayback.el;
51046
51054
  assert(video, 'video element is required');
@@ -51055,20 +51063,50 @@ class Subtitles extends UICorePlugin {
51055
51063
  }
51056
51064
  });
51057
51065
  }
51058
- getTracks() {
51059
- if (this.core.activePlayback) {
51060
- try {
51061
- const tracks = this.core.activePlayback.el
51062
- .textTracks;
51063
- if (tracks.length > 0) {
51064
- this.setTracks(tracks);
51065
- }
51066
+ onSubtitleAvailable() {
51067
+ trace(`${T$2} onSubtitleAvailable`);
51068
+ this.applyTracks();
51069
+ }
51070
+ onSubtitleChanged({ id }) {
51071
+ trace(`${T$2} onSubtitleChanged`, { id });
51072
+ if (id === -1) {
51073
+ this.clearSubtitleText();
51074
+ }
51075
+ for (const track of this.tracks) {
51076
+ if (track.id === id) {
51077
+ track.track.mode = 'showing';
51078
+ this.setSubtitleText(this.getSubtitleText(track.track));
51079
+ track.track.oncuechange = (e) => {
51080
+ try {
51081
+ if (track.track.activeCues?.length) {
51082
+ const html = track.track.activeCues[0].getCueAsHTML();
51083
+ this.setSubtitleText(html);
51084
+ }
51085
+ else {
51086
+ this.clearSubtitleText();
51087
+ }
51088
+ }
51089
+ catch (error) {
51090
+ reportError(error);
51091
+ }
51092
+ };
51066
51093
  }
51067
- catch (error) {
51068
- reportError(error);
51094
+ else {
51095
+ track.track.oncuechange = null;
51096
+ track.track.mode = 'hidden';
51069
51097
  }
51070
51098
  }
51071
51099
  }
51100
+ applyTracks() {
51101
+ try {
51102
+ this.tracks = this.core.activePlayback.closedCaptionsTracks;
51103
+ this.applyPreselectedSubtitles();
51104
+ this.render();
51105
+ }
51106
+ catch (error) {
51107
+ reportError(error);
51108
+ }
51109
+ }
51072
51110
  onStartAd() {
51073
51111
  if (this.isShowing && this.core.activeContainer) {
51074
51112
  this.hide();
@@ -51080,10 +51118,11 @@ class Subtitles extends UICorePlugin {
51080
51118
  this.stopListening(this.core.activeContainer, 'container:advertisement:finish', this.onFinishAd);
51081
51119
  }
51082
51120
  playerResize() {
51121
+ trace(`${T$2} playerResize`);
51083
51122
  const shouldShow = this.core.activeContainer &&
51084
51123
  isFullscreen(this.core.activeContainer.el) &&
51085
- this.currentLevel &&
51086
- this.currentLevel.mode &&
51124
+ this.track &&
51125
+ this.track.track.mode &&
51087
51126
  Browser.isiOS &&
51088
51127
  this.isShowing;
51089
51128
  if (shouldShow) {
@@ -51105,7 +51144,7 @@ class Subtitles extends UICorePlugin {
51105
51144
  this.$string.hide();
51106
51145
  if (this.tracks) {
51107
51146
  for (const t of this.tracks) {
51108
- t.mode = 'hidden';
51147
+ t.track.mode = 'hidden';
51109
51148
  }
51110
51149
  }
51111
51150
  }
@@ -51117,23 +51156,20 @@ class Subtitles extends UICorePlugin {
51117
51156
  this.renderIcon();
51118
51157
  if (this.core.activeContainer &&
51119
51158
  isFullscreen(this.core.activeContainer.el) &&
51120
- this.currentLevel &&
51121
- this.currentLevel.mode &&
51159
+ this.track &&
51160
+ this.track.track.mode &&
51122
51161
  Browser.isiOS) {
51123
51162
  this.$string.hide();
51124
- this.currentLevel.mode = 'showing';
51163
+ this.track.track.mode = 'showing';
51125
51164
  }
51126
51165
  else {
51127
51166
  this.$string.show();
51128
51167
  }
51129
51168
  }
51130
51169
  shouldRender() {
51131
- return !!(this.tracks && this.tracks.length > 0);
51170
+ return this.tracks.length > 0;
51132
51171
  }
51133
51172
  resizeFont() {
51134
- if (!this.core.activeContainer) {
51135
- return;
51136
- }
51137
51173
  if (!this.$string) {
51138
51174
  return;
51139
51175
  }
@@ -51150,132 +51186,72 @@ class Subtitles extends UICorePlugin {
51150
51186
  if (!this.shouldRender()) {
51151
51187
  return this;
51152
51188
  }
51153
- trace(`${T$2} render`, {
51154
- tracks: this.tracks?.length,
51155
- track: this.track?.language,
51156
- });
51157
51189
  const mediaControl = this.core.getPlugin('media_control');
51158
- assert(mediaControl, 'media_control plugin is required');
51159
51190
  this.$el.html(Subtitles.template({ tracks: this.tracks }));
51160
51191
  this.core.activeContainer.$el.find('.subtitle-string').remove();
51161
51192
  this.$string = $(Subtitles.templateString());
51162
51193
  this.resizeFont();
51163
- this.core.activeContainer.$el.append(this.$string[0]);
51164
- const ss = mediaControl.getElement('subtitlesSelector');
51165
- if (ss && ss.length > 0) {
51166
- ss.append(this.el);
51167
- }
51168
- else {
51169
- mediaControl.getRightPanel().append(this.el);
51170
- }
51171
- this.updateCurrentLevel(this.track);
51172
- this.highlightCurrentSubtitles();
51173
- this.applyPreselectedSubtitles();
51194
+ this.core.activeContainer.$el.append(this.$string);
51195
+ mediaControl.putElement('subtitlesSelector', this.$el);
51196
+ this.updateSelection();
51174
51197
  this.renderIcon();
51175
51198
  return this;
51176
51199
  }
51177
- setTracks(tracks) {
51178
- this.tracks = tracks;
51179
- this.render();
51200
+ findById(id) {
51201
+ return this.tracks.find((track) => track.id === id) ?? null;
51180
51202
  }
51181
- findLevelBy(id) {
51182
- if (this.tracks) {
51183
- for (const track of this.tracks) {
51184
- if (track.language === id) {
51185
- return track; // TODO TrackInfo?
51186
- }
51187
- }
51188
- }
51189
- }
51190
- selectLevel(id) {
51203
+ selectItem(item) {
51191
51204
  this.clearSubtitleText();
51192
- this.track = this.findLevelBy(id) || { ...NO_TRACK };
51193
- this.hideSelectLevelMenu();
51194
- if (!this.track) {
51195
- this.track = { language: 'off' };
51196
- }
51197
- this.updateCurrentLevel(this.track);
51198
- }
51199
- onLevelSelect(event) {
51200
- const id = event.target.dataset.subtitlesSelect;
51201
- if (id) {
51202
- localStorage.setItem(LOCAL_STORAGE_SUBTITLES_ID, id);
51203
- this.selectLevel(id);
51204
- }
51205
+ this.track = item;
51206
+ this.hideMenu();
51207
+ this.updateSelection();
51208
+ }
51209
+ onItemSelect(event) {
51210
+ const id = event.target.dataset.subtitlesSelect ?? '-1';
51211
+ trace(`${T$2} onItemSelect`, { id });
51212
+ localStorage.setItem(LOCAL_STORAGE_SUBTITLES_ID, id);
51213
+ this.selectItem(this.findById(Number(id)));
51205
51214
  return false;
51206
51215
  }
51207
51216
  applyPreselectedSubtitles() {
51208
51217
  if (!this.isPreselectedApplied) {
51209
51218
  this.isPreselectedApplied = true;
51219
+ if (!this.preselectedLanguage) {
51220
+ return;
51221
+ }
51210
51222
  setTimeout(() => {
51211
- this.selectLevel(this.preselectedLanguage);
51212
- }, 300);
51223
+ this.selectItem(this.tracks.find((t) => t.track.language === this.preselectedLanguage) ?? null);
51224
+ }, 300); // TODO why delay?
51213
51225
  }
51214
51226
  }
51215
- onShowLevelSelectMenu() {
51216
- trace(`${T$2} onShowLevelSelectMenu`);
51217
- this.toggleContextMenu();
51218
- }
51219
- hideSelectLevelMenu() {
51227
+ hideMenu() {
51220
51228
  this.$('[data-subtitles] ul').hide();
51221
51229
  }
51222
- toggleContextMenu() {
51230
+ toggleMenu() {
51223
51231
  this.$('[data-subtitles] ul').toggle();
51224
51232
  }
51225
- buttonElement() {
51226
- return this.$('[data-subtitles] button');
51233
+ itemElement(id) {
51234
+ return this.$(`ul li a[data-subtitles-select="${id}"]`).parent();
51227
51235
  }
51228
- levelElement(id) {
51229
- return this.$('[data-subtitles] ul a' + (id ? '[data-subtitles-select="' + id + '"]' : '')).parent();
51230
- }
51231
- startLevelSwitch() {
51232
- this.buttonElement().addClass('changing');
51233
- }
51234
- stopLevelSwitch() {
51235
- this.buttonElement().removeClass('changing');
51236
+ allItemElements() {
51237
+ return this.$('[data-subtitles] li');
51236
51238
  }
51237
51239
  selectSubtitles() {
51238
- if (!this.currentLevel) {
51239
- return;
51240
- }
51241
- if (this.tracks) {
51242
- for (let i = 0; i < this.tracks.length; i++) {
51243
- const track = this.tracks[i];
51244
- if (track.language === this.currentLevel.language) {
51245
- track.mode = 'showing';
51246
- const currentTime = this.core.activePlayback?.getCurrentTime() ?? 0;
51247
- const cues = track.cues;
51248
- let subtitleText = '';
51249
- if (cues && cues.length) {
51250
- for (const cue of cues) {
51251
- if (currentTime >= cue.startTime && currentTime <= cue.endTime) {
51252
- subtitleText +=
51253
- cue.getCueAsHTML().textContent + '\n';
51254
- }
51255
- }
51256
- }
51257
- this.setSubtitleText(subtitleText);
51258
- track.oncuechange = (e) => {
51259
- try {
51260
- if (track.activeCues?.length) {
51261
- const html = track.activeCues[0].getCueAsHTML();
51262
- this.setSubtitleText(html);
51263
- }
51264
- else {
51265
- this.clearSubtitleText();
51266
- }
51267
- }
51268
- catch (error) {
51269
- // console.error(error);
51270
- reportError(error);
51271
- }
51272
- };
51273
- continue;
51240
+ const trackId = this.track ? this.track.id : -1;
51241
+ this.core.activePlayback.closedCaptionsTrackId = trackId;
51242
+ }
51243
+ getSubtitleText(track) {
51244
+ const currentTime = this.core.activePlayback?.getCurrentTime() ?? 0;
51245
+ const cues = track.cues;
51246
+ const lines = [];
51247
+ if (cues && cues.length) {
51248
+ for (const cue of cues) {
51249
+ if (currentTime >= cue.startTime && currentTime <= cue.endTime) {
51250
+ lines.push(cue.getCueAsHTML().textContent);
51274
51251
  }
51275
- this.tracks[i].oncuechange = null;
51276
- this.tracks[i].mode = 'hidden';
51277
51252
  }
51278
51253
  }
51254
+ return lines.join('\n');
51279
51255
  }
51280
51256
  setSubtitleText(text) {
51281
51257
  this.$string.find('p').html(text);
@@ -51283,9 +51259,8 @@ class Subtitles extends UICorePlugin {
51283
51259
  clearSubtitleText() {
51284
51260
  this.setSubtitleText('');
51285
51261
  }
51286
- updateCurrentLevel(track) {
51287
- this.currentLevel = track;
51288
- if (track.language === 'off') {
51262
+ updateSelection() {
51263
+ if (!this.track) {
51289
51264
  this.hide();
51290
51265
  }
51291
51266
  else {
@@ -51295,21 +51270,22 @@ class Subtitles extends UICorePlugin {
51295
51270
  this.highlightCurrentSubtitles();
51296
51271
  }
51297
51272
  highlightCurrentSubtitles() {
51298
- this.levelElement().removeClass('current');
51299
- this.levelElement().find('a').removeClass('gcore-skin-active');
51300
- if (this.currentLevel) {
51301
- const currentLevelElement = this.levelElement(this.currentLevel.language);
51302
- currentLevelElement.addClass('current');
51303
- currentLevelElement.find('a').addClass('gcore-skin-active');
51304
- }
51273
+ this.allItemElements()
51274
+ .removeClass('current')
51275
+ .find('a')
51276
+ .removeClass('gcore-skin-active');
51277
+ trace(`${T$2} highlightCurrentSubtitles`, {
51278
+ track: this.track?.id,
51279
+ });
51280
+ const currentLevelElement = this.itemElement(this.track ? this.track.id : -1);
51281
+ currentLevelElement
51282
+ .addClass('current')
51283
+ .find('a')
51284
+ .addClass('gcore-skin-active');
51305
51285
  }
51306
51286
  renderIcon() {
51307
51287
  const icon = this.isShowing ? subtitlesOnIcon : subtitlesOffIcon;
51308
- this.core
51309
- .getPlugin('media_control')
51310
- .getElement('subtitlesSelector')
51311
- ?.find('span.subtitle-text')
51312
- .html(icon);
51288
+ this.$el.find('span.subtitle-text').html(icon);
51313
51289
  }
51314
51290
  }
51315
51291