]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Speedup embed first paint
authorChocobozzz <me@florianbigard.com>
Tue, 17 Dec 2019 10:20:24 +0000 (11:20 +0100)
committerChocobozzz <me@florianbigard.com>
Wed, 18 Dec 2019 09:14:22 +0000 (10:14 +0100)
client/src/app/videos/+video-watch/comment/video-comment-add.component.ts
client/src/assets/player/peertube-player-manager.ts
client/src/assets/player/translations-manager.ts [new file with mode: 0644]
client/src/standalone/videos/embed-api.ts
client/src/standalone/videos/embed.html
client/src/standalone/videos/embed.scss
client/src/standalone/videos/embed.ts
scripts/client-report.sh

index 083509b832b1adc1fdeb10bed3d49a7ab4d19137..1be96ad9e85b5d96551db98254e21fc01a810271 100644 (file)
@@ -137,6 +137,10 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit {
     this.router.navigate([ '/login' ])
   }
 
+  cancelCommentReply () {
+    this.cancel.emit(null)
+  }
+
   private addCommentReply (commentCreate: VideoCommentCreate) {
     return this.videoCommentService
       .addCommentReply(this.video.id, this.parentComment.id, commentCreate)
@@ -146,8 +150,4 @@ export class VideoCommentAddComponent extends FormReactive implements OnInit {
     return this.videoCommentService
       .addCommentThread(this.video.id, commentCreate)
   }
-
-  private cancelCommentReply () {
-    this.cancel.emit(null)
-  }
 }
index 2f4e0ac1a03ca30c9e77ac855dffc054cee61e76..b1551185a55b2c3431ac992a87b091caa6d10880 100644 (file)
@@ -15,11 +15,12 @@ import './videojs-components/peertube-load-progress-bar'
 import './videojs-components/theater-button'
 import { P2PMediaLoaderPluginOptions, UserWatching, VideoJSCaption, VideoJSPluginOptions, videojsUntyped } from './peertube-videojs-typings'
 import { buildVideoEmbed, buildVideoLink, copyToClipboard, getRtcConfig } from './utils'
-import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '../../../../shared/models/i18n/i18n'
+import { isDefaultLocale } from '../../../../shared/models/i18n/i18n'
 import { segmentValidatorFactory } from './p2p-media-loader/segment-validator'
 import { segmentUrlBuilderFactory } from './p2p-media-loader/segment-url-builder'
 import { RedundancyUrlManager } from './p2p-media-loader/redundancy-url-manager'
 import { getStoredP2PEnabled } from './peertube-player-local-storage'
+import { TranslationsManager } from './translations-manager'
 
 // Change 'Playback Rate' to 'Speed' (smaller for our settings menu)
 videojsUntyped.getComponent('PlaybackRateMenuButton').prototype.controlText_ = 'Speed'
@@ -86,24 +87,9 @@ export type PeertubePlayerManagerOptions = {
 }
 
 export class PeertubePlayerManager {
-
-  private static videojsLocaleCache: { [ path: string ]: any } = {}
   private static playerElementClassName: string
   private static onPlayerChange: (player: any) => void
 
-  static getServerTranslations (serverUrl: string, locale: string) {
-    const path = PeertubePlayerManager.getLocalePath(serverUrl, locale)
-    // It is the default locale, nothing to translate
-    if (!path) return Promise.resolve(undefined)
-
-    return fetch(path + '/server.json')
-      .then(res => res.json())
-      .catch(err => {
-        console.error('Cannot get server translations', err)
-        return undefined
-      })
-  }
-
   static async initialize (mode: PlayerMode, options: PeertubePlayerManagerOptions, onPlayerChange: (player: any) => void) {
     let p2pMediaLoader: any
 
@@ -120,7 +106,7 @@ export class PeertubePlayerManager {
 
     const videojsOptions = this.getVideojsOptions(mode, options, p2pMediaLoader)
 
-    await this.loadLocaleInVideoJS(options.common.serverUrl, options.common.language)
+    await TranslationsManager.loadLocaleInVideoJS(options.common.serverUrl, options.common.language, videojs)
 
     const self = this
     return new Promise(res => {
@@ -181,32 +167,6 @@ export class PeertubePlayerManager {
     })
   }
 
-  private static loadLocaleInVideoJS (serverUrl: string, locale: string) {
-    const path = PeertubePlayerManager.getLocalePath(serverUrl, locale)
-    // It is the default locale, nothing to translate
-    if (!path) return Promise.resolve(undefined)
-
-    let p: Promise<any>
-
-    if (PeertubePlayerManager.videojsLocaleCache[path]) {
-      p = Promise.resolve(PeertubePlayerManager.videojsLocaleCache[path])
-    } else {
-      p = fetch(path + '/player.json')
-        .then(res => res.json())
-        .then(json => {
-          PeertubePlayerManager.videojsLocaleCache[path] = json
-          return json
-        })
-        .catch(err => {
-          console.error('Cannot get player translations', err)
-          return undefined
-        })
-    }
-
-    const completeLocale = getCompleteLocale(locale)
-    return p.then(json => videojs.addLanguage(getShortLocale(completeLocale), json))
-  }
-
   private static getVideojsOptions (mode: PlayerMode, options: PeertubePlayerManagerOptions, p2pMediaLoaderModule?: any) {
     const commonOptions = options.common
 
@@ -519,14 +479,6 @@ export class PeertubePlayerManager {
       }
     })
   }
-
-  private static getLocalePath (serverUrl: string, locale: string) {
-    const completeLocale = getCompleteLocale(locale)
-
-    if (!is18nLocale(completeLocale) || isDefaultLocale(completeLocale)) return undefined
-
-    return serverUrl + '/client/locales/' + completeLocale
-  }
 }
 
 // ############################################################################
