@gcorevideo/player 2.22.0 → 2.22.2

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 (125) hide show
  1. package/assets/bottom-gear/bottomgear copy.ejs +10 -0
  2. package/assets/bottom-gear/bottomgear.ejs +4 -8
  3. package/assets/bottom-gear/gear-sub-menu.scss +0 -1
  4. package/assets/bottom-gear/gear.scss +0 -1
  5. package/assets/clappr-nerd-stats/button.ejs +3 -3
  6. package/assets/level-selector/button.ejs +2 -4
  7. package/assets/level-selector/list.ejs +14 -10
  8. package/assets/level-selector/style.scss +9 -4
  9. package/assets/media-control/container.scss +1 -1
  10. package/assets/playback-rate/list.ejs +5 -5
  11. package/assets/spinner-three-bounce/spinner.scss +1 -1
  12. package/dist/core.js +1 -2
  13. package/dist/index.css +885 -884
  14. package/dist/index.js +3938 -3779
  15. package/dist/player.d.ts +246 -108
  16. package/dist/plugins/index.css +1230 -1229
  17. package/dist/plugins/index.js +4036 -3878
  18. package/docs/api/player.bottomgear.additem.md +95 -0
  19. package/docs/api/player.bottomgear.md +63 -19
  20. package/docs/api/player.bottomgear.refresh.md +5 -1
  21. package/docs/api/player.clapprnerdstats.md +0 -2
  22. package/docs/api/player.clicktopause.md +1 -1
  23. package/docs/api/player.closedcaptions.md +2 -2
  24. package/docs/api/player.closedcaptionspluginsettings.md +5 -0
  25. package/docs/api/player.errorscreen.md +18 -4
  26. package/docs/api/player.errorscreenpluginsettings.md +1 -4
  27. package/docs/api/player.errorscreensettings.md +15 -0
  28. package/docs/api/{player.mediacontrolevents.md → player.gearevents.md} +7 -7
  29. package/docs/api/player.levelselector.events.md +0 -1
  30. package/docs/api/player.levelselector.md +1 -1
  31. package/docs/api/player.md +33 -36
  32. package/docs/api/{player.bottomgear.setcontent.md → player.mediacontrol.handlecustomarea.md} +5 -9
  33. package/docs/api/player.mediacontrol.md +10 -24
  34. package/docs/api/player.mediacontrol.putelement.md +2 -2
  35. package/docs/api/{player.bottomgear.getelement.md → player.mediacontrol.toggleelement.md} +23 -9
  36. package/docs/api/player.mediacontrolelement.md +1 -1
  37. package/docs/api/player.playbackrate.md +22 -3
  38. package/docs/api/{player.gearoptionsitem.md → player.playbackrateoption.md} +6 -4
  39. package/docs/api/{player.mediacontrol.getcenterpanel.md → player.playbackratesettings.md} +8 -6
  40. package/docs/api/player.sourcecontroller._constructor_.md +49 -0
  41. package/docs/api/player.sourcecontroller.md +70 -7
  42. package/docs/api/player.spinnerevents.md +1 -4
  43. package/docs/api/player.spinnerthreebounce._constructor_.md +0 -3
  44. package/docs/api/player.spinnerthreebounce.hide.md +0 -3
  45. package/docs/api/player.spinnerthreebounce.md +5 -8
  46. package/docs/api/player.spinnerthreebounce.show.md +2 -5
  47. package/lib/internal.types.d.ts +5 -0
  48. package/lib/internal.types.d.ts.map +1 -1
  49. package/lib/playback/dash-playback/DashPlayback.d.ts.map +1 -1
  50. package/lib/playback/dash-playback/DashPlayback.js +0 -1
  51. package/lib/playback.types.d.ts +0 -5
  52. package/lib/playback.types.d.ts.map +1 -1
  53. package/lib/plugins/bottom-gear/BottomGear.d.ts +93 -20
  54. package/lib/plugins/bottom-gear/BottomGear.d.ts.map +1 -1
  55. package/lib/plugins/bottom-gear/BottomGear.js +145 -37
  56. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts +2 -3
  57. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.d.ts.map +1 -1
  58. package/lib/plugins/clappr-nerd-stats/ClapprNerdStats.js +18 -15
  59. package/lib/plugins/click-to-pause/ClickToPause.d.ts +1 -1
  60. package/lib/plugins/click-to-pause/ClickToPause.d.ts.map +1 -1
  61. package/lib/plugins/click-to-pause/ClickToPause.js +3 -2
  62. package/lib/plugins/dvr-controls/DvrControls.js +1 -1
  63. package/lib/plugins/error-screen/ErrorScreen.d.ts +29 -4
  64. package/lib/plugins/error-screen/ErrorScreen.d.ts.map +1 -1
  65. package/lib/plugins/error-screen/ErrorScreen.js +17 -2
  66. package/lib/plugins/level-selector/LevelSelector.d.ts +8 -11
  67. package/lib/plugins/level-selector/LevelSelector.d.ts.map +1 -1
  68. package/lib/plugins/level-selector/LevelSelector.js +66 -102
  69. package/lib/plugins/media-control/MediaControl.d.ts +6 -15
  70. package/lib/plugins/media-control/MediaControl.d.ts.map +1 -1
  71. package/lib/plugins/media-control/MediaControl.js +36 -30
  72. package/lib/plugins/picture-in-picture/PictureInPicture.d.ts.map +1 -1
  73. package/lib/plugins/picture-in-picture/PictureInPicture.js +7 -2
  74. package/lib/plugins/playback-rate/PlaybackRate.d.ts +42 -14
  75. package/lib/plugins/playback-rate/PlaybackRate.d.ts.map +1 -1
  76. package/lib/plugins/playback-rate/PlaybackRate.js +101 -83
  77. package/lib/plugins/source-controller/SourceController.d.ts +40 -4
  78. package/lib/plugins/source-controller/SourceController.d.ts.map +1 -1
  79. package/lib/plugins/source-controller/SourceController.js +41 -4
  80. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts +8 -6
  81. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.d.ts.map +1 -1
  82. package/lib/plugins/spinner-three-bounce/SpinnerThreeBounce.js +10 -6
  83. package/lib/plugins/subtitles/ClosedCaptions.d.ts +7 -7
  84. package/lib/plugins/subtitles/ClosedCaptions.d.ts.map +1 -1
  85. package/lib/plugins/subtitles/ClosedCaptions.js +3 -3
  86. package/lib/testUtils.d.ts +1 -0
  87. package/lib/testUtils.d.ts.map +1 -1
  88. package/lib/testUtils.js +13 -0
  89. package/package.json +1 -1
  90. package/src/internal.types.ts +6 -0
  91. package/src/playback/dash-playback/DashPlayback.ts +0 -1
  92. package/src/playback.types.ts +0 -5
  93. package/src/plugins/bottom-gear/BottomGear.ts +186 -77
  94. package/src/plugins/bottom-gear/__tests__/BottomGear.test.ts +21 -5
  95. package/src/plugins/bottom-gear/__tests__/__snapshots__/BottomGear.test.ts.snap +5 -12
  96. package/src/plugins/clappr-nerd-stats/ClapprNerdStats.ts +27 -25
  97. package/src/plugins/click-to-pause/ClickToPause.ts +3 -2
  98. package/src/plugins/dvr-controls/DvrControls.ts +1 -1
  99. package/src/plugins/dvr-controls/__tests__/DvrControls.test.ts +1 -1
  100. package/src/plugins/error-screen/ErrorScreen.ts +30 -4
  101. package/src/plugins/level-selector/LevelSelector.ts +80 -120
  102. package/src/plugins/level-selector/__tests__/LevelSelector.test.ts +69 -79
  103. package/src/plugins/level-selector/__tests__/__snapshots__/LevelSelector.test.ts.snap +38 -71
  104. package/src/plugins/media-control/MediaControl.ts +50 -36
  105. package/src/plugins/media-control/__tests__/MediaControl.test.ts +4 -4
  106. package/src/plugins/picture-in-picture/PictureInPicture.ts +7 -2
  107. package/src/plugins/playback-rate/PlaybackRate.ts +136 -108
  108. package/src/plugins/playback-rate/__tests__/PlaybackRate.test.ts +84 -37
  109. package/src/plugins/playback-rate/__tests__/__snapshots__/PlaybackRate.test.ts.snap +55 -6
  110. package/src/plugins/source-controller/SourceController.ts +41 -4
  111. package/src/plugins/spinner-three-bounce/SpinnerThreeBounce.ts +10 -6
  112. package/src/plugins/subtitles/ClosedCaptions.ts +9 -10
  113. package/src/plugins/subtitles/__tests__/ClosedCaptions.test.ts +1 -1
  114. package/src/testUtils.ts +14 -0
  115. package/src/typings/vitest.d.ts +1 -0
  116. package/temp/player.api.json +303 -370
  117. package/tsconfig.tsbuildinfo +1 -1
  118. package/docs/api/player.gearitemelement.md +0 -18
  119. package/docs/api/player.mediacontrol.getleftpanel.md +0 -22
  120. package/docs/api/player.mediacontrol.getrightpanel.md +0 -22
  121. package/docs/api/player.subtitlespluginsettings.md +0 -18
  122. package/docs/api/player.texttrackitem.id.md +0 -11
  123. package/docs/api/player.texttrackitem.md +0 -87
  124. package/docs/api/player.texttrackitem.name.md +0 -11
  125. package/docs/api/player.texttrackitem.track.md +0 -11
