diff options
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 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | 1 | import { Component, OnInit, OnDestroy } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | 2 | import { ActivatedRoute, Router } from '@angular/router' |
3 | import { immutableAssign } from '@app/shared/misc/utils' | 3 | import { immutableAssign } from '@app/shared/misc/utils' |
4 | import { ComponentPagination } from '@app/shared/rest/component-pagination.model' | 4 | import { 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 | }) |
20 | export class AccountVideosComponent extends AbstractVideoList implements OnInit { | 20 | export 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 @@ | |||
1 | import { ElementRef, OnInit, ViewChild } from '@angular/core' | 1 | import { ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | 2 | import { ActivatedRoute, Router } from '@angular/router' |
3 | import { isInMobileView } from '@app/shared/misc/utils' | 3 | import { isInMobileView } from '@app/shared/misc/utils' |
4 | import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive' | 4 | import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive' |
5 | import { NotificationsService } from 'angular2-notifications' | 5 | import { NotificationsService } from 'angular2-notifications' |
6 | import 'rxjs/add/operator/debounceTime' | ||
6 | import { Observable } from 'rxjs/Observable' | 7 | import { Observable } from 'rxjs/Observable' |
7 | import { fromEvent } from 'rxjs/observable/fromEvent' | 8 | import { fromEvent } from 'rxjs/observable/fromEvent' |
9 | import { Subscription } from 'rxjs/Subscription' | ||
8 | import { AuthService } from '../../core/auth' | 10 | import { AuthService } from '../../core/auth' |
9 | import { ComponentPagination } from '../rest/component-pagination.model' | 11 | import { ComponentPagination } from '../rest/component-pagination.model' |
10 | import { SortField } from './sort-field.type' | 12 | import { SortField } from './sort-field.type' |
11 | import { Video } from './video.model' | 13 | import { Video } from './video.model' |
12 | 14 | ||
13 | export abstract class AbstractVideoList implements OnInit { | 15 | export 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 @@ | |||
1 | import { Directive, EventEmitter, Input, OnInit, Output } from '@angular/core' | 1 | import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core' |
2 | import 'rxjs/add/operator/debounceTime' | 2 | import 'rxjs/add/operator/debounceTime' |
3 | import 'rxjs/add/operator/distinct' | 3 | import 'rxjs/add/operator/distinct' |
4 | import 'rxjs/add/operator/distinctUntilChanged' | 4 | import 'rxjs/add/operator/distinctUntilChanged' |
5 | import 'rxjs/add/operator/filter' | 5 | import 'rxjs/add/operator/filter' |
6 | import 'rxjs/add/operator/map' | 6 | import 'rxjs/add/operator/map' |
7 | import 'rxjs/add/operator/share' | ||
7 | import 'rxjs/add/operator/startWith' | 8 | import 'rxjs/add/operator/startWith' |
8 | import 'rxjs/add/operator/throttleTime' | 9 | import 'rxjs/add/operator/throttleTime' |
9 | import { fromEvent } from 'rxjs/observable/fromEvent' | 10 | import { fromEvent } from 'rxjs/observable/fromEvent' |
10 | import 'rxjs/add/operator/share' | 11 | import { Subscription } from 'rxjs/Subscription' |
11 | 12 | ||
12 | @Directive({ | 13 | @Directive({ |
13 | selector: '[myInfiniteScroller]' | 14 | selector: '[myInfiniteScroller]' |
14 | }) | 15 | }) |
15 | export class InfiniteScrollerDirective implements OnInit { | 16 | export 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' | |||
7 | import { Subscription } from 'rxjs/Subscription' | 7 | import { Subscription } from 'rxjs/Subscription' |
8 | import * as videojs from 'video.js' | 8 | import * as videojs from 'video.js' |
9 | import 'videojs-hotkeys' | 9 | import 'videojs-hotkeys' |
10 | import * as WebTorrent from 'webtorrent' | ||
10 | import { UserVideoRateType, VideoRateType } from '../../../../../shared' | 11 | import { UserVideoRateType, VideoRateType } from '../../../../../shared' |
11 | import '../../../assets/player/peertube-videojs-plugin' | 12 | import '../../../assets/player/peertube-videojs-plugin' |
12 | import { AuthService, ConfirmService } from '../../core' | 13 | import { 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 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | 1 | import { Component, OnDestroy, OnInit } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | 2 | import { ActivatedRoute, Router } from '@angular/router' |
3 | import { immutableAssign } from '@app/shared/misc/utils' | 3 | import { immutableAssign } from '@app/shared/misc/utils' |
4 | import { NotificationsService } from 'angular2-notifications' | 4 | import { 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 | }) |
15 | export class VideoLocalComponent extends AbstractVideoList implements OnInit { | 15 | export 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 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | 1 | import { Component, OnDestroy, OnInit } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | 2 | import { ActivatedRoute, Router } from '@angular/router' |
3 | import { immutableAssign } from '@app/shared/misc/utils' | 3 | import { immutableAssign } from '@app/shared/misc/utils' |
4 | import { NotificationsService } from 'angular2-notifications' | 4 | import { 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 | }) |
15 | export class VideoRecentlyAddedComponent extends AbstractVideoList implements OnInit { | 15 | export 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 @@ | |||
1 | import { Component, OnInit } from '@angular/core' | 1 | import { Component, OnDestroy, OnInit } from '@angular/core' |
2 | import { ActivatedRoute, Router } from '@angular/router' | 2 | import { ActivatedRoute, Router } from '@angular/router' |
3 | import { immutableAssign } from '@app/shared/misc/utils' | 3 | import { immutableAssign } from '@app/shared/misc/utils' |
4 | import { NotificationsService } from 'angular2-notifications' | 4 | import { 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 | }) |
15 | export class VideoTrendingComponent extends AbstractVideoList implements OnInit { | 15 | export 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": { |