aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/package.json2
-rw-r--r--client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html4
-rw-r--r--client/src/app/account/account-videos/account-videos.component.ts13
-rw-r--r--client/src/app/shared/misc/help.component.ts3
-rw-r--r--client/src/app/shared/video/abstract-video-list.ts48
-rw-r--r--client/src/app/shared/video/infinite-scroller.directive.ts22
-rw-r--r--client/src/app/videos/+video-watch/comment/video-comment.component.html2
-rw-r--r--client/src/app/videos/+video-watch/comment/video-comment.component.ts3
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.html2
-rw-r--r--client/src/app/videos/+video-watch/video-watch.component.ts3
-rw-r--r--client/src/app/videos/shared/markdown.service.ts19
-rw-r--r--client/src/app/videos/video-list/video-local.component.ts8
-rw-r--r--client/src/app/videos/video-list/video-recently-added.component.ts8
-rw-r--r--client/src/app/videos/video-list/video-search.component.ts6
-rw-r--r--client/src/app/videos/video-list/video-trending.component.ts8
-rw-r--r--client/src/standalone/videos/embed.ts2
-rw-r--r--package.json2
17 files changed, 103 insertions, 52 deletions
diff --git a/client/package.json b/client/package.json
index a7aa674b2..fded52b82 100644
--- a/client/package.json
+++ b/client/package.json
@@ -1,6 +1,6 @@
1{ 1{
2 "name": "peertube-client", 2 "name": "peertube-client",
3 "version": "1.0.0-alpha.8", 3 "version": "1.0.0-alpha.9",
4 "private": true, 4 "private": true,
5 "licence": "GPLv3", 5 "licence": "GPLv3",
6 "author": { 6 "author": {
diff --git a/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html b/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html
index fcbdc6147..13a5b1117 100644
--- a/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html
+++ b/client/src/app/+admin/video-abuses/video-abuse-list/video-abuse-list.component.html
@@ -19,13 +19,13 @@
19 <tr> 19 <tr>
20 <td>{{ videoAbuse.reason }}</td> 20 <td>{{ videoAbuse.reason }}</td>
21 <td> 21 <td>
22 <a [href]="videoAbuse.reporterAccount.url" title="Go to the account" target="_blank"> 22 <a [href]="videoAbuse.reporterAccount.url" title="Go to the account" target="_blank" rel="noopener noreferrer">
23 {{ createByString(videoAbuse.reporterAccount) }} 23 {{ createByString(videoAbuse.reporterAccount) }}
24 </a> 24 </a>
25 </td> 25 </td>
26 <td>{{ videoAbuse.createdAt }}</td> 26 <td>{{ videoAbuse.createdAt }}</td>
27 <td> 27 <td>
28 <a [href]="videoAbuse.video.url" title="Go to the video" target="_blank"> 28 <a [href]="videoAbuse.video.url" title="Go to the video" target="_blank" rel="noopener noreferrer">
29 {{ videoAbuse.video.name }} 29 {{ videoAbuse.video.name }}
30 </a> 30 </a>
31 </td> 31 </td>
diff --git a/client/src/app/account/account-videos/account-videos.component.ts b/client/src/app/account/account-videos/account-videos.component.ts
index a286bad1c..cd0f8e752 100644
--- a/client/src/app/account/account-videos/account-videos.component.ts
+++ b/client/src/app/account/account-videos/account-videos.component.ts
@@ -1,4 +1,4 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnInit, OnDestroy } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { ActivatedRoute, Router } from '@angular/router'
3import { immutableAssign } from '@app/shared/misc/utils' 3import { immutableAssign } from '@app/shared/misc/utils'
4import { ComponentPagination } from '@app/shared/rest/component-pagination.model' 4import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
@@ -17,18 +17,19 @@ import { VideoService } from '../../shared/video/video.service'
17 templateUrl: './account-videos.component.html', 17 templateUrl: './account-videos.component.html',
18 styleUrls: [ './account-videos.component.scss' ] 18 styleUrls: [ './account-videos.component.scss' ]
19}) 19})
20export class AccountVideosComponent extends AbstractVideoList implements OnInit { 20export class AccountVideosComponent extends AbstractVideoList implements OnInit, OnDestroy {
21 titlePage = 'My videos' 21 titlePage = 'My videos'
22 currentRoute = '/account/videos' 22 currentRoute = '/account/videos'
23 checkedVideos: { [ id: number ]: boolean } = {} 23 checkedVideos: { [ id: number ]: boolean } = {}
24 videoHeight = 155
25 videoWidth = -1
26 pagination: ComponentPagination = { 24 pagination: ComponentPagination = {
27 currentPage: 1, 25 currentPage: 1,
28 itemsPerPage: 10, 26 itemsPerPage: 10,
29 totalItems: null 27 totalItems: null
30 } 28 }
31 29
30 protected baseVideoWidth = -1
31 protected baseVideoHeight = 155
32
32 constructor (protected router: Router, 33 constructor (protected router: Router,
33 protected route: ActivatedRoute, 34 protected route: ActivatedRoute,
34 protected authService: AuthService, 35 protected authService: AuthService,
@@ -42,6 +43,10 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit
42 super.ngOnInit() 43 super.ngOnInit()
43 } 44 }
44 45
46 ngOnDestroy () {
47 super.ngOnDestroy()
48 }
49
45 abortSelectionMode () { 50 abortSelectionMode () {
46 this.checkedVideos = {} 51 this.checkedVideos = {}
47 } 52 }
diff --git a/client/src/app/shared/misc/help.component.ts b/client/src/app/shared/misc/help.component.ts
index a4a223cd6..19ac38b58 100644
--- a/client/src/app/shared/misc/help.component.ts
+++ b/client/src/app/shared/misc/help.component.ts
@@ -46,7 +46,8 @@ export class HelpComponent implements OnInit {
46 } 46 }
47 47
48 private formatMarkdownSupport (rules: string[]) { 48 private formatMarkdownSupport (rules: string[]) {
49 return '<a href="https://en.wikipedia.org/wiki/Markdown#Example" target="_blank">Markdown</a> compatible that supports:' + 49 return '<a href="https://en.wikipedia.org/wiki/Markdown#Example" target="_blank" rel="noopener noreferrer">Markdown</a> ' +
50 'compatible that supports:' +
50 this.createMarkdownList(rules) 51 this.createMarkdownList(rules)
51 } 52 }
52 53
diff --git a/client/src/app/shared/video/abstract-video-list.ts b/client/src/app/shared/video/abstract-video-list.ts
index 7235b3425..4a220c93d 100644
--- a/client/src/app/shared/video/abstract-video-list.ts
+++ b/client/src/app/shared/video/abstract-video-list.ts
@@ -1,16 +1,18 @@
1import { ElementRef, OnInit, ViewChild } from '@angular/core' 1import { ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { ActivatedRoute, Router } from '@angular/router'
3import { isInMobileView } from '@app/shared/misc/utils' 3import { isInMobileView } from '@app/shared/misc/utils'
4import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive' 4import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive'
5import { NotificationsService } from 'angular2-notifications' 5import { NotificationsService } from 'angular2-notifications'
6import 'rxjs/add/operator/debounceTime'
6import { Observable } from 'rxjs/Observable' 7import { Observable } from 'rxjs/Observable'
7import { fromEvent } from 'rxjs/observable/fromEvent' 8import { fromEvent } from 'rxjs/observable/fromEvent'
9import { Subscription } from 'rxjs/Subscription'
8import { AuthService } from '../../core/auth' 10import { AuthService } from '../../core/auth'
9import { ComponentPagination } from '../rest/component-pagination.model' 11import { ComponentPagination } from '../rest/component-pagination.model'
10import { SortField } from './sort-field.type' 12import { SortField } from './sort-field.type'
11import { Video } from './video.model' 13import { Video } from './video.model'
12 14
13export abstract class AbstractVideoList implements OnInit { 15export abstract class AbstractVideoList implements OnInit, OnDestroy {
14 private static LINES_PER_PAGE = 3 16 private static LINES_PER_PAGE = 3
15 17
16 @ViewChild('videoElement') videosElement: ElementRef 18 @ViewChild('videoElement') videosElement: ElementRef
@@ -25,9 +27,12 @@ export abstract class AbstractVideoList implements OnInit {
25 defaultSort: SortField = '-createdAt' 27 defaultSort: SortField = '-createdAt'
26 loadOnInit = true 28 loadOnInit = true
27 pageHeight: number 29 pageHeight: number
28 videoWidth = 215 30 videoWidth: number
29 videoHeight = 230 31 videoHeight: number
30 videoPages: Video[][] 32 videoPages: Video[][] = []
33
34 protected baseVideoWidth = 215
35 protected baseVideoHeight = 230
31 36
32 protected abstract notificationsService: NotificationsService 37 protected abstract notificationsService: NotificationsService
33 protected abstract authService: AuthService 38 protected abstract authService: AuthService
@@ -39,6 +44,8 @@ export abstract class AbstractVideoList implements OnInit {
39 protected loadedPages: { [ id: number ]: Video[] } = {} 44 protected loadedPages: { [ id: number ]: Video[] } = {}
40 protected otherRouteParams = {} 45 protected otherRouteParams = {}
41 46
47 private resizeSubscription: Subscription
48
42 abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number}> 49 abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number}>
43 50
44 get user () { 51 get user () {
@@ -50,7 +57,7 @@ export abstract class AbstractVideoList implements OnInit {
50 const routeParams = this.route.snapshot.params 57 const routeParams = this.route.snapshot.params
51 this.loadRouteParams(routeParams) 58 this.loadRouteParams(routeParams)
52 59
53 fromEvent(window, 'resize') 60 this.resizeSubscription = fromEvent(window, 'resize')
54 .debounceTime(500) 61 .debounceTime(500)
55 .subscribe(() => this.calcPageSizes()) 62 .subscribe(() => this.calcPageSizes())
56 63
@@ -58,6 +65,10 @@ export abstract class AbstractVideoList implements OnInit {
58 if (this.loadOnInit === true) this.loadMoreVideos(this.pagination.currentPage) 65 if (this.loadOnInit === true) this.loadMoreVideos(this.pagination.currentPage)
59 } 66 }
60 67
68 ngOnDestroy () {
69 if (this.resizeSubscription) this.resizeSubscription.unsubscribe()
70 }
71
61 onNearOfTop () { 72 onNearOfTop () {
62 this.previousPage() 73 this.previousPage()
63 } 74 }
@@ -167,30 +178,39 @@ export abstract class AbstractVideoList implements OnInit {
167 } 178 }
168 179
169 private calcPageSizes () { 180 private calcPageSizes () {
170 if (isInMobileView()) { 181 if (isInMobileView() || this.baseVideoWidth === -1) {
171 this.pagination.itemsPerPage = 5 182 this.pagination.itemsPerPage = 5
172 183
173 // Video takes all the width 184 // Video takes all the width
174 this.videoWidth = -1 185 this.videoWidth = -1
175 this.pageHeight = this.pagination.itemsPerPage * this.videoHeight 186 this.pageHeight = this.pagination.itemsPerPage * this.videoHeight
176 } else { 187 } else {
188 this.videoWidth = this.baseVideoWidth
189 this.videoHeight = this.baseVideoHeight
190
177 const videosWidth = this.videosElement.nativeElement.offsetWidth 191 const videosWidth = this.videosElement.nativeElement.offsetWidth
178 this.pagination.itemsPerPage = Math.floor(videosWidth / this.videoWidth) * AbstractVideoList.LINES_PER_PAGE 192 this.pagination.itemsPerPage = Math.floor(videosWidth / this.videoWidth) * AbstractVideoList.LINES_PER_PAGE
179 this.pageHeight = this.videoHeight * AbstractVideoList.LINES_PER_PAGE 193 this.pageHeight = this.videoHeight * AbstractVideoList.LINES_PER_PAGE
180 } 194 }
181 195
182 // Rebuild pages because maybe we modified the number of items per page 196 // Rebuild pages because maybe we modified the number of items per page
183 let videos: Video[] = [] 197 const videos = [].concat(...this.videoPages)
184 Object.values(this.loadedPages)
185 .forEach(videosPage => videos = videos.concat(videosPage))
186 this.loadedPages = {} 198 this.loadedPages = {}
187 199
188 for (let i = 1; (i * this.pagination.itemsPerPage) <= videos.length; i++) { 200 let i = 1
189 this.loadedPages[i] = videos.slice((i - 1) * this.pagination.itemsPerPage, this.pagination.itemsPerPage * i) 201 // Don't include the last page if it not complete
202 while (videos.length >= this.pagination.itemsPerPage && i < 10000) { // 10000 -> Hard limit in case of infinite loop
203 this.loadedPages[i] = videos.splice(0, this.pagination.itemsPerPage)
204 i++
190 } 205 }
191 206
192 this.buildVideoPages() 207 // Re fetch the last page
208 if (videos.length !== 0) {
209 this.loadMoreVideos(i)
210 } else {
211 this.buildVideoPages()
212 }
193 213
194 console.log('Re calculated pages after a resize!') 214 console.log('Rebuilt pages with %s elements per page.', this.pagination.itemsPerPage)
195 } 215 }
196} 216}
diff --git a/client/src/app/shared/video/infinite-scroller.directive.ts b/client/src/app/shared/video/infinite-scroller.directive.ts
index e0f9f4f83..e2730423f 100644
--- a/client/src/app/shared/video/infinite-scroller.directive.ts
+++ b/client/src/app/shared/video/infinite-scroller.directive.ts
@@ -1,18 +1,19 @@
1import { Directive, EventEmitter, Input, OnInit, Output } from '@angular/core' 1import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'
2import 'rxjs/add/operator/debounceTime' 2import 'rxjs/add/operator/debounceTime'
3import 'rxjs/add/operator/distinct' 3import 'rxjs/add/operator/distinct'
4import 'rxjs/add/operator/distinctUntilChanged' 4import 'rxjs/add/operator/distinctUntilChanged'
5import 'rxjs/add/operator/filter' 5import 'rxjs/add/operator/filter'
6import 'rxjs/add/operator/map' 6import 'rxjs/add/operator/map'
7import 'rxjs/add/operator/share'
7import 'rxjs/add/operator/startWith' 8import 'rxjs/add/operator/startWith'
8import 'rxjs/add/operator/throttleTime' 9import 'rxjs/add/operator/throttleTime'
9import { fromEvent } from 'rxjs/observable/fromEvent' 10import { fromEvent } from 'rxjs/observable/fromEvent'
10import 'rxjs/add/operator/share' 11import { Subscription } from 'rxjs/Subscription'
11 12
12@Directive({ 13@Directive({
13 selector: '[myInfiniteScroller]' 14 selector: '[myInfiniteScroller]'
14}) 15})
15export class InfiniteScrollerDirective implements OnInit { 16export class InfiniteScrollerDirective implements OnInit, OnDestroy {
16 private static PAGE_VIEW_TOP_MARGIN = 500 17 private static PAGE_VIEW_TOP_MARGIN = 500
17 18
18 @Input() containerHeight: number 19 @Input() containerHeight: number
@@ -27,6 +28,9 @@ export class InfiniteScrollerDirective implements OnInit {
27 private decimalLimit = 0 28 private decimalLimit = 0
28 private lastCurrentBottom = -1 29 private lastCurrentBottom = -1
29 private lastCurrentTop = 0 30 private lastCurrentTop = 0
31 private scrollDownSub: Subscription
32 private scrollUpSub: Subscription
33 private pageChangeSub: Subscription
30 34
31 constructor () { 35 constructor () {
32 this.decimalLimit = this.percentLimit / 100 36 this.decimalLimit = this.percentLimit / 100
@@ -36,6 +40,12 @@ export class InfiniteScrollerDirective implements OnInit {
36 if (this.autoLoading === true) return this.initialize() 40 if (this.autoLoading === true) return this.initialize()
37 } 41 }
38 42
43 ngOnDestroy () {
44 if (this.scrollDownSub) this.scrollDownSub.unsubscribe()
45 if (this.scrollUpSub) this.scrollUpSub.unsubscribe()
46 if (this.pageChangeSub) this.pageChangeSub.unsubscribe()
47 }
48
39 initialize () { 49 initialize () {
40 // Emit the last value 50 // Emit the last value
41 const throttleOptions = { leading: true, trailing: true } 51 const throttleOptions = { leading: true, trailing: true }
@@ -48,7 +58,7 @@ export class InfiniteScrollerDirective implements OnInit {
48 .share() 58 .share()
49 59
50 // Scroll Down 60 // Scroll Down
51 scrollObservable 61 this.scrollDownSub = scrollObservable
52 // Check we scroll down 62 // Check we scroll down
53 .filter(({ current }) => { 63 .filter(({ current }) => {
54 const res = this.lastCurrentBottom < current 64 const res = this.lastCurrentBottom < current
@@ -60,7 +70,7 @@ export class InfiniteScrollerDirective implements OnInit {
60 .subscribe(() => this.nearOfBottom.emit()) 70 .subscribe(() => this.nearOfBottom.emit())
61 71
62 // Scroll up 72 // Scroll up
63 scrollObservable 73 this.scrollUpSub = scrollObservable
64 // Check we scroll up 74 // Check we scroll up
65 .filter(({ current }) => { 75 .filter(({ current }) => {
66 const res = this.lastCurrentTop > current 76 const res = this.lastCurrentTop > current
@@ -74,7 +84,7 @@ export class InfiniteScrollerDirective implements OnInit {
74 .subscribe(() => this.nearOfTop.emit()) 84 .subscribe(() => this.nearOfTop.emit())
75 85
76 // Page change 86 // Page change
77 scrollObservable 87 this.pageChangeSub = scrollObservable
78 .distinct() 88 .distinct()
79 .map(({ current }) => this.calculateCurrentPage(current)) 89 .map(({ current }) => this.calculateCurrentPage(current))
80 .distinctUntilChanged() 90 .distinctUntilChanged()
diff --git a/client/src/app/videos/+video-watch/comment/video-comment.component.html b/client/src/app/videos/+video-watch/comment/video-comment.component.html
index 831ea0521..8a649e88f 100644
--- a/client/src/app/videos/+video-watch/comment/video-comment.component.html
+++ b/client/src/app/videos/+video-watch/comment/video-comment.component.html
@@ -5,7 +5,7 @@
5 <div *ngIf="highlightedComment === true" class="highlighted-comment">Highlighted comment</div> 5 <div *ngIf="highlightedComment === true" class="highlighted-comment">Highlighted comment</div>
6 6
7 <div class="comment-account-date"> 7 <div class="comment-account-date">
8 <a target="_blank" [href]="comment.account.url" class="comment-account">{{ comment.by }}</a> 8 <a [href]="comment.account.url" target="_blank" rel="noopener noreferrer" class="comment-account">{{ comment.by }}</a>
9 <a [routerLink]="['/videos/watch', video.uuid, { 'threadId': comment.threadId }]" class="comment-date">{{ comment.createdAt | myFromNow }}</a> 9 <a [routerLink]="['/videos/watch', video.uuid, { 'threadId': comment.threadId }]" class="comment-date">{{ comment.createdAt | myFromNow }}</a>
10 </div> 10 </div>
11 <div class="comment-html" [innerHTML]="sanitizedCommentHTML"></div> 11 <div class="comment-html" [innerHTML]="sanitizedCommentHTML"></div>
diff --git a/client/src/app/videos/+video-watch/comment/video-comment.component.ts b/client/src/app/videos/+video-watch/comment/video-comment.component.ts
index cfcefed83..26fc9d0b8 100644
--- a/client/src/app/videos/+video-watch/comment/video-comment.component.ts
+++ b/client/src/app/videos/+video-watch/comment/video-comment.component.ts
@@ -107,7 +107,8 @@ export class VideoCommentComponent implements OnInit, OnChanges {
107 return { 107 return {
108 tagName, 108 tagName,
109 attribs: Object.assign(attribs, { 109 attribs: Object.assign(attribs, {
110 target: '_blank' 110 target: '_blank',
111 rel: 'noopener noreferrer'
111 }) 112 })
112 } 113 }
113 } 114 }
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 6a7da0614..6c7fc08e1 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.html
+++ b/client/src/app/videos/+video-watch/video-watch.component.html
@@ -183,7 +183,7 @@
183 <strong>Friendly Reminder:</strong> 183 <strong>Friendly Reminder:</strong>
184 <div class="privacy-concerns-text"> 184 <div class="privacy-concerns-text">
185 The sharing system used by this video implies that some technical information about your system (such as a public IP address) can be accessed publicly. 185 The sharing system used by this video implies that some technical information about your system (such as a public IP address) can be accessed publicly.
186 <a title="Get more information" target="_blank" href="/about#p2p-privacy">More information</a> 186 <a title="Get more information" target="_blank" rel="noopener noreferrer" href="/about#p2p-privacy">More information</a>
187 </div> 187 </div>
188 188
189 <div class="privacy-concerns-okay" (click)="acceptedPrivacyConcern()"> 189 <div class="privacy-concerns-okay" (click)="acceptedPrivacyConcern()">
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 7951e3927..b60e58fb0 100644
--- a/client/src/app/videos/+video-watch/video-watch.component.ts
+++ b/client/src/app/videos/+video-watch/video-watch.component.ts
@@ -7,6 +7,7 @@ import { NotificationsService } from 'angular2-notifications'
7import { Subscription } from 'rxjs/Subscription' 7import { Subscription } from 'rxjs/Subscription'
8import * as videojs from 'video.js' 8import * as videojs from 'video.js'
9import 'videojs-hotkeys' 9import 'videojs-hotkeys'
10import * as WebTorrent from 'webtorrent'
10import { UserVideoRateType, VideoRateType } from '../../../../../shared' 11import { UserVideoRateType, VideoRateType } from '../../../../../shared'
11import '../../../assets/player/peertube-videojs-plugin' 12import '../../../assets/player/peertube-videojs-plugin'
12import { AuthService, ConfirmService } from '../../core' 13import { AuthService, ConfirmService } from '../../core'
@@ -74,7 +75,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
74 } 75 }
75 76
76 ngOnInit () { 77 ngOnInit () {
77 if (localStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY) === 'true') { 78 if (WebTorrent.WEBRTC_SUPPORT === false || localStorage.getItem(VideoWatchComponent.LOCAL_STORAGE_PRIVACY_CONCERN_KEY) === 'true') {
78 this.hasAlreadyAcceptedPrivacyConcern = true 79 this.hasAlreadyAcceptedPrivacyConcern = true
79 } 80 }
80 81
diff --git a/client/src/app/videos/shared/markdown.service.ts b/client/src/app/videos/shared/markdown.service.ts
index 9d73efa46..dd8ff20d8 100644
--- a/client/src/app/videos/shared/markdown.service.ts
+++ b/client/src/app/videos/shared/markdown.service.ts
@@ -52,18 +52,19 @@ export class MarkdownService {
52 return self.renderToken(tokens, idx, options) 52 return self.renderToken(tokens, idx, options)
53 } 53 }
54 54
55 markdownIt.renderer.rules.link_open = function (tokens, idx, options, env, self) { 55 markdownIt.renderer.rules.link_open = function (tokens, index, options, env, self) {
56 // If you are sure other plugins can't add `target` - drop check below 56 const token = tokens[index]
57 const aIndex = tokens[idx].attrIndex('target')
58 57
59 if (aIndex < 0) { 58 const targetIndex = token.attrIndex('target')
60 tokens[idx].attrPush(['target', '_blank']) // add new attribute 59 if (targetIndex < 0) token.attrPush([ 'target', '_blank' ])
61 } else { 60 else token.attrs[targetIndex][1] = '_blank'
62 tokens[idx].attrs[aIndex][1] = '_blank' // replace value of existing attr 61
63 } 62 const relIndex = token.attrIndex('rel')
63 if (relIndex < 0) token.attrPush([ 'rel', 'noopener noreferrer' ])
64 else token.attrs[relIndex][1] = 'noopener noreferrer'
64 65
65 // pass token to default renderer. 66 // pass token to default renderer.
66 return defaultRender(tokens, idx, options, env, self) 67 return defaultRender(tokens, index, options, env, self)
67 } 68 }
68 } 69 }
69 70
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 8cac2c12c..8f9d50a7b 100644
--- a/client/src/app/videos/video-list/video-local.component.ts
+++ b/client/src/app/videos/video-list/video-local.component.ts
@@ -1,4 +1,4 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { 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'
@@ -12,7 +12,7 @@ import { VideoService } from '../../shared/video/video.service'
12 styleUrls: [ '../../shared/video/abstract-video-list.scss' ], 12 styleUrls: [ '../../shared/video/abstract-video-list.scss' ],
13 templateUrl: '../../shared/video/abstract-video-list.html' 13 templateUrl: '../../shared/video/abstract-video-list.html'
14}) 14})
15export class VideoLocalComponent extends AbstractVideoList implements OnInit { 15export class VideoLocalComponent extends AbstractVideoList implements OnInit, OnDestroy {
16 titlePage = 'Local videos' 16 titlePage = 'Local videos'
17 currentRoute = '/videos/local' 17 currentRoute = '/videos/local'
18 sort = '-createdAt' as SortField 18 sort = '-createdAt' as SortField
@@ -29,6 +29,10 @@ export class VideoLocalComponent extends AbstractVideoList implements OnInit {
29 super.ngOnInit() 29 super.ngOnInit()
30 } 30 }
31 31
32 ngOnDestroy () {
33 super.ngOnDestroy()
34 }
35
32 getVideosObservable (page: number) { 36 getVideosObservable (page: number) {
33 const newPagination = immutableAssign(this.pagination, { currentPage: page }) 37 const newPagination = immutableAssign(this.pagination, { currentPage: page })
34 38
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 f150e38da..1cecd14a0 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
@@ -1,4 +1,4 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { 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'
@@ -12,7 +12,7 @@ import { VideoService } from '../../shared/video/video.service'
12 styleUrls: [ '../../shared/video/abstract-video-list.scss' ], 12 styleUrls: [ '../../shared/video/abstract-video-list.scss' ],
13 templateUrl: '../../shared/video/abstract-video-list.html' 13 templateUrl: '../../shared/video/abstract-video-list.html'
14}) 14})
15export class VideoRecentlyAddedComponent extends AbstractVideoList implements OnInit { 15export class VideoRecentlyAddedComponent extends AbstractVideoList implements OnInit, OnDestroy {
16 titlePage = 'Recently added' 16 titlePage = 'Recently added'
17 currentRoute = '/videos/recently-added' 17 currentRoute = '/videos/recently-added'
18 sort: SortField = '-createdAt' 18 sort: SortField = '-createdAt'
@@ -29,6 +29,10 @@ export class VideoRecentlyAddedComponent extends AbstractVideoList implements On
29 super.ngOnInit() 29 super.ngOnInit()
30 } 30 }
31 31
32 ngOnDestroy () {
33 super.ngOnDestroy()
34 }
35
32 getVideosObservable (page: number) { 36 getVideosObservable (page: number) {
33 const newPagination = immutableAssign(this.pagination, { currentPage: page }) 37 const newPagination = immutableAssign(this.pagination, { currentPage: page })
34 38
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 241b97bc7..788797a4c 100644
--- a/client/src/app/videos/video-list/video-search.component.ts
+++ b/client/src/app/videos/video-list/video-search.component.ts
@@ -47,9 +47,9 @@ export class VideoSearchComponent extends AbstractVideoList implements OnInit, O
47 } 47 }
48 48
49 ngOnDestroy () { 49 ngOnDestroy () {
50 if (this.subActivatedRoute) { 50 super.ngOnDestroy()
51 this.subActivatedRoute.unsubscribe() 51
52 } 52 if (this.subActivatedRoute) this.subActivatedRoute.unsubscribe()
53 } 53 }
54 54
55 getVideosObservable (page: number) { 55 getVideosObservable (page: number) {
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 a42457273..1dd1ad23b 100644
--- a/client/src/app/videos/video-list/video-trending.component.ts
+++ b/client/src/app/videos/video-list/video-trending.component.ts
@@ -1,4 +1,4 @@
1import { Component, OnInit } from '@angular/core' 1import { Component, OnDestroy, OnInit } from '@angular/core'
2import { ActivatedRoute, Router } from '@angular/router' 2import { 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'
@@ -12,7 +12,7 @@ import { VideoService } from '../../shared/video/video.service'
12 styleUrls: [ '../../shared/video/abstract-video-list.scss' ], 12 styleUrls: [ '../../shared/video/abstract-video-list.scss' ],
13 templateUrl: '../../shared/video/abstract-video-list.html' 13 templateUrl: '../../shared/video/abstract-video-list.html'
14}) 14})
15export class VideoTrendingComponent extends AbstractVideoList implements OnInit { 15export class VideoTrendingComponent extends AbstractVideoList implements OnInit, OnDestroy {
16 titlePage = 'Trending' 16 titlePage = 'Trending'
17 currentRoute = '/videos/trending' 17 currentRoute = '/videos/trending'
18 defaultSort: SortField = '-views' 18 defaultSort: SortField = '-views'
@@ -29,6 +29,10 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit
29 super.ngOnInit() 29 super.ngOnInit()
30 } 30 }
31 31
32 ngOnDestroy () {
33 super.ngOnDestroy()
34 }
35
32 getVideosObservable (page: number) { 36 getVideosObservable (page: number) {
33 const newPagination = immutableAssign(this.pagination, { currentPage: page }) 37 const newPagination = immutableAssign(this.pagination, { currentPage: page })
34 return this.videoService.getVideos(newPagination, this.sort) 38 return this.videoService.getVideos(newPagination, this.sort)
diff --git a/client/src/standalone/videos/embed.ts b/client/src/standalone/videos/embed.ts
index 739ed5f45..2caab5b10 100644
--- a/client/src/standalone/videos/embed.ts
+++ b/client/src/standalone/videos/embed.ts
@@ -66,7 +66,7 @@ loadVideoInfo(videoId)
66 66
67 player.dock({ 67 player.dock({
68 title: videoInfo.name, 68 title: videoInfo.name,
69 description: 'Use P2P, other may know you are watching that video.' 69 description: 'Uses P2P, others may know you are watching this video.'
70 }) 70 })
71 }) 71 })
72 }) 72 })
diff --git a/package.json b/package.json
index 057f2b921..3e63970da 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
1{ 1{
2 "name": "peertube", 2 "name": "peertube",
3 "description": "Federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser with WebTorrent and Angular.", 3 "description": "Federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser with WebTorrent and Angular.",
4 "version": "1.0.0-alpha.8", 4 "version": "1.0.0-alpha.9",
5 "private": true, 5 "private": true,
6 "licence": "AGPLv3", 6 "licence": "AGPLv3",
7 "engines": { 7 "engines": {