diff --git a/client/src/assets/player/translations-manager.ts b/client/src/assets/player/translations-manager.ts
new file mode 100644 (file)
index 0000000..e9f300c
--- /dev/null
@@ -0,0 +1,52 @@
+import { getCompleteLocale, getShortLocale, is18nLocale, isDefaultLocale } from '../../../../shared/models'
+
+export class TranslationsManager {
+  private static videojsLocaleCache: { [ path: string ]: any } = {}
+
+  static getServerTranslations (serverUrl: string, locale: string) {
+    const path = TranslationsManager.getLocalePath(serverUrl, locale)
+    // It is the default locale, nothing to translate
+    if (!path) return Promise.resolve(undefined)
+
+    return fetch(path + '/server.json')
+      .then(res => res.json())
+      .catch(err => {
+        console.error('Cannot get server translations', err)
+        return undefined
+      })
+  }
+
+  static loadLocaleInVideoJS (serverUrl: string, locale: string, videojs: any) {
+    const path = TranslationsManager.getLocalePath(serverUrl, locale)
+    // It is the default locale, nothing to translate
+    if (!path) return Promise.resolve(undefined)
+
+    let p: Promise<any>
+
+    if (TranslationsManager.videojsLocaleCache[ path ]) {
+      p = Promise.resolve(TranslationsManager.videojsLocaleCache[ path ])
+    } else {
+      p = fetch(path + '/player.json')
+        .then(res => res.json())
+        .then(json => {
+          TranslationsManager.videojsLocaleCache[ path ] = json
+          return json
+        })
+        .catch(err => {
+          console.error('Cannot get player translations', err)
+          return undefined
+        })
+    }
+
+    const completeLocale = getCompleteLocale(locale)
+    return p.then(json => videojs.addLanguage(getShortLocale(completeLocale), json))
+  }
+
+  private static getLocalePath (serverUrl: string, locale: string) {
+    const completeLocale = getCompleteLocale(locale)
+
+    if (!is18nLocale(completeLocale) || isDefaultLocale(completeLocale)) return undefined
+
+    return serverUrl + '/client/locales/' + completeLocale
+  }
+}
index 169e371da992fe8fbada4e91e668eb120458d110..259113215ba3177aeea9794884ba5d4f84aad1da 100644 (file)
@@ -43,7 +43,6 @@ export class PeerTubeEmbedApi {
     channel.bind('setPlaybackRate', (txn, playbackRate) => this.embed.player.playbackRate(playbackRate))
     channel.bind('getPlaybackRate', (txn, params) => this.embed.player.playbackRate())
     channel.bind('getPlaybackRates', (txn, params) => this.embed.playerOptions.playbackRates)
-
     this.channel = channel
   }
 
index 5a15bf552e845ad41cf5fbfe5fe8de4e9b99901e..6edf71f48680f73eaaabfbdf31651abb2b5f0490 100644 (file)
@@ -22,5 +22,7 @@
     <video playsinline="true" id="video-container" class="video-js vjs-peertube-skin">
     </video>
 
+    <div id="placeholder-preview" />
+
   </body>
 </html>
index c40ea12080a133e6f3e8e20f20e91352e29758c8..95573dabeb06b403b0fc41e805e2b67b962f0ba6 100644 (file)
@@ -79,6 +79,16 @@ html, body {
   }
 }
 