@@ -1 +1 @@
1
- {"version":3,"file":"ClosedCaptions.d.ts","sourceRoot":"","sources":["../../../src/plugins/subtitles/ClosedCaptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAwB,MAAM,cAAc,CAAA;AAOzE,OAAO,sCAAsC,CAAA;AAe7C,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG,4BAA4B,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,oBAAoB,CAAQ;IAEpC,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,KAAK,CAA6B;IAE1C,OAAO,CAAC,MAAM,CAAsB;IAEpC,OAAO,CAAC,KAAK,CAA2B;IAExC;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED;;OAEG;IACH,MAAM,KAAK,OAAO,WAEjB;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAEzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAuB;IAE7D;;OAEG;IACH,IAAa,UAAU;;MAItB;IAED;;OAEG;IACH,IAAa,MAAM;;;MAKlB;IAED,OAAO,KAAK,mBAAmB,GAE9B;IAED;;OAEG;IACM,UAAU;IAUnB,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,kBAAkB;IAwC1B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,YAAY;IAqBpB;;OAEG;IACH,IAAI;IAWJ;;OAEG;IACH,IAAI;IAiBJ,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACM,MAAM;IA0Bf,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,yBAAyB;IAgBjC,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,yBAAyB;IAgBjC,OAAO,CAAC,UAAU;CAKnB"}
1
+ {"version":3,"file":"ClosedCaptions.d.ts","sourceRoot":"","sources":["../../../src/plugins/subtitles/ClosedCaptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,YAAY,EAAwB,MAAM,cAAc,CAAA;AAOzE,OAAO,sCAAsC,CAAA;AAe7C;;;GAGG;AACH,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,cAAe,SAAQ,YAAY;IAC9C,OAAO,CAAC,oBAAoB,CAAQ;IAEpC,OAAO,CAAC,SAAS,CAAQ;IAEzB,OAAO,CAAC,KAAK,CAA6B;IAE1C,OAAO,CAAC,MAAM,CAAsB;IAEpC,OAAO,CAAC,KAAK,CAA2B;IAExC;;OAEG;IACH,IAAI,IAAI,WAEP;IAED;;OAEG;IACH,IAAI,gBAAgB;;MAEnB;IAED;;OAEG;IACH,MAAM,KAAK,OAAO,WAEjB;IAED,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAyB;IAEzD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAuB;IAE7D;;OAEG;IACH,IAAa,UAAU;;MAItB;IAED;;OAEG;IACH,IAAa,MAAM;;;MAKlB;IAED,OAAO,KAAK,mBAAmB,GAE9B;IAED;;OAEG;IACM,UAAU;IAUnB,OAAO,CAAC,WAAW;IAYnB,OAAO,CAAC,kBAAkB;IAwC1B,OAAO,CAAC,mBAAmB;IAK3B,OAAO,CAAC,iBAAiB;IA+BzB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,SAAS;IAWjB,OAAO,CAAC,UAAU;IASlB,OAAO,CAAC,YAAY;IAqBpB;;OAEG;IACH,IAAI;IAWJ;;OAEG;IACH,IAAI;IAiBJ,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,UAAU;IAUlB;;OAEG;IACM,MAAM;IA0Bf,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,yBAAyB;IAgBjC,OAAO,CAAC,QAAQ;IAIhB,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,eAAe;IAMvB,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,yBAAyB;IAgBjC,OAAO,CAAC,UAAU;CAKnB"}
@@ -16,7 +16,7 @@ const T = 'plugins.cc';
16
16
  * @beta
17
17
  *
18
18
  * @remarks
19
- * The plugin is activated when closed captions tracks are provided with the media source.
19
+ * The plugin is activated when closed captions tracks are detected in the media source.
20
20
  * It shows a familiar "CC" button with a dropdown menu to select the subtitles language.
21
21
  *
22
22
  * Depends on:
@@ -33,7 +33,7 @@ const T = 'plugins.cc';
33
33
  * new Player({
34
34
  * ...
35
35
  * cc: {
36
- * language: 'en',
36
+ * language: 'pt-BR',
37
37
  * },
38
38
  * })
39
39
  * ```
@@ -248,7 +248,7 @@ export class ClosedCaptions extends UICorePlugin {
248
248
  this.$line = $(ClosedCaptions.templateString());
249
249
  this.resizeFont();
250
250
  this.core.activeContainer.$el.append(this.$line);
251
- mediaControl.putElement('cc', this.el);
251
+ mediaControl.putElement('cc', this.$el);
252
252
  this.updateSelection();
253
253
  this.renderIcon();
254
254
  return this;
@@ -108,4 +108,5 @@ export declare function createMockContainer(playback?: any): Events<string | sym
108
108
  trigger: <T extends string | symbol>(event: T, ...args: any[]) => boolean;
109
109
  };
110
110
  export declare function createMockMediaControl(core: any): UICorePlugin;
111
+ export declare function createMockBottomGear(core: any): any;
111
112
  //# sourceMappingURL=testUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,YAAY,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,MAAM,MAAM,eAAe,CAAA;AAElC;;;;GAIG;AACH,qBAAa,aAAc,SAAQ,MAAM;IAErC,SAAS,CAAC,OAAO,EAAE,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,GAAG;IAClB,SAAS,CAAC,WAAW,CAAC,EAAE,GAAG;gBAFjB,OAAO,EAAE,GAAG,EACb,IAAI,EAAE,GAAG,EACR,WAAW,CAAC,EAAE,GAAG,YAAA;IAK7B,IAAI,IAAI,WAEP;IAED,OAAO;IAEP,IAAI;IAEJ,KAAK;IAEL,IAAI;IAEJ,OAAO;IAEP,IAAI;IAEJ,cAAc;IAEd,WAAW;IAIX,QAAQ;IAER,OAAO;IAEP,eAAe;IAIf,kBAAkB;IAIlB,cAAc;IAId,qBAAqB;IAIrB,IAAI;IAEJ,MAAM;IAEN,MAAM;IAEN,SAAS;IAET,eAAe;IAIf,WAAW;IAIX,QAAQ;IAIR,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;CAGtC;AAED,wBAAgB,cAAc,CAC5B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,SAAS,GAAE,GAA2B;;;;;;;;;;;;;;;;EAqBvC;AAED,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,mBAAmB;;;;;;EAKlC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC/C;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,GAA0B;;;;;;;;;;;;;EAiBvE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,gBAiB/C"}
1
+ {"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,YAAY,EAAE,MAAM,cAAc,CAAA;AACxD,OAAO,MAAM,MAAM,eAAe,CAAA;AAElC;;;;GAIG;AACH,qBAAa,aAAc,SAAQ,MAAM;IAErC,SAAS,CAAC,OAAO,EAAE,GAAG;IACtB,QAAQ,CAAC,IAAI,EAAE,GAAG;IAClB,SAAS,CAAC,WAAW,CAAC,EAAE,GAAG;gBAFjB,OAAO,EAAE,GAAG,EACb,IAAI,EAAE,GAAG,EACR,WAAW,CAAC,EAAE,GAAG,YAAA;IAK7B,IAAI,IAAI,WAEP;IAED,OAAO;IAEP,IAAI;IAEJ,KAAK;IAEL,IAAI;IAEJ,OAAO;IAEP,IAAI;IAEJ,cAAc;IAEd,WAAW;IAIX,QAAQ;IAER,OAAO;IAEP,eAAe;IAIf,kBAAkB;IAIlB,cAAc;IAId,qBAAqB;IAIrB,IAAI;IAEJ,MAAM;IAEN,MAAM;IAEN,SAAS;IAET,eAAe;IAIf,WAAW;IAIX,QAAQ;IAIR,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE;CAGtC;AAED,wBAAgB,cAAc,CAC5B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,SAAS,GAAE,GAA2B;;;;;;;;;;;;;;;;EAqBvC;AAED,wBAAgB,gBAAgB;;;EAK/B;AAED,wBAAgB,mBAAmB;;;;;;EAKlC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAiC/C;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,GAAE,GAA0B;;;;;;;;;;;;;EAiBvE;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,GAAG,gBAiB/C;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,GAAG,OAY7C"}
package/lib/testUtils.js CHANGED
@@ -161,3 +161,16 @@ export function createMockMediaControl(core) {
161
161
  mediaControl.toggleElement = vi.fn();
162
162
  return mediaControl;
163
163
  }
164
+ export function createMockBottomGear(core) {
165
+ const plugin = new UICorePlugin(core);
166
+ plugin.getItem = vi.fn();
167
+ plugin.addItem = vi.fn().mockImplementation((name, $el) => {
168
+ const existing = plugin.$el.find(`[data-${name}]`);
169
+ if (existing.length) {
170
+ return existing;
171
+ }
172
+ return $('<li></li>').attr(`data-${name}`, '').append($el).appendTo(plugin.$el);
173
+ });
174
+ plugin.refresh = vi.fn();
175
+ return plugin;
176
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gcorevideo/player",
3
- "version": "2.22.0",
3
+ "version": "2.22.2",
4
4
  "description": "Gcore JavaScript video player",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -143,3 +143,9 @@ export type CoreOptions = {
143
143
  watermarkLink?: string
144
144
  width?: number
145
145
  }
146
+
147
+ export interface TextTrackItem {
148
+ id: number
149
+ name: string
150
+ track: TextTrack
151
+ }
@@ -662,7 +662,6 @@ export default class DashPlayback extends BasePlayback {
662
662
  get audioTracks(): AudioTrack[] {
663
663
  assert.ok(this._dash, 'DASH.js MediaPlayer is not initialized')
664
664
  const tracks = this._dash.getTracksFor('audio')
665
- trace(`${T} get audioTracks`, { tracks })
666
665
  return tracks.map(toClapprTrack)
667
666
  }
668
667
 
@@ -131,8 +131,3 @@ export interface PlaybackError {
131
131
  }
132
132
  }
133
133
 
134
- export interface TextTrackItem {
135
- id: number
136
- name: string
137
- track: TextTrack
138
- }
@@ -1,66 +1,123 @@
1
- import { UICorePlugin, template, Events as ClapprEvents } from '@clappr/core';
2
- import { trace } from '@gcorevideo/utils';
3
- import assert from 'assert';
1
+ import { UICorePlugin, template, Events as ClapprEvents, $ } from '@clappr/core'
2
+ import { trace } from '@gcorevideo/utils'
3
+ import assert from 'assert'
4
4
 
5
- import { CLAPPR_VERSION } from '../../build.js';
5
+ import { CLAPPR_VERSION } from '../../build.js'
6
6
 
7
- import pluginHtml from '../../../assets/bottom-gear/bottomgear.ejs';
8
- import '../../../assets/bottom-gear/gear.scss';
9
- import '../../../assets/bottom-gear/gear-sub-menu.scss';
10
- import gearIcon from '../../../assets/icons/new/gear.svg';
11
- import gearHdIcon from '../../../assets/icons/new/gear-hd.svg';
12
- import { ZeptoResult } from '../../types.js';
13
- import { MediaControlEvents } from '../media-control/MediaControl';
7
+ import pluginHtml from '../../../assets/bottom-gear/bottomgear.ejs'
8
+ import '../../../assets/bottom-gear/gear.scss'
9
+ import '../../../assets/bottom-gear/gear-sub-menu.scss'
10
+ import gearIcon from '../../../assets/icons/new/gear.svg'
11
+ import gearHdIcon from '../../../assets/icons/new/gear-hd.svg'
12
+ import { ZeptoResult } from '../../types.js'
14
13
 
15
- const VERSION = '2.19.12';
14
+ const VERSION = '2.19.12'
16
15
 
17
- const T = 'plugins.bottom_gear';
16
+ const T = 'plugins.bottom_gear'
18
17
 
19
18
  /**
20
- * An element inside the gear menu
19
+ * Events triggered by the plugin
21
20
  * @beta
22
21
  */
23
- export type GearOptionsItem = 'quality' | 'rate' | 'nerd';
24
-
25
- /**
26
- * @deprecated Use {@link GearOptionsItem} instead
27
- */
28
- export type GearItemElement = GearOptionsItem;
22
+ export enum GearEvents {
23
+ /**
24
+ * Use this event to accurately attach an item to the gear menu
25
+ */
26
+ RENDERED = 'rendered',
27
+ }
29
28
 
30
29
  // TODO disabled if no items added
31
30
 
32
31
  /**
33
- * `PLUGIN` that adds the gear button with an extra options menu on the right side of the {@link MediaControl | media control} UI
32
+ * `PLUGIN` that adds a button to extend the media controls UI with extra options.
34
33
  * @beta
35
34
  * @remarks
36
- * The plugins provides a base for attaching custom settings UI in the gear menu
37
- *
35
+ * The plugin renders small gear icon to the right of the media controls.
36
+ * It provides a base for attaching custom settings UI in the gear menu
37
+ *
38
38
  * Depends on:
39
39
  *
40
40
  * - {@link MediaControl}
41
+ *
42
+ * @example
43
+ * You can use bottom gear to add custom settings UI to the gear menu.
44
+ *
45
+ * ```ts
46
+ * import { BottomGear } from '@gcorevideo/player/plugins/bottom-gear';
47
+ *
48
+ * class CustomOptionsPlugin extends UICorePlugin {
49
+ * // ...
50
+ *
51
+ * override get events() {
52
+ * return {
53
+ * 'click #my-button': 'doMyAction',
54
+ * }
55
+ * }
56
+ *
57
+ * private doMyAction() {
58
+ * // ...
59
+ * }
60
+ *
61
+ * override render() {
62
+ * const bottomGear = this.core.getPlugin('bottom_gear');
63
+ * if (!bottomGear) {
64
+ * return this;
65
+ * }
66
+ * this.$el.html('<button class="custom-option">Custom option</button>');
67
+ * // Put rendered element into the gear menu
68
+ * bottomGear.addItem('custom').html(this.$el)
69
+ * return this;
70
+ * }
71
+ *
72
+ * // alternatively, add an option with a submenu
73
+ * override render() {
74
+ * this.$el.html(template(templateHtml)({
75
+ * // ...
76
+ * })));
77
+ * return this;
78
+ * }
79
+ *
80
+ * private addGearOption() {
81
+ * this.core.getPlugin('bottom_gear')
82
+ * .addItem('custom', this.$el)
83
+ * .html($('<button class="custom-option">Custom option</button>'))
84
+ * }
85
+ *
86
+ * override bindEvents() {
87
+ * this.listenToOnce(this.core, ClapprEvents.CORE_READY, () => {
88
+ * const bottomGear = this.core.getPlugin('bottom_gear');
89
+ * assert(bottomGear, 'bottom_gear plugin is required');
90
+ * // simple case
91
+ * this.listenTo(bottomGear, GearEvents.RENDERED, this.render);
92
+ * // or with a submenu
93
+ * this.listenTo(bottomGear, GearEvents.RENDERED, this.addGearOption);
94
+ * });
95
+ * }
96
+ * }
97
+ * ```
41
98
  */
42
99
  export class BottomGear extends UICorePlugin {
43
- private isHd = false;
100
+ private isHd = false
44
101
 
45
102
  /**
46
103
  * @internal
47
104
  */
48
105
  get name() {
49
- return 'bottom_gear';
106
+ return 'bottom_gear'
50
107
  }
51
108
 
52
109
  /**
53
110
  * @internal
54
111
  */
55
112
  get supportedVersion() {
56
- return { min: CLAPPR_VERSION };
113
+ return { min: CLAPPR_VERSION }
57
114
  }
58
115
 
59
116
  /**
60
117
  * @internal
61
118
  */
62
119
  static get version() {
63
- return VERSION;
120
+ return VERSION
64
121
  }
65
122
 
66
123
  private static readonly template = template(pluginHtml)
@@ -70,8 +127,8 @@ export class BottomGear extends UICorePlugin {
70
127
  */
71
128
  override get attributes() {
72
129
  return {
73
- 'class': 'media-control-gear',
74
- };
130
+ class: 'media-control-gear',
131
+ }
75
132
  }
76
133
 
77
134
  /**
@@ -79,94 +136,146 @@ export class BottomGear extends UICorePlugin {
79
136
  */
80
137
  override get events() {
81
138
  return {
82
- 'click .button-gear': 'toggleGearMenu',
83
- };
139
+ 'click #gear-button': 'toggleGearMenu',
140
+ }
84
141
  }
85
142
 
86
143
  /**
87
144
  * @internal
88
145
  */
89
146
  override bindEvents() {
90
- this.listenTo(this.core, ClapprEvents.CORE_READY, this.onCoreReady)
91
- this.listenTo(this.core, ClapprEvents.CORE_ACTIVE_CONTAINER_CHANGED, this.onActiveContainerChanged);
92
- }
93
-
94
- /**
95
- * @param name - Name of a gear menu placeholder item to attach custom UI
96
- * @returns Zepto result of the element
97
- */
98
- getElement(name: GearOptionsItem): ZeptoResult | null {
99
- return this.$el.find(`.gear-options-list [data-${name}]`);
147
+ this.listenToOnce(this.core, ClapprEvents.CORE_READY, this.onCoreReady)
148
+ this.listenTo(
149
+ this.core,
150
+ ClapprEvents.CORE_ACTIVE_CONTAINER_CHANGED,
151
+ this.onActiveContainerChanged,
152
+ )
100
153
  }
101
154
 
102
- // TODO implement putElement/addElement method
103
-
104
155
  /**
105
- * Replaces the content of the gear menu
106
- * @param content - Zepto result of the element
156
+ * Adds a custom option to the gear menu
157
+ * @param name - A unique name of the option
158
+ * @param $subMenu - The submenu to attach to the option
159
+ * @returns The added item placeholder to attach custom markup
160
+ * @remarks
161
+ * When called with $submenu param, a click on the added item will toggle the submenu visibility.
162
+ *
163
+ * When added without submenu, it's responsibility of the caller to handle the click event however needed.
164
+ * @example
165
+ * ```ts
166
+ * class MyPlugin extends UICorePlugin {
167
+ * override render() {
168
+ * this.$el.html('<div class="my-awesome-settings">...</div>')
169
+ * this.core.getPlugin('bottom_gear')
170
+ * ?.addItem('custom', this.$el)
171
+ * .html($('<button>Custom settings</button>'))
172
+ * return this
173
+ * }
174
+ * }
175
+ * ```
107
176
  */
108
- setContent(content: ZeptoResult) {
109
- this.$el.find('.gear-wrapper').html(content);
177
+ addItem(name: string, $subMenu?: ZeptoResult): ZeptoResult {
178
+ const $existingItem = this.$el.find(`#gear-options li[data-${name}`)
179
+ if ($existingItem.length) {
180
+ trace(`${T} addItem already exists`, { name })
181
+ return $existingItem
182
+ }
183
+ const $item = $('<li></li>')
184
+ .attr(`data-${name}`, '')
185
+ .appendTo(this.$el.find('#gear-options'))
186
+ if ($subMenu) {
187
+ trace(`${T} addItem adding submenu`, { name })
188
+ $subMenu
189
+ .addClass('gear-sub-menu-wrapper')
190
+ .hide()
191
+ .appendTo(this.$el.find('#gear-options-wrapper'))
192
+ $item.on('click', (e: MouseEvent) => {
193
+ trace(`${T} addItem submenu clicked`, { name })
194
+ e.stopPropagation()
195
+ $subMenu.show()
196
+ this.$el.find('#gear-options').hide()
197
+ })
198
+ }
199
+ return $item
110
200
  }
