Rewrite infinite scroll
authorChocobozzz <me@florianbigard.com>
Tue, 13 Feb 2018 13:11:05 +0000 (14:11 +0100)
committerChocobozzz <me@florianbigard.com>
Tue, 13 Feb 2018 13:20:46 +0000 (14:20 +0100)
15 files changed:
client/package.json
client/src/app/account/account-videos/account-videos.component.html
client/src/app/account/account-videos/account-videos.component.scss
client/src/app/account/account-videos/account-videos.component.ts
client/src/app/shared/misc/utils.ts
client/src/app/shared/shared.module.ts
client/src/app/shared/video/abstract-video-list.html
client/src/app/shared/video/abstract-video-list.ts
client/src/app/shared/video/infinite-scroller.directive.ts [new file with mode: 0644]
client/src/app/videos/+video-watch/comment/video-comments.component.html
client/src/app/videos/+video-watch/comment/video-comments.component.ts
client/src/app/videos/video-list/video-recently-added.component.ts
client/src/app/videos/video-list/video-search.component.ts
client/src/app/videos/video-list/video-trending.component.ts
client/yarn.lock

index 4cb0b002c316dca961985b311e1015480a1b44de..fe8bdd1f9544487476b9d0f96e4fb66d53337476 100644 (file)
@@ -61,7 +61,6 @@
     "ngx-bootstrap": "2.0.2",
     "ngx-chips": "1.6.3",
     "ngx-clipboard": "9.0.1",
-    "ngx-infinite-scroll": "0.7.2",
     "ngx-pipes": "^2.0.5",
     "node-sass": "^4.1.1",
     "npm-font-source-sans-pro": "^1.0.2",
index 0755158b98050ce55d6db588900cdec189d845b7..3d8c656eefd7a24e2bd9083b13495705725872a4 100644 (file)
@@ -1,44 +1,44 @@
 <div *ngIf="pagination.totalItems === 0">No results.</div>
 
 <div
-  class="videos"
-  infiniteScroll
-  [infiniteScrollDistance]="0.5"
-  [infiniteScrollUpDistance]="1.5"
-  (scrolled)="onNearOfBottom()"
-  (scrolledUp)="onNearOfTop()"
+  myInfiniteScroller
+  [pageHeight]="pageHeight"
+  (nearOfTop)="onNearOfTop()" (nearOfBottom)="onNearOfBottom()" (pageChanged)="onPageChanged($event)"
+  class="videos" #videoElement
 >
-  <div class="video" *ngFor="let video of videos; let i = index">
-    <div class="checkbox-container">
-      <input [id]="'video-check-' + i" type="checkbox" [(ngModel)]="checkedVideos[video.id]" />
-      <label [for]="'video-check-' + i"></label>
-    </div>
+  <div *ngFor="let videos of videoPages; let i = index" class="videos-page">
+    <div class="video" *ngFor="let video of videos; let j = index">
+      <div class="checkbox-container">
+        <input [id]="'video-check-' + video.id" type="checkbox" [(ngModel)]="checkedVideos[video.id]" />
+        <label [for]="'video-check-' + video.id"></label>
+      </div>
 
-    <my-video-thumbnail [video]="video"></my-video-thumbnail>
+      <my-video-thumbnail [video]="video"></my-video-thumbnail>
 