+#placeholder-preview {
+  position: absolute;
+  top: 0;
+  left: 0;
+  background-size: 100% auto;
+  width: 100%;
+  height: 100%;
+  background-position: 50% 50%;
+}
+
 @media screen and (max-width: 300px) {
   #error-block {
     font-size: 36px;
index bd012f5065af26a28debc07049711bd1fa78c992..f33dd8869ff38c1b4346270eb016d4ce1445f68e 100644 (file)
@@ -1,16 +1,24 @@
 import './embed.scss'
 
-import { peertubeTranslate, ResultList, ServerConfig, VideoDetails } from '../../../../shared'
+import {
+  getCompleteLocale,
+  is18nLocale,
+  isDefaultLocale,
+  peertubeTranslate,
+  ResultList,
+  ServerConfig,
+  VideoDetails
+} from '../../../../shared'
 import { VideoJSCaption } from '../../assets/player/peertube-videojs-typings'
 import { VideoCaption } from '../../../../shared/models/videos/caption/video-caption.model'
 import {
   P2PMediaLoaderOptions,
-  PeertubePlayerManager,
   PeertubePlayerManagerOptions,
   PlayerMode
 } from '../../assets/player/peertube-player-manager'
 import { VideoStreamingPlaylistType } from '../../../../shared/models/videos/video-streaming-playlist.type'
 import { PeerTubeEmbedApi } from './embed-api'
+import { TranslationsManager } from '../../assets/player/translations-manager'
 
 export class PeerTubeEmbed {
   videoElement: HTMLVideoElement
@@ -154,20 +162,30 @@ export class PeerTubeEmbed {
     const urlParts = window.location.pathname.split('/')
     const videoId = urlParts[ urlParts.length - 1 ]
 
-    const [ serverTranslations, videoResponse, captionsResponse, configResponse ] = await Promise.all([
-      PeertubePlayerManager.getServerTranslations(window.location.origin, navigator.language),
-      this.loadVideoInfo(videoId),
-      this.loadVideoCaptions(videoId),
-      this.loadConfig()
-    ])
+    const videoPromise = this.loadVideoInfo(videoId)
+    const captionsPromise = this.loadVideoCaptions(videoId)
+    const configPromise = this.loadConfig()
+
+    const translationsPromise = TranslationsManager.getServerTranslations(window.location.origin, navigator.language)
+    const videoResponse = await videoPromise
 
     if (!videoResponse.ok) {
+      const serverTranslations = await translationsPromise
+
       if (videoResponse.status === 404) return this.videoNotFound(serverTranslations)
 
       return this.videoFetchError(serverTranslations)
     }
 
     const videoInfo: VideoDetails = await videoResponse.json()
+    this.loadPlaceholder(videoInfo)
+
+    const PeertubePlayerManagerModulePromise = import('../../assets/player/peertube-player-manager')
+
+    const promises = [ translationsPromise, captionsPromise, configPromise, PeertubePlayerManagerModulePromise ]
+    const [ serverTranslations, captionsResponse, configResponse, PeertubePlayerManagerModule ] = await Promise.all(promises)
+
+    const PeertubePlayerManager = PeertubePlayerManagerModule.PeertubePlayerManager
     const videoCaptions = await this.buildCaptions(serverTranslations, captionsResponse)
 
     this.loadParams(videoInfo)
@@ -220,7 +238,7 @@ export class PeerTubeEmbed {
       })
     }
 
-    this.player = await PeertubePlayerManager.initialize(this.mode, options, player => this.player = player)
+    this.player = await PeertubePlayerManager.initialize(this.mode, options, (player: any) => this.player = player)
     this.player.on('customError', (event: any, data: any) => this.handleError(data.err, serverTranslations))
 
     window[ 'videojsPlayer' ] = this.player
@@ -230,6 +248,8 @@ export class PeerTubeEmbed {
     await this.buildDock(videoInfo, configResponse)
 
     this.initializeApi()
+
+    this.removePlaceholder()
   }
 
   private handleError (err: Error, translations?: { [ id: string ]: string }) {
@@ -282,6 +302,22 @@ export class PeerTubeEmbed {
 
     return []
   }
+
+  private loadPlaceholder (video: VideoDetails) {
+    const placeholder = this.getPlaceholderElement()
+
+    const url = window.location.origin + video.previewPath
+    placeholder.style.backgroundImage = `url("${url}")`
+  }
+
+  private removePlaceholder () {
+    const placeholder = this.getPlaceholderElement()
+    placeholder.parentElement.removeChild(placeholder)
+  }
+
+  private getPlaceholderElement () {
+    return document.getElementById('placeholder-preview')
+  }
 }
 
 PeerTubeEmbed.main()
index a758a211c22adb516d4a6afd41688a3e92940a20..76609686b9188ba0bad0541c66e6786c09d3028b 100755 (executable)
@@ -5,5 +5,5 @@ set -eu
 gawk -i inplace 'BEGIN { found=0 } { if (found || $0 ~ /^{/) { found=1; print }}' ./client/dist/embed-stats.json
 
 npm run concurrently -- -k \
-    "cd client && npm run webpack-bundle-analyzer -- -p 8888 ./dist/en_US/stats-es2015.json" \
+    "cd client && npm run webpack-bundle-analyzer -- -p 8888 ./dist/en-US/stats-es2015.json" \
     "cd client && npm run webpack-bundle-analyzer -- -p 8889 ./dist/embed-stats.json"