111
201
 
112
202
  private onActiveContainerChanged() {
113
- trace(`${T} onActiveContainerChanged`);
114
- this.bindContainerEvents();
203
+ trace(`${T} onActiveContainerChanged`)
204
+ this.bindContainerEvents()
115
205
  }
116
206
 
117
207
  private bindContainerEvents() {
118
- trace(`${T} bindContainerEvents`);
119
- this.listenTo(this.core.activeContainer, ClapprEvents.CONTAINER_HIGHDEFINITIONUPDATE, this.highDefinitionUpdate);
208
+ trace(`${T} bindContainerEvents`)
209
+ this.listenTo(
210
+ this.core.activeContainer,
211
+ ClapprEvents.CONTAINER_HIGHDEFINITIONUPDATE,
212
+ this.highDefinitionUpdate,
213
+ )
120
214
  }
121
215
 
122
216
  private highDefinitionUpdate(isHd: boolean) {
123
- trace(`${T} highDefinitionUpdate`, { isHd });
124
- this.isHd = isHd;
125
- this.$el.find('.gear-icon').html(isHd ? gearHdIcon : gearIcon);
217
+ trace(`${T} highDefinitionUpdate`, { isHd })
218
+ this.isHd = isHd
219
+ this.$el.find('.gear-icon').html(isHd ? gearHdIcon : gearIcon)
126
220
  }
