]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Add player controls on mobile
authorChocobozzz <me@florianbigard.com>
Tue, 11 Jan 2022 10:26:35 +0000 (11:26 +0100)
committerChocobozzz <me@florianbigard.com>
Tue, 11 Jan 2022 10:26:35 +0000 (11:26 +0100)
client/src/assets/player/bezels/pause-bezel.ts
client/src/assets/player/mobile/peertube-mobile-buttons.ts [new file with mode: 0644]
client/src/assets/player/mobile/peertube-mobile-plugin.ts [new file with mode: 0644]
client/src/assets/player/peertube-player-manager.ts
client/src/assets/player/peertube-plugin.ts
client/src/assets/player/peertube-videojs-typings.ts
client/src/assets/player/videojs-components/next-previous-video-button.ts
client/src/sass/player/_player-variables.scss
client/src/sass/player/control-bar.scss
client/src/sass/player/mobile.scss
client/src/sass/player/settings-menu.scss

index 886574380924f48a1eeed98458d33f75f0c659cd..3159643118679f376d4d150cc3ea0e4c230c7d86 100644 (file)
@@ -1,4 +1,5 @@
 import videojs from 'video.js'
+import { isMobile } from '../utils'
 
 function getPauseBezel () {
   return `
@@ -37,6 +38,9 @@ class PauseBezel extends Component {
   constructor (player: videojs.Player, options?: videojs.ComponentOptions) {
     super(player, options)
 
+    // Hide bezels on mobile since we already have our mobile overlay
+    if (isMobile()) return
+
     player.on('pause', (_: any) => {
       if (player.seeking() || player.ended()) return
       this.container.innerHTML = getPauseBezel()
diff --git a/client/src/assets/player/mobile/peertube-mobile-buttons.ts b/client/src/assets/player/mobile/peertube-mobile-buttons.ts
new file mode 100644 (file)
index 0000000..d6f8f35
--- /dev/null
@@ -0,0 +1,42 @@
+import videojs from 'video.js'
+
+import debug from 'debug'
+
+const logger = debug('peertube:player:mobile')
+
+const Component = videojs.getComponent('Component')
+class PeerTubeMobileButtons extends Component {
+
+  createEl () {
+    const container = super.createEl('div', {
+      className: 'vjs-mobile-buttons-overlay'
+    }) as HTMLDivElement
+
+    container.addEventListener('click', () => {
+      logger('Set user as inactive')
+
+      this.player_.userActive(false)
+    })
+
+    const mainButton = super.createEl('div', {
+      className: 'main-button'
+    }) as HTMLDivElement
+
+    mainButton.addEventListener('click', e => {
+      e.stopPropagation()
+
+      if (this.player_.paused() || this.player_.ended()) {
+        this.player_.play()
+        return
+      }
+
+      this.player_.pause()
+    })
+
+    container.appendChild(mainButton)
+
+    return container
+  }
+}
+
+videojs.registerComponent('PeerTubeMobileButtons', PeerTubeMobileButtons)
diff --git a/client/src/assets/player/mobile/peertube-mobile-plugin.ts b/client/src/assets/player/mobile/peertube-mobile-plugin.ts
new file mode 100644 (file)
index 0000000..b3834e2
--- /dev/null
@@ -0,0 +1,16 @@
+import videojs from 'video.js'
+import './peertube-mobile-buttons'
+
+const Plugin = videojs.getPlugin('plugin')
+
+class PeerTubeMobilePlugin extends Plugin {
+
+  constructor (player: videojs.Player, options: videojs.PlayerOptions) {
+    super(player, options)
+
+    player.addChild('PeerTubeMobileButtons')
+  }
+}
+
+videojs.registerPlugin('peertubeMobile', PeerTubeMobilePlugin)
+export { PeerTubeMobilePlugin }
index ac8134fa8ce9b24db51f69e6ba044a16c0aa8de6..6b6c1e5815b2b97110be0e697f7d1294edded426 100644 (file)
@@ -21,6 +21,7 @@ import './videojs-components/settings-panel'
 import './videojs-components/settings-panel-child'
 import './videojs-components/theater-button'
 import './playlist/playlist-plugin'
+import './mobile/peertube-mobile-plugin'
 import videojs from 'video.js'
 import { HlsJsEngineSettings } from '@peertube/p2p-media-loader-hlsjs'
 import { PluginsManager } from '@root-helpers/plugins-manager'
@@ -43,7 +44,7 @@ import {
   VideoJSPluginOptions
 } from './peertube-videojs-typings'
 import { TranslationsManager } from './translations-manager'
-import { buildVideoOrPlaylistEmbed, getRtcConfig, isIOS, isSafari } from './utils'
+import { buildVideoOrPlaylistEmbed, getRtcConfig, isIOS, isMobile, isSafari } from './utils'
 
 // Change 'Playback Rate' to 'Speed' (smaller for our settings menu)
 (videojs.getComponent('PlaybackRateMenuButton') as any).prototype.controlText_ = 'Speed'
@@ -189,7 +190,10 @@ export class PeertubePlayerManager {
           videoEmbedTitle: options.common.embedTitle
         })
 
+        if (isMobile()) player.peertubeMobile()
+
         player.bezels()
+
         player.stats({
           videoUUID: options.common.videoUUID,
           videoIsLive: options.common.isLive,
index 451b4a161ffeae73dbc5be64e5b850acbdf2cf75..272f5353da0048b5b015493913f90af943210d88 100644 (file)
@@ -12,6 +12,9 @@ import {
 import { PeerTubePluginOptions, UserWatching, VideoJSCaption } from './peertube-videojs-typings'
 import { isMobile } from './utils'
 import { SettingsButton } from './videojs-components/settings-menu-button'
+import debug from 'debug'
+
+const logger = debug('peertube:player:peertube')
 
 const Plugin = videojs.getPlugin('plugin')
 
@@ -233,7 +236,7 @@ class PeerTubePlugin extends Plugin {
   }
 
   private alterInactivity () {
-    if (this.menuOpened || this.mouseInSettings || this.mouseInControlBar || this.isTouchEnabled()) {
+    if (this.menuOpened || this.mouseInSettings || this.mouseInControlBar) {
       this.setInactivityTimeout(0)
       return
     }
@@ -245,6 +248,8 @@ class PeerTubePlugin extends Plugin {
   private setInactivityTimeout (timeout: number) {
     (this.player as any).cache_.inactivityTimeout = timeout
     this.player.options_.inactivityTimeout = timeout
+
+    logger('Set player inactivity to ' + timeout)
   }
 
   private isTouchEnabled () {
index f97d7a208ded263d1bc4a94bcacea0c2f9174435..e4013d8151e292ceb6a2cd3e4b0e43055a9cdbaa 100644 (file)
@@ -42,6 +42,8 @@ declare module 'video.js' {
 
     bezels (): void
 
+    peertubeMobile (): void
+
     stats (options?: StatsCardOptions): StatsForNerdsPlugin
 
     textTracks (): TextTrackList & {
index 228231a225ac4192cbd2d579c33b25210ece4f45..fe17ce2cef29e234c9764a824a488ba146757cc8 100644 (file)
@@ -40,7 +40,6 @@ class NextPreviousVideoButton extends Button {
 
   update () {
     const disabled = this.nextPreviousVideoButtonOptions.isDisabled()
-    console.log(disabled)
 
     if (disabled) this.addClass('vjs-disabled')
     else this.removeClass('vjs-disabled')
index 2625576d4db61e1a206686196adf698e707ead4c..dec3fe911e9fe909975607d7140f1ef1ea1d9878 100644 (file)
@@ -8,11 +8,14 @@ $font-size: 13px;
 $control-bar-height: 38px;
 $control-bar-icon-size: 26px;
 $control-bar-volume-slider-height: 14px;
+$control-bar-slider-top: -10px;
 $control-bar-font-size: 14px;
 $control-bar-play-font-size: 34px;
 $control-bar-next-previous-play-font-size: 14px;
 $control-bar-button-width: 38px;
 
+$control-bar-total-height: $control-bar-height - $control-bar-slider-top;
+
 $slider-bg-color: lighten($primary-background-color, 33%);
 
 $progress-margin: 10px;
index b3a96510ab4349b5d07ee06e176f7661947564fc..c4e1283f8fa066f4f6f97fd55e1c047404413799 100644 (file)
@@ -4,6 +4,8 @@
 @use './_player-variables' as *;
 
 .video-js.vjs-peertube-skin .vjs-control-bar {
+  z-index: 100;
+
   height: $control-bar-height;
   background: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.6));
   box-shadow: 0 -15px 40px 10px rgba(0, 0, 0, 0.2);
@@ -49,7 +51,7 @@
     @include margin-left($progress-margin);
 
     position: absolute;
-    top: -10px;
+    top: $control-bar-slider-top;
     z-index: 100; // On top of the progress bar
     width: calc(100% - (2 * #{$progress-margin}));
     height: 14px;
index 86c0902005a2c73c1e308b1a608d43f91d30096f..d72dc41df319adf217fb017d55d8fbc30b1e3b57 100644 (file)
@@ -1,5 +1,7 @@
+@use 'sass:math';
 @use '_variables' as *;
 @use '_mixins' as *;
+@use './_player-variables' as *;
 
 /* Special mobile style */
 
     }
   }
 }
+
+.vjs-mobile-buttons-overlay {
+  display: none;
+
+  position: absolute;
+  background-color: rgba(0, 0, 0, 0.4);
+  width: 100%;
+  height: 100%;
+  top: 0;
+
+  .vjs-user-active,
+  .vjs-paused {
+    display: block;
+  }
+
+  .main-button {
+    font-family: VideoJS;
+    font-weight: normal;
+    font-style: normal;
+    font-size: 5em;
+    width: fit-content;
+    margin: auto;
+    position: relative;
+    top: calc(50% - 10px);
+    transform: translateY(-50%);
+  }
+}
+
+.vjs-paused {
+  .main-button {
+    &:before {
+      content: '\f101';
+    }
+  }
+}
+
+.vjs-playing {
+  .main-button {
+    &:before {
+      content: '\f103';
+    }
+  }
+}
+
+.vjs-ended {
+  .main-button {
+    &:before {
+      content: '\f116';
+    }
+  }
+}
+
+.vjs-has-started {
+
+  &.vjs-user-active,
+  &.vjs-paused {
+    .vjs-mobile-buttons-overlay {
+      display: block;
+    }
+  }
+
+  &.vjs-seeking,
+  &.vjs-scrubbing,
+  &.vjs-waiting {
+    .vjs-mobile-buttons-overlay {
+      display: none;
+    }
+  }
+}
index 5a476259e105762b2da9e4692da589dc31a10b21..8aa2c2ac3ecc5ed0dcdd85f88c8b7526f0cad110 100644 (file)
@@ -22,6 +22,7 @@ $setting-transition-easing: ease-out;
     opacity: $primary-foreground-opacity;
     margin: 0 auto;
     font-size: $font-size !important;
+    z-index: 100;
 
     width: auto;
     overflow: hidden;