]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Resume videos for non-logged in users (#3885)
authorkontrollanten <6680299+kontrollanten@users.noreply.github.com>
Wed, 31 Mar 2021 09:26:32 +0000 (11:26 +0200)
committerGitHub <noreply@github.com>
Wed, 31 Mar 2021 09:26:32 +0000 (11:26 +0200)
* client: resume videos for non-logged in users

closes #3866

* fix build for embeded

* Update client/src/app/app.component.ts

* fix review comments

client/src/app/+videos/+video-watch/video-watch.component.ts
client/src/assets/player/peertube-player-local-storage.ts
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/standalone/videos/embed.ts

index 571d1e99a4a47409fa1ebedb59a98d64300f85ce..075f70f56dbca3dfd91f6ea4bf4a706c56727a55 100644 (file)
@@ -29,7 +29,7 @@ import { MetaService } from '@ngx-meta/core'
 import { peertubeLocalStorage } from '@root-helpers/peertube-web-storage'
 import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
 import { ServerConfig, ServerErrorCode, UserVideoRateType, VideoCaption, VideoPrivacy, VideoState } from '@shared/models'
-import { getStoredP2PEnabled, getStoredTheater } from '../../../assets/player/peertube-player-local-storage'
+import { cleanupVideoWatch, getStoredP2PEnabled, getStoredTheater, getStoredVideoWatchHistory } from '../../../assets/player/peertube-player-local-storage'
 import {
   CustomizationOptions,
   P2PMediaLoaderOptions,
@@ -195,6 +195,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
     this.theaterEnabled = getStoredTheater()
 
     this.hooks.runAction('action:video-watch.init', 'video-watch')
+
+    setTimeout(cleanupVideoWatch, 1500) // Run in timeout to ensure we're not blocking the UI
   }
 
   ngOnDestroy () {
@@ -768,9 +770,11 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
     const getStartTime = () => {
       const byUrl = urlOptions.startTime !== undefined
       const byHistory = video.userHistory && (!this.playlist || urlOptions.resume !== undefined)
+      const byLocalStorage = getStoredVideoWatchHistory(video.uuid)
 
       if (byUrl) return timeToInt(urlOptions.startTime)
       if (byHistory) return video.userHistory.currentTime
+      if (byLocalStorage) return byLocalStorage.duration
 
       return 0
     }
@@ -828,7 +832,9 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
 
         serverUrl: environment.apiUrl,
 
-        videoCaptions: playerCaptions
+        videoCaptions: playerCaptions,
+
+        videoUUID: video.uuid
       },
 
       webtorrent: {
index 75ccfe6181ef5724c5c88743855292ee53a93af7..cf2cfb472e6b4bbdf80e41e1eecd810847f5ea40 100644 (file)
@@ -68,6 +68,51 @@ function getStoredLastSubtitle () {
   return getLocalStorage('last-subtitle')
 }
 
+function saveVideoWatchHistory(videoUUID: string, duration: number) {
+  return setLocalStorage(`video-watch-history`, JSON.stringify({
+    ...getStoredVideoWatchHistory(),
+    [videoUUID]: {
+      duration,
+      date: `${(new Date()).toISOString()}`
+    }
+  }))
+}
+
+function getStoredVideoWatchHistory(videoUUID?: string) {
+  let data
+
+  try {
+    data = JSON.parse(getLocalStorage('video-watch-history'))
+  } catch (error) {
+    console.error('Cannot parse video watch history from local storage: ', error)
+  }
+
+  data = data || {}
+
+  if (videoUUID) return data[videoUUID]
+
+  return data
+}
+
+function cleanupVideoWatch() {
+  const data = getStoredVideoWatchHistory()
+
+  const newData = Object.keys(data).reduce((acc, videoUUID) => {
+    const date = Date.parse(data[videoUUID].date)
+
+    const diff = Math.ceil(((new Date()).getTime() - date) / (1000 * 3600 * 24))
+
+    if (diff > 30) return acc
+
+    return {
+      ...acc,
+      [videoUUID]: data[videoUUID]
+    }
+  }, {})
+
+  setLocalStorage('video-watch-history', JSON.stringify(newData))
+}
+
 // ---------------------------------------------------------------------------
 
 export {
@@ -81,7 +126,10 @@ export {
   saveAverageBandwidth,
   getAverageBandwidthInStore,
   saveLastSubtitle,
-  getStoredLastSubtitle
+  getStoredLastSubtitle,
+  saveVideoWatchHistory,
+  getStoredVideoWatchHistory,
+  cleanupVideoWatch
 }
 
 // ---------------------------------------------------------------------------
index 1d335805bf56de859c46c399acdb1cf72a5c8669..119dec379098968d2228b95ea7f8d1a0562300d9 100644 (file)
@@ -106,6 +106,8 @@ export interface CommonOptions extends CustomizationOptions {
 
   videoCaptions: VideoJSCaption[]
 
+  videoUUID: string
+
   userWatching?: UserWatching
 
   serverUrl: string
@@ -231,7 +233,8 @@ export class PeertubePlayerManager {
         subtitle: commonOptions.subtitle,
         videoCaptions: commonOptions.videoCaptions,
         stopTime: commonOptions.stopTime,
-        isLive: commonOptions.isLive
+        isLive: commonOptions.isLive,
+        videoUUID: commonOptions.videoUUID
       }
     }
 
index 75a6e662ebec2c260f5e185efc28b24ebbaacb10..07c7e33f6f8ff4ac004571f9e1d57da43437ffa4 100644 (file)
@@ -13,6 +13,7 @@ import {
   getStoredVolume,
   saveLastSubtitle,
   saveMuteInStore,
+  saveVideoWatchHistory,
   saveVolumeInStore
 } from './peertube-player-local-storage'
 
@@ -120,7 +121,7 @@ class PeerTubePlugin extends Plugin {
       this.initializePlayer()
       this.runViewAdd()
 
-      if (options.userWatching) this.runUserWatchVideo(options.userWatching)
+      this.runUserWatchVideo(options.userWatching, options.videoUUID)
     })
   }
 
@@ -178,7 +179,7 @@ class PeerTubePlugin extends Plugin {
     }, 1000)
   }
 
