From 244e76a552ef05a5067134b1065d26dd89246d8c Mon Sep 17 00:00:00 2001 From: Rigel Kent Date: Tue, 17 Apr 2018 00:49:04 +0200 Subject: feature: initial syndication feeds support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- .../videos/+video-watch/video-watch.component.html | 1 + .../videos/+video-watch/video-watch.component.scss | 5 +++++ .../videos/+video-watch/video-watch.component.ts | 23 ++++++++++++++++++---- .../app/videos/video-list/video-local.component.ts | 11 +++++++++++ .../video-list/video-recently-added.component.ts | 10 ++++++++++ .../videos/video-list/video-search.component.ts | 5 +++++ .../videos/video-list/video-trending.component.ts | 10 ++++++++++ 7 files changed, 61 insertions(+), 4 deletions(-) (limited to 'client/src/app/videos') 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 @@
By {{ video.by }} Account avatar +
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 @@ } } + my-video-feed { + margin-left: 5px; + margin-top: 1px; + } + .video-actions-rates { display: flex; 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 @@ -import { Component, ElementRef, NgZone, OnDestroy, OnInit, ViewChild } from '@angular/core' +import { Component, ElementRef, NgZone, OnDestroy, OnInit, ViewChild, OnChanges } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router' import { RedirectService } from '@app/core/routing/redirect.service' import { peertubeLocalStorage } from '@app/shared/misc/peertube-local-storage' @@ -9,18 +9,20 @@ import { Subscription } from 'rxjs/Subscription' import * as videojs from 'video.js' import 'videojs-hotkeys' import * as WebTorrent from 'webtorrent' -import { UserVideoRateType, VideoRateType } from '../../../../../shared' +import { UserVideoRateType, VideoRateType, FeedFormat } from '../../../../../shared' import '../../../assets/player/peertube-videojs-plugin' import { AuthService, ConfirmService } from '../../core' import { VideoBlacklistService } from '../../shared' import { Account } from '../../shared/account/account.model' import { VideoDetails } from '../../shared/video/video-details.model' +import { VideoFeedComponent } from '../../shared/video/video-feed.component' import { Video } from '../../shared/video/video.model' import { VideoService } from '../../shared/video/video.service' import { MarkdownService } from '../shared' import { VideoDownloadComponent } from './modal/video-download.component' import { VideoReportComponent } from './modal/video-report.component' import { VideoShareComponent } from './modal/video-share.component' +import { environment } from '../../../environments/environment' import { getVideojsOptions } from '../../../assets/player/peertube-player' @Component({ @@ -38,6 +40,8 @@ export class VideoWatchComponent implements OnInit, OnDestroy { otherVideosDisplayed: Video[] = [] + syndicationItems = {} + player: videojs.Player playerElement: HTMLVideoElement userRating: UserVideoRateType = null @@ -98,14 +102,15 @@ export class VideoWatchComponent implements OnInit, OnDestroy { } const uuid = routeParams['uuid'] - // Video did not changed + // Video did not change if (this.video && this.video.uuid === uuid) return - + // Video did change this.videoService.getVideo(uuid).subscribe( video => { const startTime = this.route.snapshot.queryParams.start this.onVideoFetched(video, startTime) .catch(err => this.handleError(err)) + this.generateSyndicationList() }, error => { @@ -242,6 +247,16 @@ export class VideoWatchComponent implements OnInit, OnDestroy { return this.video.tags.join(', ') } + generateSyndicationList () { + const feeds = this.videoService.getAccountFeed( + this.video.account.id, + (this.video.isLocal) ? environment.apiUrl : this.video.account.host + ) + this.syndicationItems['rss 2.0'] = feeds[FeedFormat.RSS] + this.syndicationItems['atom 1.0'] = feeds[FeedFormat.ATOM] + this.syndicationItems['json 1.0'] = feeds[FeedFormat.JSON] + } + isVideoRemovable () { return this.video.isRemovableBy(this.authService.getUser()) } 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' import { immutableAssign } from '@app/shared/misc/utils' import { NotificationsService } from 'angular2-notifications' import { AuthService } from '../../core/auth' +import { PopoverModule } from 'ngx-bootstrap/popover' import { AbstractVideoList } from '../../shared/video/abstract-video-list' import { SortField } from '../../shared/video/sort-field.type' import { VideoService } from '../../shared/video/video.service' +import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum' +import * as url from 'url' @Component({ selector: 'my-videos-local', @@ -27,6 +30,7 @@ export class VideoLocalComponent extends AbstractVideoList implements OnInit, On ngOnInit () { super.ngOnInit() + this.generateSyndicationList() } ngOnDestroy () { @@ -38,4 +42,11 @@ export class VideoLocalComponent extends AbstractVideoList implements OnInit, On return this.videoService.getVideos(newPagination, this.sort, 'local') } + + generateSyndicationList () { + const feeds = this.videoService.getFeed('local') + this.syndicationItems['rss 2.0'] = feeds[FeedFormat.RSS] + this.syndicationItems['atom 1.0'] = feeds[FeedFormat.ATOM] + this.syndicationItems['json 1.0'] = feeds[FeedFormat.JSON] + } } 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' import { AbstractVideoList } from '../../shared/video/abstract-video-list' import { SortField } from '../../shared/video/sort-field.type' import { VideoService } from '../../shared/video/video.service' +import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum' +import * as url from 'url' @Component({ selector: 'my-videos-recently-added', @@ -27,6 +29,7 @@ export class VideoRecentlyAddedComponent extends AbstractVideoList implements On ngOnInit () { super.ngOnInit() + this.generateSyndicationList() } ngOnDestroy () { @@ -38,4 +41,11 @@ export class VideoRecentlyAddedComponent extends AbstractVideoList implements On return this.videoService.getVideos(newPagination, this.sort) } + + generateSyndicationList () { + const feeds = this.videoService.getFeed('local') + this.syndicationItems['rss 2.0'] = feeds[FeedFormat.RSS] + this.syndicationItems['atom 1.0'] = feeds[FeedFormat.ATOM] + this.syndicationItems['json 1.0'] = feeds[FeedFormat.JSON] + } } 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' import { AuthService } from '../../core/auth' import { AbstractVideoList } from '../../shared/video/abstract-video-list' import { VideoService } from '../../shared/video/video.service' +import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum' @Component({ selector: 'my-videos-search', @@ -61,4 +62,8 @@ export class VideoSearchComponent extends AbstractVideoList implements OnInit, O const newPagination = immutableAssign(this.pagination, { currentPage: page }) return this.videoService.searchVideos(this.otherRouteParams.search, newPagination, this.sort) } + + generateSyndicationList () { + throw new Error('Method not implemented.') + } } 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' import { AbstractVideoList } from '../../shared/video/abstract-video-list' import { SortField } from '../../shared/video/sort-field.type' import { VideoService } from '../../shared/video/video.service' +import { FeedFormat } from '../../../../../shared/models/feeds/feed-format.enum' +import * as url from 'url' @Component({ selector: 'my-videos-trending', @@ -27,6 +29,7 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit, ngOnInit () { super.ngOnInit() + this.generateSyndicationList() } ngOnDestroy () { @@ -37,4 +40,11 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit, const newPagination = immutableAssign(this.pagination, { currentPage: page }) return this.videoService.getVideos(newPagination, this.sort) } + + generateSyndicationList () { + const feeds = this.videoService.getFeed('local') + this.syndicationItems['rss 2.0'] = feeds[FeedFormat.RSS] + this.syndicationItems['atom 1.0'] = feeds[FeedFormat.ATOM] + this.syndicationItems['json 1.0'] = feeds[FeedFormat.JSON] + } } -- cgit v1.2.3