diff options
author | Chocobozzz <me@florianbigard.com> | 2018-09-17 17:36:46 +0200 |
---|---|---|
committer | Chocobozzz <me@florianbigard.com> | 2018-09-17 17:45:55 +0200 |
commit | a8ecc6f6709bdb54c47c7dd7cd18ef371254c3af (patch) | |
tree | 25f510b34e7401ec5cbc59b3a6b38323992694a5 | |
parent | 415acc63cf3b51c91f70f75fe93ad0384f7d176a (diff) | |
download | PeerTube-a8ecc6f6709bdb54c47c7dd7cd18ef371254c3af.tar.gz PeerTube-a8ecc6f6709bdb54c47c7dd7cd18ef371254c3af.tar.zst PeerTube-a8ecc6f6709bdb54c47c7dd7cd18ef371254c3af.zip |
Try to improve infinite pagination
-rw-r--r-- | client/src/app/shared/video/abstract-video-list.html | 2 | ||||
-rw-r--r-- | client/src/app/shared/video/abstract-video-list.ts | 29 | ||||
-rw-r--r-- | client/src/app/shared/video/infinite-scroller.directive.ts | 13 |
3 files changed, 37 insertions, 7 deletions
diff --git a/client/src/app/shared/video/abstract-video-list.html b/client/src/app/shared/video/abstract-video-list.html index 0f48b9a64..4ad4e3568 100644 --- a/client/src/app/shared/video/abstract-video-list.html +++ b/client/src/app/shared/video/abstract-video-list.html | |||
@@ -7,7 +7,7 @@ | |||
7 | <div class="no-results" i18n *ngIf="pagination.totalItems === 0">No results.</div> | 7 | <div class="no-results" i18n *ngIf="pagination.totalItems === 0">No results.</div> |
8 | <div | 8 | <div |
9 | myInfiniteScroller | 9 | myInfiniteScroller |
10 | [pageHeight]="pageHeight" | 10 | [pageHeight]="pageHeight" [firstLoadedPage]="firstLoadedPage" |
11 | (nearOfTop)="onNearOfTop()" (nearOfBottom)="onNearOfBottom()" (pageChanged)="onPageChanged($event)" | 11 | (nearOfTop)="onNearOfTop()" (nearOfBottom)="onNearOfBottom()" (pageChanged)="onPageChanged($event)" |
12 | class="videos" #videosElement | 12 | class="videos" #videosElement |
13 | > | 13 | > |
diff --git a/client/src/app/shared/video/abstract-video-list.ts b/client/src/app/shared/video/abstract-video-list.ts index b8fd7f8eb..9df4cfc22 100644 --- a/client/src/app/shared/video/abstract-video-list.ts +++ b/client/src/app/shared/video/abstract-video-list.ts | |||
@@ -38,7 +38,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy { | |||
38 | ownerDisplayType: OwnerDisplayType = 'account' | 38 | ownerDisplayType: OwnerDisplayType = 'account' |
39 | 39 | ||
40 | protected baseVideoWidth = 215 | 40 | protected baseVideoWidth = 215 |
41 | protected baseVideoHeight = 230 | 41 | protected baseVideoHeight = 205 |
42 | 42 | ||
43 | protected abstract notificationsService: NotificationsService | 43 | protected abstract notificationsService: NotificationsService |
44 | protected abstract authService: AuthService | 44 | protected abstract authService: AuthService |
@@ -55,6 +55,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy { | |||
55 | protected otherRouteParams = {} | 55 | protected otherRouteParams = {} |
56 | 56 | ||
57 | private resizeSubscription: Subscription | 57 | private resizeSubscription: Subscription |
58 | private firstLoadedPage: number | ||
58 | 59 | ||
59 | abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number}> | 60 | abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number}> |
60 | abstract generateSyndicationList () | 61 | abstract generateSyndicationList () |
@@ -100,7 +101,11 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy { | |||
100 | this.loadMoreVideos(this.pagination.currentPage) | 101 | this.loadMoreVideos(this.pagination.currentPage) |
101 | } | 102 | } |
102 | 103 | ||
103 | loadMoreVideos (page: number) { | 104 | loadMoreVideos (page: number, loadOnTop = false) { |
105 | this.adjustVideoPageHeight() | ||
106 | |||
107 | const currentY = window.scrollY | ||
108 | |||
104 | if (this.loadedPages[page] !== undefined) return | 109 | if (this.loadedPages[page] !== undefined) return |
105 | if (this.loadingPage[page] === true) return | 110 | if (this.loadingPage[page] === true) return |
106 | 111 | ||
@@ -111,6 +116,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy { | |||
111 | ({ videos, totalVideos }) => { | 116 | ({ videos, totalVideos }) => { |
112 | this.loadingPage[page] = false | 117 | this.loadingPage[page] = false |
113 | 118 | ||
119 | if (this.firstLoadedPage === undefined || this.firstLoadedPage > page) this.firstLoadedPage = page | ||
120 | |||
114 | // Paging is too high, return to the first one | 121 | // Paging is too high, return to the first one |
115 | if (this.pagination.currentPage > 1 && totalVideos <= ((this.pagination.currentPage - 1) * this.pagination.itemsPerPage)) { | 122 | if (this.pagination.currentPage > 1 && totalVideos <= ((this.pagination.currentPage - 1) * this.pagination.itemsPerPage)) { |
116 | this.pagination.currentPage = 1 | 123 | this.pagination.currentPage = 1 |
@@ -125,8 +132,17 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy { | |||
125 | // Initialize infinite scroller now we loaded the first page | 132 | // Initialize infinite scroller now we loaded the first page |
126 | if (Object.keys(this.loadedPages).length === 1) { | 133 | if (Object.keys(this.loadedPages).length === 1) { |
127 | // Wait elements creation | 134 | // Wait elements creation |
128 | setTimeout(() => this.infiniteScroller.initialize(), 500) | 135 | setTimeout(() => { |
136 | this.infiniteScroller.initialize() | ||
137 | |||
138 | // At our first load, we did not load the first page | ||
139 | // Load the previous page so the user can move on the top (and browser previous pages) | ||
140 | if (this.pagination.currentPage > 1) this.loadMoreVideos(this.pagination.currentPage - 1, true) | ||
141 | }, 500) | ||
129 | } | 142 | } |
143 | |||
144 | // Insert elements on the top but keep the scroll in the previous position | ||
145 | if (loadOnTop) setTimeout(() => { window.scrollTo(0, currentY + this.pageHeight) }, 0) | ||
130 | }, | 146 | }, |
131 | error => { | 147 | error => { |
132 | this.loadingPage[page] = false | 148 | this.loadingPage[page] = false |
@@ -189,6 +205,13 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy { | |||
189 | this.videoPages = Object.values(this.loadedPages) | 205 | this.videoPages = Object.values(this.loadedPages) |
190 | } | 206 | } |
191 | 207 | ||
208 | protected adjustVideoPageHeight () { | ||
209 | const numberOfPagesLoaded = Object.keys(this.loadedPages).length | ||
210 | if (!numberOfPagesLoaded) return | ||
211 | |||
212 | this.pageHeight = this.videosElement.nativeElement.offsetHeight / numberOfPagesLoaded | ||
213 | } | ||
214 | |||
192 | protected buildVideoHeight () { | 215 | protected buildVideoHeight () { |
193 | // Same ratios than base width/height | 216 | // Same ratios than base width/height |
194 | return this.videosElement.nativeElement.offsetWidth * (this.baseVideoHeight / this.baseVideoWidth) | 217 | return this.videosElement.nativeElement.offsetWidth * (this.baseVideoHeight / this.baseVideoWidth) |
diff --git a/client/src/app/shared/video/infinite-scroller.directive.ts b/client/src/app/shared/video/infinite-scroller.directive.ts index 4dc1f86e7..a02e9444a 100644 --- a/client/src/app/shared/video/infinite-scroller.directive.ts +++ b/client/src/app/shared/video/infinite-scroller.directive.ts | |||
@@ -6,10 +6,9 @@ import { fromEvent, Subscription } from 'rxjs' | |||
6 | selector: '[myInfiniteScroller]' | 6 | selector: '[myInfiniteScroller]' |
7 | }) | 7 | }) |
8 | export class InfiniteScrollerDirective implements OnInit, OnDestroy { | 8 | export class InfiniteScrollerDirective implements OnInit, OnDestroy { |
9 | private static PAGE_VIEW_TOP_MARGIN = 500 | ||
10 | |||
11 | @Input() containerHeight: number | 9 | @Input() containerHeight: number |
12 | @Input() pageHeight: number | 10 | @Input() pageHeight: number |
11 | @Input() firstLoadedPage = 1 | ||
13 | @Input() percentLimit = 70 | 12 | @Input() percentLimit = 70 |
14 | @Input() autoInit = false | 13 | @Input() autoInit = false |
15 | 14 | ||
@@ -23,6 +22,7 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { | |||
23 | private scrollDownSub: Subscription | 22 | private scrollDownSub: Subscription |
24 | private scrollUpSub: Subscription | 23 | private scrollUpSub: Subscription |
25 | private pageChangeSub: Subscription | 24 | private pageChangeSub: Subscription |
25 | private middleScreen: number | ||
26 | 26 | ||
27 | constructor () { | 27 | constructor () { |
28 | this.decimalLimit = this.percentLimit / 100 | 28 | this.decimalLimit = this.percentLimit / 100 |
@@ -39,6 +39,8 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { | |||
39 | } | 39 | } |
40 | 40 | ||
41 | initialize () { | 41 | initialize () { |
42 | this.middleScreen = window.innerHeight / 2 | ||
43 | |||
42 | // Emit the last value | 44 | // Emit the last value |
43 | const throttleOptions = { leading: true, trailing: true } | 45 | const throttleOptions = { leading: true, trailing: true } |
44 | 46 | ||
@@ -92,6 +94,11 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy { | |||
92 | } | 94 | } |
93 | 95 | ||
94 | private calculateCurrentPage (current: number) { | 96 | private calculateCurrentPage (current: number) { |
95 | return Math.max(1, Math.round((current + InfiniteScrollerDirective.PAGE_VIEW_TOP_MARGIN) / this.pageHeight)) | 97 | const scrollY = current + this.middleScreen |
98 | |||
99 | const page = Math.max(1, Math.ceil(scrollY / this.pageHeight)) | ||
100 | |||
101 | // Offset page | ||
102 | return page + (this.firstLoadedPage - 1) | ||
96 | } | 103 | } |
97 | } | 104 | } |