127
221
 
128
222
  /**
129
223
  * @internal
130
224
  */
131
225
  override render() {
132
- const mediaControl = this.core.getPlugin('media_control');
226
+ trace(`${T} render`)
227
+ const mediaControl = this.core.getPlugin('media_control')
228
+ if (!mediaControl) {
229
+ return this // TODO test
230
+ }
231
+ const icon = this.isHd ? gearHdIcon : gearIcon
232
+ this.$el
233
+ .html(BottomGear.template({ icon }))
234
+ .find('#gear-sub-menu-wrapper')
235
+ .hide()
133
236
 
134
- // TODO use options.mediaControl.gear.items
135
- const items: GearOptionsItem[] = [
136
- 'quality',
137
- 'rate',
138
- 'nerd',
139
- ];
140
- const icon = this.isHd ? gearHdIcon : gearIcon;
141
- this.$el.html(BottomGear.template({ icon, items }));
237
+ // TODO make non-clickable when there are no items
238
+ mediaControl.putElement('gear', this.$el)
142
239
 
143
- mediaControl.putElement('gear', this.el);
144
- mediaControl.trigger(MediaControlEvents.MEDIACONTROL_GEAR_RENDERED);
145
- return this;
240
+ setTimeout(() => {
241
+ this.trigger(GearEvents.RENDERED)
242
+ }, 0)
243
+
244
+ return this
146
245
  }