-  private runUserWatchVideo (options: UserWatching) {
+  private runUserWatchVideo (options: UserWatching, videoUUID: string) {
     let lastCurrentTime = 0
 
     this.userWatchingVideoInterval = setInterval(() => {
@@ -187,8 +188,12 @@ class PeerTubePlugin extends Plugin {
       if (currentTime - lastCurrentTime >= 1) {
         lastCurrentTime = currentTime
 
-        this.notifyUserIsWatching(currentTime, options.url, options.authorizationHeader)
-          .catch(err => console.error('Cannot notify user is watching.', err))
+        if (options) {
+          this.notifyUserIsWatching(currentTime, options.url, options.authorizationHeader)
+            .catch(err => console.error('Cannot notify user is watching.', err))
+        } else {
+          saveVideoWatchHistory(videoUUID, currentTime)
+        }
       }
     }, this.CONSTANTS.USER_WATCHING_VIDEO_INTERVAL)
   }
index e5259092c6cdfaac0a056d424f0288faada30062..4a6c8024767cd20f15c45a1e941ba60315879fcf 100644 (file)
@@ -108,6 +108,8 @@ type PeerTubePluginOptions = {
   stopTime: number | string
 
   isLive: boolean
+
+  videoUUID: string
 }
 
 type PlaylistPluginOptions = {
index 614a1cc0b2a4ba261a85781c320090e8a5e36c55..ae8f176b73aa00837c4ca5177ed2b0752c115224 100644 (file)
@@ -531,6 +531,7 @@ export class PeerTubeEmbed {
         videoCaptions,
         inactivityTimeout: 2500,
         videoViewUrl: this.getVideoUrl(videoInfo.uuid) + '/views',
+        videoUUID: videoInfo.uuid,
 
         isLive: videoInfo.isLive,