shaka-player 2.5.4 → 2.5.5
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.
- package/.csslintrc +13 -0
- package/CHANGELOG.md +56 -0
- package/build/build.py +4 -1
- package/build/check.py +17 -0
- package/build/compiler.py +40 -0
- package/build/types/core +1 -0
- package/build/types/ui +4 -1
- package/demo/asset_card.js +41 -11
- package/demo/cast_receiver/receiver_app.css +19 -13
- package/demo/close_button.js +0 -6
- package/demo/common/asset.js +6 -1
- package/demo/common/assets.js +72 -14
- package/demo/demo.less +105 -16
- package/demo/index.html +8 -5
- package/demo/load.js +5 -7
- package/demo/main.js +81 -16
- package/dist/.csslintstamp +0 -0
- package/dist/controls.css +1 -1
- package/dist/controls.css.map +1 -1
- package/dist/demo.compiled.debug.js +46 -39
- package/dist/demo.compiled.debug.map +3 -3
- package/dist/demo.compiled.js +46 -39
- package/dist/demo.compiled.map +3 -3
- package/dist/demo.css +1 -1
- package/dist/demo.css.map +1 -1
- package/dist/deps.js +11 -7
- package/dist/receiver.compiled.debug.js +10 -6
- package/dist/receiver.compiled.debug.map +3 -3
- package/dist/receiver.compiled.js +10 -6
- package/dist/receiver.compiled.map +3 -3
- package/dist/shaka-player.compiled.debug.externs.js +123 -92
- package/dist/shaka-player.compiled.debug.js +113 -105
- package/dist/shaka-player.compiled.debug.map +4 -4
- package/dist/shaka-player.compiled.externs.js +123 -92
- package/dist/shaka-player.compiled.js +551 -548
- package/dist/shaka-player.compiled.map +4 -4
- package/dist/shaka-player.ui.debug.externs.js +170 -101
- package/dist/shaka-player.ui.debug.js +187 -188
- package/dist/shaka-player.ui.debug.map +4 -4
- package/dist/shaka-player.ui.externs.js +170 -101
- package/dist/shaka-player.ui.js +651 -651
- package/dist/shaka-player.ui.map +3 -3
- package/docs/tutorials/drm-config.md +1 -0
- package/docs/tutorials/fairplay.md +77 -0
- package/docs/tutorials/index.json +1 -0
- package/docs/tutorials/ui-customization.md +3 -0
- package/docs/tutorials/ui.md +3 -1
- package/externs/mediasession.js +16 -1
- package/externs/shaka/net.js +5 -1
- package/externs/shaka/player.js +136 -90
- package/externs/webkitmediakeys.js +4 -0
- package/lib/dash/content_protection.js +33 -1
- package/lib/dash/dash_parser.js +12 -4
- package/lib/hls/hls_parser.js +20 -4
- package/lib/media/drm_engine.js +29 -2
- package/lib/media/media_source_engine.js +7 -3
- package/lib/media/playhead.js +8 -3
- package/lib/media/streaming_engine.js +24 -8
- package/lib/media/video_wrapper.js +8 -3
- package/lib/net/networking_engine.js +1 -0
- package/lib/player.js +3 -2
- package/lib/polyfill/patchedmediakeys_apple.js +2 -72
- package/lib/util/error.js +12 -0
- package/lib/util/fairplay_utils.js +122 -0
- package/lib/util/player_configuration.js +5 -0
- package/lib/util/pssh.js +41 -0
- package/package.json +4 -3
- package/shaka-player.uncompiled.js +5 -1
- package/test/dash/dash_parser_content_protection_unit.js +35 -1
- package/test/dash/dash_parser_manifest_unit.js +31 -0
- package/test/hls/hls_live_unit.js +7 -1
- package/test/hls/hls_parser_unit.js +50 -0
- package/test/media/media_source_engine_integration.js +12 -0
- package/test/media/playhead_unit.js +2 -0
- package/test/player_external.js +3 -2
- package/test/player_integration.js +75 -0
- package/test/test/externs/jasmine.js +6 -0
- package/test/test/util/test_scheme.js +32 -1
- package/test/test/util/ui_utils.js +41 -0
- package/test/ui/ui_unit.js +129 -3
- package/ui/audio_language_selection.js +17 -96
- package/ui/big_play_button.js +61 -0
- package/ui/controls.js +111 -86
- package/ui/controls.less +3 -5
- package/ui/externs/ui.js +14 -2
- package/ui/fullscreen_button.js +2 -52
- package/ui/less/buttons.less +8 -8
- package/ui/less/containers.less +21 -21
- package/ui/less/general.less +11 -0
- package/ui/less/other_elements.less +2 -1
- package/ui/less/overflow_menu.less +11 -10
- package/ui/less/range_elements.less +6 -0
- package/ui/less/spinner.less +2 -0
- package/ui/pip_button.js +1 -1
- package/ui/{play_pause_button.js → play_button.js} +17 -47
- package/ui/resolution_selection.js +41 -104
- package/ui/seek_bar.js +15 -17
- package/ui/settings_menu.js +113 -0
- package/ui/small_play_button.js +73 -0
- package/ui/text_displayer.js +2 -2
- package/ui/text_selection.js +39 -105
- package/ui/ui.js +12 -0
package/ui/controls.js
CHANGED
|
@@ -149,8 +149,6 @@ shaka.ui.Controls = function(player, videoContainer, video, config) {
|
|
|
149
149
|
// Configure and create the layout of the controls
|
|
150
150
|
this.configure(this.config_);
|
|
151
151
|
|
|
152
|
-
this.updateLocalizedStrings_();
|
|
153
|
-
|
|
154
152
|
this.addEventListeners_();
|
|
155
153
|
|
|
156
154
|
/**
|
|
@@ -358,8 +356,18 @@ shaka.ui.Controls.prototype.configure = function(config) {
|
|
|
358
356
|
|
|
359
357
|
this.castProxy_.changeReceiverId(config.castReceiverAppId);
|
|
360
358
|
|
|
359
|
+
// Deconstruct the old layout if applicable
|
|
360
|
+
if (this.seekBar_) {
|
|
361
|
+
this.seekBar_.destroy();
|
|
362
|
+
this.seekBar_ = null;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (this.playButton_) {
|
|
366
|
+
this.playButton_.destroy();
|
|
367
|
+
this.playButton_ = null;
|
|
368
|
+
}
|
|
369
|
+
|
|
361
370
|
if (this.controlsContainer_) {
|
|
362
|
-
// Deconstruct the old layout if applicable
|
|
363
371
|
shaka.util.Dom.removeAllChildren(this.controlsContainer_);
|
|
364
372
|
this.videoContainer_.removeChild(this.spinnerContainer_);
|
|
365
373
|
} else {
|
|
@@ -369,9 +377,31 @@ shaka.ui.Controls.prototype.configure = function(config) {
|
|
|
369
377
|
// Create the new layout
|
|
370
378
|
this.createDOM_();
|
|
371
379
|
|
|
372
|
-
|
|
373
|
-
|
|
380
|
+
// Init the play state
|
|
381
|
+
this.onPlayStateChange_();
|
|
374
382
|
|
|
383
|
+
// Elements that should not propagate clicks (controls panel, menus)
|
|
384
|
+
const noPropagationElements = this.videoContainer_.getElementsByClassName(
|
|
385
|
+
'shaka-no-propagation');
|
|
386
|
+
for (const element of noPropagationElements) {
|
|
387
|
+
const cb = (event) => event.stopPropagation();
|
|
388
|
+
this.eventManager_.listen(element, 'click', cb);
|
|
389
|
+
this.eventManager_.listen(element, 'dblclick', cb);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
// Keep showing controls if one of those elements is hovered
|
|
393
|
+
const showControlsElements = this.videoContainer_.getElementsByClassName(
|
|
394
|
+
'shaka-show-controls-on-mouse-over');
|
|
395
|
+
for (const element of showControlsElements) {
|
|
396
|
+
this.eventManager_.listen(element, 'mouseover', () => {
|
|
397
|
+
this.overrideCssShowControls_ = true;
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
this.eventManager_.listen(element, 'mouseleave', () => {
|
|
401
|
+
this.overrideCssShowControls_ = false;
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
};
|
|
375
405
|
|
|
376
406
|
/**
|
|
377
407
|
* Enable or disable the custom controls. Enabling disables native
|
|
@@ -405,6 +435,15 @@ shaka.ui.Controls.prototype.setEnabledShakaControls = function(enabled) {
|
|
|
405
435
|
};
|
|
406
436
|
|
|
407
437
|
|
|
438
|
+
/**
|
|
439
|
+
* @param {boolean} seeking
|
|
440
|
+
* @export
|
|
441
|
+
*/
|
|
442
|
+
shaka.ui.Controls.prototype.setSeeking = function(seeking) {
|
|
443
|
+
this.isSeeking_ = seeking;
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
|
|
408
447
|
/**
|
|
409
448
|
* Enable or disable native browser controls. Enabling disables shaka
|
|
410
449
|
* controls.
|
|
@@ -443,6 +482,24 @@ shaka.ui.Controls.prototype.getLocalization = function() {
|
|
|
443
482
|
return this.localization_;
|
|
444
483
|
};
|
|
445
484
|
|
|
485
|
+
/** @export */
|
|
486
|
+
shaka.ui.Controls.prototype.toggleFullScreen = async function() {
|
|
487
|
+
if (document.fullscreenElement) {
|
|
488
|
+
document.exitFullscreen();
|
|
489
|
+
} else {
|
|
490
|
+
// If we are in PiP mode, leave PiP mode first.
|
|
491
|
+
try {
|
|
492
|
+
if (document.pictureInPictureElement) {
|
|
493
|
+
await document.exitPictureInPicture();
|
|
494
|
+
}
|
|
495
|
+
} catch (error) {
|
|
496
|
+
this.dispatchEvent(new shaka.util.FakeEvent('error', {
|
|
497
|
+
detail: error,
|
|
498
|
+
}));
|
|
499
|
+
}
|
|
500
|
+
await this.videoContainer_.requestFullscreen();
|
|
501
|
+
}
|
|
502
|
+
};
|
|
446
503
|
|
|
447
504
|
/**
|
|
448
505
|
* @return {!HTMLElement}
|
|
@@ -576,33 +633,16 @@ shaka.ui.Controls.prototype.hideSettingsMenus = function() {
|
|
|
576
633
|
};
|
|
577
634
|
|
|
578
635
|
|
|
579
|
-
/**
|
|
580
|
-
* @private
|
|
581
|
-
*/
|
|
582
|
-
shaka.ui.Controls.prototype.updateLocalizedStrings_ = function() {
|
|
583
|
-
const LocIds = shaka.ui.Locales.Ids;
|
|
584
|
-
|
|
585
|
-
// Localize state-dependant labels
|
|
586
|
-
const makePlayNotPause = this.video_.paused && !this.isSeeking_;
|
|
587
|
-
const playButtonAriaLabelId = makePlayNotPause ? LocIds.PLAY : LocIds.PAUSE;
|
|
588
|
-
this.playButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
|
|
589
|
-
this.localization_.resolve(playButtonAriaLabelId));
|
|
590
|
-
};
|
|
591
|
-
|
|
592
|
-
|
|
593
636
|
/**
|
|
594
637
|
* @private
|
|
595
638
|
*/
|
|
596
639
|
shaka.ui.Controls.prototype.createDOM_ = function() {
|
|
597
|
-
if (this.seekBar_) {
|
|
598
|
-
this.seekBar_.destroy();
|
|
599
|
-
this.seekBar_ = null;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
640
|
this.videoContainer_.classList.add('shaka-video-container');
|
|
603
641
|
this.video_.classList.add('shaka-video');
|
|
604
642
|
|
|
605
|
-
this.
|
|
643
|
+
if (this.config_.addBigPlayButton) {
|
|
644
|
+
this.addPlayButton_();
|
|
645
|
+
}
|
|
606
646
|
|
|
607
647
|
this.addBufferingSpinner_();
|
|
608
648
|
|
|
@@ -645,16 +685,13 @@ shaka.ui.Controls.prototype.addControlsContainer_ = function() {
|
|
|
645
685
|
* @private
|
|
646
686
|
*/
|
|
647
687
|
shaka.ui.Controls.prototype.addPlayButton_ = function() {
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
this.
|
|
651
|
-
this.controlsContainer_.appendChild(this.playButtonContainer_);
|
|
688
|
+
const playButtonContainer = shaka.util.Dom.createHTMLElement('div');
|
|
689
|
+
playButtonContainer.classList.add('shaka-play-button-container');
|
|
690
|
+
this.controlsContainer_.appendChild(playButtonContainer);
|
|
652
691
|
|
|
653
|
-
/** @private {
|
|
654
|
-
this.playButton_ =
|
|
655
|
-
|
|
656
|
-
this.playButtonContainer_.appendChild(this.playButton_);
|
|
657
|
-
this.onPlayStateChange_();
|
|
692
|
+
/** @private {shaka.ui.BigPlayButton} */
|
|
693
|
+
this.playButton_ =
|
|
694
|
+
new shaka.ui.BigPlayButton(playButtonContainer, this);
|
|
658
695
|
};
|
|
659
696
|
|
|
660
697
|
|
|
@@ -712,6 +749,14 @@ shaka.ui.Controls.prototype.addControlsButtonPanel_ = function() {
|
|
|
712
749
|
this.controlsButtonPanel_.classList.add('shaka-show-controls-on-mouse-over');
|
|
713
750
|
this.bottomControls_.appendChild(this.controlsButtonPanel_);
|
|
714
751
|
|
|
752
|
+
// Overflow menus are supposed to hide once you click elsewhere
|
|
753
|
+
// on the video element. The code in onContainerClick_ ensures that.
|
|
754
|
+
// However, clicks on controls panel don't propagate to the container,
|
|
755
|
+
// so we have to explicitly hide the menus onclick here.
|
|
756
|
+
this.eventManager_.listen(this.controlsButtonPanel_, 'click', () => {
|
|
757
|
+
this.hideSettingsMenus();
|
|
758
|
+
});
|
|
759
|
+
|
|
715
760
|
// Create the elements specified by controlPanelElements
|
|
716
761
|
for (let i = 0; i < this.config_.controlPanelElements.length; i++) {
|
|
717
762
|
const name = this.config_.controlPanelElements[i];
|
|
@@ -727,6 +772,30 @@ shaka.ui.Controls.prototype.addControlsButtonPanel_ = function() {
|
|
|
727
772
|
|
|
728
773
|
|
|
729
774
|
/**
|
|
775
|
+
* When a mobile device is rotated to landscape layout, and the video is
|
|
776
|
+
* loaded, make the demo app go into fullscreen.
|
|
777
|
+
* Similarly, exit fullscreen when the device is rotated to portrait layout.
|
|
778
|
+
* @private
|
|
779
|
+
*/
|
|
780
|
+
shaka.ui.Controls.prototype.onScreenRotation_ = function() {
|
|
781
|
+
if (!this.video_ ||
|
|
782
|
+
this.video_.readyState == 0 ||
|
|
783
|
+
this.castProxy_.isCasting()) { return; }
|
|
784
|
+
|
|
785
|
+
if (screen.orientation.type.includes('landscape') &&
|
|
786
|
+
!document.fullscreenElement) {
|
|
787
|
+
this.videoContainer_.requestFullscreen();
|
|
788
|
+
} else if (screen.orientation.type.includes('portrait') &&
|
|
789
|
+
document.fullscreenElement) {
|
|
790
|
+
document.exitFullscreen();
|
|
791
|
+
}
|
|
792
|
+
};
|
|
793
|
+
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Adds static event listeners. This should only add event listeners to
|
|
797
|
+
* things that don't change (e.g. Player). Dynamic elements (e.g. controls)
|
|
798
|
+
* should have their event listeners added when they are created.
|
|
730
799
|
* @private
|
|
731
800
|
*/
|
|
732
801
|
shaka.ui.Controls.prototype.addEventListeners_ = function() {
|
|
@@ -742,6 +811,9 @@ shaka.ui.Controls.prototype.addEventListeners_ = function() {
|
|
|
742
811
|
// for focused elements.
|
|
743
812
|
this.eventManager_.listen(window, 'keydown', this.onKeyDown_.bind(this));
|
|
744
813
|
|
|
814
|
+
this.eventManager_.listen(
|
|
815
|
+
this.controlsContainer_, 'dblclick', () => this.toggleFullScreen());
|
|
816
|
+
|
|
745
817
|
this.eventManager_.listen(this.video_,
|
|
746
818
|
'play', this.onPlayStateChange_.bind(this));
|
|
747
819
|
this.eventManager_.listen(this.video_,
|
|
@@ -752,32 +824,6 @@ shaka.ui.Controls.prototype.addEventListeners_ = function() {
|
|
|
752
824
|
this.eventManager_.listen(this.video_,
|
|
753
825
|
'ended', this.onPlayStateChange_.bind(this));
|
|
754
826
|
|
|
755
|
-
|
|
756
|
-
// Elements that should not propagate clicks (controls panel, menus)
|
|
757
|
-
const noPropagationElements = this.videoContainer_.getElementsByClassName(
|
|
758
|
-
'shaka-no-propagation');
|
|
759
|
-
for (let i = 0; i < noPropagationElements.length; i++) {
|
|
760
|
-
let element = noPropagationElements[i];
|
|
761
|
-
this.eventManager_.listen(element,
|
|
762
|
-
'click', function(event) { event.stopPropagation(); });
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
// Keep showing controls if one of those elements is hovered
|
|
766
|
-
let showControlsElements = this.videoContainer_.getElementsByClassName(
|
|
767
|
-
'shaka-show-controls-on-mouse-over');
|
|
768
|
-
for (let i = 0; i < showControlsElements.length; i++) {
|
|
769
|
-
let element = showControlsElements[i];
|
|
770
|
-
this.eventManager_.listen(element,
|
|
771
|
-
'mouseover', () => {
|
|
772
|
-
this.overrideCssShowControls_ = true;
|
|
773
|
-
});
|
|
774
|
-
|
|
775
|
-
this.eventManager_.listen(element,
|
|
776
|
-
'mouseleave', () => {
|
|
777
|
-
this.overrideCssShowControls_ = false;
|
|
778
|
-
});
|
|
779
|
-
}
|
|
780
|
-
|
|
781
827
|
this.eventManager_.listen(this.videoContainer_,
|
|
782
828
|
'mousemove', this.onMouseMove_.bind(this));
|
|
783
829
|
this.eventManager_.listen(this.videoContainer_,
|
|
@@ -787,14 +833,6 @@ shaka.ui.Controls.prototype.addEventListeners_ = function() {
|
|
|
787
833
|
this.eventManager_.listen(this.videoContainer_,
|
|
788
834
|
'mouseleave', this.onMouseLeave_.bind(this));
|
|
789
835
|
|
|
790
|
-
// Overflow menus are supposed to hide once you click elsewhere
|
|
791
|
-
// on the video element. The code in onContainerClick_ ensures that.
|
|
792
|
-
// However, clicks on controls panel don't propagate to the container,
|
|
793
|
-
// so we have to explicitly hide the menus onclick here.
|
|
794
|
-
this.eventManager_.listen(this.controlsButtonPanel_, 'click', () => {
|
|
795
|
-
this.hideSettingsMenusTimer_.tickNow();
|
|
796
|
-
});
|
|
797
|
-
|
|
798
836
|
this.eventManager_.listen(this.castProxy_,
|
|
799
837
|
'caststatuschanged', (e) => {
|
|
800
838
|
this.onCastStatusChange_(e);
|
|
@@ -803,13 +841,11 @@ shaka.ui.Controls.prototype.addEventListeners_ = function() {
|
|
|
803
841
|
this.eventManager_.listen(this.videoContainer_,
|
|
804
842
|
'keyup', this.onKeyUp_.bind(this));
|
|
805
843
|
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
shaka.ui.Localization.LOCALE_CHANGED,
|
|
812
|
-
(e) => this.updateLocalizedStrings_());
|
|
844
|
+
if (screen.orientation) {
|
|
845
|
+
this.eventManager_.listen(screen.orientation, 'change', () => {
|
|
846
|
+
this.onScreenRotation_();
|
|
847
|
+
});
|
|
848
|
+
}
|
|
813
849
|
};
|
|
814
850
|
|
|
815
851
|
|
|
@@ -988,17 +1024,6 @@ shaka.ui.Controls.prototype.onPlayStateChange_ = function() {
|
|
|
988
1024
|
if (this.video_.ended && !this.video_.paused) {
|
|
989
1025
|
this.video_.pause();
|
|
990
1026
|
}
|
|
991
|
-
|
|
992
|
-
// Video is paused during seek, so don't show the play arrow while seeking:
|
|
993
|
-
if (this.enabled_ && this.video_.paused && !this.isSeeking_) {
|
|
994
|
-
this.playButton_.setAttribute('icon', 'play');
|
|
995
|
-
this.playButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
|
|
996
|
-
this.localization_.resolve(shaka.ui.Locales.Ids.PLAY));
|
|
997
|
-
} else {
|
|
998
|
-
this.playButton_.setAttribute('icon', 'pause');
|
|
999
|
-
this.playButton_.setAttribute(shaka.ui.Constants.ARIA_LABEL,
|
|
1000
|
-
this.localization_.resolve(shaka.ui.Locales.Ids.PAUSE));
|
|
1001
|
-
}
|
|
1002
1027
|
};
|
|
1003
1028
|
|
|
1004
1029
|
|
package/ui/controls.less
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
@import "less/spinner.less";
|
|
23
23
|
@import "less/other_elements.less";
|
|
24
24
|
@import "less/overflow_menu.less";
|
|
25
|
-
|
|
26
25
|
@import (css, inline) "https://fonts.googleapis.com/css?family=Roboto";
|
|
27
26
|
@import (css, inline) "https://fonts.googleapis.com/icon?family=Material+Icons";
|
|
28
27
|
|
|
@@ -35,6 +34,7 @@
|
|
|
35
34
|
font-size: 150%;
|
|
36
35
|
padding: 5px;
|
|
37
36
|
|
|
37
|
+
/* dimensions */
|
|
38
38
|
bottom: 50px;
|
|
39
39
|
left: 0;
|
|
40
40
|
right: 0;
|
|
@@ -53,12 +53,10 @@ to make them override display setting previously set in
|
|
|
53
53
|
.overflowMenu button.
|
|
54
54
|
See https://goo.gl/egXAJY for explanation of
|
|
55
55
|
how CSS cascade rules work. */
|
|
56
|
-
button.shaka-hidden,
|
|
57
|
-
.shaka-hidden {
|
|
56
|
+
button.shaka-hidden, .shaka-hidden {
|
|
58
57
|
.hidden();
|
|
59
58
|
}
|
|
60
59
|
|
|
61
|
-
button.shaka-displayed,
|
|
62
|
-
.shaka-displayed {
|
|
60
|
+
button.shaka-displayed, .shaka-displayed {
|
|
63
61
|
display: flex;
|
|
64
62
|
}
|
package/ui/externs/ui.js
CHANGED
|
@@ -34,7 +34,9 @@ shaka.extern = {};
|
|
|
34
34
|
* controlPanelElements: !Array.<string>,
|
|
35
35
|
* overflowMenuButtons: !Array.<string>,
|
|
36
36
|
* addSeekBar: boolean,
|
|
37
|
-
*
|
|
37
|
+
* addBigPlayButton: boolean,
|
|
38
|
+
* castReceiverAppId: string,
|
|
39
|
+
* clearBufferOnQualityChange: boolean
|
|
38
40
|
* }}
|
|
39
41
|
*
|
|
40
42
|
* @property {!Array.<string>} controlPanelElements
|
|
@@ -43,9 +45,19 @@ shaka.extern = {};
|
|
|
43
45
|
* The ordered list of the overflow menu buttons.
|
|
44
46
|
* @property {boolean} addSeekBar
|
|
45
47
|
* Whether or not a seek bar should be part of the UI.
|
|
48
|
+
* @property {boolean} addBigPlayButton
|
|
49
|
+
* Whether or not a big play button in the center of the video
|
|
50
|
+
* should be part of the UI.
|
|
46
51
|
* @property {string} castReceiverAppId
|
|
47
52
|
* Receiver app id to use for the Chromecast support.
|
|
48
|
-
* @
|
|
53
|
+
* @property {boolean} clearBufferOnQualityChange
|
|
54
|
+
* Only applicable if the resolution selection is part of the UI.
|
|
55
|
+
* Whether buffer should be cleared when changing resolution
|
|
56
|
+
* via UI. Clearing buffer would result in immidiate change of quality,
|
|
57
|
+
* but playback may flicker/stall for a sec as the content in new
|
|
58
|
+
* resolution is being buffered. Not clearing the buffer will mean
|
|
59
|
+
* we play the content in the previously selected resolution that we
|
|
60
|
+
* already have buffered before switching to the new resolution.
|
|
49
61
|
*/
|
|
50
62
|
shaka.extern.UIConfiguration;
|
|
51
63
|
|
package/ui/fullscreen_button.js
CHANGED
|
@@ -51,9 +51,6 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
|
|
|
51
51
|
this.parent.appendChild(this.button_);
|
|
52
52
|
this.updateAriaLabel_();
|
|
53
53
|
|
|
54
|
-
/** @private {!HTMLElement} */
|
|
55
|
-
this.videoContainer_ = this.controls.getVideoContainer();
|
|
56
|
-
|
|
57
54
|
this.eventManager.listen(
|
|
58
55
|
this.localization, shaka.ui.Localization.LOCALE_UPDATED, () => {
|
|
59
56
|
this.updateAriaLabel_();
|
|
@@ -65,14 +62,8 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
|
|
|
65
62
|
});
|
|
66
63
|
|
|
67
64
|
this.eventManager.listen(this.button_, 'click', () => {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
if (screen.orientation) {
|
|
72
|
-
this.eventManager.listen(screen.orientation, 'change', () => {
|
|
73
|
-
this.onScreenRotation_();
|
|
74
|
-
});
|
|
75
|
-
}
|
|
65
|
+
this.controls.toggleFullScreen();
|
|
66
|
+
});
|
|
76
67
|
|
|
77
68
|
this.eventManager.listen(document, 'fullscreenchange', () => {
|
|
78
69
|
this.updateIcon_();
|
|
@@ -101,47 +92,6 @@ shaka.ui.FullscreenButton = class extends shaka.ui.Element {
|
|
|
101
92
|
shaka.ui.Enums.MaterialDesignIcons.EXIT_FULLSCREEN :
|
|
102
93
|
shaka.ui.Enums.MaterialDesignIcons.FULLSCREEN;
|
|
103
94
|
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* @private
|
|
107
|
-
*/
|
|
108
|
-
async toggleFullScreen_() {
|
|
109
|
-
if (document.fullscreenElement) {
|
|
110
|
-
document.exitFullscreen();
|
|
111
|
-
} else {
|
|
112
|
-
// If you are in PiP mode, leave PiP mode first.
|
|
113
|
-
try {
|
|
114
|
-
if (document.pictureInPictureElement) {
|
|
115
|
-
await document.exitPictureInPicture();
|
|
116
|
-
}
|
|
117
|
-
} catch (error) {
|
|
118
|
-
this.controls.dispatchEvent(new shaka.util.FakeEvent('error', {
|
|
119
|
-
detail: error,
|
|
120
|
-
}));
|
|
121
|
-
}
|
|
122
|
-
await this.videoContainer_.requestFullscreen();
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* When a mobile device is rotated to landscape layout, and the video is
|
|
128
|
-
* loaded, make the demo app go into fullscreen.
|
|
129
|
-
* Similarly, exit fullscreen when the device is rotated to portrait layout.
|
|
130
|
-
* @private
|
|
131
|
-
*/
|
|
132
|
-
onScreenRotation_() {
|
|
133
|
-
if (!this.video ||
|
|
134
|
-
this.video.readyState == 0 ||
|
|
135
|
-
this.controls.getCastProxy().isCasting()) return;
|
|
136
|
-
|
|
137
|
-
if (screen.orientation.type.includes('landscape') &&
|
|
138
|
-
!document.fullscreenElement) {
|
|
139
|
-
this.videoContainer_.requestFullscreen();
|
|
140
|
-
} else if (screen.orientation.type.includes('portrait') &&
|
|
141
|
-
document.fullscreenElement) {
|
|
142
|
-
document.exitFullscreen();
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
95
|
};
|
|
146
96
|
|
|
147
97
|
|
package/ui/less/buttons.less
CHANGED
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
border-radius: 50%;
|
|
42
42
|
|
|
43
43
|
/* A small drop shadow below the button. */
|
|
44
|
-
box-shadow: rgba(0, 0, 0, 0.1)
|
|
44
|
+
box-shadow: rgba(0, 0, 0, 0.1) 0 0 20px 0;
|
|
45
45
|
|
|
46
46
|
/* No border. */
|
|
47
47
|
border: none;
|
|
@@ -52,8 +52,9 @@
|
|
|
52
52
|
background-size: 50%;
|
|
53
53
|
background-repeat: no-repeat;
|
|
54
54
|
background-position: center center;
|
|
55
|
+
|
|
55
56
|
/* A background color behind the play arrow. */
|
|
56
|
-
background-color: rgba(255, 255, 255, .9);
|
|
57
|
+
background-color: rgba(255, 255, 255, 0.9);
|
|
57
58
|
|
|
58
59
|
/* Actual icon images for the two states this could be in.
|
|
59
60
|
* These will be inlined as data URIs when compiled, and so do not need to be
|
|
@@ -62,6 +63,7 @@
|
|
|
62
63
|
&[icon="play"] {
|
|
63
64
|
background-image: data-uri('images/play_arrow.svg');
|
|
64
65
|
}
|
|
66
|
+
|
|
65
67
|
&[icon="pause"] {
|
|
66
68
|
background-image: data-uri('images/pause.svg');
|
|
67
69
|
}
|
|
@@ -91,11 +93,11 @@
|
|
|
91
93
|
|
|
92
94
|
/* Use a consistent outline focus style across browsers. */
|
|
93
95
|
.shaka-controls-container {
|
|
94
|
-
button:focus,
|
|
95
|
-
input:focus {
|
|
96
|
+
button:focus, input:focus {
|
|
96
97
|
/* Most browsers will fall back to "Highlight" (system setting) color for
|
|
97
98
|
* the focus outline. */
|
|
98
99
|
outline: 1px solid Highlight;
|
|
100
|
+
|
|
99
101
|
/* WebKit-based and Blink-based browsers have this as their default outline
|
|
100
102
|
* color. */
|
|
101
103
|
outline: 1px solid -webkit-focus-ring-color;
|
|
@@ -103,8 +105,7 @@
|
|
|
103
105
|
|
|
104
106
|
/* Disable this Mozilla-specific focus ring, since we have an outline defined
|
|
105
107
|
* for focus. */
|
|
106
|
-
button
|
|
107
|
-
input::-moz-focus-outer {
|
|
108
|
+
button:-moz-focus-inner, input:-moz-focus-outer {
|
|
108
109
|
outline: none;
|
|
109
110
|
border: 0;
|
|
110
111
|
}
|
|
@@ -114,8 +115,7 @@
|
|
|
114
115
|
* it doesn't look great. This removes the outline for
|
|
115
116
|
* mouse users while leaving it for keyboard users. */
|
|
116
117
|
.shaka-controls-container:not(.shaka-keyboard-navigation) {
|
|
117
|
-
button:focus,
|
|
118
|
-
input:focus {
|
|
118
|
+
button:focus, input:focus {
|
|
119
119
|
outline: none;
|
|
120
120
|
border: 0;
|
|
121
121
|
}
|
package/ui/less/containers.less
CHANGED
|
@@ -17,6 +17,8 @@
|
|
|
17
17
|
|
|
18
18
|
/* All of the top-level containers into which various visible features go. */
|
|
19
19
|
|
|
20
|
+
@transparent: rgba(0, 0, 0, 0);
|
|
21
|
+
|
|
20
22
|
/* A container for the entire video + controls combo. This is the auto-setup
|
|
21
23
|
* div which we populate. */
|
|
22
24
|
.shaka-video-container {
|
|
@@ -31,6 +33,7 @@
|
|
|
31
33
|
.material-icons {
|
|
32
34
|
font-family: 'Material Icons';
|
|
33
35
|
}
|
|
36
|
+
|
|
34
37
|
* {
|
|
35
38
|
font-family: Roboto-Regular, Roboto, sans-serif;
|
|
36
39
|
}
|
|
@@ -44,12 +47,14 @@
|
|
|
44
47
|
* pseudo-class they don't support. */
|
|
45
48
|
.fullscreen-container() {
|
|
46
49
|
.fill-container();
|
|
50
|
+
|
|
47
51
|
background-color: black;
|
|
48
52
|
|
|
49
53
|
.shaka-text-container {
|
|
50
54
|
/* In fullscreen mode, the text displayer's font size should be relative to
|
|
51
|
-
* the window height instead of a
|
|
52
|
-
|
|
55
|
+
* the either window height or width (whichever is smaller), instead of a
|
|
56
|
+
* fixed size. */
|
|
57
|
+
font-size: 4.4vmin;
|
|
53
58
|
}
|
|
54
59
|
}
|
|
55
60
|
.shaka-video-container:fullscreen { .fullscreen-container(); }
|
|
@@ -77,18 +82,18 @@
|
|
|
77
82
|
|
|
78
83
|
/* A flex container, to make layout of children easier to reason about. */
|
|
79
84
|
display: flex;
|
|
85
|
+
|
|
80
86
|
/* Defines in which direction the children should flow. */
|
|
81
87
|
flex-direction: column;
|
|
88
|
+
|
|
82
89
|
/* Pushes the children toward the bottom of the container. */
|
|
83
90
|
justify-content: flex-end;
|
|
91
|
+
|
|
84
92
|
/* Centers children horizontally. */
|
|
85
93
|
align-items: center;
|
|
86
94
|
|
|
87
95
|
/* A black gradient at the bottom, behind the controls, but only so high. */
|
|
88
|
-
background: linear-gradient(
|
|
89
|
-
to top,
|
|
90
|
-
rgba(0, 0, 0, 1) 0,
|
|
91
|
-
rgba(0, 0, 0, 0) 92px);
|
|
96
|
+
background: linear-gradient(to top, rgba(0, 0, 0, 1) 0, @transparent 92px);
|
|
92
97
|
|
|
93
98
|
/* By default, do not allow any of our controls to shrink.
|
|
94
99
|
* Specific controls can use .shrinkable() to override. */
|
|
@@ -98,7 +103,7 @@
|
|
|
98
103
|
opacity: 0;
|
|
99
104
|
|
|
100
105
|
/* When we show/hide this, do it gradually using cubic-bezier timing. */
|
|
101
|
-
transition: opacity cubic-bezier(0.4, 0
|
|
106
|
+
transition: opacity cubic-bezier(0.4, 0, 0.6, 1) 600ms;
|
|
102
107
|
|
|
103
108
|
/* Position the controls container in front of the text container, so that
|
|
104
109
|
* the text container doesn't interfere with the control buttons. */
|
|
@@ -119,7 +124,6 @@
|
|
|
119
124
|
}
|
|
120
125
|
}
|
|
121
126
|
|
|
122
|
-
|
|
123
127
|
/* Container for controls positioned at the bottom of the video container:
|
|
124
128
|
* controls button panel and the seek bar. */
|
|
125
129
|
.shaka-bottom-controls {
|
|
@@ -148,8 +152,10 @@
|
|
|
148
152
|
/* This is itself a flex container, with children layed out horizontally. */
|
|
149
153
|
display: flex;
|
|
150
154
|
flex-direction: row;
|
|
155
|
+
|
|
151
156
|
/* Push children to the right. */
|
|
152
157
|
justify-content: flex-end;
|
|
158
|
+
|
|
153
159
|
/* Center children vertically. */
|
|
154
160
|
align-items: center;
|
|
155
161
|
|
|
@@ -196,24 +202,21 @@
|
|
|
196
202
|
margin: 0;
|
|
197
203
|
.fill-container();
|
|
198
204
|
.shrinkable();
|
|
205
|
+
.absolute-position();
|
|
199
206
|
|
|
200
207
|
/* Keep the play button in the middle of this container. */
|
|
201
208
|
display: flex;
|
|
202
209
|
justify-content: center;
|
|
203
210
|
align-items: center;
|
|
204
|
-
position: absolute;
|
|
205
|
-
/* Specify left and top for IE's sake. Otherwise, the container ends up below
|
|
206
|
-
* and to the right of where it should be. */
|
|
207
|
-
top: 0;
|
|
208
|
-
left: 0;
|
|
209
211
|
}
|
|
210
212
|
|
|
211
213
|
.shaka-text-container {
|
|
214
|
+
.absolute-position();
|
|
215
|
+
|
|
212
216
|
bottom: 15%;
|
|
213
|
-
top: 0;
|
|
214
|
-
left: 0;
|
|
215
217
|
width: 100%;
|
|
216
218
|
min-width: 48px;
|
|
219
|
+
text-align: center;
|
|
217
220
|
|
|
218
221
|
/* Set the captions in the middle horizontally by default. */
|
|
219
222
|
display: flex;
|
|
@@ -226,9 +229,6 @@
|
|
|
226
229
|
* overflow content. */
|
|
227
230
|
overflow: hidden;
|
|
228
231
|
|
|
229
|
-
text-align: center;
|
|
230
|
-
position: absolute;
|
|
231
|
-
|
|
232
232
|
/* These are defaults which are overridden by JS or cue styles. */
|
|
233
233
|
font-size: 20px;
|
|
234
234
|
line-height: 1.4; // relative to font size.
|
|
@@ -242,10 +242,9 @@
|
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
244
|
|
|
245
|
-
|
|
246
245
|
/* The buffering spinner. */
|
|
247
246
|
.shaka-spinner-container {
|
|
248
|
-
position
|
|
247
|
+
.absolute-position();
|
|
249
248
|
.fill-container();
|
|
250
249
|
|
|
251
250
|
flex-shrink: 1;
|
|
@@ -262,8 +261,9 @@
|
|
|
262
261
|
for the detailed explanation. */
|
|
263
262
|
|
|
264
263
|
/* For the padding thing to work, spinner div needs to be an
|
|
265
|
-
overlay-parent and spinner svg - an overlay child
|
|
264
|
+
overlay-parent and spinner svg - an overlay child. */
|
|
266
265
|
.overlay-parent();
|
|
266
|
+
|
|
267
267
|
margin: 0;
|
|
268
268
|
box-sizing: border-box;
|
|
269
269
|
padding: @spinner-size-percentage / 2;
|
package/ui/less/general.less
CHANGED
|
@@ -77,6 +77,17 @@
|
|
|
77
77
|
.fill-container();
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
.absolute-position() {
|
|
81
|
+
/* When setting "position: absolute" it uses the left,right,top,bottom
|
|
82
|
+
* properties to determine the positioning. We should set all these
|
|
83
|
+
* properties to ensure it is positioned properly on all platforms. */
|
|
84
|
+
position: absolute;
|
|
85
|
+
left: 0;
|
|
86
|
+
right: 0;
|
|
87
|
+
top: 0;
|
|
88
|
+
bottom: 0;
|
|
89
|
+
}
|
|
90
|
+
|
|
80
91
|
/* For things that should not shrink inside a flex container.
|
|
81
92
|
* This will be used for all controls by default. */
|
|
82
93
|
.unshrinkable() {
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
/* Make the element grow to take up the remaining space. */
|
|
30
30
|
flex-grow: 1;
|
|
31
31
|
|
|
32
|
-
/* Margins don't shrink. Remove margins in order to be more flexible when
|
|
32
|
+
/* Margins don't shrink. Remove margins in order to be more flexible when
|
|
33
|
+
* shrinking. */
|
|
33
34
|
margin: 0;
|
|
34
35
|
}
|