147
246
 
148
247
  /**
149
- * Re-renders the gear menu.
150
- * It fires the {@link MediaControlEvents.MEDIACONTROL_GEAR_RENDERED | MEDIACONTROL_GEAR_RENDERED} event,
151
- * which the plugins that attach to the gear menu can listen to to re-render themselves.
248
+ * Collapses any submenu open back to the gear menu.
249
+ * @remarks
250
+ * Should be called by the UI plugin that added a gear item with a submenu when the latter is closed (e.g., when a "back" button is clicked).
152
251
  */
153
252
  refresh() {
154
- this.render();
155
- this.$el.find('.gear-wrapper').show();
253
+ this.$el.find('.gear-sub-menu-wrapper').hide()
254
+ this.$el.find('#gear-options').show()
156
255
  }
157
256
 
158
257
  private toggleGearMenu() {
159
- this.$el.find('.gear-wrapper').toggle();
258
+ this.$el.find('#gear-options-wrapper').toggle()
160
259
  }
161
260
 
162
261
  private hide() {
163
- this.$el.find('.gear-wrapper').hide();
262
+ this.$el.find('#gear-options-wrapper').hide()
164
263
  }
165
264
 
166
265
  private onCoreReady() {
167
- const mediaControl = this.core.getPlugin('media_control');
168
- assert(mediaControl, 'media_control plugin is required');
169
- this.listenTo(mediaControl, ClapprEvents.MEDIACONTROL_RENDERED, this.render);
170
- this.listenTo(mediaControl, ClapprEvents.MEDIACONTROL_HIDE, this.hide); // TODO mediacontrol show as well
266
+ trace(`${T} onCoreReady`)
267
+ const mediaControl = this.core.getPlugin('media_control')
268
+ assert(mediaControl, 'media_control plugin is required')
269
+ this.listenTo(
270
+ mediaControl,
271
+ ClapprEvents.MEDIACONTROL_RENDERED,
272
+ this.onMediaControlRendered,
273
+ )
274
+ this.listenTo(mediaControl, ClapprEvents.MEDIACONTROL_HIDE, this.hide)
275
+ }
276
+
277
+ private onMediaControlRendered() {
278
+ trace(`${T} onMediaControlRendered`)
279
+ this.render()
171
280
  }
