Fix infinite scroll on big screens
authorChocobozzz <me@florianbigard.com>
Fri, 2 Aug 2019 12:49:25 +0000 (14:49 +0200)
committerChocobozzz <me@florianbigard.com>
Fri, 2 Aug 2019 12:49:25 +0000 (14:49 +0200)
28 files changed:
client/src/app/+about/about-follows/about-follows.component.html
client/src/app/+about/about-follows/about-follows.component.ts
client/src/app/+accounts/account-video-channels/account-video-channels.component.html
client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.html
client/src/app/+admin/plugins/plugin-list-installed/plugin-list-installed.component.ts
client/src/app/+admin/plugins/plugin-search/plugin-search.component.html
client/src/app/+admin/plugins/plugin-search/plugin-search.component.ts
client/src/app/+my-account/my-account-history/my-account-history.component.html
client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.html
client/src/app/+my-account/my-account-subscriptions/my-account-subscriptions.component.ts
client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.html
client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.scss
client/src/app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component.ts
client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.html
client/src/app/+my-account/my-account-video-playlists/my-account-video-playlists.component.ts
client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html
client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts
client/src/app/shared/users/user-notifications.component.html
client/src/app/shared/users/user-notifications.component.ts
client/src/app/shared/video-playlist/video-add-to-playlist.component.ts
client/src/app/shared/video-playlist/video-playlist.service.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
client/src/app/shared/video/videos-selection.component.html
client/src/app/videos/+video-watch/comment/video-comments.component.html
client/src/app/videos/+video-watch/comment/video-comments.component.ts

index 18689bbf7b153d5a6b0cfef859347d3a7ed12482..5d7a50c744fce2e2980f0f5a1cb01daba8962684 100644 (file)
@@ -1,4 +1,4 @@
-<div class="row" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()">
+<div class="row" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()">
   <div class="col-xl-6 col-md-12">
     <div i18n class="subtitle">Followers</div>
 
index f0e1375d66e4d5d34256b3c8d63cf4a1a08f613d..d6030792864892728ca805721f67165e94c4c014 100644 (file)
@@ -4,6 +4,7 @@ import { ComponentPagination, hasMoreItems } from '@app/shared/rest/component-pa
 import { Notifier } from '@app/core'
 import { RestService } from '@app/shared'
 import { SortMeta } from 'primeng/api'
