From 900f7820814b95b07ef0bcac04036a95abfbe060 Mon Sep 17 00:00:00 2001
From: Chocobozzz <me@florianbigard.com>
Date: Fri, 26 Mar 2021 15:53:18 +0100
Subject: [PATCH] Redesign account's channels page

---
 .../account-video-channels.component.html     |  45 +++--
 .../account-video-channels.component.scss     | 168 ++++++++++++++++--
 .../account-video-channels.component.ts       |  47 +++--
 .../src/app/+accounts/accounts.component.html |   4 +-
 .../src/app/+accounts/accounts.component.scss |  22 ++-
 .../src/app/+accounts/accounts.component.ts   |   4 +
 .../video-channel-videos.component.ts         |  13 +-
 .../video-channels.component.html             |   8 +-
 .../video-channels.component.scss             |  14 +-
 .../misc/simple-search-input.component.scss   |   4 +-
 client/src/sass/include/_miniature.scss       |  41 +++--
 client/src/sass/include/_variables.scss       |   1 +
 12 files changed, 298 insertions(+), 73 deletions(-)

diff --git a/client/src/app/+accounts/account-video-channels/account-video-channels.component.html b/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
index 5dbb341d2..0b22e7526 100644
--- a/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
+++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.html
@@ -1,33 +1,50 @@
 <h1 class="sr-only" i18n>Video channels</h1>
+
 <div class="margin-content">
 
   <div class="no-results" i18n *ngIf="channelPagination.totalItems === 0">This account does not have channels.</div>
 
   <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">
-          <img [src]="videoChannel.avatarUrl" alt="Avatar" />
+    <div class="channel" *ngFor="let videoChannel of videoChannels">
 
