Skip to content

Commit

Permalink
Merge branch 'feature/complete-settings-menu' of https://github.com/b…
Browse files Browse the repository at this point in the history
…itmovin/bitmovin-player-ui into feature/complete-settings-menu
  • Loading branch information
alesmaye committed Aug 19, 2024
2 parents 9baef8e + 5e799e2 commit 18c61ec
Show file tree
Hide file tree
Showing 9 changed files with 428 additions and 17 deletions.
9 changes: 6 additions & 3 deletions src/scss/skin-super-modern/_skin-modern-smallscreen.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,18 @@
}

// Decrease huge play button size and replace icon with normal play icon
.#{$prefix}-ui-hugeplaybacktogglebutton {
.#{$prefix}-ui-hugeplaybacktogglebutton,
.#{$prefix}-ui-smallcenteredplaybacktogglebutton {
.#{$prefix}-image {
background-image: url('../../assets/skin-super-modern/images/play.svg');
background-size: 3em;
}
}

// When casting, also display pause icon and disable animations because the transition doesn't look right
// sass-lint:disable nesting-depth
&.#{$prefix}-remote-control {
.#{$prefix}-ui-hugeplaybacktogglebutton {
.#{$prefix}-ui-hugeplaybacktogglebutton,
.#{$prefix}-ui-smallcenteredplaybacktogglebutton {
&.#{$prefix}-on {
.#{$prefix}-image {
animation: none;
Expand All @@ -71,6 +72,7 @@
&.#{$prefix}-layout-max-width-400 {
.#{$prefix}-ui-settings-panel,
.#{$prefix}-ui-hugeplaybacktogglebutton,
.#{$prefix}-ui-smallcenteredplaybacktogglebutton,
.#{$prefix}-ui-hugereplaybutton,
.#{$prefix}-ui-errormessage-overlay,
.#{$prefix}-ui-buffering-overlay,
Expand All @@ -84,6 +86,7 @@
&.#{$prefix}-layout-max-width-600 {
.#{$prefix}-ui-settings-panel,
.#{$prefix}-ui-hugeplaybacktogglebutton,
.#{$prefix}-ui-smallcenteredplaybacktogglebutton,
.#{$prefix}-ui-hugereplaybutton,
.#{$prefix}-ui-errormessage-overlay,
.#{$prefix}-ui-buffering-overlay,
Expand Down
2 changes: 2 additions & 0 deletions src/scss/skin-super-modern/_skin.scss
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@
@import 'components/spacer';
@import 'components/subtitlesettings/subtitlesettings';
@import 'components/subtitlesettingspaneltogglebutton';
@import 'components/touch-control-overlay';
@import 'components/smallcenteredplaybacktogglebutton';
@import 'skin-ads';
@import 'skin-cast-receiver';
@import 'skin-modern-smallscreen';
Expand Down
2 changes: 1 addition & 1 deletion src/scss/skin-super-modern/components/_controlbar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
background: linear-gradient(to bottom, $color-transparent, $color-background-bars);
box-sizing: border-box;
line-height: 1em;
padding: 1em 1em .5em;
padding: 0 1em .5em;

.#{$prefix}-controlbar-top,
.#{$prefix}-controlbar-bottom {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
@import '../variables';

.#{$prefix}-ui-smallcenteredplaybacktogglebutton {
@extend %ui-button;

@keyframes #{$prefix}-fade-out {
from {
opacity: 1;
visibility: visible;
}

to {
opacity: 0;
transform: scale(2);
visibility: hidden;
}
}

@keyframes #{$prefix}-fade-in {
from {
opacity: 0;
transform: scale(2);
visibility: visible;
}

to {
opacity: 1;
}
}

@keyframes #{$prefix}-breathe {
30% {
transform: scale(1.1);
}

60% {
transform: scale(1);
}
}

cursor: default;
height: 2.5em;
outline: none;
overflow: hidden; // hide overflow from scale animation
width: 2.5em;

.#{$prefix}-image {
background-position: center;
background-repeat: no-repeat;
background-size: 4em;
height: 100%;
width: 100%;
}

&.#{$prefix}-on {
.#{$prefix}-image {
background-image: url('../../assets/skin-super-modern/images/pause.svg');
}
}

&.#{$prefix}-off {
.#{$prefix}-image {
background-image: url('../../assets/skin-super-modern/images/play.svg');
}
}

&.#{$prefix}-no-transition-animations {
&.#{$prefix}-on,
&.#{$prefix}-off {
.#{$prefix}-image {
animation: none;
transition: none;
}
}
}
}
12 changes: 12 additions & 0 deletions src/scss/skin-super-modern/components/_touch-control-overlay.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@import '../variables';
@import '../mixins';