+import { Subject } from 'rxjs'
 
 @Component({
   selector: 'my-about-follows',
@@ -17,13 +18,13 @@ export class AboutFollowsComponent implements OnInit {
 
   followersPagination: ComponentPagination = {
     currentPage: 1,
-    itemsPerPage: 40,
+    itemsPerPage: 20,
     totalItems: null
   }
 
   followingsPagination: ComponentPagination = {
     currentPage: 1,
-    itemsPerPage: 40,
+    itemsPerPage: 20,
     totalItems: null
   }
 
@@ -32,6 +33,8 @@ export class AboutFollowsComponent implements OnInit {
     order: -1
   }
 
+  onDataSubject = new Subject<any[]>()
+
   constructor (
     private restService: RestService,
     private notifier: Notifier,
@@ -78,6 +81,8 @@ export class AboutFollowsComponent implements OnInit {
             this.followers = this.followers.concat(newFollowers)
 
             this.followersPagination.totalItems = resultList.total
+
+            this.onDataSubject.next(newFollowers)
           },
 
           err => this.notifier.error(err.message)
@@ -94,6 +99,8 @@ export class AboutFollowsComponent implements OnInit {
             this.followings = this.followings.concat(newFollowings)
 
             this.followingsPagination.totalItems = resultList.total
+
+            this.onDataSubject.next(newFollowings)
           },
 
           err => this.notifier.error(err.message)
index ea5f61b18a5bfea55b231160d7a82f74518f72e3..4ebad514cd6febf9b5c2cae2d51f2902b77b7fb6 100644 (file)
@@ -2,7 +2,7 @@
 
   <div class="no-results" i18n *ngIf="channelPagination.totalItems === 0">This account does not have channels.</div>
 
-  <div class="channels" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true">
+  <div class="channels" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onChannelDataSubject.asObservable()">
     <div class="section channel" *ngFor="let videoChannel of videoChannels">
       <div class="section-title">
         <a [routerLink]="getVideoChannelLink(videoChannel)" i18n-title title="See this video channel">
index 7144f4b5f501260d94c6a9ba1953e59700495517..85dedd7defe03d49a778639d0028f44715acf29d 100644 (file)
@@ -4,7 +4,7 @@ import { Account } from '@app/shared/account/account.model'
 import { AccountService } from '@app/shared/account/account.service'
 import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
 import { concatMap, map, switchMap, tap } from 'rxjs/operators'
-import { from, Subscription } from 'rxjs'
+import { from, Subject, Subscription } from 'rxjs'
 import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
 import { Video } from '@app/shared/video/video.model'
 import { AuthService } from '@app/core'
@@ -33,6 +33,8 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
   }
   videosSort: VideoSortField = '-publishedAt'
 
+  onChannelDataSubject = new Subject<any>()
+
   private accountSub: Subscription
 
   constructor (
@@ -75,6 +77,8 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
         this.videoChannels.push(videoChannel)
 
         this.videos[videoChannel.id] = videos
+
+        this.onChannelDataSubject.next([ videoChannel ])
       })
   }
 
index 6d215533202d6353e3dd441053d898ea682bbf53..4526aaf66a296ec7a5283bbf44097e1079f92056 100644 (file)
@@ -6,7 +6,7 @@
   {{ getNoResultMessage() }}
 </div>
 
-<div class="plugins" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true">
+<div class="plugins" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()">
   <div class="card plugin" *ngFor="let plugin of plugins">
     <div class="card-body">
       <div class="first-row">
index dced14dee9c0a9d3189c46f15d19ec66d43c4169..b30b136bdf61a61551e0ffafb70c9cf815fac0ac 100644 (file)
@@ -8,6 +8,7 @@ import { PeerTubePlugin } from '@shared/models/plugins/peertube-plugin.model'
 import { ActivatedRoute, Router } from '@angular/router'
 import { compareSemVer } from '@shared/core-utils/miscs/miscs'
 import { PluginService } from '@app/core/plugins/plugin.service'
+import { Subject } from 'rxjs'
 
 @Component({
   selector: 'my-plugin-list-installed',
@@ -33,6 +34,8 @@ export class PluginListInstalledComponent implements OnInit {
 
   PluginType = PluginType
 
+  onDataSubject = new Subject<any[]>()
+
   constructor (
     private i18n: I18n,
     private pluginService: PluginService,
@@ -67,6 +70,8 @@ export class PluginListInstalledComponent implements OnInit {
           res => {
             this.plugins = this.plugins.concat(res.data)
             this.pagination.totalItems = res.total
+
+            this.onDataSubject.next(res.data)
           },
 
           err => this.notifier.error(err.message)
index 87f1c86ee3a4dd19571d62fa3ecf5c4b0dfa61fe..6ec6301b177cd43cec84323f33d5f4cd52831120 100644 (file)
@@ -29,7 +29,7 @@
   No results.
 </div>
 
-<div class="plugins" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true">
+<div class="plugins" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()">
   <div class="card plugin" *ngFor="let plugin of plugins">
     <div class="card-body">
       <div class="first-row">
index a6fbeed842748c47bbaec3f3b2292ee1a37dee5e..65566ab7996616da342fb67cd0d6858166cb9860 100644 (file)
@@ -36,6 +36,8 @@ export class PluginSearchComponent implements OnInit {
   installing: { [name: string]: boolean } = {}
   pluginInstalled = false
 
+  onDataSubject = new Subject<any[]>()
+
   private searchSubject = new Subject<string>()
 
   constructor (
@@ -90,6 +92,8 @@ export class PluginSearchComponent implements OnInit {
 
             this.plugins = this.plugins.concat(res.data)
             this.pagination.totalItems = res.total
+
+            this.onDataSubject.next(res.data)
           },
 
           err => {
index 6e274f6898d8de13de6b8a086424d794cb9fee7f..7258fcc1f6de6abe18ed6f0c031b636118bf6fd7 100644 (file)
@@ -13,7 +13,7 @@
 
 <div class="no-history" i18n *ngIf="pagination.totalItems === 0">You don't have videos history yet.</div>
 
-<div myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" class="videos">
+<div myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()" class="videos">
   <div class="video" *ngFor="let video of videos">
     <my-video-miniature
       [video]="video" [displayAsRow]="true"
index fc23053c8ec8fc1d94899474a05ae15061221aa0..ce43ed6ddfffcb48e2a55bcfce481667c3d3e78a 100644 (file)
@@ -1,6 +1,6 @@
 <div class="no-results" i18n *ngIf="pagination.totalItems === 0">You don't have any subscriptions yet.</div>
 
-<div class="video-channels" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()">
+<div class="video-channels" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()">
   <div *ngFor="let videoChannel of videoChannels" class="video-channel">
     <a [routerLink]="[ '/video-channels', videoChannel.nameWithHost ]">
       <img [src]="videoChannel.avatarUrl" alt="Avatar" />
index 6ce22989b44184d3b87460ddddcec916ee230e9e..b347fc3fef50515e27d18e41b3638ddab6be216d 100644 (file)
@@ -3,6 +3,7 @@ import { Notifier } from '@app/core'
 import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
 import { UserSubscriptionService } from '@app/shared/user-subscription'
 import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
+import { Subject } from 'rxjs'
 
 @Component({
   selector: 'my-account-subscriptions',
@@ -18,6 +19,8 @@ export class MyAccountSubscriptionsComponent implements OnInit {
     totalItems: null
   }
 
+  onDataSubject = new Subject<any[]>()
+
   constructor (
     private userSubscriptionService: UserSubscriptionService,
     private notifier: Notifier
@@ -33,6 +36,8 @@ export class MyAccountSubscriptionsComponent implements OnInit {
           res => {
             this.videoChannels = this.videoChannels.concat(res.data)
             this.pagination.totalItems = res.total
+
+            this.onDataSubject.next(res.data)
           },
 
           error => this.notifier.error(error.message)
index 4de4e69da5ee273cc288f10800e666320125a1b6..a3de3da4a27a9531e5231f1ae538d341c2e4c1d2 100644 (file)
@@ -12,7 +12,7 @@
 
     <div
       class="videos" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()"
-      cdkDropList (cdkDropListDropped)="drop($event)"
+      cdkDropList (cdkDropListDropped)="drop($event)" [dataObservable]="onDataSubject.asObservable()"
     >
       <div class="video" *ngFor="let playlistElement of playlistElements; trackBy: trackByFn" cdkDrag>
         <my-video-playlist-element-miniature
index 900669827f50ab4c9687e780d4dfc8f8ecea5bc0..9657ac11dced0afdc933c8b9c82358aa2fcfa81d 100644 (file)
@@ -7,7 +7,7 @@
   margin-left: -15px;
   margin-top: -$sub-menu-margin-bottom;
 
-  padding: $sub-menu-margin-bottom 0;
+  padding: $sub-menu-margin-bottom 0 -15px 0;
 
   display: flex;
   justify-content: center;
index 6f307a0583b49da79fa02b2a18a6054ea9a272f6..22c9af566b5984910b62bf507fee4a0f3cc64f96 100644 (file)
@@ -3,7 +3,7 @@ import { Notifier, ServerService } from '@app/core'
 import { AuthService } from '../../core/auth'
 import { ConfirmService } from '../../core/confirm'
 import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
-import { Subscription } from 'rxjs'
+import { Subject, Subscription } from 'rxjs'
 import { ActivatedRoute } from '@angular/router'
 import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
 import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
@@ -22,10 +22,12 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro
 
   pagination: ComponentPagination = {
     currentPage: 1,
-    itemsPerPage: 30,
+    itemsPerPage: 10,
     totalItems: null
   }
 
+  onDataSubject = new Subject<any[]>()
+
   private videoPlaylistId: string | number
   private paramsSub: Subscription
 
@@ -102,6 +104,8 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro
         .subscribe(({ total, data }) => {
           this.playlistElements = this.playlistElements.concat(data)
           this.pagination.totalItems = total
+
+          this.onDataSubject.next(data)
         })
   }
 
index 32256067368ed08b018bc2753d6ed2f7c407a1bc..307884c7063d2f2023b18db29433a9bf035b063f 100644 (file)
@@ -5,7 +5,7 @@
   </a>
 </div>
 
-<div class="video-playlists" myInfiniteScroller (nearOfBottom)="onNearOfBottom()">
+<div class="video-playlists" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()">
   <div *ngFor="let playlist of videoPlaylists" class="video-playlist">
     <div class="miniature-wrapper">
       <my-video-playlist-miniature [playlist]="playlist" [toManage]="true" [displayChannel]="true" [displayDescription]="true" [displayPrivacy]="true"
index e30656b92cebfe7759416202ab63d44fc97af571..0c4e4b0d6223ce13563facdb7a0214db8ac6db4d 100644 (file)
@@ -9,6 +9,7 @@ import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
 import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
 import { VideoPlaylistService } from '@app/shared/video-playlist/video-playlist.service'
 import { VideoPlaylistType } from '@shared/models'
+import { Subject } from 'rxjs'
 
 @Component({
   selector: 'my-account-video-playlists',
@@ -20,10 +21,12 @@ export class MyAccountVideoPlaylistsComponent implements OnInit {
 
   pagination: ComponentPagination = {
     currentPage: 1,
-    itemsPerPage: 10,
+    itemsPerPage: 5,
     totalItems: null
   }
 
+  onDataSubject = new Subject<any[]>()
+
   private user: User
 
   constructor (
@@ -78,11 +81,15 @@ export class MyAccountVideoPlaylistsComponent implements OnInit {
   }
 
   private loadVideoPlaylists () {
+    const playlistsObservable = this.videoPlaylistService.listAccountPlaylists(this.user.account, this.pagination, '-updatedAt')
+
     this.authService.userInformationLoaded
-        .pipe(flatMap(() => this.videoPlaylistService.listAccountPlaylists(this.user.account, '-updatedAt')))
+        .pipe(flatMap(() => playlistsObservable))
         .subscribe(res => {
           this.videoPlaylists = this.videoPlaylists.concat(res.data)
           this.pagination.totalItems = res.total
+
+          this.onDataSubject.next(res.data)
         })
   }
 }
index befc7143cde58b0aa01ddfacf8d2a26e5886baaf..1adc5018076f1d7351206dd6b7817a7fbf772b9a 100644 (file)
@@ -4,7 +4,7 @@
 
 <div i18n class="no-results" *ngIf="pagination.totalItems === 0">This channel does not have playlists.</div>
 
-<div class="video-playlist" myInfiniteScroller (nearOfBottom)="onNearOfBottom()">
+<div class="video-playlist" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()">
   <div *ngFor="let playlist of videoPlaylists">
     <my-video-playlist-miniature [playlist]="playlist" [toManage]="false"></my-video-playlist-miniature>
   </div>
index 7990044a2baababf4c830c895eeb2552c05e9b12..0b003308221ad995378a95a65d852835759ade60 100644 (file)
@@ -2,7 +2,7 @@ import { Component, OnDestroy, OnInit } from '@angular/core'
 import { ConfirmService } from '../../core/confirm'
 import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
 import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
-import { Subscription } from 'rxjs'
+import { Subject, Subscription } from 'rxjs'
 import { Notifier } from '@app/core'
 import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
 import { ComponentPagination, hasMoreItems } from '@app/shared/rest/component-pagination.model'
@@ -22,6 +22,8 @@ export class VideoChannelPlaylistsComponent implements OnInit, OnDestroy {
     totalItems: null
   }
 
+  onDataSubject = new Subject<any[]>()
+
   private videoChannelSub: Subscription
   private videoChannel: VideoChannel
 
@@ -53,10 +55,12 @@ export class VideoChannelPlaylistsComponent implements OnInit, OnDestroy {
   }
 
   private loadVideoPlaylists () {
-    this.videoPlaylistService.listChannelPlaylists(this.videoChannel)
+    this.videoPlaylistService.listChannelPlaylists(this.videoChannel, this.pagination)
         .subscribe(res => {
           this.videoPlaylists = this.videoPlaylists.concat(res.data)
           this.pagination.totalItems = res.total
+
+          this.onDataSubject.next(res.data)
         })
   }
 }
index d0d9d9f359475d1f18ee39619115f7e5744c85b8..29281342607a5d37f75837c01823005f6453c96d 100644 (file)
@@ -1,6 +1,6 @@
 <div *ngIf="componentPagination.totalItems === 0" class="no-notification" i18n>You don't have notifications.</div>
 
-<div class="notifications" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()">
+<div class="notifications" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()">
   <div *ngFor="let notification of notifications" class="notification" [ngClass]="{ unread: !notification.read }" (click)="markAsRead(notification)">
 
     <ng-container [ngSwitch]="notification.type">
index ce43b604a33a929abd25447310a5e2fb01f7efd3..3c9eb369d3c54b0268b611cd4ada48c2e73735e9 100644 (file)
@@ -4,6 +4,7 @@ import { UserNotificationType } from '../../../../../shared'
 import { ComponentPagination, hasMoreItems } from '@app/shared/rest/component-pagination.model'
 import { Notifier } from '@app/core'
 import { UserNotification } from '@app/shared/users/user-notification.model'
+import { Subject } from 'rxjs'
 
 @Component({
   selector: 'my-user-notifications',
@@ -24,6 +25,8 @@ export class UserNotificationsComponent implements OnInit {
 
   componentPagination: ComponentPagination
 
+  onDataSubject = new Subject<any[]>()
+
   constructor (
     private userNotificationService: UserNotificationService,
     private notifier: Notifier
@@ -47,6 +50,8 @@ export class UserNotificationsComponent implements OnInit {
             this.componentPagination.totalItems = result.total
 
             this.notificationsLoaded.emit()
+
+            this.onDataSubject.next(result.data)
           },
 
           err => this.notifier.error(err.message)
index 08ceb21bc350688bf12dd8d87af8ef2dd7f99f4c..72de84703d1e99a83cd4ae6eb89c08484eb826fa 100644 (file)
@@ -83,7 +83,7 @@ export class VideoAddToPlaylistComponent extends FormReactive implements OnInit,
 
   load () {
     forkJoin([
-      this.videoPlaylistService.listAccountPlaylists(this.user.account, '-updatedAt'),
+      this.videoPlaylistService.listAccountPlaylists(this.user.account, undefined,'-updatedAt'),
       this.videoPlaylistService.doesVideoExistInPlaylist(this.video.id)
     ])
       .subscribe(
index b93a19356306957988166ac37bfb1b2c5343db2c..376387082dfe2421d9c05e58bc48a1c864765279 100644 (file)
@@ -45,21 +45,28 @@ export class VideoPlaylistService {
     )
   }
 
-  listChannelPlaylists (videoChannel: VideoChannel): Observable<ResultList<VideoPlaylist>> {
+  listChannelPlaylists (videoChannel: VideoChannel, componentPagination: ComponentPagination): Observable<ResultList<VideoPlaylist>> {
     const url = VideoChannelService.BASE_VIDEO_CHANNEL_URL + videoChannel.nameWithHost + '/video-playlists'
+    const pagination = this.restService.componentPaginationToRestPagination(componentPagination)
 
-    return this.authHttp.get<ResultList<VideoPlaylist>>(url)
+    let params = new HttpParams()
+    params = this.restService.addRestGetParams(params, pagination)
+
+    return this.authHttp.get<ResultList<VideoPlaylist>>(url, { params })
                .pipe(
                  switchMap(res => this.extractPlaylists(res)),
                  catchError(err => this.restExtractor.handleError(err))
                )
   }
 
-  listAccountPlaylists (account: Account, sort: string): Observable<ResultList<VideoPlaylist>> {
+  listAccountPlaylists (account: Account, componentPagination: ComponentPagination, sort: string): Observable<ResultList<VideoPlaylist>> {
     const url = AccountService.BASE_ACCOUNT_URL + account.nameWithHost + '/video-playlists'
+    const pagination = componentPagination
+      ? this.restService.componentPaginationToRestPagination(componentPagination)
+      : undefined
 
     let params = new HttpParams()
-    params = this.restService.addRestGetParams(params, undefined, sort)
+    params = this.restService.addRestGetParams(params, pagination, sort)
 
     return this.authHttp.get<ResultList<VideoPlaylist>>(url, { params })
                .pipe(
index efd369bcadef871858403802304ac251dd22e0d8..13aedcc74279859fbe38837f8270a060149e8bd5 100644 (file)
@@ -19,7 +19,7 @@
 
   <div class="no-results" i18n *ngIf="pagination.totalItems === 0">No results.</div>
   <div
-    myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true"
+    myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onDataSubject.asObservable()"
     class="videos"
   >
     <ng-container *ngFor="let video of videos; trackBy: videoById;">
index 8a247a9af726c87fac3c3970216c355ba2ff4063..2926b179b566a2ee2d909705bb20a6e4975960a3 100644 (file)
@@ -1,7 +1,7 @@
 import { debounceTime, first, tap } from 'rxjs/operators'
 import { OnDestroy, OnInit } from '@angular/core'
 import { ActivatedRoute, Router } from '@angular/router'
-import { fromEvent, Observable, of, Subscription } from 'rxjs'
+import { fromEvent, Observable, of, Subject, Subscription } from 'rxjs'
 import { AuthService } from '../../core/auth'
 import { ComponentPagination } from '../rest/component-pagination.model'
 import { VideoSortField } from './sort-field.type'
@@ -59,6 +59,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
     blacklistInfo: false
   }
 
+  onDataSubject = new Subject<any[]>()
+
   protected abstract notifier: Notifier
   protected abstract authService: AuthService
   protected abstract route: ActivatedRoute
@@ -147,6 +149,8 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
         if (this.groupByDate) this.buildGroupedDateLabels()
 
         this.onMoreVideos()
+
+        this.onDataSubject.next(data)
       },
 
       error => this.notifier.error(error.message)
index b1e88882c546333d7de8b586bcbb0fad6d8be517..9f613c5fa8b16d364e262e736de7505f1e6fc457 100644 (file)
@@ -1,14 +1,15 @@
-import { distinct, distinctUntilChanged, filter, map, share, startWith, throttleTime } from 'rxjs/operators'
-import { Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'
-import { fromEvent, Subscription } from 'rxjs'
+import { distinctUntilChanged, filter, map, share, startWith, tap, throttleTime } from 'rxjs/operators'
+import { AfterContentChecked, Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'
+import { fromEvent, Observable, Subscription } from 'rxjs'
 
 @Directive({
   selector: '[myInfiniteScroller]'
 })
-export class InfiniteScrollerDirective implements OnInit, OnDestroy {
+export class InfiniteScrollerDirective implements OnInit, OnDestroy, AfterContentChecked {
   @Input() percentLimit = 70
   @Input() autoInit = false
   @Input() onItself = false
+  @Input() dataObservable: Observable<any[]>
 
   @Output() nearOfBottom = new EventEmitter<void>()
 
@@ -17,10 +18,22 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
   private scrollDownSub: Subscription
   private container: HTMLElement
 
+  private checkScroll = false
+
   constructor (private el: ElementRef) {
     this.decimalLimit = this.percentLimit / 100
   }
 
+  ngAfterContentChecked () {
+    if (this.checkScroll) {
+      this.checkScroll = false
+
+      console.log('Checking if the initial state has a scroll.')
+
+      if (this.hasScroll() === false) this.nearOfBottom.emit()
+    }
+  }
+
   ngOnInit () {
     if (this.autoInit === true) return this.initialize()
   }
@@ -30,14 +43,15 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
   }
 
   initialize () {
-    if (this.onItself) {
-      this.container = this.el.nativeElement
-    }
+    this.container = this.onItself
+      ? this.el.nativeElement
+      : document.documentElement
 
     // Emit the last value
     const throttleOptions = { leading: true, trailing: true }
 
-    const scrollObservable = fromEvent(this.container || window, 'scroll')
+    const scrollableElement = this.onItself ? this.container : window
+    const scrollObservable = fromEvent(scrollableElement, 'scroll')
       .pipe(
         startWith(null as string), // FIXME: typings
         throttleTime(200, undefined, throttleOptions),
@@ -49,23 +63,34 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
     // Scroll Down
     this.scrollDownSub = scrollObservable
       .pipe(
-        // 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)
+        filter(({ current }) => this.isScrollingDown(current)),
+        filter(({ current, maximumScroll }) => (current / maximumScroll) > this.decimalLimit)
       )
       .subscribe(() => this.nearOfBottom.emit())
+
+    if (this.dataObservable) {
+      this.dataObservable
+          .pipe(filter(d => d.length !== 0))
+          .subscribe(() => this.checkScroll = true)
+    }
   }
 
   private getScrollInfo () {
-    if (this.container) {
-      return { current: this.container.scrollTop, maximumScroll: this.container.scrollHeight }
-    }
+    return { current: this.container.scrollTop, maximumScroll: this.getMaximumScroll() }
+  }
+
+  private getMaximumScroll () {
+    return this.container.scrollHeight - window.innerHeight
+  }
+
+  private hasScroll () {
+    return this.getMaximumScroll() > 0
+  }
+
+  private isScrollingDown (current: number) {
+    const result = this.lastCurrentBottom < current
 
-    return { current: window.scrollY, maximumScroll: document.body.clientHeight - window.innerHeight }
+    this.lastCurrentBottom = current
+    return result
   }
 }
index 120c168cd96b71df20cef32eda6901c40873922e..2b4b353cf29693fc3b20b28e0733b55481fc1bd1 100644 (file)
@@ -1,6 +1,6 @@
 <div class="no-results" i18n *ngIf="pagination.totalItems === 0">No results.</div>
 
-<div myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" class="videos">
+<div myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()" class="videos">
   <div class="video" *ngFor="let video of videos; let i = index; trackBy: videoById">
 
     <div class="checkbox-container">
index 7b941454a96672a6bf1b83cbe6a4390d4bb15ff1..be20a84906afc5f989b4950a48bc799c39525c94 100644 (file)
@@ -21,6 +21,7 @@
       myInfiniteScroller
       [autoInit]="true"
       (nearOfBottom)="onNearOfBottom()"
+      [dataObservable]="onDataSubject.asObservable()"
     >
       <div #commentHighlightBlock id="highlighted-comment">
         <my-video-comment
index 64bd18072f9cf4ac9001ac91aae37d765a57a3e9..a3e5ed880c9021df7cdec3c9ac466be8d6c8be78 100644 (file)
@@ -1,7 +1,7 @@
 import { Component, ElementRef, Input, OnChanges, OnDestroy, OnInit, SimpleChanges, ViewChild } from '@angular/core'
 import { ActivatedRoute } from '@angular/router'
 import { ConfirmService, Notifier } from '@app/core'
-import { Subscription } from 'rxjs'
+import { Subject, Subscription } from 'rxjs'
 import { VideoCommentThreadTree } from '../../../../../../shared/models/videos/video-comment.model'
 import { AuthService } from '../../../core/auth'
 import { ComponentPagination, hasMoreItems } from '../../../shared/rest/component-pagination.model'
@@ -38,6 +38,8 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
 
   syndicationItems: Syndication[] = []
 
+  onDataSubject = new Subject<any[]>()
+
   private sub: Subscription
 
   constructor (
@@ -124,6 +126,8 @@ export class VideoCommentsComponent implements OnInit, OnChanges, OnDestroy {
       res => {
         this.comments = this.comments.concat(res.data)
         this.componentPagination.totalItems = res.total
+
+        this.onDataSubject.next(res.data)
       },
 
       err => this.notifier.error(err.message)