]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Add live autostart/messages in embed
authorChocobozzz <me@florianbigard.com>
Tue, 31 May 2022 12:18:41 +0000 (14:18 +0200)
committerChocobozzz <me@florianbigard.com>
Tue, 31 May 2022 12:24:07 +0000 (14:24 +0200)
client/src/assets/player/shared/webtorrent/webtorrent-plugin.ts
client/src/sass/player/peertube-skin.scss
client/src/standalone/videos/embed.scss
client/src/standalone/videos/embed.ts
client/src/standalone/videos/shared/index.ts
client/src/standalone/videos/shared/live-manager.ts [new file with mode: 0644]
client/src/standalone/videos/shared/player-html.ts
server/lib/client-html.ts

index b482031483be2fd34bb92dea1a86101a6c9f3dd7..83b483d876eef4942fd6e5005476c91f97997aa1 100644 (file)
@@ -430,6 +430,11 @@ class WebTorrentPlugin extends Plugin {
   private initializePlayer () {
     this.buildQualities()
 
+    if (this.videoFiles.length === 0) {
+      this.player.addClass('disabled')
+      return
+    }
+
     if (this.autoplay) {
       this.player.posterImage.hide()
 
index c420e825e9ec5dbacc6912c6d0613cbdd5de3f52..43c1446242f3ffc6e3b30897ea1001d6c365eb2d 100644 (file)
@@ -20,6 +20,15 @@ body {
   font-size: $font-size;
   color: pvar(--embedForegroundColor);
 
+  &.disabled {
+    cursor: default;
+    pointer-events: none;
+
+    .vjs-big-play-button {
+      display: none !important;
+    }
+  }
+
   .vjs-audio-button {
     display: none;
   }
index 91ab822c8409bdedf3be83680f67c4eca7407b1f..8c20bae795baa34307571462233caf10bd89e316 100644 (file)
@@ -92,6 +92,17 @@ body {
   width: 100%;
   height: 100%;
   background-position: 50% 50%;
+  background-repeat: no-repeat;
+}
+
+.player-information {
+  width: 100%;
+  color: #fff;
+  background: rgba(0, 0, 0, 0.6);
+  padding: 20px 0;
+  position: absolute;
+  bottom: 0;
+  text-align: center;
 }
 
 @media screen and (max-width: 300px) {
index c5d017d4af6184ec2fb7048e784727e9a70634ba..0a2b0ccbde7ae82a789f914757a575e509722405 100644 (file)
@@ -4,12 +4,12 @@ import '../../assets/player/shared/dock/peertube-dock-plugin'
 import videojs from 'video.js'
 import { peertubeTranslate } from '../../../../shared/core-utils/i18n'
 import { HTMLServerConfig, LiveVideo, ResultList, VideoDetails, VideoPlaylist, VideoPlaylistElement } from '../../../../shared/models'
+import { PeertubePlayerManager } from '../../assets/player'
 import { TranslationsManager } from '../../assets/player/translations-manager'
 import { getParamString } from '../../root-helpers'
 import { PeerTubeEmbedApi } from './embed-api'
-import { AuthHTTP, PeerTubePlugin, PlayerManagerOptions, PlaylistFetcher, PlaylistTracker, VideoFetcher } from './shared'
+import { AuthHTTP, LiveManager, PeerTubePlugin, PlayerManagerOptions, PlaylistFetcher, PlaylistTracker, VideoFetcher } from './shared'
 import { PlayerHTML } from './shared/player-html'
-import { PeertubePlayerManager } from '../../assets/player'
 
 export class PeerTubeEmbed {
   player: videojs.Player
@@ -26,6 +26,7 @@ export class PeerTubeEmbed {
   private readonly peertubePlugin: PeerTubePlugin
   private readonly playerHTML: PlayerHTML
   private readonly playerManagerOptions: PlayerManagerOptions
+  private readonly liveManager: LiveManager
 
   private playlistTracker: PlaylistTracker
 
@@ -37,6 +38,7 @@ export class PeerTubeEmbed {
     this.peertubePlugin = new PeerTubePlugin(this.http)
     this.playerHTML = new PlayerHTML(videoWrapperId)
     this.playerManagerOptions = new PlayerManagerOptions(this.playerHTML, this.videoFetcher, this.peertubePlugin)
+    this.liveManager = new LiveManager(this.playerHTML)
 
     try {
       this.config = JSON.parse(window['PeerTubeServerConfig'])
@@ -235,6 +237,17 @@ export class PeerTubeEmbed {
     }
 
     this.peertubePlugin.getPluginsManager().runHook('action:embed.player.loaded', undefined, { player: this.player, videojs, video })
+
+    if (video.isLive) {
+      this.liveManager.displayInfoAndListenForChanges({
+        video,
+        translations,
+        onPublishedVideo: () => {
+          this.liveManager.stopListeningForChanges(video)
+          this.loadVideoAndBuildPlayer(video.uuid)
+        }
+      })
+    }
   }
 
   private resetPlayerElement () {
index 4b4e05b7cc6761447e906af4792c66f47fec080f..928b8e270773f0e476e97954a7591037d8f72a97 100644 (file)
@@ -1,5 +1,6 @@
 export * from './auth-http'
 export * from './peertube-plugin'
+export * from './live-manager'
 export * from './player-html'
 export * from './player-manager-options'
 export * from './playlist-fetcher'
diff --git a/client/src/standalone/videos/shared/live-manager.ts b/client/src/standalone/videos/shared/live-manager.ts
new file mode 100644 (file)
index 0000000..422d397
--- /dev/null
@@ -0,0 +1,69 @@
+import { Socket } from 'socket.io-client'
+import { LiveVideoEventPayload, VideoDetails, VideoState } from '../../../../../shared/models'
+import { PlayerHTML } from './player-html'
+import { Translations } from './translations'
+
+export class LiveManager {
+  private liveSocket: Socket
+
+  constructor (
+    private readonly playerHTML: PlayerHTML
+  ) {
+
+  }
+
+  async displayInfoAndListenForChanges (options: {
+    video: VideoDetails
+    translations: Translations
+    onPublishedVideo: () => any
+  }) {
+    const { video, onPublishedVideo } = options
+
+    this.displayAppropriateInfo(options)
+
+    if (!this.liveSocket) {
+      const io = (await import('socket.io-client')).io
+      this.liveSocket = io(window.location.origin + '/live-videos')
+    }
+
+    this.liveSocket.on('state-change', (payload: LiveVideoEventPayload) => {
+      if (payload.state === VideoState.PUBLISHED) {
+        this.playerHTML.removeInformation()
+        onPublishedVideo()
+        return
+      }
+    })
+
+    this.liveSocket.emit('subscribe', { videoId: video.id })
+  }
+
+  stopListeningForChanges (video: VideoDetails) {
+    this.liveSocket.emit('unsubscribe', { videoId: video.id })
+  }
+
+  private displayAppropriateInfo (options: {
+    video: VideoDetails
+    translations: Translations
+  }) {
+    const { video, translations } = options
+
+    if (video.state.id === VideoState.WAITING_FOR_LIVE) {
+      this.displayWaitingForLiveInfo(translations)
+      return
+    }
+
+    if (video.state.id === VideoState.LIVE_ENDED) {
+      this.displayEndedLiveInfo(translations)
+      return
+    }
+  }
+
+  private displayWaitingForLiveInfo (translations: Translations) {
+    this.playerHTML.displayInformation('This live has not started yet.', translations)
+  }
+
+  private displayEndedLiveInfo (translations: Translations) {
+    this.playerHTML.displayInformation('This live has ended.', translations)
+
+  }
+}
index 110124417921b62ebcf67fc43cfe443c97082cbc..eb6324ac70b970752ae4e2a098354b23a989d7a9 100644 (file)
@@ -6,6 +6,7 @@ export class PlayerHTML {
   private readonly wrapperElement: HTMLElement
 
   private playerElement: HTMLVideoElement
+  private informationElement: HTMLDivElement
 
   constructor (private readonly videoWrapperId: string) {
     this.wrapperElement = document.getElementById(this.videoWrapperId)
@@ -66,6 +67,20 @@ export class PlayerHTML {
     placeholder.style.display = 'none'
   }
 
+  displayInformation (text: string, translations: Translations) {
+    if (this.informationElement) this.removeInformation()
+
+    this.informationElement = document.createElement('div')
+    this.informationElement.className = 'player-information'
+    this.informationElement.innerText = peertubeTranslate(text, translations)
+
+    document.body.appendChild(this.informationElement)
+  }
+
+  removeInformation () {
+    this.removeElement(this.informationElement)
+  }
+
   private getPlaceholderElement () {
     return document.getElementById('placeholder-preview')
   }
index 337364ac9c324f3a08568e10b2f31d1e6c7535a3..1e8d030230cd18e90a271a7c6b0e55aeb5873052 100644 (file)
@@ -30,6 +30,7 @@ import { MAccountActor, MChannelActor } from '../types/models'
 import { getActivityStreamDuration } from './activitypub/activity'
 import { getBiggestActorImage } from './actor-image'
 import { ServerConfigManager } from './server-config-manager'
+import { isTestInstance } from '@server/helpers/core-utils'
 
 type Tags = {
   ogType: string
@@ -232,7 +233,10 @@ class ClientHtml {
   static async getEmbedHTML () {
     const path = ClientHtml.getEmbedPath()
 
-    if (ClientHtml.htmlCache[path]) return ClientHtml.htmlCache[path]
+    // Disable HTML cache in dev mode because webpack can regenerate JS files
+    if (!isTestInstance() && ClientHtml.htmlCache[path]) {
+      return ClientHtml.htmlCache[path]
+    }
 
     const buffer = await readFile(path)
     const serverConfig = await ServerConfigManager.Instance.getHTMLServerConfig()