.#{$prefix}-ui-touchcontrol-overlay {
@extend %ui-container;
@include layout-cover;

align-items: center;
display: flex;
justify-content: center;
text-align: center;
}
114 changes: 114 additions & 0 deletions src/ts/components/smallcenteredplaybacktogglebutton.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import {PlaybackToggleButton, PlaybackToggleButtonConfig} from './playbacktogglebutton';
import {DOM} from '../dom';
import {UIInstanceManager} from '../uimanager';
import { PlayerAPI, PlayerEventBase, WarningEvent } from 'bitmovin-player';
import { i18n } from '../localization/i18n';

export class SmallCenteredPlaybackToggleButton extends PlaybackToggleButton {

constructor(config: PlaybackToggleButtonConfig = {}) {
super(config);

this.config = this.mergeConfig(config, {
cssClass: 'ui-smallcenteredplaybacktogglebutton',
text: i18n.getLocalizer('playPause'),
role: 'button',
}, this.config);
}

configure(player: PlayerAPI, uimanager: UIInstanceManager): void {
// Update button state through API events
super.configure(player, uimanager, false);

// Set enterFullscreenOnInitialPlayback if set in the uimanager config
if (typeof uimanager.getConfig().enterFullscreenOnInitialPlayback === 'boolean') {
this.config.enterFullscreenOnInitialPlayback = uimanager.getConfig().enterFullscreenOnInitialPlayback;
}

let togglePlayback = () => {
if (player.isPlaying() || this.isPlayInitiated) {
player.pause('ui');
} else {
player.play('ui');
}
};

let firstPlay = true;

this.onClick.subscribe(() => {
togglePlayback();

if (firstPlay && this.config.enterFullscreenOnInitialPlayback) {
player.setViewMode(player.exports.ViewMode.Fullscreen);
}
});

player.on(player.exports.PlayerEvent.Playing, () => {
// Playback has really started, we can disable the flag to switch to normal toggle button handling
firstPlay = false;
});

const suppressPlayButtonTransitionAnimation = () => {
// Disable the current animation
this.setTransitionAnimationsEnabled(false);

// Enable the transition animations for the next state change
this.onToggle.subscribeOnce(() => {
this.setTransitionAnimationsEnabled(true);
});
};

// Hide the play button animation when the UI is loaded (it should only be animated on state changes)
suppressPlayButtonTransitionAnimation();

const isAutoplayEnabled = Boolean(player.getConfig().playback?.autoplay);
// We only know if an autoplay attempt is upcoming if the player is not yet ready. If the player is already ready,
// the attempt might be upcoming or might have already happened, but we don't have to handle that because we can
// simply rely on isPlaying and the play state events.
const isAutoplayUpcoming = !player.getSource() && isAutoplayEnabled;

// Hide the play button when the player is already playing or autoplay is upcoming
if (player.isPlaying() || isAutoplayUpcoming) {
// Hide the play button (switch to playing state)
this.on();
// Disable the animation of the playing state switch
suppressPlayButtonTransitionAnimation();

// Show the play button without an animation if a play attempt is blocked
player.on(player.exports.PlayerEvent.Warning, (event: WarningEvent) => {
if (event.code === player.exports.WarningCode.PLAYBACK_COULD_NOT_BE_STARTED) {
suppressPlayButtonTransitionAnimation();
}
});
}
}

protected toDomElement(): DOM {
let buttonElement = super.toDomElement();

// Add child that contains the play button image
// Setting the image directly on the button does not work together with scaling animations, because the button
// can cover the whole video player are and scaling would extend it beyond. By adding an inner element, confined
// to the size if the image, it can scale inside the player without overshooting.
buttonElement.append(new DOM('div', {
'class': this.prefixCss('image'),
}));

return buttonElement;
}

/**
* Enables or disables the play state transition animations of the play button image. Can be used to suppress
* animations.
* @param {boolean} enabled true to enable the animations (default), false to disable them
*/
protected setTransitionAnimationsEnabled(enabled: boolean): void {
const noTransitionAnimationsClass = this.prefixCss('no-transition-animations');

if (enabled) {
this.getDomElement().removeClass(noTransitionAnimationsClass);
} else if (!this.getDomElement().hasClass(noTransitionAnimationsClass)) {
this.getDomElement().addClass(noTransitionAnimationsClass);
}
}
}
Loading

0 comments on commit 18c61ec

Please sign in to comment.