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,
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 () {
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
}
serverUrl: environment.apiUrl,
- videoCaptions: playerCaptions
+ videoCaptions: playerCaptions,
+
+ videoUUID: video.uuid
},
webtorrent: {
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 {
saveAverageBandwidth,
getAverageBandwidthInStore,
saveLastSubtitle,
- getStoredLastSubtitle
+ getStoredLastSubtitle,
+ saveVideoWatchHistory,
+ getStoredVideoWatchHistory,
+ cleanupVideoWatch
}
// ---------------------------------------------------------------------------
videoCaptions: VideoJSCaption[]
+ videoUUID: string
+
userWatching?: UserWatching
serverUrl: string
subtitle: commonOptions.subtitle,
videoCaptions: commonOptions.videoCaptions,
stopTime: commonOptions.stopTime,
- isLive: commonOptions.isLive
+ isLive: commonOptions.isLive,
+ videoUUID: commonOptions.videoUUID
}
}
getStoredVolume,
saveLastSubtitle,
saveMuteInStore,
+ saveVideoWatchHistory,
saveVolumeInStore
} from './peertube-player-local-storage'
this.initializePlayer()
this.runViewAdd()
- if (options.userWatching) this.runUserWatchVideo(options.userWatching)
+ this.runUserWatchVideo(options.userWatching, options.videoUUID)
})
}
}, 1000)
}
- private runUserWatchVideo (options: UserWatching) {
+ private runUserWatchVideo (options: UserWatching, videoUUID: string) {
let lastCurrentTime = 0
this.userWatchingVideoInterval = setInterval(() => {
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)
}
stopTime: number | string
isLive: boolean
+
+ videoUUID: string
}
type PlaylistPluginOptions = {
videoCaptions,
inactivityTimeout: 2500,
videoViewUrl: this.getVideoUrl(videoInfo.uuid) + '/views',
+ videoUUID: videoInfo.uuid,
isLive: videoInfo.isLive,