-    <div class="video-info">
-      <a class="video-info-name" [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name">{{ video.name }}</a>
-      <span class="video-info-date-views">{{ video.createdAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
-    </div>
+      <div class="video-info">
+        <a class="video-info-name" [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name">{{ video.name }}</a>
+        <span class="video-info-date-views">{{ video.createdAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
+      </div>
 
-    <!-- Display only once -->
-    <div class="action-selection-mode" *ngIf="isInSelectionMode() === true && i === 0">
-      <div class="action-selection-mode-child">
-        <span class="action-button action-button-cancel-selection" (click)="abortSelectionMode()">
-          Cancel
-        </span>
+      <!-- Display only once -->
+      <div class="action-selection-mode" *ngIf="isInSelectionMode() === true && i === 0 && j === 0">
+        <div class="action-selection-mode-child">
+          <span class="action-button action-button-cancel-selection" (click)="abortSelectionMode()">
+            Cancel
+          </span>
 
-        <span class="action-button action-button-delete-selection" (click)="deleteSelectedVideos()">
-          <span class="icon icon-delete-white"></span>
-          Delete
-        </span>
+          <span class="action-button action-button-delete-selection" (click)="deleteSelectedVideos()">
+            <span class="icon icon-delete-white"></span>
+            Delete
+          </span>
+        </div>
       </div>
-    </div>
 
-    <div class="video-buttons" *ngIf="isInSelectionMode() === false">
-      <my-delete-button (click)="deleteVideo(video)"></my-delete-button>
+      <div class="video-buttons" *ngIf="isInSelectionMode() === false">
+        <my-delete-button (click)="deleteVideo(video)"></my-delete-button>
 
-      <my-edit-button [routerLink]="[ '/videos', 'edit', video.uuid ]"></my-edit-button>
+        <my-edit-button [routerLink]="[ '/videos', 'edit', video.uuid ]"></my-edit-button>
+      </div>
     </div>
   </div>
 </div>
index 707bd66add980e2efcc5471439636e6d97b4fcd1..449cc6af4ae1eb1c99d73face6b609ae4c20f762 100644 (file)
   display: flex;
   min-height: 130px;
   padding-bottom: 20px;
+  margin-bottom: 20px;
+  border-bottom: 1px solid #C6C6C6;
 
   &:first-child {
     margin-top: 47px;
   }
 
-  &:not(:last-child) {
-    margin-bottom: 20px;
-    border-bottom: 1px solid #C6C6C6;
-  }
-
   .checkbox-container {
     display: flex;
     align-items: center;
index bce13555792222ba119e193520d4be6e6f6d7a64..e9d044dbf43d27c797dab02b7853ccf8b93704f8 100644 (file)
@@ -1,5 +1,7 @@
 import { Component, OnInit } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
+import { immutableAssign } from '@app/shared/misc/utils'
+import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
 import { NotificationsService } from 'angular2-notifications'
 import 'rxjs/add/observable/from'
 import 'rxjs/add/operator/concatAll'
@@ -19,7 +21,9 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit
   titlePage = 'My videos'
   currentRoute = '/account/videos'
   checkedVideos: { [ id: number ]: boolean } = {}
-  pagination = {
+  videoHeight = 155
+  videoWidth = -1
+  pagination: ComponentPagination = {
     currentPage: 1,
     itemsPerPage: 10,
     totalItems: null
@@ -46,8 +50,10 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit
     return Object.keys(this.checkedVideos).some(k => this.checkedVideos[k] === true)
   }
 
-  getVideosObservable () {
-    return this.videoService.getMyVideos(this.pagination, this.sort)
+  getVideosObservable (page: number) {
+    const newPagination = immutableAssign(this.pagination, { currentPage: page })
+
+    return this.videoService.getMyVideos(newPagination, this.sort)
   }
 
   deleteSelectedVideos () {
@@ -71,9 +77,12 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit
         Observable.from(observables)
           .concatAll()
           .subscribe(
-            res => this.notificationsService.success('Success', `${toDeleteVideosIds.length} videos deleted.`),
+            res => {
+              this.notificationsService.success('Success', `${toDeleteVideosIds.length} videos deleted.`)
+              this.buildVideoPages()
+            },
 
-          err => this.notificationsService.error('Error', err.message)
+            err => this.notificationsService.error('Error', err.message)
           )
       }
     )
@@ -89,6 +98,7 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit
             status => {
               this.notificationsService.success('Success', `Video ${video.name} deleted.`)
               this.spliceVideosById(video.id)
+              this.buildVideoPages()
             },
 
             error => this.notificationsService.error('Error', error.message)
@@ -98,7 +108,14 @@ export class AccountVideosComponent extends AbstractVideoList implements OnInit
   }
 
   private spliceVideosById (id: number) {
-    const index = this.videos.findIndex(v => v.id === id)
-    this.videos.splice(index, 1)
+    for (const key of Object.keys(this.loadedPages)) {
+      const videos = this.loadedPages[key]
+      const index = videos.findIndex(v => v.id === id)
+
+      if (index !== -1) {
+        videos.splice(index, 1)
+        return
+      }
+    }
   }
 }
index 6620ac9737f5fe5678c125d32cd6d36d26b4811f..e6a6970983a0a8a45f9603c49a21d9ef925bc8e2 100644 (file)
@@ -55,6 +55,10 @@ function dateToHuman (date: string) {
   return datePipe.transform(date, 'medium')
 }
 
+function immutableAssign <A, B> (target: A, source: B) {
+  return Object.assign({}, target, source)
+}
+
 function isInSmallView () {
   return window.innerWidth < 600
 }
@@ -70,5 +74,6 @@ export {
   getAbsoluteAPIUrl,
   dateToHuman,
   isInSmallView,
-  isInMobileView
+  isInMobileView,
+  immutableAssign
 }
index d8f98bdf6c87e30991a9a66fb0a9a84dd8535e52..330a0ba84a4d3c5240900b0840a0cfe94e629777 100644 (file)
@@ -4,13 +4,13 @@ import { NgModule } from '@angular/core'
 import { FormsModule, ReactiveFormsModule } from '@angular/forms'
 import { RouterModule } from '@angular/router'
 import { MarkdownTextareaComponent } from '@app/shared/forms/markdown-textarea.component'
+import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive'
 import { MarkdownService } from '@app/videos/shared'
 import { LoadingBarHttpClientModule } from '@ngx-loading-bar/http-client'
 
 import { BsDropdownModule } from 'ngx-bootstrap/dropdown'
 import { ModalModule } from 'ngx-bootstrap/modal'
 import { TabsModule } from 'ngx-bootstrap/tabs'
-import { InfiniteScrollModule } from 'ngx-infinite-scroll'
 import { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes'
 import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared'
 
@@ -42,7 +42,6 @@ import { VideoService } from './video/video.service'
     ModalModule.forRoot(),
 
     PrimeSharedModule,
-    InfiniteScrollModule,
     NgPipesModule,
     TabsModule.forRoot()
   ],
@@ -55,7 +54,8 @@ import { VideoService } from './video/video.service'
     EditButtonComponent,
     NumberFormatterPipe,
     FromNowPipe,
-    MarkdownTextareaComponent
+    MarkdownTextareaComponent,
+    InfiniteScrollerDirective
   ],
 
   exports: [
@@ -70,7 +70,6 @@ import { VideoService } from './video/video.service'
     BsDropdownModule,
     ModalModule,
     PrimeSharedModule,
-    InfiniteScrollModule,
     BytesPipe,
     KeysPipe,
 
@@ -80,6 +79,7 @@ import { VideoService } from './video/video.service'
     DeleteButtonComponent,
     EditButtonComponent,
     MarkdownTextareaComponent,
+    InfiniteScrollerDirective,
 
     NumberFormatterPipe,
     FromNowPipe
index 60a2563b3dc2f56ada96d3a063daf29723a2c3a5..fb7f8685281f8684883013d2edd07b338f114fe2 100644 (file)
@@ -6,17 +6,17 @@
   <div *ngIf="pagination.totalItems === 0">No results.</div>
 
   <div
-    class="videos"
-    infiniteScroll
-    [infiniteScrollUpDistance]="1.5"
-    [infiniteScrollDistance]="0.5"
-    (scrolled)="onNearOfBottom()"
-    (scrolledUp)="onNearOfTop()"
+    myInfiniteScroller
+    [pageHeight]="pageHeight"
+    (nearOfTop)="onNearOfTop()" (nearOfBottom)="onNearOfBottom()" (pageChanged)="onPageChanged($event)"
+    class="videos" #videoElement
   >
-    <my-video-miniature
-      class="ng-animate"
-      *ngFor="let video of videos" [video]="video" [user]="user"
-    >
-    </my-video-miniature>
+    <div *ngFor="let videos of videoPages" class="videos-page">
+      <my-video-miniature
+        class="ng-animate"
+        *ngFor="let video of videos" [video]="video" [user]="user"
+      >
+      </my-video-miniature>
+    </div>
   </div>
 </div>
index a25fc532c4b319c37ab4bcd59b45eae16273b5c8..034d0d879a9e4372e2e9047b5353c2a7073169cd 100644 (file)
@@ -1,6 +1,7 @@
-import { OnInit } from '@angular/core'
+import { ElementRef, OnInit, ViewChild, ViewChildren } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
-import { isInMobileView, isInSmallView } from '@app/shared/misc/utils'
+import { isInMobileView } from '@app/shared/misc/utils'
+import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive'
 import { NotificationsService } from 'angular2-notifications'
 import { Observable } from 'rxjs/Observable'
 import { AuthService } from '../../core/auth'
@@ -9,30 +10,35 @@ import { SortField } from './sort-field.type'
 import { Video } from './video.model'
 
 export abstract class AbstractVideoList implements OnInit {
+  private static LINES_PER_PAGE = 3
+
+  @ViewChild('videoElement') videosElement: ElementRef
+  @ViewChild(InfiniteScrollerDirective) infiniteScroller: InfiniteScrollerDirective
+
   pagination: ComponentPagination = {
     currentPage: 1,
-    itemsPerPage: 25,
+    itemsPerPage: 10,
     totalItems: null
   }
   sort: SortField = '-createdAt'
   defaultSort: SortField = '-createdAt'
-  videos: Video[] = []
   loadOnInit = true
+  pageHeight: number
+  videoWidth = 215
+  videoHeight = 230
+  videoPages: Video[][]
 
   protected abstract notificationsService: NotificationsService
   protected abstract authService: AuthService
   protected abstract router: Router
   protected abstract route: ActivatedRoute
-
   protected abstract currentRoute: string
-
   abstract titlePage: string
 
-  protected otherParams = {}
-
-  private loadedPages: { [ id: number ]: boolean } = {}
+  protected loadedPages: { [ id: number ]: Video[] } = {}
+  protected otherRouteParams = {}
 
-  abstract getVideosObservable (): Observable<{ videos: Video[], totalVideos: number}>
+  abstract getVideosObservable (page: number): Observable<{ videos: Video[], totalVideos: number}>
 
   get user () {
     return this.authService.getUser()
@@ -45,15 +51,26 @@ export abstract class AbstractVideoList implements OnInit {
 
     if (isInMobileView()) {
       this.pagination.itemsPerPage = 5
+      this.videoWidth = -1
+    }
+
+    if (this.videoWidth !== -1) {
+      const videosWidth = this.videosElement.nativeElement.offsetWidth
+      this.pagination.itemsPerPage = Math.floor(videosWidth / this.videoWidth) * AbstractVideoList.LINES_PER_PAGE
+    }
+
+    // Video takes all the width
+    if (this.videoWidth === -1) {
+      this.pageHeight = this.pagination.itemsPerPage * this.videoHeight
+    } else {
+      this.pageHeight = this.videoHeight * AbstractVideoList.LINES_PER_PAGE
     }
 
-    if (this.loadOnInit === true) this.loadMoreVideos('after')
+    if (this.loadOnInit === true) this.loadMoreVideos(this.pagination.currentPage)
   }
 
   onNearOfTop () {
-    if (this.pagination.currentPage > 1) {
-      this.previousPage()
-    }
+    this.previousPage()
   }
 
   onNearOfBottom () {
@@ -62,16 +79,20 @@ export abstract class AbstractVideoList implements OnInit {
     }
   }
 
+  onPageChanged (page: number) {
+    this.pagination.currentPage = page
+    this.setNewRouteParams()
+  }
+
   reloadVideos () {
-    this.videos = []
     this.loadedPages = {}
-    this.loadMoreVideos('before')
+    this.loadMoreVideos(this.pagination.currentPage)
   }
 
-  loadMoreVideos (where: 'before' | 'after') {
-    if (this.loadedPages[this.pagination.currentPage] === true) return
+  loadMoreVideos (page: number) {
+    if (this.loadedPages[page] !== undefined) return
 
-    const observable = this.getVideosObservable()
+    const observable = this.getVideosObservable(page)
 
     observable.subscribe(
       ({ videos, totalVideos }) => {
@@ -82,13 +103,14 @@ export abstract class AbstractVideoList implements OnInit {
           return this.reloadVideos()
         }
 
-        this.loadedPages[this.pagination.currentPage] = true
+        this.loadedPages[page] = videos
+        this.buildVideoPages()
         this.pagination.totalItems = totalVideos
 
-        if (where === 'before') {
-          this.videos = videos.concat(this.videos)
-        } else {
-          this.videos = this.videos.concat(videos)
+        // Initialize infinite scroller now we loaded the first page
+        if (Object.keys(this.loadedPages).length === 1) {
+          // Wait elements creation
+          setTimeout(() => this.infiniteScroller.initialize(), 500)
         }
       },
       error => this.notificationsService.error('Error', error.message)
@@ -107,17 +129,15 @@ export abstract class AbstractVideoList implements OnInit {
   }
 
   protected previousPage () {
-    this.pagination.currentPage--
+    const min = this.minPageLoaded()
 
-    this.setNewRouteParams()
-    this.loadMoreVideos('before')
+    if (min > 1) {
+      this.loadMoreVideos(min - 1)
+    }
   }
 
   protected nextPage () {
-    this.pagination.currentPage++
-
-    this.setNewRouteParams()
-    this.loadMoreVideos('after')
+    this.loadMoreVideos(this.maxPageLoaded() + 1)
   }
 
   protected buildRouteParams () {
@@ -127,7 +147,7 @@ export abstract class AbstractVideoList implements OnInit {
       page: this.pagination.currentPage
     }
 
-    return Object.assign(params, this.otherParams)
+    return Object.assign(params, this.otherRouteParams)
   }
 
   protected loadRouteParams (routeParams: { [ key: string ]: any }) {
@@ -144,4 +164,16 @@ export abstract class AbstractVideoList implements OnInit {
     const routeParams = this.buildRouteParams()
     this.router.navigate([ this.currentRoute, routeParams ])
   }
+
+  protected buildVideoPages () {
+    this.videoPages = Object.values(this.loadedPages)
+  }
+
+  private minPageLoaded () {
+    return Math.min(...Object.keys(this.loadedPages).map(e => parseInt(e, 10)))
+  }
+
+  private maxPageLoaded () {
+    return Math.max(...Object.keys(this.loadedPages).map(e => parseInt(e, 10)))
+  }
 }
diff --git a/client/src/app/shared/video/infinite-scroller.directive.ts b/client/src/app/shared/video/infinite-scroller.directive.ts
new file mode 100644 (file)
index 0000000..43e014c
--- /dev/null
@@ -0,0 +1,77 @@
+import { Directive, EventEmitter, Input, OnInit, Output } from '@angular/core'
+import 'rxjs/add/operator/distinct'
+import 'rxjs/add/operator/startWith'
+import { fromEvent } from 'rxjs/observable/fromEvent'
+
+@Directive({
+  selector: '[myInfiniteScroller]'
+})
+export class InfiniteScrollerDirective implements OnInit {
+  private static PAGE_VIEW_TOP_MARGIN = 500
+
+  @Input() containerHeight: number
+  @Input() pageHeight: number
+  @Input() percentLimit = 70
+  @Input() autoLoading = false
+
+  @Output() nearOfBottom = new EventEmitter<void>()
+  @Output() nearOfTop = new EventEmitter<void>()
+  @Output() pageChanged = new EventEmitter<number>()
+
+  private decimalLimit = 0
+  private lastCurrentBottom = -1
+  private lastCurrentTop = 0
+
+  constructor () {
+    this.decimalLimit = this.percentLimit / 100
+  }
+
+  ngOnInit () {
+    if (this.autoLoading === true) return this.initialize()
+  }
+
+  initialize () {
+    const scrollObservable = fromEvent(window, 'scroll')
+      .startWith(true)
+      .map(() => ({ current: window.scrollY, maximumScroll: document.body.clientHeight - window.innerHeight }))
+
+    // Scroll Down
+    scrollObservable
+      // Check we scroll down
+      .filter(({ current }) => {
+        const res = this.lastCurrentBottom < current
+
+        this.lastCurrentBottom = current
+        return res
+      })
+      .filter(({ current, maximumScroll }) => maximumScroll <= 0 || (current / maximumScroll) > this.decimalLimit)
+      .debounceTime(200)
+      .distinct()
+      .subscribe(() => this.nearOfBottom.emit())
+
+    // Scroll up
+    scrollObservable
+      // Check we scroll up
+      .filter(({ current }) => {
+        const res = this.lastCurrentTop > current
+
+        this.lastCurrentTop = current
+        return res
+      })
+      .filter(({ current, maximumScroll }) => {
+        return current !== 0 && (1 - (current / maximumScroll)) > this.decimalLimit
+      })
+      .debounceTime(200)
+      .distinct()
+      .subscribe(() => this.nearOfTop.emit())
+
+    // Page change
+    scrollObservable
+      .debounceTime(500)
+      .distinct()
+      .map(({ current }) => Math.max(1, Math.round((current + InfiniteScrollerDirective.PAGE_VIEW_TOP_MARGIN) / this.pageHeight)))
+      .distinctUntilChanged()
+      .subscribe(res => this.pageChanged.emit(res))
+  }
+
+}
index 80b2009312d20ea95fc1aa71579224550a009b42..7f2e96e938d709cb687fdb13fc7e7b7cfb4bf988 100644 (file)
 
     <div
       class="comment-threads"
-      infiniteScroll
-      [infiniteScrollUpDistance]="1.5"
-      [infiniteScrollDistance]="0.5"
-      (scrolled)="onNearOfBottom()"
+      myInfiniteScroller
+      [autoLoading]="true"
+      (nearOfBottom)="onNearOfBottom()"
     >
       <div *ngFor="let comment of comments">
         <my-video-comment
index 6025256deccfbc8505858f3c812855a0d13a8363..7ca3bafb50815c1a5beeabf819902077ba60d5b4 100644 (file)
@@ -160,11 +160,8 @@ export class VideoCommentsComponent implements OnChanges {
       this.threadComments = {}
       this.threadLoading = {}
       this.inReplyToCommentId = undefined
-      this.componentPagination = {
-        currentPage: 1,
-        itemsPerPage: 10,
-        totalItems: null
-      }
+      this.componentPagination.currentPage = 1
+      this.componentPagination.totalItems = null
 
       this.loadMoreComments()
     }
index 3020b8c3019c53d41616215ab52a8e36865df186..f150e38dabe2b3369f37779977abc14bafa9b548 100644 (file)
@@ -1,5 +1,6 @@
 import { Component, OnInit } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
+import { immutableAssign } from '@app/shared/misc/utils'
 import { NotificationsService } from 'angular2-notifications'
 import { AuthService } from '../../core/auth'
 import { AbstractVideoList } from '../../shared/video/abstract-video-list'
@@ -28,7 +29,9 @@ export class VideoRecentlyAddedComponent extends AbstractVideoList implements On
     super.ngOnInit()
   }
 
-  getVideosObservable () {
-    return this.videoService.getVideos(this.pagination, this.sort)
+  getVideosObservable (page: number) {
+    const newPagination = immutableAssign(this.pagination, { currentPage: page })
+
+    return this.videoService.getVideos(newPagination, this.sort)
   }
 }
index 67726afdcaaf61769ffec590c072b88700999518..241b97bc7e1aa75c288dfe904114a8d0f0006c65 100644 (file)
@@ -1,5 +1,6 @@
 import { Component, OnDestroy, OnInit } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
+import { immutableAssign } from '@app/shared/misc/utils'
 import { NotificationsService } from 'angular2-notifications'
 import { Subscription } from 'rxjs/Subscription'
 import { AuthService } from '../../core/auth'
@@ -16,7 +17,7 @@ export class VideoSearchComponent extends AbstractVideoList implements OnInit, O
   currentRoute = '/videos/search'
   loadOnInit = false
 
-  protected otherParams = {
+  protected otherRouteParams = {
     search: ''
   }
   private subActivatedRoute: Subscription
@@ -35,9 +36,9 @@ export class VideoSearchComponent extends AbstractVideoList implements OnInit, O
     this.subActivatedRoute = this.route.queryParams.subscribe(
       queryParams => {
         const querySearch = queryParams['search']
-        if (!querySearch || this.otherParams.search === querySearch) return
+        if (!querySearch || this.otherRouteParams.search === querySearch) return
 
-        this.otherParams.search = querySearch
+        this.otherRouteParams.search = querySearch
         this.reloadVideos()
       },
 
@@ -51,7 +52,8 @@ export class VideoSearchComponent extends AbstractVideoList implements OnInit, O
     }
   }
 
-  getVideosObservable () {
-    return this.videoService.searchVideos(this.otherParams.search, this.pagination, this.sort)
+  getVideosObservable (page: number) {
+    const newPagination = immutableAssign(this.pagination, { currentPage: page })
+    return this.videoService.searchVideos(this.otherRouteParams.search, newPagination, this.sort)
   }
 }
index fc48086d6ec184cdd0f086342e71b9ea1ba0e309..a42457273125d8c790086767d338d4436dbde9c3 100644 (file)
@@ -1,5 +1,6 @@
 import { Component, OnInit } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
+import { immutableAssign } from '@app/shared/misc/utils'
 import { NotificationsService } from 'angular2-notifications'
 import { AuthService } from '../../core/auth'
 import { AbstractVideoList } from '../../shared/video/abstract-video-list'
@@ -28,7 +29,8 @@ export class VideoTrendingComponent extends AbstractVideoList implements OnInit
     super.ngOnInit()
   }
 
-  getVideosObservable () {
-    return this.videoService.getVideos(this.pagination, this.sort)
+  getVideosObservable (page: number) {
+    const newPagination = immutableAssign(this.pagination, { currentPage: page })
+    return this.videoService.getVideos(newPagination, this.sort)
   }
 }
index cd449215067fa9e8d32bc0b3383f3962196c4392..dd0a6bb9cd7d8816d24a4e3f0675424dfe6a76ac 100644 (file)
@@ -4526,10 +4526,6 @@ ngx-clipboard@9.0.1:
   dependencies:
     ngx-window-token "0.0.4"
 
-ngx-infinite-scroll@0.7.2:
-  version "0.7.2"
-  resolved "https://registry.yarnpkg.com/ngx-infinite-scroll/-/ngx-infinite-scroll-0.7.2.tgz#c1f0e7fba4731a55f15557dc6fce2721fd562420"
-
 ngx-pipes@^2.0.5:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/ngx-pipes/-/ngx-pipes-2.1.0.tgz#969cbc78f1c7512b12cc050f441c2528fb3a05a0"