aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app/videos
diff options
context:
space:
mode:
authorRigel Kent <sendmemail@rigelk.eu>2018-04-17 00:49:04 +0200
committerRigel <sendmemail@rigelk.eu>2018-04-17 01:09:06 +0200
commit244e76a552ef05a5067134b1065d26dd89246d8c (patch)
treea15fcd52bce99797fc9366572fea62a7a44aaabe /client/src/app/videos
parentc36d5a6b98056ef7fec3db43fbee880ee7332dcf (diff)
downloadPeerTube-244e76a552ef05a5067134b1065d26dd89246d8c.tar.gz
PeerTube-244e76a552ef05a5067134b1065d26dd89246d8c.tar.zst
PeerTube-244e76a552ef05a5067134b1065d26dd89246d8c.zip
feature: initial syndication feeds support
Provides rss 2.0, atom 1.0 and json 1.0 feeds for videos (instance and account-wide) on listings and video-watch views. * still lacks redis caching * still lacks lastBuildDate support * still lacks channel-wide support * still lacks semantic annotation (for licenses, NSFW warnings, etc.) * still lacks love ( ˘ ³˘) * RSS: has MRSS support for torrent lists! * RSS: includes the first torrent in an enclosure * JSON: lists all torrents in the 'attachments' object * ATOM: lacking torrent listing support Advances #23 Partial implementation for the accountId generation in the client, which will need a hotfix to add a way to get the proper account id.
Diffstat (limited to 'client/src/app/videos')
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.html1
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.scss5
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.ts23
-rw-r--r--client/src/app/videos/video-list/video-local.component.ts11
-rw-r--r--client/src/app/videos/video-list/video-recently-added.component.ts10
-rw-r--r--client/src/app/videos/video-list/video-search.component.ts5
-rw-r--r--client/src/app/videos/video-list/video-trending.component.ts10
7 files changed, 61 insertions, 4 deletions
diff --git a/client/src/app/videos/+video-watch/video-watch.component.html b/client/src/app/videos/+video-watch/video-watch.component.html
index 03f64bd12..52e3e429a 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.html
+++ b/client/src/app/videos/+video-watch/video-watch.component.html
@@ -24,6 +24,7 @@
24 <div class="video-info-by"> 24 <div class="video-info-by">
25 By {{ video.by }} 25 By {{ video.by }}
26 <img [src]="getAvatarPath()" alt="Account avatar" /> 26 <img [src]="getAvatarPath()" alt="Account avatar" />
27 <my-video-feed [syndicationItems]="syndicationItems"></my-video-feed>
27 </div> 28 </div>
28 </div> 29 </div>
29 30
diff --git a/client/src/app/videos/+video-watch/video-watch.component.scss b/client/src/app/videos/+video-watch/video-watch.component.scss
index 03f960339..8a3e2584b 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.scss
+++ b/client/src/app/videos/+video-watch/video-watch.component.scss
@@ -80,6 +80,11 @@
80 } 80 }
81 } 81 }
82 82
83 my-video-feed {
84 margin-left: 5px;
85 margin-top: 1px;
86 }
87
83 .video-actions-rates { 88 .video-actions-rates {
84 display: flex; 89 display: flex;
85 flex-direction: column; 90 flex-direction: column;
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 df5b8d02d..b3ebe3e4b 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.ts
+++ b/client/src/app/videos/+video-watch/video-watch.component.ts
@@ -1,4 +1,4 @@
1import { Component, ElementRef, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core' 1import { Component, ElementRef, NgZone, OnDestroy, OnInit, ViewChild, OnChanges } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { ActivatedRoute, Router } from '@angular/router'
3import { RedirectService } from '@app/core/routing/redirect.service' 3import { RedirectService } from '@app/core/routing/redirect.service'
4import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' 4import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage'
@@ -9,18 +9,20 @@ import { Subscription } from 'rxjs/Subscription'
9import * as videojs from 'video.js' 9import * as videojs from 'video.js'
10import 'videojs-hotkeys' 10import 'videojs-hotkeys'
11import * as WebTorrent from 'webtorrent' 11import * as WebTorrent from 'webtorrent'
12import { UserVideoRateType, VideoRateType } from '../../../../../shared' 12import { UserVideoRateType, VideoRateType, FeedFormat } from '../../../../../shared'
13import '../../../assets/player/peertube-videojs-plugin' 13import '../../../assets/player/peertube-videojs-plugin'
14import { AuthService, ConfirmService } from '../../core' 14import { AuthService, ConfirmService } from '../../core'
15import { VideoBlacklistService } from '../../shared' 15import { VideoBlacklistService } from '../../shared'
16import { Account } from '../../shared/account/account.model' 16import { Account } from '../../shared/account/account.model'
17import { VideoDetails } from '../../shared/video/video-details.model' 17import { VideoDetails } from '../../shared/video/video-details.model'
18import { VideoFeedComponent } from '../../shared/video/video-feed.component'
18import { Video } from '../../shared/video/video.model' 19import { Video } from '../../shared/video/video.model'
19import { VideoService } from '../../shared/video/video.service' 20import { VideoService } from '../../shared/video/video.service'
20import { MarkdownService } from '../shared' 21import { MarkdownService } from '../shared'
21import { VideoDownloadComponent } from './modal/video-download.component' 22import { VideoDownloadComponent } from './modal/video-download.component'
22import { VideoReportComponent } from './modal/video-report.component' 23import { VideoReportComponent } from './modal/video-report.component'
23import { VideoShareComponent } from './modal/video-share.component' 24import { VideoShareComponent } from './modal/video-share.component'
25import { environment } from '../../../environments/environment'
24import { getVideojsOptions } from '../../../assets/player/peertube-player' 26import { getVideojsOptions } from '../../../assets/player/peertube-player'
25 27
26@Component({ 28@Component({
@@ -38,6 +40,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
38 40
39 otherVideosDisplayed: Video[] = [] 41 otherVideosDisplayed: Video[] = []
40 42
43 syndicationItems = {}
44
41 player: videojs.Player 45 player: videojs.Player
42 playerElement: HTMLVideoElement 46 playerElement: HTMLVideoElement
43 userRating: UserVideoRateType = null 47 userRating: UserVideoRateType = null
@@ -98,14 +102,15 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
98 } 102 }
99 103
100 const uuid = routeParams['uuid'] 104 const uuid = routeParams['uuid']
101 // Video did not changed 105 // Video did not change
102 if (this.video && this.video.uuid === uuid) return 106 if (this.video && this.video.uuid === uuid) return
103 107 // Video did change
104 this.videoService.getVideo(uuid).subscribe( 108 this.videoService.getVideo(uuid).subscribe(
105 video => { 109 video => {
106 const startTime = this.route.snapshot.queryParams.start 110 const startTime = this.route.snapshot.queryParams.start
107 this.onVideoFetched(video, startTime) 111 this.onVideoFetched(video, startTime)
108 .catch(err => this.handleError(err)) 112 .catch(err => this.handleError(err))
113 this.generateSyndicationList()
109 }, 114 },
110 115
111 error => { 116 error => {
@@ -242,6 +247,16 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
242 return this.video.tags.join(', ') 247 return this.video.tags.join(', ')
243 } 248 }
244 249
250 generateSyndicationList () {
251 const feeds = this.videoService.getAccountFeed(
252 this.video.account.id,
253 (this.video.isLocal) ? environment.apiUrl : this.video.account.host
254 )
255 this.syndicationItems['rss 2.0'] = feeds[FeedFormat.RSS]
256 this.syndicationItems['atom 1.0'] = feeds[FeedFormat.ATOM]
257 this.syndicationItems['json 1.0'] = feeds[FeedFormat.JSON]
258 }
259
245 isVideoRemovable () { 260 isVideoRemovable () {
246 return this.video.isRemovableBy(this.authService.getUser()) 261 return this.video.isRemovableBy(this.authService.getUser())
247 } 262 }
diff --git a/client/src/app/videos/video-list/video-local.component.ts b/client/src/app/videos/video-list/video-local.component.ts
index 8f9d50a7b..9d626abd1 100644
--- a/client/src/app/videos/video-list/video-local.component.ts
+++ b/client/src/app/videos/video-list/video-local.component.ts
@@ -3,9 +3,12 @@ import { ActivatedRoute, Router } from '@angular/router'
3import { immutableAssign } from '@app/shared/misc/utils' 3import { immutableAssign } from '@app/shared/misc/utils'
4import { NotificationsService } from 'angular2-notifications' 4import { NotificationsService } from 'angular2-notifications'
5import { AuthService } from '../../core/auth' 5import { AuthService } from '../../core/auth'
6import { PopoverModule } from 'ngx-bootstrap/popover'
6import { AbstractVideoList } from '../../shared/video/abstract-video-list' 7import { AbstractVideoList } from '../../shared/video/abstract-video-list'
7import { SortField } from '../../shared/video/sort-field.type' 8import { SortField } from '../../shared/video/sort-field.type'
8import { VideoService } from '../../shared/video/video.service' 9import { VideoService } from '../../shared/video/video.service'
10import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum'
11import * as url from 'url'
9 12
10@Component({ 13@Component({
11 selector: 'my-videos-local', 14 selector: 'my-videos-local',
@@ -27,6 +30,7 @@ export class VideoLocalComponent extends AbstractVideoList implements OnInit, On
27 30
28 ngOnInit () { 31 ngOnInit () {
29 super.ngOnInit() 32 super.ngOnInit()
33 this.generateSyndicationList()
30 } 34 }
31 35
32 ngOnDestroy () { 36 ngOnDestroy () {
@@ -38,4 +42,11 @@ export class VideoLocalComponent extends AbstractVideoList implements OnInit, On
38 42
39 return this.videoService.getVideos(newPagination, this.sort, 'local') 43 return this.videoService.getVideos(newPagination, this.sort, 'local')
40 } 44 }
45
46 generateSyndicationList () {
47 const feeds = this.videoService.getFeed('local')
48 this.syndicationItems['rss 2.0'] = feeds[FeedFormat.RSS]
49 this.syndicationItems['atom 1.0'] = feeds[FeedFormat.ATOM]
50 this.syndicationItems['json 1.0'] = feeds[FeedFormat.JSON]
51 }
41} 52}
diff --git a/client/src/app/videos/video-list/video-recently-added.component.ts b/client/src/app/videos/video-list/video-recently-added.component.ts
index 1cecd14a0..2bdc20d92 100644
--- a/client/src/app/videos/video-list/video-recently-added.component.ts
+++ b/client/src/app/videos/video-list/video-recently-added.component.ts
@@ -6,6 +6,8 @@ import { AuthService } from '../../core/auth'
6import { AbstractVideoList } from '../../shared/video/abstract-video-list' 6import { AbstractVideoList } from '../../shared/video/abstract-video-list'
7import { SortField } from '../../shared/video/sort-field.type' 7import { SortField } from '../../shared/video/sort-field.type'
8import { VideoService } from '../../shared/video/video.service' 8import { VideoService } from '../../shared/video/video.service'
9import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum'
10import * as url from 'url'
9 11
10@Component({ 12@Component({
11 selector: 'my-videos-recently-added', 13 selector: 'my-videos-recently-added',
@@ -27,6 +29,7 @@ export class VideoRecentlyAddedComponent extends AbstractVideoList implements On
27 29
28 ngOnInit () { 30 ngOnInit () {
29 super.ngOnInit() 31 super.ngOnInit()
32 this.generateSyndicationList()
30 } 33 }
31 34
32 ngOnDestroy () { 35 ngOnDestroy () {
@@ -38,4 +41,11 @@ export class VideoRecentlyAddedComponent extends AbstractVideoList implements On
38 41
39 return this.videoService.getVideos(newPagination, this.sort) 42 return this.videoService.getVideos(newPagination, this.sort)
40 } 43 }
44
45 generateSyndicationList () {
46 const feeds = this.videoService.getFeed('local')
47 this.syndicationItems['rss 2.0'] = feeds[FeedFormat.RSS]
48 this.syndicationItems['atom 1.0'] = feeds[FeedFormat.ATOM]
49 this.syndicationItems['json 1.0'] = feeds[FeedFormat.JSON]
50 }
41} 51}
diff --git a/client/src/app/videos/video-list/video-search.component.ts b/client/src/app/videos/video-list/video-search.component.ts
index b94be8e11..ef9afa757 100644
--- a/client/src/app/videos/video-list/video-search.component.ts
+++ b/client/src/app/videos/video-list/video-search.component.ts
@@ -7,6 +7,7 @@ import { Subscription } from 'rxjs/Subscription'
7import { AuthService } from '../../core/auth' 7import { AuthService } from '../../core/auth'
8import { AbstractVideoList } from '../../shared/video/abstract-video-list' 8import { AbstractVideoList } from '../../shared/video/abstract-video-list'
9import { VideoService } from '../../shared/video/video.service' 9import { VideoService } from '../../shared/video/video.service'
10import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum'
10 11
11@Component({ 12@Component({
12 selector: 'my-videos-search', 13 selector: 'my-videos-search',
@@ -61,4 +62,8 @@ export class VideoSearchComponent extends AbstractVideoList implements OnInit, O
61 const newPagination = immutableAssign(this.pagination, { currentPage: page }) 62 const newPagination = immutableAssign(this.pagination, { currentPage: page })
62 return this.videoService.searchVideos(this.otherRouteParams.search, newPagination, this.sort) 63 return this.videoService.searchVideos(this.otherRouteParams.search, newPagination, this.sort)
63 } 64 }
65
66 generateSyndicationList () {
67 throw new Error('Method not implemented.')
68 }
64} 69}
diff --git a/client/src/app/videos/video-list/video-trending.component.ts b/client/src/app/videos/video-list/video-trending.component.ts
index 1dd1ad23b..905c75ab0 100644
--- a/client/src/app/videos/video-list/video-trending.component.ts
+++ b/client/src/app/videos/video-list/video-trending.component.ts
@@ -6,6 +6,8 @@ import { AuthService } from '../../core/auth'
6import { AbstractVideoList } from '../../shared/video/abstract-video-list' 6import { AbstractVideoList } from '../../shared/video/abstract-video-list'
7import { SortField } from '../../shared/video/sort-field.type' 7import { SortField } from '../../shared/video/sort-field.type'
8import { VideoService } from '../../shared/video/video.service' 8import { VideoService } from '../../shared/video/video.service'
9import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum'
10import * as url from 'url'
9 11
10@Component({ 12@Component({
11 selector: 'my-videos-trending', 13 selector: 'my-videos-trending',
@@ -27,6 +29,7 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
27 29
28 ngOnInit () { 30 ngOnInit () {
29 super.ngOnInit() 31 super.ngOnInit()
32 this.generateSyndicationList()
30 } 33 }
31 34
32 ngOnDestroy () { 35 ngOnDestroy () {
@@ -37,4 +40,11 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit,
37 const newPagination = immutableAssign(this.pagination, { currentPage: page }) 40 const newPagination = immutableAssign(this.pagination, { currentPage: page })
38 return this.videoService.getVideos(newPagination, this.sort) 41 return this.videoService.getVideos(newPagination, this.sort)
39 } 42 }
43
44 generateSyndicationList () {
45 const feeds = this.videoService.getFeed('local')
46 this.syndicationItems['rss 2.0'] = feeds[FeedFormat.RSS]
47 this.syndicationItems['atom 1.0'] = feeds[FeedFormat.ATOM]
48 this.syndicationItems['json 1.0'] = feeds[FeedFormat.JSON]
49 }
40} 50}