Add video channel view
authorChocobozzz <me@florianbigard.com>
Thu, 14 Mar 2019 13:05:36 +0000 (14:05 +0100)
committerChocobozzz <chocobozzz@cpy.re>
Mon, 18 Mar 2019 10:17:59 +0000 (11:17 +0100)
26 files changed:
client/src/app/+my-account/my-account-routing.module.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.scss
client/src/app/+my-account/my-account-videos/my-account-videos.component.html
client/src/app/+my-account/my-account-videos/my-account-videos.component.scss
client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html [new file with mode: 0644]
client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.scss [new file with mode: 0644]
client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts [new file with mode: 0644]
client/src/app/+video-channels/video-channels-routing.module.ts
client/src/app/+video-channels/video-channels.component.html
client/src/app/+video-channels/video-channels.module.ts
client/src/app/shared/video-playlist/video-playlist-element-miniature.component.html
client/src/app/shared/video-playlist/video-playlist-element-miniature.component.scss
client/src/app/shared/video-playlist/video-playlist-element-miniature.component.ts
client/src/app/shared/video-playlist/video-playlist-miniature.component.html
client/src/app/shared/video-playlist/video-playlist-miniature.component.scss
client/src/app/shared/video-playlist/video-playlist-miniature.component.ts
client/src/app/shared/video/infinite-scroller.directive.ts
client/src/app/videos/+video-watch/video-watch.component.html
client/src/app/videos/+video-watch/video-watch.component.scss
client/src/app/videos/+video-watch/video-watch.component.ts
client/src/sass/application.scss
client/src/sass/include/_variables.scss

index 3f921b13fa2666c1941a8273e4b8d34787152a40..07557a029b2bf03407d019bdf25cb97106fb560f 100644 (file)
@@ -85,20 +85,20 @@ const myAccountRoutes: Routes = [
         }
       },
       {
-        path: 'video-playlists/:videoPlaylistId',
-        component: MyAccountVideoPlaylistElementsComponent,
+        path: 'video-playlists/create',
+        component: MyAccountVideoPlaylistCreateComponent,
         data: {
           meta: {
-            title: 'Playlist elements'
+            title: 'Create new playlist'
           }
         }
       },
       {
-        path: 'video-playlists/create',
-        component: MyAccountVideoPlaylistCreateComponent,
+        path: 'video-playlists/:videoPlaylistId',
+        component: MyAccountVideoPlaylistElementsComponent,
         data: {
           meta: {
-            title: 'Create new playlist'
+            title: 'Playlist elements'
           }
         }
       },
index bc26e198ed269c61254fda29dad5a8b6b808c7e4..95d4519fa7474574746ced052b392d2cf4452753 100644 (file)
@@ -1,11 +1,26 @@
-<div i18n class="no-results" *ngIf="pagination.totalItems === 0">No videos in this playlist.</div>
+<div class="row">
 
-<div
-  class="videos" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()"
-  cdkDropList (cdkDropListDropped)="drop($event)"
->
-  <div class="video" *ngFor="let video of videos" cdkDrag (cdkDragMoved)="onDragMove($event)">
-    <my-video-playlist-element-miniature [video]="video" [playlist]="playlist" [owned]="true" (elementRemoved)="onElementRemoved($event)">
-    </my-video-playlist-element-miniature>
+  <div class="playlist-info col-xs-12 col-md-5 col-xl-3">
+    <my-video-playlist-miniature
+      *ngIf="playlist" [playlist]="playlist" [toManage]="false" [displayChannel]="true"
+      [displayDescription]="true" [displayPrivacy]="true"
+    ></my-video-playlist-miniature>
+  </div>
+
+  <div class="col-xs-12 col-md-7 col-xl-9">
+    <div i18n class="no-results" *ngIf="pagination.totalItems === 0">No videos in this playlist.</div>
+
+    <div
+      class="videos" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()"
+      cdkDropList (cdkDropListDropped)="drop($event)"
+    >
+      <div class="video" *ngFor="let video of videos; trackBy: trackByFn" cdkDrag (cdkDragMoved)="onDragMove($event)">
+        <my-video-playlist-element-miniature
+          [video]="video" [playlist]="playlist" [owned]="true" (elementRemoved)="onElementRemoved($event)"
+          [position]="video.playlistElement.position"
+        >
+        </my-video-playlist-element-miniature>
+      </div>
+    </div>
   </div>
 </div>
