mirror of
https://github.com/Chocobozzz/PeerTube.git
synced 2024-09-11 21:47:09 +03:00
Stop loop recommendation for anonymous users
This commit is contained in:
parent
671c6c1f96
commit
ada73259ff
@ -9,7 +9,7 @@ import { VideoCommentService } from '@app/shared/shared-video-comment/video-comm
|
|||||||
import { LiveVideoService } from '@app/shared/shared-video-live/live-video.service'
|
import { LiveVideoService } from '@app/shared/shared-video-live/live-video.service'
|
||||||
import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service'
|
import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service'
|
||||||
import { OverviewService } from '../video-list'
|
import { OverviewService } from '../video-list'
|
||||||
import { RecentVideosRecommendationService, RecommendedVideosStore } from './shared'
|
import { VideoRecommendationService } from './shared'
|
||||||
import { VideoWatchComponent } from './video-watch.component'
|
import { VideoWatchComponent } from './video-watch.component'
|
||||||
import { BulkService } from '@app/shared/shared-moderation/bulk.service'
|
import { BulkService } from '@app/shared/shared-moderation/bulk.service'
|
||||||
|
|
||||||
@ -24,8 +24,7 @@ export default [
|
|||||||
VideoBlockService,
|
VideoBlockService,
|
||||||
LiveVideoService,
|
LiveVideoService,
|
||||||
VideoCommentService,
|
VideoCommentService,
|
||||||
RecentVideosRecommendationService,
|
VideoRecommendationService,
|
||||||
RecommendedVideosStore,
|
|
||||||
SearchService,
|
SearchService,
|
||||||
AbuseService,
|
AbuseService,
|
||||||
UserAdminService,
|
UserAdminService,
|
||||||
|
@ -1,4 +1,2 @@
|
|||||||
export * from './recent-videos-recommendation.service'
|
export * from './video-recommendation.service'
|
||||||
export * from './recommendation-info.model'
|
|
||||||
export * from './recommended-videos.component'
|
export * from './recommended-videos.component'
|
||||||
export * from './recommended-videos.store'
|
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
export interface RecommendationInfo {
|
|
||||||
uuid: string
|
|
||||||
tags?: string[]
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { Observable } from 'rxjs'
|
|
||||||
import { RecommendationInfo } from './recommendation-info.model'
|
|
||||||
import { Video } from '@app/shared/shared-main/video/video.model'
|
|
||||||
|
|
||||||
export interface RecommendationService {
|
|
||||||
getRecommendations (recommendation: RecommendationInfo): Observable<Video[]>
|
|
||||||
}
|
|
@ -1,12 +1,14 @@
|
|||||||
<div class="other-videos" [ngClass]="{ 'display-as-row': displayAsRow }">
|
<div class="other-videos" [ngClass]="{ 'display-as-row': displayAsRow }">
|
||||||
<ng-container *ngIf="hasVideos$ | async">
|
@if (videos.length !== 0) {
|
||||||
<div class="title-page-container">
|
<div class="title-page-container">
|
||||||
<h2 i18n class="title-page">Other videos</h2>
|
<h2 i18n class="title-page">Other videos</h2>
|
||||||
|
|
||||||
<div *ngIf="!playlist" class="title-page-autoplay"
|
<div
|
||||||
|
*ngIf="!playlist" class="title-page-autoplay"
|
||||||
[ngbTooltip]="autoPlayNextVideoTooltip" placement="bottom-right auto"
|
[ngbTooltip]="autoPlayNextVideoTooltip" placement="bottom-right auto"
|
||||||
>
|
>
|
||||||
<span i18n>AUTOPLAY</span>
|
<span i18n>AUTOPLAY</span>
|
||||||
|
|
||||||
<my-input-switch
|
<my-input-switch
|
||||||
i18n-label label="Toggle autoplay next video"
|
i18n-label label="Toggle autoplay next video"
|
||||||
class="small" inputName="autoplay-next-video"
|
class="small" inputName="autoplay-next-video"
|
||||||
@ -15,8 +17,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngFor="let video of (videos$ | async); let i = index; let length = count">
|
<ng-container *ngFor="let video of videos; let i = index; let length = count">
|
||||||
<span i18n *ngIf="!playlist && i === 0 && length !== 0 && autoPlayNextVideo" class="title-page-next-video-label">Next video to be played</span>
|
<span i18n *ngIf="!playlist && i === 0 && length !== 0 && autoPlayNextVideo" class="title-page-next-video-label">Next video to be played</span>
|
||||||
|
|
||||||
<my-video-miniature
|
<my-video-miniature
|
||||||
[displayOptions]="displayOptions" [video]="video" [user]="user" [displayAsRow]="displayAsRow"
|
[displayOptions]="displayOptions" [video]="video" [user]="user" [displayAsRow]="displayAsRow"
|
||||||
(videoBlocked)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()" (videoAccountMuted)="onVideoRemoved()"
|
(videoBlocked)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()" (videoAccountMuted)="onVideoRemoved()"
|
||||||
@ -26,5 +29,5 @@
|
|||||||
|
|
||||||
<hr *ngIf="!playlist && i === 0 && length > 1 && autoPlayNextVideo" />
|
<hr *ngIf="!playlist && i === 0 && length > 1 && autoPlayNextVideo" />
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
import { Observable, startWith, Subscription, switchMap } from 'rxjs'
|
import { AsyncPipe, NgClass, NgFor, NgIf } from '@angular/common'
|
||||||
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core'
|
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output } from '@angular/core'
|
||||||
import { AuthService, Notifier, User, UserService } from '@app/core'
|
|
||||||
import { Video } from '@app/shared/shared-main/video/video.model'
|
|
||||||
import { RecommendationInfo } from './recommendation-info.model'
|
|
||||||
import { RecommendedVideosStore } from './recommended-videos.store'
|
|
||||||
import { MiniatureDisplayOptions, VideoMiniatureComponent } from '../../../../shared/shared-video-miniature/video-miniature.component'
|
|
||||||
import { FormsModule } from '@angular/forms'
|
import { FormsModule } from '@angular/forms'
|
||||||
import { InputSwitchComponent } from '../../../../shared/shared-forms/input-switch.component'
|
import { AuthService, Notifier, User, UserService } from '@app/core'
|
||||||
|
import { VideoDetails } from '@app/shared/shared-main/video/video-details.model'
|
||||||
|
import { Video } from '@app/shared/shared-main/video/video.model'
|
||||||
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
|
import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'
|
||||||
import { NgClass, NgIf, NgFor, AsyncPipe } from '@angular/common'
|
|
||||||
import { VideoPlaylist } from '@peertube/peertube-models'
|
import { VideoPlaylist } from '@peertube/peertube-models'
|
||||||
|
import { Subscription, startWith, switchMap } from 'rxjs'
|
||||||
|
import { InputSwitchComponent } from '../../../../shared/shared-forms/input-switch.component'
|
||||||
|
import { MiniatureDisplayOptions, VideoMiniatureComponent } from '../../../../shared/shared-video-miniature/video-miniature.component'
|
||||||
|
import { VideoRecommendationService } from './video-recommendation.service'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-recommended-videos',
|
selector: 'my-recommended-videos',
|
||||||
@ -19,12 +19,14 @@ import { VideoPlaylist } from '@peertube/peertube-models'
|
|||||||
imports: [ NgClass, NgIf, NgbTooltip, InputSwitchComponent, FormsModule, NgFor, VideoMiniatureComponent, AsyncPipe ]
|
imports: [ NgClass, NgIf, NgbTooltip, InputSwitchComponent, FormsModule, NgFor, VideoMiniatureComponent, AsyncPipe ]
|
||||||
})
|
})
|
||||||
export class RecommendedVideosComponent implements OnInit, OnChanges, OnDestroy {
|
export class RecommendedVideosComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
@Input() inputRecommendation: RecommendationInfo
|
@Input() currentVideo: VideoDetails
|
||||||
@Input() playlist: VideoPlaylist
|
@Input() playlist: VideoPlaylist
|
||||||
@Input() displayAsRow: boolean
|
@Input() displayAsRow: boolean
|
||||||
|
|
||||||
@Output() gotRecommendations = new EventEmitter<Video[]>()
|
@Output() gotRecommendations = new EventEmitter<Video[]>()
|
||||||
|
|
||||||
|
videos: Video[] = []
|
||||||
|
|
||||||
autoPlayNextVideo: boolean
|
autoPlayNextVideo: boolean
|
||||||
autoPlayNextVideoTooltip: string
|
autoPlayNextVideoTooltip: string
|
||||||
|
|
||||||
@ -39,19 +41,12 @@ export class RecommendedVideosComponent implements OnInit, OnChanges, OnDestroy
|
|||||||
|
|
||||||
private userSub: Subscription
|
private userSub: Subscription
|
||||||
|
|
||||||
readonly hasVideos$: Observable<boolean>
|
|
||||||
readonly videos$: Observable<Video[]>
|
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private userService: UserService,
|
private userService: UserService,
|
||||||
private authService: AuthService,
|
private authService: AuthService,
|
||||||
private notifier: Notifier,
|
private notifier: Notifier,
|
||||||
private store: RecommendedVideosStore
|
private videoRecommendation: VideoRecommendationService
|
||||||
) {
|
) {
|
||||||
this.videos$ = this.store.recommendations$
|
|
||||||
this.hasVideos$ = this.store.hasRecommendations$
|
|
||||||
this.videos$.subscribe(videos => this.gotRecommendations.emit(videos))
|
|
||||||
|
|
||||||
this.autoPlayNextVideoTooltip = $localize`When active, the next video is automatically played after the current one.`
|
this.autoPlayNextVideoTooltip = $localize`When active, the next video is automatically played after the current one.`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,8 +63,8 @@ export class RecommendedVideosComponent implements OnInit, OnChanges, OnDestroy
|
|||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges () {
|
ngOnChanges () {
|
||||||
if (this.inputRecommendation) {
|
if (this.currentVideo) {
|
||||||
this.store.requestNewRecommendations(this.inputRecommendation)
|
this.loadRecommendations()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,7 +73,7 @@ export class RecommendedVideosComponent implements OnInit, OnChanges, OnDestroy
|
|||||||
}
|
}
|
||||||
|
|
||||||
onVideoRemoved () {
|
onVideoRemoved () {
|
||||||
this.store.requestNewRecommendations(this.inputRecommendation)
|
this.loadRecommendations()
|
||||||
}
|
}
|
||||||
|
|
||||||
switchAutoPlayNextVideo () {
|
switchAutoPlayNextVideo () {
|
||||||
@ -97,4 +92,17 @@ export class RecommendedVideosComponent implements OnInit, OnChanges, OnDestroy
|
|||||||
this.userService.updateMyAnonymousProfile(details)
|
this.userService.updateMyAnonymousProfile(details)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private loadRecommendations () {
|
||||||
|
this.videoRecommendation.getRecommendations(this.currentVideo, this.videoRecommendation.getRecommentationHistory())
|
||||||
|
.subscribe({
|
||||||
|
next: videos => {
|
||||||
|
this.videos = videos
|
||||||
|
|
||||||
|
this.gotRecommendations.emit(this.videos)
|
||||||
|
},
|
||||||
|
|
||||||
|
error: err => this.notifier.error(err.message)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
import { Observable, ReplaySubject } from 'rxjs'
|
|
||||||
import { map, shareReplay, switchMap, take } from 'rxjs/operators'
|
|
||||||
import { Inject, Injectable } from '@angular/core'
|
|
||||||
import { Video } from '@app/shared/shared-main/video/video.model'
|
|
||||||
import { RecentVideosRecommendationService } from './recent-videos-recommendation.service'
|
|
||||||
import { RecommendationInfo } from './recommendation-info.model'
|
|
||||||
import { RecommendationService } from './recommendations.service'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This store is intended to provide data for the RecommendedVideosComponent.
|
|
||||||
*/
|
|
||||||
@Injectable()
|
|
||||||
export class RecommendedVideosStore {
|
|
||||||
public readonly recommendations$: Observable<Video[]>
|
|
||||||
public readonly hasRecommendations$: Observable<boolean>
|
|
||||||
private readonly requestsForLoad$$ = new ReplaySubject<RecommendationInfo>(1)
|
|
||||||
|
|
||||||
constructor (
|
|
||||||
@Inject(RecentVideosRecommendationService) private recommendations: RecommendationService
|
|
||||||
) {
|
|
||||||
this.recommendations$ = this.requestsForLoad$$.pipe(
|
|
||||||
switchMap(requestedRecommendation => {
|
|
||||||
return this.recommendations.getRecommendations(requestedRecommendation)
|
|
||||||
.pipe(take(1))
|
|
||||||
}),
|
|
||||||
shareReplay()
|
|
||||||
)
|
|
||||||
|
|
||||||
this.hasRecommendations$ = this.recommendations$.pipe(
|
|
||||||
map(otherVideos => otherVideos.length > 0)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
requestNewRecommendations (recommend: RecommendationInfo) {
|
|
||||||
this.requestsForLoad$$.next(recommend)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +1,20 @@
|
|||||||
import { Observable, of } from 'rxjs'
|
|
||||||
import { map, switchMap } from 'rxjs/operators'
|
|
||||||
import { Injectable } from '@angular/core'
|
import { Injectable } from '@angular/core'
|
||||||
import { ServerService, UserService } from '@app/core'
|
import { ServerService, UserService } from '@app/core'
|
||||||
import { HTMLServerConfig } from '@peertube/peertube-models'
|
import { VideoDetails } from '@app/shared/shared-main/video/video-details.model'
|
||||||
import { RecommendationInfo } from './recommendation-info.model'
|
|
||||||
import { RecommendationService } from './recommendations.service'
|
|
||||||
import { Video } from '@app/shared/shared-main/video/video.model'
|
import { Video } from '@app/shared/shared-main/video/video.model'
|
||||||
import { VideoService } from '@app/shared/shared-main/video/video.service'
|
import { VideoService } from '@app/shared/shared-main/video/video.service'
|
||||||
import { SearchService } from '@app/shared/shared-search/search.service'
|
|
||||||
import { AdvancedSearch } from '@app/shared/shared-search/advanced-search.model'
|
import { AdvancedSearch } from '@app/shared/shared-search/advanced-search.model'
|
||||||
|
import { SearchService } from '@app/shared/shared-search/search.service'
|
||||||
|
import { HTMLServerConfig } from '@peertube/peertube-models'
|
||||||
|
import { Observable, of } from 'rxjs'
|
||||||
|
import { map, switchMap } from 'rxjs/operators'
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides "recommendations" by providing the most recently uploaded videos.
|
|
||||||
*/
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class RecentVideosRecommendationService implements RecommendationService {
|
export class VideoRecommendationService {
|
||||||
readonly pageSize = 5
|
|
||||||
|
|
||||||
private config: HTMLServerConfig
|
private config: HTMLServerConfig
|
||||||
|
|
||||||
|
private readonly videoIdsHistory = new Set<number>()
|
||||||
|
|
||||||
constructor (
|
constructor (
|
||||||
private videos: VideoService,
|
private videos: VideoService,
|
||||||
private searchService: SearchService,
|
private searchService: SearchService,
|
||||||
@ -28,19 +24,37 @@ export class RecentVideosRecommendationService implements RecommendationService
|
|||||||
this.config = this.serverService.getHTMLConfig()
|
this.config = this.serverService.getHTMLConfig()
|
||||||
}
|
}
|
||||||
|
|
||||||
getRecommendations (recommendation: RecommendationInfo): Observable<Video[]> {
|
getRecommentationHistory () {
|
||||||
|
return this.videoIdsHistory
|
||||||
|
}
|
||||||
|
|
||||||
return this.fetchPage(1, recommendation)
|
getRecommendations (currentVideo: VideoDetails, exceptions = new Set<number>()): Observable<Video[]> {
|
||||||
|
this.videoIdsHistory.add(currentVideo.id)
|
||||||
|
|
||||||
|
// We want 5 results max
|
||||||
|
// +1 to exclude the currentVideo if needed
|
||||||
|
// +exceptions.size to exclude the videos we don't want to include
|
||||||
|
// Cap to 30 results maximum
|
||||||
|
const totalVideos = 5
|
||||||
|
const internalTotalVideos = Math.min(totalVideos + 1 + exceptions.size, 30)
|
||||||
|
|
||||||
|
return this.fetchPage(currentVideo, internalTotalVideos)
|
||||||
.pipe(
|
.pipe(
|
||||||
map(videos => {
|
map(videos => {
|
||||||
const otherVideos = videos.filter(v => v.uuid !== recommendation.uuid)
|
let otherVideos = videos.filter(v => v.uuid !== currentVideo.uuid && !exceptions.has(v.id))
|
||||||
return otherVideos.slice(0, this.pageSize)
|
|
||||||
|
// Stop using exclude list if we excluded all videos
|
||||||
|
if (otherVideos.length === 0 && videos.length !== 0) {
|
||||||
|
otherVideos = videos.filter(v => v.uuid !== currentVideo.uuid)
|
||||||
|
}
|
||||||
|
|
||||||
|
return otherVideos.slice(0, totalVideos)
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fetchPage (page: number, recommendation: RecommendationInfo): Observable<Video[]> {
|
private fetchPage (currentVideo: VideoDetails, totalItems: number): Observable<Video[]> {
|
||||||
const pagination = { currentPage: page, itemsPerPage: this.pageSize + 1 }
|
const pagination = { currentPage: 1, itemsPerPage: totalItems }
|
||||||
|
|
||||||
return this.userService.getAnonymousOrLoggedUser()
|
return this.userService.getAnonymousOrLoggedUser()
|
||||||
.pipe(
|
.pipe(
|
||||||
@ -66,7 +80,7 @@ export class RecentVideosRecommendationService implements RecommendationService
|
|||||||
componentPagination: pagination,
|
componentPagination: pagination,
|
||||||
skipCount: true,
|
skipCount: true,
|
||||||
advancedSearch: new AdvancedSearch({
|
advancedSearch: new AdvancedSearch({
|
||||||
tagsOneOf: recommendation.tags.join(','),
|
tagsOneOf: currentVideo.tags.join(','),
|
||||||
sort: '-publishedAt',
|
sort: '-publishedAt',
|
||||||
searchTarget: 'local',
|
searchTarget: 'local',
|
||||||
nsfw,
|
nsfw,
|
@ -102,7 +102,7 @@
|
|||||||
|
|
||||||
<my-recommended-videos
|
<my-recommended-videos
|
||||||
[displayAsRow]="displayOtherVideosAsRow()"
|
[displayAsRow]="displayOtherVideosAsRow()"
|
||||||
[inputRecommendation]="{ uuid: video.uuid, tags: video.tags }"
|
[currentVideo]="video"
|
||||||
[playlist]="playlist"
|
[playlist]="playlist"
|
||||||
(gotRecommendations)="onRecommendations($event)"
|
(gotRecommendations)="onRecommendations($event)"
|
||||||
></my-recommended-videos>
|
></my-recommended-videos>
|
||||||
|
@ -1,25 +1,34 @@
|
|||||||
import { forkJoin, map, Observable, of, Subscription, switchMap } from 'rxjs'
|
import { NgClass, NgIf, NgTemplateOutlet, PlatformLocation } from '@angular/common'
|
||||||
import { PlatformLocation, NgClass, NgIf, NgTemplateOutlet } from '@angular/common'
|
|
||||||
import { Component, ElementRef, Inject, LOCALE_ID, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core'
|
import { Component, ElementRef, Inject, LOCALE_ID, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core'
|
||||||
import { ActivatedRoute, Router, RouterLink } from '@angular/router'
|
import { ActivatedRoute, Router, RouterLink } from '@angular/router'
|
||||||
import {
|
import {
|
||||||
AuthService,
|
AuthService,
|
||||||
AuthUser,
|
AuthUser,
|
||||||
ConfirmService,
|
ConfirmService,
|
||||||
|
Hotkey,
|
||||||
|
HotkeysService,
|
||||||
|
MetaService,
|
||||||
Notifier,
|
Notifier,
|
||||||
PeerTubeSocket,
|
PeerTubeSocket,
|
||||||
PluginService,
|
PluginService,
|
||||||
RestExtractor,
|
RestExtractor,
|
||||||
ScreenService,
|
ScreenService,
|
||||||
ServerService,
|
ServerService,
|
||||||
Hotkey,
|
|
||||||
HotkeysService,
|
|
||||||
User,
|
User,
|
||||||
UserService,
|
UserService
|
||||||
MetaService
|
|
||||||
} from '@app/core'
|
} from '@app/core'
|
||||||
import { HooksService } from '@app/core/plugins/hooks.service'
|
import { HooksService } from '@app/core/plugins/hooks.service'
|
||||||
import { isXPercentInViewport, scrollToTop, toBoolean } from '@app/helpers'
|
import { isXPercentInViewport, scrollToTop, toBoolean } from '@app/helpers'
|
||||||
|
import { VideoCaptionService } from '@app/shared/shared-main/video-caption/video-caption.service'
|
||||||
|
import { VideoChapterService } from '@app/shared/shared-main/video/video-chapter.service'
|
||||||
|
import { VideoDetails } from '@app/shared/shared-main/video/video-details.model'
|
||||||
|
import { VideoFileTokenService } from '@app/shared/shared-main/video/video-file-token.service'
|
||||||
|
import { Video } from '@app/shared/shared-main/video/video.model'
|
||||||
|
import { VideoService } from '@app/shared/shared-main/video/video.service'
|
||||||
|
import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription/subscribe-button.component'
|
||||||
|
import { LiveVideoService } from '@app/shared/shared-video-live/live-video.service'
|
||||||
|
import { VideoPlaylist } from '@app/shared/shared-video-playlist/video-playlist.model'
|
||||||
|
import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service'
|
||||||
import { timeToInt } from '@peertube/peertube-core-utils'
|
import { timeToInt } from '@peertube/peertube-core-utils'
|
||||||
import {
|
import {
|
||||||
HTMLServerConfig,
|
HTMLServerConfig,
|
||||||
@ -36,6 +45,7 @@ import {
|
|||||||
} from '@peertube/peertube-models'
|
} from '@peertube/peertube-models'
|
||||||
import { logger } from '@root-helpers/logger'
|
import { logger } from '@root-helpers/logger'
|
||||||
import { isP2PEnabled, videoRequiresFileToken, videoRequiresUserAuth } from '@root-helpers/video'
|
import { isP2PEnabled, videoRequiresFileToken, videoRequiresUserAuth } from '@root-helpers/video'
|
||||||
|
import { forkJoin, map, Observable, of, Subscription, switchMap } from 'rxjs'
|
||||||
import {
|
import {
|
||||||
HLSOptions,
|
HLSOptions,
|
||||||
PeerTubePlayer,
|
PeerTubePlayer,
|
||||||
@ -46,29 +56,19 @@ import {
|
|||||||
} from '../../../assets/player'
|
} from '../../../assets/player'
|
||||||
import { cleanupVideoWatch, getStoredTheater, getStoredVideoWatchHistory } from '../../../assets/player/peertube-player-local-storage'
|
import { cleanupVideoWatch, getStoredTheater, getStoredVideoWatchHistory } from '../../../assets/player/peertube-player-local-storage'
|
||||||
import { environment } from '../../../environments/environment'
|
import { environment } from '../../../environments/environment'
|
||||||
import { VideoWatchPlaylistComponent } from './shared'
|
|
||||||
import { PlayerStylesComponent } from './player-styles.component'
|
|
||||||
import { PrivacyConcernsComponent } from './shared/information/privacy-concerns.component'
|
|
||||||
import { RecommendedVideosComponent } from './shared/recommendations/recommended-videos.component'
|
|
||||||
import { VideoCommentsComponent } from './shared/comment/video-comments.component'
|
|
||||||
import { VideoAttributesComponent } from './shared/metadata/video-attributes.component'
|
|
||||||
import { VideoDescriptionComponent } from './shared/metadata/video-description.component'
|
|
||||||
import { VideoAvatarChannelComponent } from './shared/metadata/video-avatar-channel.component'
|
|
||||||
import { ActionButtonsComponent } from './shared/action-buttons/action-buttons.component'
|
|
||||||
import { VideoViewsCounterComponent } from '../../shared/shared-video/video-views-counter.component'
|
|
||||||
import { DateToggleComponent } from '../../shared/shared-main/date/date-toggle.component'
|
import { DateToggleComponent } from '../../shared/shared-main/date/date-toggle.component'
|
||||||
import { VideoAlertComponent } from './shared/information/video-alert.component'
|
|
||||||
import { PluginPlaceholderComponent } from '../../shared/shared-main/plugins/plugin-placeholder.component'
|
import { PluginPlaceholderComponent } from '../../shared/shared-main/plugins/plugin-placeholder.component'
|
||||||
import { VideoDetails } from '@app/shared/shared-main/video/video-details.model'
|
import { VideoViewsCounterComponent } from '../../shared/shared-video/video-views-counter.component'
|
||||||
import { VideoCaptionService } from '@app/shared/shared-main/video-caption/video-caption.service'
|
import { PlayerStylesComponent } from './player-styles.component'
|
||||||
import { VideoChapterService } from '@app/shared/shared-main/video/video-chapter.service'
|
import { VideoWatchPlaylistComponent } from './shared'
|
||||||
import { VideoFileTokenService } from '@app/shared/shared-main/video/video-file-token.service'
|
import { ActionButtonsComponent } from './shared/action-buttons/action-buttons.component'
|
||||||
import { VideoService } from '@app/shared/shared-main/video/video.service'
|
import { VideoCommentsComponent } from './shared/comment/video-comments.component'
|
||||||
import { Video } from '@app/shared/shared-main/video/video.model'
|
import { PrivacyConcernsComponent } from './shared/information/privacy-concerns.component'
|
||||||
import { VideoPlaylist } from '@app/shared/shared-video-playlist/video-playlist.model'
|
import { VideoAlertComponent } from './shared/information/video-alert.component'
|
||||||
import { SubscribeButtonComponent } from '@app/shared/shared-user-subscription/subscribe-button.component'
|
import { VideoAttributesComponent } from './shared/metadata/video-attributes.component'
|
||||||
import { LiveVideoService } from '@app/shared/shared-video-live/live-video.service'
|
import { VideoAvatarChannelComponent } from './shared/metadata/video-avatar-channel.component'
|
||||||
import { VideoPlaylistService } from '@app/shared/shared-video-playlist/video-playlist.service'
|
import { VideoDescriptionComponent } from './shared/metadata/video-description.component'
|
||||||
|
import { RecommendedVideosComponent } from './shared/recommendations/recommended-videos.component'
|
||||||
|
|
||||||
type URLOptions = {
|
type URLOptions = {
|
||||||
playerMode: PlayerMode
|
playerMode: PlayerMode
|
||||||
|
Loading…
Reference in New Issue
Block a user