diff options
author | Rigel Kent <sendmemail@rigelk.eu> | 2019-12-10 23:15:09 +0100 |
---|---|---|
committer | Chocobozzz <chocobozzz@cpy.re> | 2019-12-13 09:13:43 +0100 |
commit | d816f3a063febac1cad09ab3a32e5f0d29353627 (patch) | |
tree | 2c74b4f3503bd5fe58c2761804fa3c0aa68ae957 /client/src/app | |
parent | 2f6b5e2d6ebcac88d9005ea2654ffa77907d5db2 (diff) | |
download | PeerTube-d816f3a063febac1cad09ab3a32e5f0d29353627.tar.gz PeerTube-d816f3a063febac1cad09ab3a32e5f0d29353627.tar.zst PeerTube-d816f3a063febac1cad09ab3a32e5f0d29353627.zip |
autoplay next video switch for both user and visitors
Diffstat (limited to 'client/src/app')
6 files changed, 93 insertions, 5 deletions
diff --git a/client/src/app/header/header.component.html b/client/src/app/header/header.component.html index 46a87c79c..8ee41c4de 100644 --- a/client/src/app/header/header.component.html +++ b/client/src/app/header/header.component.html | |||
@@ -1,5 +1,5 @@ | |||
1 | <input | 1 | <input |
2 | type="text" id="search-video" name="search-video" i18n-placeholder placeholder="Search..." | 2 | type="text" id="search-video" name="search-video" i18n-placeholder placeholder="Search videos, channels…" |
3 | [(ngModel)]="searchValue" (keyup.enter)="doSearch()" | 3 | [(ngModel)]="searchValue" (keyup.enter)="doSearch()" |
4 | > | 4 | > |
5 | <span (click)="doSearch()" class="icon icon-search"></span> | 5 | <span (click)="doSearch()" class="icon icon-search"></span> |
diff --git a/client/src/app/videos/+video-watch/video-watch.component.ts b/client/src/app/videos/+video-watch/video-watch.component.ts index 0de621aca..156a3235a 100644 --- a/client/src/app/videos/+video-watch/video-watch.component.ts +++ b/client/src/app/videos/+video-watch/video-watch.component.ts | |||
@@ -45,6 +45,7 @@ import { randomInt } from '@shared/core-utils/miscs/miscs' | |||
45 | }) | 45 | }) |
46 | export class VideoWatchComponent implements OnInit, OnDestroy { | 46 | export class VideoWatchComponent implements OnInit, OnDestroy { |
47 | private static LOCAL_STORAGE_PRIVACY_CONCERN_KEY = 'video-watch-privacy-concern' | 47 | private static LOCAL_STORAGE_PRIVACY_CONCERN_KEY = 'video-watch-privacy-concern' |
48 | private static LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO = 'auto_play_next_video' | ||
48 | 49 | ||
49 | @ViewChild('videoWatchPlaylist', { static: true }) videoWatchPlaylist: VideoWatchPlaylistComponent | 50 | @ViewChild('videoWatchPlaylist', { static: true }) videoWatchPlaylist: VideoWatchPlaylistComponent |
50 | @ViewChild('videoShareModal', { static: false }) videoShareModal: VideoShareComponent | 51 | @ViewChild('videoShareModal', { static: false }) videoShareModal: VideoShareComponent |
@@ -436,7 +437,10 @@ export class VideoWatchComponent implements OnInit, OnDestroy { | |||
436 | this.player.one('ended', () => { | 437 | this.player.one('ended', () => { |
437 | if (this.playlist) { | 438 | if (this.playlist) { |
438 | this.zone.run(() => this.videoWatchPlaylist.navigateToNextPlaylistVideo()) | 439 | this.zone.run(() => this.videoWatchPlaylist.navigateToNextPlaylistVideo()) |
439 | } else if (this.user && this.user.autoPlayNextVideo) { | 440 | } else if ( |
441 | this.user && this.user.autoPlayNextVideo || | ||
442 | peertubeLocalStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true' | ||
443 | ) { | ||
440 | this.zone.run(() => this.autoplayNext()) | 444 | this.zone.run(() => this.autoplayNext()) |
441 | } | 445 | } |
442 | }) | 446 | }) |
diff --git a/client/src/app/videos/recommendations/recommendations.module.ts b/client/src/app/videos/recommendations/recommendations.module.ts index 5a46ea739..3e279cc29 100644 --- a/client/src/app/videos/recommendations/recommendations.module.ts +++ b/client/src/app/videos/recommendations/recommendations.module.ts | |||
@@ -1,4 +1,5 @@ | |||
1 | import { NgModule } from '@angular/core' | 1 | import { NgModule } from '@angular/core' |
2 | import { InputSwitchModule } from 'primeng/inputswitch' | ||
2 | import { RecommendedVideosComponent } from '@app/videos/recommendations/recommended-videos.component' | 3 | import { RecommendedVideosComponent } from '@app/videos/recommendations/recommended-videos.component' |
3 | import { RecommendedVideosStore } from '@app/videos/recommendations/recommended-videos.store' | 4 | import { RecommendedVideosStore } from '@app/videos/recommendations/recommended-videos.store' |
4 | import { CommonModule } from '@angular/common' | 5 | import { CommonModule } from '@angular/common' |
@@ -7,6 +8,7 @@ import { RecentVideosRecommendationService } from '@app/videos/recommendations/r | |||
7 | 8 | ||
8 | @NgModule({ | 9 | @NgModule({ |
9 | imports: [ | 10 | imports: [ |
11 | InputSwitchModule, | ||
10 | SharedModule, | 12 | SharedModule, |
11 | CommonModule | 13 | CommonModule |
12 | ], | 14 | ], |
diff --git a/client/src/app/videos/recommendations/recommended-videos.component.html b/client/src/app/videos/recommendations/recommended-videos.component.html index 5b5951f99..5f223078a 100644 --- a/client/src/app/videos/recommendations/recommended-videos.component.html +++ b/client/src/app/videos/recommendations/recommended-videos.component.html | |||
@@ -1,7 +1,13 @@ | |||
1 | <div class="other-videos"> | 1 | <div class="other-videos"> |
2 | <ng-container *ngIf="hasVideos$ | async"> | 2 | <ng-container *ngIf="hasVideos$ | async"> |
3 | <div i18n class="title-page title-page-single"> | 3 | <div class="d-flex title-page-container"> |
4 | Other videos | 4 | <div i18n class="title-page title-page-single"> |
5 | Other videos | ||
6 | </div> | ||
7 | <div class="d-flex title-page-autoplay"> | ||
8 | <span>Autoplay</span> | ||
9 | <p-inputSwitch [(ngModel)]="autoPlayNextVideo" (ngModelChange)="switchAutoPlayNextVideo()"></p-inputSwitch> | ||
10 | </div> | ||
5 | </div> | 11 | </div> |
6 | 12 | ||
7 | <div *ngFor="let video of (videos$ | async)"> | 13 | <div *ngFor="let video of (videos$ | async)"> |
diff --git a/client/src/app/videos/recommendations/recommended-videos.component.scss b/client/src/app/videos/recommendations/recommended-videos.component.scss new file mode 100644 index 000000000..c337979d8 --- /dev/null +++ b/client/src/app/videos/recommendations/recommended-videos.component.scss | |||
@@ -0,0 +1,44 @@ | |||
1 | .title-page-container { | ||
2 | justify-content: space-between; | ||
3 | align-items: center; | ||
4 | margin-bottom: 25px; | ||
5 | |||
6 | .title-page.active, .title-page.title-page-single { | ||
7 | margin-bottom: unset; | ||
8 | } | ||
9 | } | ||
10 | |||
11 | .title-page-autoplay { | ||
12 | width: max-content; | ||
13 | height: max-content; | ||
14 | align-items: center; | ||
15 | |||
16 | span { | ||
17 | margin-right: 0.3rem; | ||
18 | text-transform: uppercase; | ||
19 | font-size: 85%; | ||
20 | font-weight: 600; | ||
21 | } | ||
22 | } | ||
23 | |||
24 | /* p-inputSwitch styles to reduce the switch size */ | ||
25 | |||
26 | ::ng-deep { | ||
27 | p-inputswitch { | ||
28 | height: 20px; | ||
29 | } | ||
30 | |||
31 | .ui-inputswitch { | ||
32 | width: 2.5em !important; | ||
33 | height: 1.45em !important; | ||
34 | |||
35 | .ui-inputswitch-slider::before { | ||
36 | height: 1em !important; | ||
37 | width: 1em !important; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | .ui-inputswitch-checked .ui-inputswitch-slider::before { | ||
42 | transform: translateX(1em) !important; | ||
43 | } | ||
44 | } | ||
diff --git a/client/src/app/videos/recommendations/recommended-videos.component.ts b/client/src/app/videos/recommendations/recommended-videos.component.ts index 7e0fb8856..4c3cde225 100644 --- a/client/src/app/videos/recommendations/recommended-videos.component.ts +++ b/client/src/app/videos/recommendations/recommended-videos.component.ts | |||
@@ -4,12 +4,18 @@ import { Video } from '@app/shared/video/video.model' | |||
4 | import { RecommendationInfo } from '@app/shared/video/recommendation-info.model' | 4 | import { RecommendationInfo } from '@app/shared/video/recommendation-info.model' |
5 | import { RecommendedVideosStore } from '@app/videos/recommendations/recommended-videos.store' | 5 | import { RecommendedVideosStore } from '@app/videos/recommendations/recommended-videos.store' |
6 | import { User } from '@app/shared' | 6 | import { User } from '@app/shared' |
7 | import { AuthService, Notifier } from '@app/core' | ||
8 | import { UserService } from '@app/shared/users/user.service' | ||
9 | import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' | ||
7 | 10 | ||
8 | @Component({ | 11 | @Component({ |
9 | selector: 'my-recommended-videos', | 12 | selector: 'my-recommended-videos', |
10 | templateUrl: './recommended-videos.component.html' | 13 | templateUrl: './recommended-videos.component.html', |
14 | styleUrls: [ './recommended-videos.component.scss' ] | ||
11 | }) | 15 | }) |
12 | export class RecommendedVideosComponent implements OnChanges { | 16 | export class RecommendedVideosComponent implements OnChanges { |
17 | private static LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO = 'auto_play_next_video' | ||
18 | |||
13 | @Input() inputRecommendation: RecommendationInfo | 19 | @Input() inputRecommendation: RecommendationInfo |
14 | @Input() user: User | 20 | @Input() user: User |
15 | @Output() gotRecommendations = new EventEmitter<Video[]>() | 21 | @Output() gotRecommendations = new EventEmitter<Video[]>() |
@@ -17,12 +23,21 @@ export class RecommendedVideosComponent implements OnChanges { | |||
17 | readonly hasVideos$: Observable<boolean> | 23 | readonly hasVideos$: Observable<boolean> |
18 | readonly videos$: Observable<Video[]> | 24 | readonly videos$: Observable<Video[]> |
19 | 25 | ||
26 | private autoPlayNextVideo: boolean | ||
27 | |||
20 | constructor ( | 28 | constructor ( |
29 | private userService: UserService, | ||
30 | private authService: AuthService, | ||
31 | private notifier: Notifier, | ||
21 | private store: RecommendedVideosStore | 32 | private store: RecommendedVideosStore |
22 | ) { | 33 | ) { |
23 | this.videos$ = this.store.recommendations$ | 34 | this.videos$ = this.store.recommendations$ |
24 | this.hasVideos$ = this.store.hasRecommendations$ | 35 | this.hasVideos$ = this.store.hasRecommendations$ |
25 | this.videos$.subscribe(videos => this.gotRecommendations.emit(videos)) | 36 | this.videos$.subscribe(videos => this.gotRecommendations.emit(videos)) |
37 | |||
38 | this.autoPlayNextVideo = this.authService.isLoggedIn() | ||
39 | ? this.authService.getUser().autoPlayNextVideo | ||
40 | : peertubeLocalStorage.getItem(RecommendedVideosComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO) === 'true' || false | ||
26 | } | 41 | } |
27 | 42 | ||
28 | public ngOnChanges (): void { | 43 | public ngOnChanges (): void { |
@@ -34,4 +49,21 @@ export class RecommendedVideosComponent implements OnChanges { | |||
34 | onVideoRemoved () { | 49 | onVideoRemoved () { |
35 | this.store.requestNewRecommendations(this.inputRecommendation) | 50 | this.store.requestNewRecommendations(this.inputRecommendation) |
36 | } | 51 | } |
52 | |||
53 | switchAutoPlayNextVideo () { | ||
54 | peertubeLocalStorage.setItem(RecommendedVideosComponent.LOCAL_STORAGE_AUTO_PLAY_NEXT_VIDEO, this.autoPlayNextVideo.toString()) | ||
55 | |||
56 | if (this.authService.isLoggedIn()) { | ||
57 | const details = { | ||
58 | autoPlayNextVideo: this.autoPlayNextVideo | ||
59 | } | ||
60 | |||
61 | this.userService.updateMyProfile(details).subscribe( | ||
62 | () => { | ||
63 | this.authService.refreshUserInformation() | ||
64 | }, | ||
65 | err => this.notifier.error(err.message) | ||
66 | ) | ||
67 | } | ||
68 | } | ||
37 | } | 69 | } |