-          <h2 class="section-title">{{ videoChannel.displayName }}</h2>
-          <div class="followers" i18n>{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div>
+      <div class="channel-avatar-row">
+        <a class="avatar-link" [routerLink]="getVideoChannelLink(videoChannel)" i18n-title title="See this video channel">
+          <img [src]="videoChannel.avatarUrl" alt="Avatar" />
         </a>
 
-        <my-subscribe-button [videoChannels]="[videoChannel]"></my-subscribe-button>
+        <h2>
+          <a [routerLink]="getVideoChannelLink(videoChannel)" i18n-title title="See this video channel">
+            {{ videoChannel.displayName }}
+          </a>
+        </h2>
+
+        <div class="actor-counters">
+          <div class="followers" i18n>{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div>
+
+          <span class="videos-count" *ngIf="getTotalVideosOf(videoChannel) !== undefined" i18n>
+            {getTotalVideosOf(videoChannel), splural, =1 {1 videos} other {{{ getTotalVideosOf(videoChannel) }} videos}}
+          </span>
+        </div>
+
+        <div class="description-html" [innerHTML]="getChannelDescription(videoChannel)"></div>
       </div>
 
-      <div *ngIf="getVideosOf(videoChannel)" class="videos">
-        <div class="no-results my-5" i18n *ngIf="getVideosOf(videoChannel).length === 0">This channel doesn't have any videos.</div>
+      <my-subscribe-button [videoChannels]="[videoChannel]"></my-subscribe-button>
+
+      <a i18n class="button-show-channel peertube-button-link orange-button-inverted" [routerLink]="getVideoChannelLink(videoChannel)">Show this channel</a>
+
+      <div class="videos">
+        <div class="no-results" i18n *ngIf="getTotalVideosOf(videoChannel) === 0">This channel doesn't have any videos.</div>
 
         <my-video-miniature
           *ngFor="let video of getVideosOf(videoChannel)"
-          [video]="video" [user]="userMiniature" [displayVideoActions]="true"
+          [video]="video" [user]="userMiniature" [displayVideoActions]="true" [displayOptions]="miniatureDisplayOptions"
         ></my-video-miniature>
-      </div>
 
-      <a *ngIf="getVideosOf(videoChannel).length !== 0" class="show-more" i18n [routerLink]="getVideoChannelLink(videoChannel)">
-        SHOW THIS CHANNEL
-      </a>
+        <div *ngIf="getTotalVideosOf(videoChannel)" class="miniature-show-channel">
+          <a i18n [routerLink]="getVideoChannelLink(videoChannel)">SHOW THIS CHANNEL ></a>
+        </div>
+      </div>
     </div>
   </div>
 </div>
diff --git a/client/src/app/+accounts/account-video-channels/account-video-channels.component.scss b/client/src/app/+accounts/account-video-channels/account-video-channels.component.scss
index 4957e91d7..ca4c35cb4 100644
--- a/client/src/app/+accounts/account-video-channels/account-video-channels.component.scss
+++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.scss
@@ -3,37 +3,169 @@
 @import '_miniature';
 
 .margin-content {
-  @include fluid-videos-miniature-layout;
+  @include fluid-videos-miniature-margins;
 }
 
-.section {
-  @include miniature-rows;
+.channel {
+  max-width: $max-channels-width;
+  background-color: pvar(--channelBackgroundColor);
+  padding: 15px;
 
-  padding-top: 0 !important;
+  margin: 30px 0;
 
-  .section-title {
+  display: grid;
+  grid-template-columns: 1fr auto;
+  grid-template-rows: auto auto;
+  column-gap: 15px;
+}
+
+.channel-avatar-row {
+  grid-column: 1;
+  grid-row: 1;
+
+  display: grid;
+  grid-template-columns: auto auto 1fr;
+  grid-template-rows: auto 1fr;
+
+  .avatar-link {
+    grid-column: 1;
+    grid-row: 1 / 3;
+    margin-right: 30px;
+  }
+
+  img {
+    @include channel-avatar(75px);
+  }
+
+  a {
+    color: pvar(--mainForegroundColor);
+  }
+
+  h2 {
+    grid-row: 1;
+    grid-column: 2;
+    font-size: 20px;
+    line-height: 1;
+    font-weight: $font-bold;
+    margin: 0;
+  }
+
+  .actor-counters {
+    grid-row: 1;
+    grid-column: 3;
+    color: pvar(--greyForegroundColor);
+    font-size: 16px;
+    display: flex;
     align-items: center;
+    margin-left: 15px;
   }
 
-  .videos {
-    overflow: hidden;
-
-    .no-results {
-      height: 50px;
-    }
+  .actor-counters > *:not(:last-child)::after {
+    content: '•';
+    margin: 0 10px;
+    color: pvar(--mainColor);
   }
 
-  my-video-miniature ::ng-deep my-video-actions-dropdown > my-action-dropdown {
-    // Fix our overflow
-    position: absolute;
+  .description-html {
+    grid-column: 2 / 4;
+    grid-row: 2;
+
+    max-height: 80px;
+    font-size: 16px;
+
+    @include fade-text(30px, pvar(--channelBackgroundColor));
   }
 }
 
+my-subscribe-button {
+  grid-row: 1;
+  grid-column: 2;
+}
+
+.videos {
+  display: flex;
+  grid-column: 1 / 3;
+  grid-row: 2;
+  margin-top: 30px;
+
+  position: relative;
+  overflow: hidden;
+
+  my-video-miniature {
+    margin-right: 15px;
+  }
+
+  .no-results {
+    height: auto;
+  }
+}
+
+.miniature-show-channel {
+  height: 100%;
+  position: absolute;
+  right: 0;
+  background: linear-gradient(90deg, transparent 0, pvar(--channelBackgroundColor) 45px);
+  padding: ($video-thumbnail-height / 2 - 10px) 15px 0 60px;
+  z-index: z(miniature) + 1;
+
+  a {
+    color: pvar(--mainColor);
+    font-size: 16px;
+    font-weight: $font-semibold;
+  }
+}
+
+.button-show-channel {
+  display: none;
+}
+
 @media screen and (max-width: $mobile-view) {
-  .section {
-    .section-title {
-      flex-direction: column;
-      align-items: normal;
+  .channel-avatar-row {
+    grid-template-columns: auto auto auto 1fr;
+
+    .avatar-link {
+      grid-row: 1 / 4;
+    }
+
+    h2 {
+      font-size: 16px;
+    }
+
+    .actor-counters {
+      margin: 0;
+      font-size: 13px;
+      grid-row: 2;
+      grid-column: 2 / 4;
+    }
+
+    .description-html {
+      grid-row: 3;
+      font-size: 14px;
     }
   }
+
+  .show-channel a {
+    @include peertube-button-link;
+    @include orange-button-inverted;
+  }
+
+  .videos {
+    display: none;
+  }
+
+  my-subscribe-button,
+  .button-show-channel {
+    grid-column: 1 / 4;
+    grid-row: 3;
+    margin-top: 15px;
+  }
+
+  my-subscribe-button {
+    justify-self: start;
+  }
+
+  .button-show-channel {
+    display: block;
+    justify-self: end;
+  }
 }
diff --git a/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts b/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
index f2beb6689..0628c7a96 100644
--- a/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
+++ b/client/src/app/+accounts/account-video-channels/account-video-channels.component.ts
@@ -1,9 +1,10 @@
 import { from, Subject, Subscription } from 'rxjs'
 import { concatMap, map, switchMap, tap } from 'rxjs/operators'
 import { Component, OnDestroy, OnInit } from '@angular/core'
-import { ComponentPagination, hasMoreItems, ScreenService, User, UserService } from '@app/core'
+import { ComponentPagination, hasMoreItems, MarkdownService, ScreenService, User, UserService } from '@app/core'
 import { Account, AccountService, Video, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
 import { NSFWPolicyType, VideoSortField } from '@shared/models'
+import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature'
 
 @Component({
   selector: 'my-account-video-channels',
@@ -13,7 +14,10 @@ import { NSFWPolicyType, VideoSortField } from '@shared/models'
 export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
   account: Account
   videoChannels: VideoChannel[] = []
-  videos: { [id: number]: Video[] } = {}
+
+  videos: { [id: number]: { total: number, videos: Video[] } } = {}
+
+  channelsDescriptionHTML: { [ id: number ]: string } = {}
 
   channelPagination: ComponentPagination = {
     currentPage: 1,
@@ -23,7 +27,7 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
 
   videosPagination: ComponentPagination = {
     currentPage: 1,
-    itemsPerPage: 12,
+    itemsPerPage: 5,
     totalItems: null
   }
   videosSort: VideoSortField = '-publishedAt'
@@ -32,6 +36,16 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
 
   userMiniature: User
   nsfwPolicy: NSFWPolicyType
+  miniatureDisplayOptions: MiniatureDisplayOptions = {
+    date: true,
+    views: true,
+    by: false,
+    avatar: false,
+    privacyLabel: false,
+    privacyText: false,
+    state: false,
+    blacklistInfo: false
+  }
 
   private accountSub: Subscription
 
@@ -39,7 +53,7 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
     private accountService: AccountService,
     private videoChannelService: VideoChannelService,
     private videoService: VideoService,
-    private screenService: ScreenService,
+    private markdown: MarkdownService,
     private userService: UserService
   ) { }
 
@@ -78,23 +92,36 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy {
           }
 
           return this.videoService.getVideoChannelVideos(options)
-            .pipe(map(data => ({ videoChannel, videos: data.data })))
+            .pipe(map(data => ({ videoChannel, videos: data.data, total: data.total })))
         })
       )
-      .subscribe(({ videoChannel, videos }) => {
+      .subscribe(async ({ videoChannel, videos, total }) => {
+        this.channelsDescriptionHTML[videoChannel.id] = await this.markdown.textMarkdownToHTML(videoChannel.description)
+
         this.videoChannels.push(videoChannel)
 
-        this.videos[videoChannel.id] = videos
+        this.videos[videoChannel.id] = { videos, total }
 
         this.onChannelDataSubject.next([ videoChannel ])
       })
   }
 
   getVideosOf (videoChannel: VideoChannel) {
-    const numberOfVideos = this.screenService.getNumberOfAvailableMiniatures()
+    const obj = this.videos[ videoChannel.id ]
+    if (!obj) return []
 
-    // 2 rows
-    return this.videos[ videoChannel.id ].slice(0, numberOfVideos * 2)
+    return obj.videos
+  }
+
+  getTotalVideosOf (videoChannel: VideoChannel) {
+    const obj = this.videos[ videoChannel.id ]
+    if (!obj) return undefined
+
+    return obj.total
+  }
+
+  getChannelDescription (videoChannel: VideoChannel) {
+    return this.channelsDescriptionHTML[videoChannel.id]
   }
 
   onNearOfBottom () {
diff --git a/client/src/app/+accounts/accounts.component.html b/client/src/app/+accounts/accounts.component.html
index 92d24ce94..e149d0bc6 100644
--- a/client/src/app/+accounts/accounts.component.html
+++ b/client/src/app/+accounts/accounts.component.html
@@ -60,11 +60,11 @@
     </div>
 
     <div class="buttons">
-      <a *ngIf="isManageable() && !isInSmallView()" routerLink="/my-account" class="peertube-button-link orange-button" i18n>
+      <a *ngIf="isManageable()" routerLink="/my-account" class="peertube-button-link orange-button" i18n>
         Manage account
       </a>
 
-      <my-subscribe-button *ngIf="videoChannels" [account]="account" [videoChannels]="videoChannels"></my-subscribe-button>
+      <my-subscribe-button *ngIf="hasVideoChannels() && !isManageable()" [account]="account" [videoChannels]="videoChannels"></my-subscribe-button>
     </div>
   </div>
 
diff --git a/client/src/app/+accounts/accounts.component.scss b/client/src/app/+accounts/accounts.component.scss
index c1cf53f3a..6a51dd038 100644
--- a/client/src/app/+accounts/accounts.component.scss
+++ b/client/src/app/+accounts/accounts.component.scss
@@ -4,7 +4,7 @@
 @import '_miniature';
 
 .root {
-  --myGlobalPadding: 60px;
+  --myGlobalTopPadding: 60px;
   --myImgMargin: 30px;
   --myFontSize: 16px;
   --myGreyFontSize: 16px;
@@ -15,12 +15,16 @@
 }
 
 .links {
-  @include fluid-videos-miniature-layout;
+  @include fluid-videos-miniature-margins;
 
   display: flex;
   justify-content: space-between;
   align-items: center;
-  max-width: 800px;
+  max-width: $max-channels-width;
+
+  simple-search-input {
+    margin-left: auto;
+  }
 }
 
 my-user-moderation-dropdown,
@@ -40,13 +44,15 @@ my-user-moderation-dropdown,
 }
 
 .account-info {
+  @include fluid-videos-miniature-margins(false, 15px);
+
   display: grid;
   grid-template-columns: 1fr min-content;
   grid-template-rows: auto auto;
 
   background-color: pvar(--submenuColor);
   margin-bottom: 45px;
-  padding: var(--myGlobalPadding) var(--myGlobalPadding) 0 var(--myGlobalPadding);
+  padding-top: var(--myGlobalTopPadding);
   font-size: var(--myFontSize);
 }
 
@@ -83,11 +89,15 @@ my-user-moderation-dropdown,
   > *:not(:last-child) {
     margin-bottom: 15px;
   }
+
+  > a {
+    white-space: nowrap;
+  }
 }
 
 @media screen and (max-width: $small-view) {
   .root {
-    --myGlobalPadding: 45px;
+    --myGlobalTopPadding: 45px;
     --myChannelImgMargin: 15px;
   }
 
@@ -113,7 +123,7 @@ my-user-moderation-dropdown,
 
 @media screen and (max-width: $mobile-view) {
   .root {
-    --myGlobalPadding: 15px;
+    --myGlobalTopPadding: 15px;
     --myFontSize: 14px;
     --myGreyFontSize: 13px;
   }
diff --git a/client/src/app/+accounts/accounts.component.ts b/client/src/app/+accounts/accounts.component.ts
index a00063129..abee0b9bb 100644
--- a/client/src/app/+accounts/accounts.component.ts
+++ b/client/src/app/+accounts/accounts.component.ts
@@ -143,6 +143,10 @@ export class AccountsComponent implements OnInit, OnDestroy {
     this.hideMenu = this.isInSmallView() && displayed
   }
 
+  hasVideoChannels () {
+    return this.videoChannels.length !== 0
+  }
+
   private async onAccount (account: Account) {
     this.accountFollowerTitle = $localize`${account.followersCount} direct account followers`
 
diff --git a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
index 803651505..5e2af1b92 100644
--- a/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
+++ b/client/src/app/+video-channels/video-channel-videos/video-channel-videos.component.ts
@@ -5,7 +5,7 @@ import { ActivatedRoute, Router } from '@angular/router'
 import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core'
 import { immutableAssign } from '@app/helpers'
 import { VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main'
-import { AbstractVideoList } from '@app/shared/shared-video-miniature'
+import { AbstractVideoList, MiniatureDisplayOptions } from '@app/shared/shared-video-miniature'
 import { VideoFilter } from '@shared/models'
 
 @Component({
@@ -22,6 +22,17 @@ export class VideoChannelVideosComponent extends AbstractVideoList implements On
 
   filter: VideoFilter = null
 
+  displayOptions: MiniatureDisplayOptions = {
+    date: true,
+    views: true,
+    by: false,
+    avatar: false,
+    privacyLabel: true,
+    privacyText: false,
+    state: false,
+    blacklistInfo: false
+  }
+
   private videoChannel: VideoChannel
   private videoChannelSub: Subscription
 
diff --git a/client/src/app/+video-channels/video-channels.component.html b/client/src/app/+video-channels/video-channels.component.html
index d1eb15dff..9f9c1f2ca 100644
--- a/client/src/app/+video-channels/video-channels.component.html
+++ b/client/src/app/+video-channels/video-channels.component.html
@@ -2,17 +2,17 @@
   <div class="channel-info">
 
     <ng-template #buttonsTemplate>
-        <a *ngIf="isManageable() && !isInSmallView()" [routerLink]="[ '/my-library/video-channels/update', videoChannel.nameWithHost ]" class="peertube-button-link orange-button" i18n>
+        <a *ngIf="isManageable()" [routerLink]="[ '/my-library/video-channels/update', videoChannel.nameWithHost ]" class="peertube-button-link orange-button" i18n>
           Manage channel
         </a>
 
-        <my-subscribe-button #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button>
+        <my-subscribe-button *ngIf="!isManageable()" #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button>
     </ng-template>
 
     <ng-template #ownerTemplate>
       <div class="owner-block">
         <div class="avatar-row">
-          <img class="channel-avatar" [src]="videoChannel.ownerAvatarUrl" alt="Owner account avatar" />
+          <img class="account-avatar" [src]="videoChannel.ownerAvatarUrl" alt="Owner account avatar" />
 
           <div class="actor-info">
             <h4>{{ videoChannel.ownerAccount.displayName }}</h4>
@@ -36,7 +36,7 @@
     </ng-template>
 
     <div class="channel-avatar-row">
-      <img [src]="videoChannel.avatarUrl" alt="Avatar" />
+      <img class="channel-avatar" [src]="videoChannel.avatarUrl" alt="Avatar" />
 
       <div>
         <div class="section-label" i18n>VIDEO CHANNEL</div>
diff --git a/client/src/app/+video-channels/video-channels.component.scss b/client/src/app/+video-channels/video-channels.component.scss
index f5547b4e9..fb71844bd 100644
--- a/client/src/app/+video-channels/video-channels.component.scss
+++ b/client/src/app/+video-channels/video-channels.component.scss
@@ -4,7 +4,7 @@
 @import '_miniature';
 
 .root {
-  --myGlobalPadding: 60px;
+  --myGlobalTopPadding: 60px;
   --myChannelImgMargin: 30px;
   --myFontSize: 16px;
   --myGreyChannelFontSize: 16px;
@@ -16,17 +16,19 @@
 }
 
 .links {
-  @include fluid-videos-miniature-layout;
+  @include fluid-videos-miniature-margins;
 }
 
 .channel-info {
+  @include fluid-videos-miniature-margins(false, 15px);
+
   display: grid;
   grid-template-columns: 1fr auto;
   grid-template-rows: auto auto;
 
   background-color: pvar(--channelBackgroundColor);
   margin-bottom: 45px;
-  padding: var(--myGlobalPadding) var(--myGlobalPadding) 0 var(--myGlobalPadding);
+  padding-top: var(--myGlobalTopPadding);
   font-size: var(--myFontSize);
 }
 
@@ -146,7 +148,7 @@
 
 @media screen and (max-width: 1100px) {
   .root {
-    --myGlobalPadding: 45px;
+    --myGlobalTopPadding: 45px;
     --myChannelImgMargin: 15px;
   }
 
@@ -184,7 +186,7 @@
     display: block;
     width: 100%;
     border-bottom: 2px solid $separator-border-color;
-    padding: var(--myGlobalPadding) 45px;
+    padding: var(--myGlobalTopPadding) 45px;
     margin-bottom: 60px;
   }
 
@@ -223,7 +225,7 @@
 
 @media screen and (max-width: $mobile-view) {
   .root {
-    --myGlobalPadding: 15px;
+    --myGlobalTopPadding: 15px;
     --myFontSize: 14px;
     --myGreyChannelFontSize: 13px;
     --myGreyOwnerFontSize: 13px;
diff --git a/client/src/app/shared/shared-main/misc/simple-search-input.component.scss b/client/src/app/shared/shared-main/misc/simple-search-input.component.scss
index 037937f80..116ff7ea0 100644
--- a/client/src/app/shared/shared-main/misc/simple-search-input.component.scss
+++ b/client/src/app/shared/shared-main/misc/simple-search-input.component.scss
@@ -6,8 +6,8 @@
 }
 
 my-global-icon {
-  height: 26px;
-  width: 26px;
+  height: 28px;
+  width: 28px;
   margin-left: 10px;
   cursor: pointer;
 
diff --git a/client/src/sass/include/_miniature.scss b/client/src/sass/include/_miniature.scss
index 134b307b1..326d4677a 100644
--- a/client/src/sass/include/_miniature.scss
+++ b/client/src/sass/include/_miniature.scss
@@ -176,14 +176,41 @@ $play-overlay-width: 18px;
   }
 }
 
-@mixin fluid-videos-miniature-layout {
-  margin-left: $not-expanded-horizontal-margins !important;
-  margin-right: $not-expanded-horizontal-margins !important;
+// Use margin by default, or padding if $margin is false
+@mixin fluid-videos-miniature-margins ($margin: true, $min-margin: 0) {
+  @if $margin {
+    margin-left: $not-expanded-horizontal-margins !important;
+    margin-right: $not-expanded-horizontal-margins !important;
+  } @else {
+    padding-left: $not-expanded-horizontal-margins !important;
+    padding-right: $not-expanded-horizontal-margins !important;
+  }
 
   @media screen and (max-width: $mobile-view) {
     width: auto;
-    margin: 0 !important;
 
+    @if $margin {
+      margin: $min-margin !important;
+    } @else {
+      padding: $min-margin !important;
+    }
+  }
+
+  @media screen and (min-width: #{breakpoint(fhd)}) {
+    @if $margin {
+      margin-left: 6vw !important;
+      margin-right: 6vw !important;
+    } @else {
+      padding-left: 6vw !important;
+      padding-right: 6vw !important;
+    }
+  }
+}
+
+@mixin fluid-videos-miniature-layout {
+  @include fluid-videos-miniature-margins;
+
+  @media screen and (max-width: $mobile-view) {
     .videos {
       text-align: center;
 
@@ -209,13 +236,7 @@ $play-overlay-width: 18px;
     }
   }
 
-  @media screen and (min-width: #{breakpoint(fhd)}) {
-    margin-left: 6vw !important;
-    margin-right: 6vw !important;
-  }
-
   @media screen and (min-width: $mobile-view) {
-
     .videos {
       --miniature-min-width: #{$video-thumbnail-width - 15px};
       --miniature-max-width: #{$video-thumbnail-width};
diff --git a/client/src/sass/include/_variables.scss b/client/src/sass/include/_variables.scss
index bcd28215b..724a897fa 100644
--- a/client/src/sass/include/_variables.scss
+++ b/client/src/sass/include/_variables.scss
@@ -52,6 +52,7 @@ $sub-menu-color: #F7F7F7;
 $sub-menu-height: 81px;
 
 $channel-background-color: #f6ede8;
+$max-channels-width: 1200px;
 
 $footer-height: 30px;
 $footer-margin: 30px;