172
281
  }
@@ -1,8 +1,7 @@
1
1
  import { MockedFunction, beforeEach, describe, expect, it, vi } from 'vitest'
2
2
 
3
- import { BottomGear } from '../BottomGear'
3
+ import { BottomGear, GearEvents } from '../BottomGear'
4
4
  import { createMockCore, createMockMediaControl } from '../../../testUtils'
5
- import { MediaControlEvents } from '../../media-control/MediaControl'
6
5
 
7
6
  describe('BottomGear', () => {
8
7
  let mediaControl: any
@@ -19,16 +18,33 @@ describe('BottomGear', () => {
19
18
  )
20
19
  bottomGear = new BottomGear(core)
21
20
  onGearRendered = vi.fn()
22
- mediaControl.on(MediaControlEvents.MEDIACONTROL_GEAR_RENDERED, onGearRendered, null)
21
+ bottomGear.on(GearEvents.RENDERED, onGearRendered, null)
23
22
  bottomGear.render()
24
23
  })
25
24
  it('should render', () => {
26
25
  expect(bottomGear.el.innerHTML).toMatchSnapshot()
27
26
  })
28
27
  it('should attach to media control', () => {
29
- expect(mediaControl.putElement).toHaveBeenCalledWith('gear', bottomGear.el)
28
+ expect(mediaControl.putElement).toHaveBeenCalledWith('gear', bottomGear.$el)
30
29
  })
31
- it('should emit event', () => {
30
+ it('should emit event in the next cycle', async () => {
31
+ expect(onGearRendered).not.toHaveBeenCalled()
32
+ await new Promise((resolve) => setTimeout(resolve, 0))
32
33
  expect(onGearRendered).toHaveBeenCalled()
33
34
  })
35
+ it('should render the gear menu hidden', () => {
36
+ expect(bottomGear.$el.find('#gear-options-wrapper').css('display')).toBe(
37
+ 'none',
38
+ )
39
+ })
40
+ describe('when clicked', () => {
41
+ beforeEach(() => {
42
+ bottomGear.$el.find('#gear-button').click()
43
+ })
44
+ it('should toggle the gear menu', () => {
45
+ expect(bottomGear.$el.find('#gear-options-wrapper').css('display')).toBe(
46
+ 'block',
47
+ )
48
+ })
49
+ })
34
50
  })
@@ -1,18 +1,11 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
3
  exports[`BottomGear > should render 1`] = `
4
- "<button type="button" class="button-gear media-control-button gplayer-lite-btn gcore-skin-button-color gear-icon" data-gear-button="-1" id="gear-button">
4
+ "<button type="button" class="media-control-button gplayer-lite-btn gcore-skin-button-color gear-icon" id="gear-button">
5
5
  /assets/icons/new/gear.svg
6
6
  </button>
7
- <div class="gear-wrapper gcore-skin-bg-color">
8
- <ul class="gear-options-list" id="gear-options">
9
-
10
- <li data-quality=""></li>
11
-
12
- <li data-rate=""></li>
13
-
14
- <li data-nerd=""></li>
15
-
16
- </ul>
17
- </div>"
7
+ <div class="gear-wrapper gcore-skin-bg-color" id="gear-options-wrapper" style="display: none;">
8
+ <ul class="gear-options-list" id="gear-options"></ul>
9
+ </div>
10
+ "
18
11
  `;
@@ -1,5 +1,5 @@
1
1
  import { UICorePlugin, Events, template, Core, Container } from '@clappr/core'
2
- import { reportError } from '@gcorevideo/utils'
2
+ import { reportError, trace } from '@gcorevideo/utils'
3
3
  import Mousetrap from 'mousetrap'
4
4
 
5
5
  import { CLAPPR_VERSION } from '../../build.js'
@@ -24,8 +24,8 @@ import '../../../assets/clappr-nerd-stats/clappr-nerd-stats.scss'
24
24
  import pluginHtml from '../../../assets/clappr-nerd-stats/clappr-nerd-stats.ejs'
25
25
  import buttonHtml from '../../../assets/clappr-nerd-stats/button.ejs'
26
26
  import statsIcon from '../../../assets/icons/new/stats.svg'
27
- import { BottomGear } from '../bottom-gear/BottomGear.js'
28
- import { MediaControl, MediaControlEvents } from '../media-control/MediaControl.js'
27
+ import { BottomGear, GearEvents } from '../bottom-gear/BottomGear.js'
28
+ import { MediaControl } from '../media-control/MediaControl.js'
29
29
  import assert from 'assert'
30
30
 
31
31
  const qualityClasses = [
@@ -114,7 +114,7 @@ type Metrics = BaseMetrics & {
114
114
  }
115
115
  }
116
116
 
117
- // const T = 'plugins.clappr_nerd_stats';
117
+ const T = 'plugins.clappr_nerd_stats'
118
118
 
119
119
  /**
120
120
  * `PLUGIN` that displays useful network-related statistics.
@@ -123,8 +123,6 @@ type Metrics = BaseMetrics & {
123
123
  * @remarks
124
124
  * Depends on:
125
125
  *
126
- * - {@link MediaControl}
127
- *
128
126
  * - {@link BottomGear}
129
127
  *
130
128
  * - {@link ClapprStats}
@@ -151,6 +149,8 @@ export class ClapprNerdStats extends UICorePlugin {
151
149
 
152
150
  private iconPosition: IconPosition
153
151
 
152
+ private static readonly buttonTemplate = template(buttonHtml)
153
+
154
154
  /**
155
155
  * @internal
156
156
  */
@@ -224,17 +224,15 @@ export class ClapprNerdStats extends UICorePlugin {
224
224
  * @internal
225
225
  */
226
226
  override bindEvents() {
227
- const mediaControl = this.core.getPlugin('media_control') as MediaControl
228
- assert(mediaControl, 'media_control plugin is required')
229
- this.listenToOnce(this.core, Events.CORE_READY, this.init)
230
- this.listenTo(
231
- mediaControl,
232
- MediaControlEvents.MEDIACONTROL_GEAR_RENDERED,
233
- this.addToBottomGear,
234
- )
227
+ this.listenToOnce(this.core, Events.CORE_READY, this.onCoreReady)
235
228
  }
236
229
 
237
- private init() {
230
+ private onCoreReady() {
231
+ const bottomGear = this.core.getPlugin('bottom_gear') as BottomGear
232
+ assert(bottomGear, 'bottom_gear plugin is required')
233
+
234
+ this.listenTo(bottomGear, GearEvents.RENDERED, this.addToBottomGear)
235
+
238
236
  this.container = this.core.activeContainer
239
237
  const clapprStats = this.container?.getPlugin('clappr_stats')
240
238
 
@@ -375,6 +373,7 @@ export class ClapprNerdStats extends UICorePlugin {
375
373
  * @internal
376
374
  */
377
375
  override render() {
376
+ trace(`${T} render`)
378
377
  // TODO append to the container
379
378
  this.core.$el.append(this.$el[0])
380
379
  this.hide()
@@ -383,17 +382,20 @@ export class ClapprNerdStats extends UICorePlugin {
383
382
  }
384
383
 
385
384
  private addToBottomGear() {
385
+ trace(`${T} addToBottomGear`)
386
386
  const gear = this.core.getPlugin('bottom_gear') as BottomGear
387
- const $el = gear.getElement('nerd')
388
- $el.html(buttonHtml)
389
- const $button = $el.find('.nerd-button')
390
-
391
- $button.find('.stats-icon').html(statsIcon)
392
-
393
- $button.on('click', (e: MouseEvent) => {
394
- e.stopPropagation()
395
- this.toggle()
396
- })
387
+ const $button = gear
388
+ .addItem('nerd')
389
+ .html(
390
+ ClapprNerdStats.buttonTemplate({
391
+ icon: statsIcon,
392
+ i18n: this.core.i18n,
393
+ }),
394
+ )
395
+ .on('click', (e: MouseEvent) => {
396
+ e.stopPropagation()
397
+ this.toggle()
398
+ })
397
399
  }
398
400
 
399
401
  private clearCustomMetrics() {
@@ -1,4 +1,5 @@
1
- //Copyright 2014 Globo.com Player authors. All rights reserved.
1
+ // This work is based on the original work of the following authors:
2
+ // Copyright 2014 Globo.com Player authors. All rights reserved.
2
3
  // Use of this source code is governed by a BSD-style
3
4
  // license that can be found at https://github.com/clappr/clappr-plugins/blob/master/LICENSE.
4
5
 
@@ -12,7 +13,7 @@ type Timer = ReturnType<typeof setTimeout>
12
13
  const T = 'plugins.click_to_pause_custom'
13
14
 
14
15
  /**
15
- * `PLUGIN` that adds a behavior of toggling the playback state on click over the container
16
+ * A small `PLUGIN` that toggles the playback state on click over the video container
16
17
  * @beta
17
18
  */
18
19
  export class ClickToPause extends ContainerPlugin {