diff options
7 files changed, 68 insertions, 26 deletions
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/video/abstract-video-list.ts b/client/src/app/shared/video/abstract-video-list.ts index 570aaae9d..4a220c93d 100644 --- a/client/src/app/shared/video/abstract-video-list.ts +++ b/client/src/app/shared/video/abstract-video-list.ts | |||
@@ -1,4 +1,4 @@ | |||
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' |
@@ -6,12 +6,13 @@ import { NotificationsService } from 'angular2-notifications' | |||
6 | import 'rxjs/add/operator/debounceTime' | 6 | import 'rxjs/add/operator/debounceTime' |
7 | import { Observable } from 'rxjs/Observable' | 7 | import { Observable } from 'rxjs/Observable' |
8 | import { fromEvent } from 'rxjs/observable/fromEvent' | 8 | import { fromEvent } from 'rxjs/observable/fromEvent' |
9 | import { Subscription } from 'rxjs/Subscription' | ||
9 | import { AuthService } from '../../core/auth' | 10 | import { AuthService } from '../../core/auth' |
10 | import { ComponentPagination } from '../rest/component-pagination.model' | 11 | import { ComponentPagination } from '../rest/component-pagination.model' |
11 | import { SortField } from './sort-field.type' | 12 | import { SortField } from './sort-field.type' |
12 | import { Video } from './video.model' | 13 | import { Video } from './video.model' |
13 | 14 | ||
14 | export abstract class AbstractVideoList implements OnInit { | 15 | export abstract class AbstractVideoList implements OnInit, OnDestroy { |
15 | private static LINES_PER_PAGE = 3 | 16 | private static LINES_PER_PAGE = 3 |
16 | 17 | ||
17 | @ViewChild('videoElement') videosElement: ElementRef | 18 | @ViewChild('videoElement') videosElement: ElementRef |
@@ -30,6 +31,9 @@ export abstract class AbstractVideoList implements OnInit { | |||
30 | videoHeight: number | 31 | videoHeight: number |
31 | videoPages: Video[][] = [] | 32 | videoPages: Video[][] = [] |
32 | 33 | ||
34 | protected baseVideoWidth = 215 | ||
35 | protected baseVideoHeight = 230 | ||
36 | |||
33 | protected abstract notificationsService: NotificationsService | 37 | protected abstract notificationsService: NotificationsService |
34 | protected abstract authService: AuthService | 38 | protected abstract authService: AuthService |
35 | protected abstract router: Router | 39 | protected abstract router: Router |
@@ -40,6 +44,8 @@ export abstract class AbstractVideoList implements OnInit { | |||
40 | protected loadedPages: { [ id: number ]: Video[] } = {} | 44 | protected loadedPages: { [ id: number ]: Video[] } = {} |
41 | protected otherRouteParams = {} | 45 | protected otherRouteParams = {} |
42 | 46 | ||
47 | private resizeSubscription: Subscription | ||
48 | |||
43 | abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number}> | 49 | abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number}> |
44 | 50 | ||
45 | get user () { | 51 | get user () { |
@@ -51,7 +57,7 @@ export abstract class AbstractVideoList implements OnInit { | |||
51 | const routeParams = this.route.snapshot.params | 57 | const routeParams = this.route.snapshot.params |
52 | this.loadRouteParams(routeParams) | 58 | this.loadRouteParams(routeParams) |
53 | 59 | ||
54 | fromEvent(window, 'resize') | 60 | this.resizeSubscription = fromEvent(window, 'resize') |
55 | .debounceTime(500) | 61 | .debounceTime(500) |
56 | .subscribe(() => this.calcPageSizes()) | 62 | .subscribe(() => this.calcPageSizes()) |
57 | 63 | ||
@@ -59,6 +65,10 @@ export abstract class AbstractVideoList implements OnInit { | |||
59 | if (this.loadOnInit === true) this.loadMoreVideos(this.pagination.currentPage) | 65 | if (this.loadOnInit === true) this.loadMoreVideos(this.pagination.currentPage) |
60 | } | 66 | } |
61 | 67 | ||
68 | ngOnDestroy () { | ||
69 | if (this.resizeSubscription) this.resizeSubscription.unsubscribe() | ||
70 | } | ||
71 | |||
62 | onNearOfTop () { | 72 | onNearOfTop () { |
63 | this.previousPage() | 73 | this.previousPage() |
64 | } | 74 | } |
@@ -168,15 +178,15 @@ export abstract class AbstractVideoList implements OnInit { | |||
168 | } | 178 | } |
169 | 179 | ||
170 | private calcPageSizes () { | 180 | private calcPageSizes () { |
171 | if (isInMobileView()) { | 181 | if (isInMobileView() || this.baseVideoWidth === -1) { |
172 | this.pagination.itemsPerPage = 5 | 182 | this.pagination.itemsPerPage = 5 |
173 | 183 | ||
174 | // Video takes all the width | 184 | // Video takes all the width |
175 | this.videoWidth = -1 | 185 | this.videoWidth = -1 |
176 | this.pageHeight = this.pagination.itemsPerPage * this.videoHeight | 186 | this.pageHeight = this.pagination.itemsPerPage * this.videoHeight |
177 | } else { | 187 | } else { |
178 | this.videoWidth = 215 | 188 | this.videoWidth = this.baseVideoWidth |
179 | this.videoHeight = 230 | 189 | this.videoHeight = this.baseVideoHeight |
180 | 190 | ||
181 | const videosWidth = this.videosElement.nativeElement.offsetWidth | 191 | const videosWidth = this.videosElement.nativeElement.offsetWidth |
182 | 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 |
@@ -194,7 +204,12 @@ export abstract class AbstractVideoList implements OnInit { | |||
194 | i++ | 204 | i++ |
195 | } | 205 | } |
196 | 206 | ||
197 | this.buildVideoPages() | 207 | // Re fetch the last page |
208 | if (videos.length !== 0) { | ||
209 | this.loadMoreVideos(i) | ||
210 | } else { | ||
211 | this.buildVideoPages() | ||
212 | } | ||
198 | 213 | ||
199 | console.log('Rebuilt pages with %s elements per page.', this.pagination.itemsPerPage) | 214 | console.log('Rebuilt pages with %s elements per page.', this.pagination.itemsPerPage) |
200 | } | 215 | } |
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-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) |