index b05af0490d72605e32dd3006957978d5fc30cbbc..900669827f50ab4c9687e780d4dfc8f8ecea5bc0 100644 (file)
@@ -2,6 +2,17 @@
 @import '_mixins';
 @import '_miniature';
 
+.playlist-info {
+  background-color: var(--submenuColor);
+  margin-left: -15px;
+  margin-top: -$sub-menu-margin-bottom;
+
+  padding: $sub-menu-margin-bottom 0;
+
+  display: flex;
+  justify-content: center;
+}
+
 // Thanks Angular CDK <3 https://material.angular.io/cdk/drag-drop/examples
 .cdk-drag-preview {
   box-sizing: border-box;
index dcf470be3748e3f8d7ccfcca025e41fd14cccfdc..25d51d2cbdb5de89f0201ae0ff7c982048872c1c 100644 (file)
@@ -24,7 +24,7 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro
 
   pagination: ComponentPagination = {
     currentPage: 1,
-    itemsPerPage: 10,
+    itemsPerPage: 30,
     totalItems: null
   }
 
@@ -123,6 +123,10 @@ export class MyAccountVideoPlaylistElementsComponent implements OnInit, OnDestro
     this.loadElements()
   }
 
+  trackByFn (index: number, elem: Video) {
+    return elem.id
+  }
+
   private loadElements () {
     this.videoService.getPlaylistVideos(this.videoPlaylistId, this.pagination)
         .subscribe(({ totalVideos, videos }) => {
index 7d1bed12a89f1696e3dc642350d353a29fc74f49..32256067368ed08b018bc2753d6ed2f7c407a1bc 100644 (file)
@@ -8,7 +8,8 @@
 <div class="video-playlists" myInfiniteScroller (nearOfBottom)="onNearOfBottom()">
   <div *ngFor="let playlist of videoPlaylists" class="video-playlist">
     <div class="miniature-wrapper">
-      <my-video-playlist-miniature [playlist]="playlist" [toManage]="true"></my-video-playlist-miniature>
+      <my-video-playlist-miniature [playlist]="playlist" [toManage]="true" [displayChannel]="true" [displayDescription]="true" [displayPrivacy]="true"
+      ></my-video-playlist-miniature>
     </div>
 
     <div *ngIf="isRegularPlaylist(playlist)" class="video-playlist-buttons">
index 88fba5b05540a32d44908ea9254bbfeb8f1395ca..f648c33e4786ea121569db1a8155b6a6a0543c5b 100644 (file)
@@ -20,8 +20,9 @@
     /deep/ .miniature {
       display: flex;
 
-      .miniature-bottom {
+      .miniature-info {
         margin-left: 10px;
+        width: auto;
       }
     }
   }
index 69748ef372ab29cdd3b18a3c0aa5e16c348dce2c..b09e845ace2876b3674894724654906a40042ec6 100644 (file)
@@ -17,7 +17,7 @@
       <div class="video-info">
         <a class="video-info-name" [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name">{{ video.name }}</a>
         <span i18n class="video-info-date-views">{{ video.createdAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
-        <div class="video-info-private">{{ video.privacy.label }}{{ getStateLabel(video) }}</div>
+        <div class="video-info-privacy">{{ video.privacy.label }}{{ getStateLabel(video) }}</div>
         <div *ngIf="video.blacklisted" class="video-info-blacklisted">
           <span class="blacklisted-label" i18n>Blacklisted</span>
           <span class="blacklisted-reason" *ngIf="video.blacklistedReason">{{ video.blacklistedReason }}</span>
index 39d0cf2f7997838047bbd6b2eb420670d82db8b3..f6b5faa45dc1417428f99fb6855cfa63ca7ff95a 100644 (file)
     }
 
     .video-info-date-views,
-    .video-info-private,
+    .video-info-privacy,
     .video-info-blacklisted {
       font-size: 13px;
 
-      &.video-info-private,
+      &.video-info-privacy,
       &.video-info-blacklisted .blacklisted-label {
         font-weight: $font-semibold;
       }
diff --git a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.html
new file mode 100644 (file)
index 0000000..0d9fba3
--- /dev/null
@@ -0,0 +1,11 @@
+<div i18n class="title-page title-page-single">
+  Created {{pagination.totalItems}} playlists
+</div>
+
+<div i18n class="no-results" *ngIf="pagination.totalItems === 0">This channel does not have playlists.</div>
+
+<div class="video-playlist" myInfiniteScroller (nearOfBottom)="onNearOfBottom()">
+  <div *ngFor="let playlist of videoPlaylists">
+    <my-video-playlist-miniature [playlist]="playlist" [toManage]="false"></my-video-playlist-miniature>
+  </div>
+</div>
diff --git a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.scss b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.scss
new file mode 100644 (file)
index 0000000..fe91047
--- /dev/null
@@ -0,0 +1,9 @@
+.video-playlist {
+  display: flex;
+  justify-content: center;
+
+  my-video-playlist-miniature {
+    margin-right: 15px;
+    margin-bottom: 30px;
+  }
+}
diff --git a/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts b/client/src/app/+video-channels/video-channel-playlists/video-channel-playlists.component.ts
new file mode 100644 (file)
index 0000000..f878a5a
--- /dev/null
@@ -0,0 +1,67 @@
+import { Component, OnDestroy, OnInit } from '@angular/core'
+import { AuthService } from '../../core/auth'
+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 { flatMap } from 'rxjs/operators'
+import { Subscription } from 'rxjs'
+import { Notifier } from '@app/core'
+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'
+
+@Component({
+  selector: 'my-video-channel-playlists',
+  templateUrl: './video-channel-playlists.component.html',
+  styleUrls: [ './video-channel-playlists.component.scss' ]
+})
+export class VideoChannelPlaylistsComponent implements OnInit, OnDestroy {
+  videoPlaylists: VideoPlaylist[] = []
+
+  pagination: ComponentPagination = {
+    currentPage: 1,
+    itemsPerPage: 20,
+    totalItems: null
+  }
+
+  private videoChannelSub: Subscription
+  private videoChannel: VideoChannel
+
+  constructor (
+    private authService: AuthService,
+    private notifier: Notifier,
+    private confirmService: ConfirmService,
+    private videoPlaylistService: VideoPlaylistService,
+    private videoChannelService: VideoChannelService
+  ) {}
+
+  ngOnInit () {
+    // Parent get the video channel for us
+    this.videoChannelSub = this.videoChannelService.videoChannelLoaded
+                               .subscribe(videoChannel => {
+                                 this.videoChannel = videoChannel
+                                 this.loadVideoPlaylists()
+                               })
+  }
+
+  ngOnDestroy () {
+    if (this.videoChannelSub) this.videoChannelSub.unsubscribe()
+  }
+
+  onNearOfBottom () {
+    // Last page
+    if (this.pagination.totalItems <= (this.pagination.currentPage * this.pagination.itemsPerPage)) return
+
+    this.pagination.currentPage += 1
+    this.loadVideoPlaylists()
+  }
+
+  private loadVideoPlaylists () {
+    this.authService.userInformationLoaded
+        .pipe(flatMap(() => this.videoPlaylistService.listChannelPlaylists(this.videoChannel)))
+        .subscribe(res => {
+          this.videoPlaylists = this.videoPlaylists.concat(res.data)
+          this.pagination.totalItems = res.total
+        })
+  }
+}
index 3ac3533d9e41f9941b5d4249e68f53f0bc3d4196..cedd07d39a533250e99a75162b47d2f5e03daa99 100644 (file)
@@ -4,6 +4,7 @@ import { MetaGuard } from '@ngx-meta/core'
 import { VideoChannelsComponent } from './video-channels.component'
 import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component'
 import { VideoChannelAboutComponent } from './video-channel-about/video-channel-about.component'
+import { VideoChannelPlaylistsComponent } from '@app/+video-channels/video-channel-playlists/video-channel-playlists.component'
 
 const videoChannelsRoutes: Routes = [
   {
@@ -25,6 +26,15 @@ const videoChannelsRoutes: Routes = [
           }
         }
       },
+      {
+        path: 'video-playlists',
+        component: VideoChannelPlaylistsComponent,
+        data: {
+          meta: {
+            title: 'Video channel playlists'
+          }
+        }
+      },
       {
         path: 'about',
         component: VideoChannelAboutComponent,
index c65b5713d76b25943993eec491543c9e87cd1adc..600b7a36577c1cd9039902efe40af36dc2c7017b 100644 (file)
@@ -22,6 +22,7 @@
 
     <div class="links">
       <a i18n routerLink="videos" routerLinkActive="active" class="title-page">Videos</a>
+      <a i18n routerLink="video-playlists" routerLinkActive="active" class="title-page">Video playlists</a>
       <a i18n routerLink="about" routerLinkActive="active" class="title-page">About</a>
     </div>
   </div>
index a09ea6f11d40e15d8d9d7ee493486c251f482f11..6975d05b20a4b7847b479376f04d6b39224197d0 100644 (file)
@@ -4,6 +4,7 @@ import { VideoChannelsRoutingModule } from './video-channels-routing.module'
 import { VideoChannelsComponent } from './video-channels.component'
 import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component'
 import { VideoChannelAboutComponent } from './video-channel-about/video-channel-about.component'
+import { VideoChannelPlaylistsComponent } from '@app/+video-channels/video-channel-playlists/video-channel-playlists.component'
 
 @NgModule({
   imports: [
@@ -14,7 +15,8 @@ import { VideoChannelAboutComponent } from './video-channel-about/video-channel-
   declarations: [
     VideoChannelsComponent,
     VideoChannelVideosComponent,
-    VideoChannelAboutComponent
+    VideoChannelAboutComponent,
+    VideoChannelPlaylistsComponent
   ],
 
   exports: [
index 1f178675fde9333e39e36825153ad2c73d11a2af..4764fc0e1511ca6f1921d0e9202a198c01967c3c 100644 (file)
@@ -2,7 +2,7 @@
   <a [routerLink]="buildRouterLink()" [queryParams]="buildRouterQuery()">
     <div class="position">
       <my-global-icon *ngIf="playing" iconName="play"></my-global-icon>
-      <ng-container *ngIf="!playing">{{ video.playlistElement.position }}</ng-container>
+      <ng-container *ngIf="!playing">{{ position }}</ng-container>
     </div>
 
     <my-video-thumbnail
index eb869f69a99eb290e38f77a808263627e2463e17..f57fd2e1cadfbb3ffb160970555eb758c3f947c4 100644 (file)
@@ -34,7 +34,7 @@
       font-weight: $font-semibold;
       margin-right: 10px;
       color: $grey-foreground-color;
-      min-width: 20px;
+      min-width: 25px;
 
       my-global-icon {
         @include apply-svg-color($grey-foreground-color);
@@ -59,7 +59,7 @@
 
       a {
         color: var(--mainForegroundColor);
-        width: fit-content;
+        width: auto;
 
         &:hover {
           text-decoration: underline !important;
index c0cfd855df59a7828d966a27b2b80a2dfe2886e8..6cc5b87b4ac6d897ae7c0e15b591d1ba5d5ee633 100644 (file)
@@ -1,4 +1,4 @@
-import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core'
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, Output, ViewChild } from '@angular/core'
 import { Video } from '@app/shared/video/video.model'
 import { VideoPlaylistElementUpdate } from '@shared/models'
 import { AuthService, ConfirmService, Notifier, ServerService } from '@app/core'
@@ -13,7 +13,8 @@ import { secondsToTime } from '../../../assets/player/utils'
 @Component({
   selector: 'my-video-playlist-element-miniature',
   styleUrls: [ './video-playlist-element-miniature.component.scss' ],
-  templateUrl: './video-playlist-element-miniature.component.html'
+  templateUrl: './video-playlist-element-miniature.component.html',
+  changeDetection: ChangeDetectionStrategy.OnPush
 })
 export class VideoPlaylistElementMiniatureComponent {
   @ViewChild('moreDropdown') moreDropdown: NgbDropdown
@@ -24,6 +25,7 @@ export class VideoPlaylistElementMiniatureComponent {
   @Input() playing = false
   @Input() rowLink = false
   @Input() accountLink = true
+  @Input() position: number
 
   @Output() elementRemoved = new EventEmitter<Video>()
 
@@ -44,7 +46,8 @@ export class VideoPlaylistElementMiniatureComponent {
     private route: ActivatedRoute,
     private i18n: I18n,
     private videoService: VideoService,
-    private videoPlaylistService: VideoPlaylistService
+    private videoPlaylistService: VideoPlaylistService,
+    private cdr: ChangeDetectorRef
   ) {}
 
   buildRouterLink () {
@@ -95,6 +98,8 @@ export class VideoPlaylistElementMiniatureComponent {
 
             video.playlistElement.startTimestamp = body.startTimestamp
             video.playlistElement.stopTimestamp = body.stopTimestamp
+
+            this.cdr.detectChanges()
           },
 
           err => this.notifier.error(err.message)
@@ -145,5 +150,10 @@ export class VideoPlaylistElementMiniatureComponent {
         this.timestampOptions.stopTimestamp = video.playlistElement.stopTimestamp
       }
     }
+
+    // FIXME: why do we have to use setTimeout here?
+    setTimeout(() => {
+      this.cdr.detectChanges()
+    })
   }
 }
index a136f923377df5726090dd7b792f6a825796ea8e..c01c7301223a359a8a962be0c98112c8ae11e12b 100644 (file)
@@ -1,6 +1,6 @@
 <div class="miniature" [ngClass]="{ 'no-videos': playlist.videosLength === 0, 'to-manage': toManage }">
   <a
-    [routerLink]="getPlaylistUrl()" [attr.title]="playlist.displayName"
+    [routerLink]="getPlaylistUrl()" [attr.title]="playlist.description"
     class="miniature-thumbnail"
   >
     <img alt="" [attr.aria-labelledby]="playlist.displayName" [attr.src]="playlist.thumbnailUrl" />
     </div>
   </a>
 
-  <div class="miniature-bottom">
-    <a tabindex="-1" class="miniature-name" [routerLink]="getPlaylistUrl()" [attr.title]="playlist.displayName">
+  <div class="miniature-info">
+    <a tabindex="-1" class="miniature-name" [routerLink]="getPlaylistUrl()" [attr.title]="playlist.description">
       {{ playlist.displayName }}
     </a>
+
+    <div class="video-info-privacy" *ngIf="displayPrivacy">{{ playlist.privacy.label }}</div>
+
+    <div class="video-info-by-date">
+      <a i18n [routerLink]="[ '/video-channels', playlist.videoChannelBy ]" class="by" *ngIf="displayChannel && playlist.videoChannelBy">
+        {{ playlist.videoChannelBy }}
+      </a>
+
+      <div i18n class="updated-at">Updated {{ playlist.updatedAt | myFromNow }}</div>
+    </div>
+
+    <div *ngIf="displayDescription" class="video-info-description">{{ playlist.description }}</div>
   </div>
 </div>
index 72158eb10258f3d8f8ffa38a9a97875a32e77ac7..94edd11778e26fecaf3939eb818bbf8fa16f1a83 100644 (file)
     }
   }
 
-  &.to-manage .play-overlay,
+  &.to-manage,
   &.no-videos {
-    display: none;
+    .play-overlay {
+      display: none;
+    }
   }
 
   .miniature-thumbnail {
@@ -34,7 +36,7 @@
     }
   }
 
-  .miniature-bottom {
+  .miniature-info {
     width: 200px;
     margin-top: 2px;
     line-height: normal;
     .miniature-name {
       @include miniature-name;
     }
+
+    .video-info-by-date {
+      display: flex;
+      font-size: 13px;
+      margin: 5px 0;
+
+      .by {
+        @include disable-default-a-behaviour;
+
+        display: block;
+        color: var(--mainForegroundColor);
+
+        &::after {
+          content: '-';
+          margin: 0 3px;
+        }
+      }
+    }
+
+    .video-info-privacy {
+      font-size: 13px;
+      font-weight: $font-semibold;
+    }
+
+    .video-info-description {
+      margin-top: 10px;
+      color: $grey-foreground-color;
+    }
   }
 }
index cb58034007146fb49acc17e97549d197c6c84d98..523e96f2a8fe8cbc8e8daa70b77cd92db7037968 100644 (file)
@@ -9,6 +9,9 @@ import { VideoPlaylist } from '@app/shared/video-playlist/video-playlist.model'
 export class VideoPlaylistMiniatureComponent {
   @Input() playlist: VideoPlaylist
   @Input() toManage = false
+  @Input() displayChannel = false
+  @Input() displayDescription = false
+  @Input() displayPrivacy = false
 
   getPlaylistUrl () {
     if (this.toManage) return [ '/my-account/video-playlists', this.playlist.uuid ]
index 186597a3a04d9bd911a8e113a191b30704f0658b..a9e75007cb26ef4fc21de07cf23d711244f3bd80 100644 (file)
@@ -1,5 +1,5 @@
 import { distinct, distinctUntilChanged, filter, map, share, startWith, throttleTime } from 'rxjs/operators'
-import { Directive, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'
+import { Directive, ElementRef, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'
 import { fromEvent, Subscription } from 'rxjs'
 
 @Directive({
@@ -11,7 +11,7 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
   @Input() firstLoadedPage = 1
   @Input() percentLimit = 70
   @Input() autoInit = false
-  @Input() container = document.body
+  @Input() onItself = false
 
   @Output() nearOfBottom = new EventEmitter<void>()
   @Output() nearOfTop = new EventEmitter<void>()
@@ -24,8 +24,9 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
   private scrollUpSub: Subscription
   private pageChangeSub: Subscription
   private middleScreen: number
+  private container: HTMLElement
 
-  constructor () {
+  constructor (private el: ElementRef) {
     this.decimalLimit = this.percentLimit / 100
   }
 
@@ -40,16 +41,20 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
   }
 
   initialize () {
+    if (this.onItself) {
+      this.container = this.el.nativeElement
+    }
+
     this.middleScreen = window.innerHeight / 2
 
     // Emit the last value
     const throttleOptions = { leading: true, trailing: true }
 
-    const scrollObservable = fromEvent(window, 'scroll')
+    const scrollObservable = fromEvent(this.container || window, 'scroll')
       .pipe(
         startWith(null),
         throttleTime(200, undefined, throttleOptions),
-        map(() => ({ current: window.scrollY, maximumScroll: this.container.clientHeight - window.innerHeight })),
+        map(() => this.getScrollInfo()),
         distinctUntilChanged((o1, o2) => o1.current === o2.current),
         share()
       )
@@ -102,4 +107,12 @@ export class InfiniteScrollerDirective implements OnInit, OnDestroy {
     // Offset page
     return page + (this.firstLoadedPage - 1)
   }
+
+  private getScrollInfo () {
+    if (this.container) {
+      return { current: this.container.scrollTop, maximumScroll: this.container.scrollHeight }
+    }
+
+    return { current: window.scrollY, maximumScroll: document.body.clientHeight - window.innerHeight }
+  }
 }
index 7f3d1cc2ed80ac331d120123a8d41a096dba0441..3df5b7b1913b7d6d10a93cd0449854a226d62b36 100644 (file)
@@ -9,7 +9,7 @@
 
     <div id="videojs-wrapper"></div>
 
-    <div *ngIf="playlist && video" class="playlist">
+    <div *ngIf="playlist && video" class="playlist"  myInfiniteScroller [autoInit]="true" [onItself]="true" (nearOfBottom)="onPlaylistVideosNearOfBottom()">
       <div class="playlist-info">
         <div class="playlist-display-name">
           {{ playlist.displayName }}
         </div>
       </div>
 
-      <div *ngFor="let playlistVideo of playlistVideos" myInfiniteScroller [autoInit]="true" #elem [container]="elem" (nearOfBottom)="onPlaylistVideosNearOfBottom()">
+      <div *ngFor="let playlistVideo of playlistVideos">
         <my-video-playlist-element-miniature
           [video]="playlistVideo" [playlist]="playlist" [owned]="isPlaylistOwned()" (elementRemoved)="onElementRemoved($event)"
-          [playing]="currentPlaylistPosition === playlistVideo.playlistElement.position" [accountLink]="false"
+          [playing]="currentPlaylistPosition === playlistVideo.playlistElement.position" [accountLink]="false" [position]="playlistVideo.playlistElement.position"
         ></my-video-playlist-element-miniature>
       </div>
     </div>
index e1cb249efcf77c5c0b4bb041722adcd80ca75cab..281b9240b8a03e086bd796352b19e5f232534498 100644 (file)
@@ -43,11 +43,12 @@ $other-videos-width: 260px;
   .playlist {
     width: 400px;
     height: 66vh;
-    background-color: #e4e4e4;
+    background-color: var(--mainBackgroundColor);
     overflow-y: auto;
 
     .playlist-info {
       padding: 5px 30px;
+      background-color: #e4e4e4;
 
       .playlist-display-name {
         font-size: 18px;
index ddd0f17661bb64c1e1488c38b928c36e2b5270d7..adb728abae9db7f57519ecae890573afef3ece1d 100644 (file)
@@ -58,7 +58,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
   playlistVideos: Video[] = []
   playlistPagination: ComponentPagination = {
     currentPage: 1,
-    itemsPerPage: 10,
+    itemsPerPage: 30,
     totalItems: null
   }
   noPlaylistVideos = false
@@ -401,7 +401,7 @@ export class VideoWatchComponent implements OnInit, OnDestroy {
   }
 
   private loadPlaylistElements (redirectToFirst = false) {
-    this.videoService.getPlaylistVideos(this.playlist.id, this.playlistPagination)
+    this.videoService.getPlaylistVideos(this.playlist.uuid, this.playlistPagination)
         .subscribe(({ totalVideos, videos }) => {
           this.playlistVideos = this.playlistVideos.concat(videos)
           this.playlistPagination.totalItems = totalVideos
index 478737a434dec20f0c0a428fff82078a79938782..28b466c01cd1f20f4acf51f09c11570bf7e183cc 100644 (file)
@@ -104,7 +104,7 @@ label {
     background-color: var(--submenuColor);
     width: 100%;
     height: 81px;
-    margin-bottom: 30px;
+    margin-bottom: $sub-menu-margin-bottom;
     display: flex;
     align-items: center;
     padding-left: $not-expanded-horizontal-margins;
index deabbf6d49a92fc6cbb6d8ffd11f13c074d73580..b8eb06f2ce95c2e51f05c585320745391836237d 100644 (file)
@@ -54,6 +54,8 @@ $theater-bottom-space: 115px;
 $input-background-color: $bg-color;
 $input-placeholder-color: #898989;
 
+$sub-menu-margin-bottom: 30px;
+
 /*** map theme ***/
 
 // pass variables into a sass map,