]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Improve channel card custom markup
authorChocobozzz <me@florianbigard.com>
Wed, 9 Jun 2021 08:31:27 +0000 (10:31 +0200)
committerChocobozzz <me@florianbigard.com>
Wed, 9 Jun 2021 08:31:27 +0000 (10:31 +0200)
client/src/app/+accounts/account-video-channels/account-video-channels.component.scss
client/src/app/shared/shared-custom-markup/custom-markup-container.component.scss
client/src/app/shared/shared-custom-markup/custom-markup.service.ts
client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.html
client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.scss
client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts
client/src/sass/include/_mixins.scss
shared/models/custom-markup/custom-markup-data.model.ts

index da3751b478501606a3b8e8cf220f6509252487af..60914ec121ddc4c221b045b81b8ebd038180a1af 100644 (file)
 
   .actor-counters {
     @include margin-left(15px);
+    @include actor-counters;
 
     grid-row: 1;
     grid-column: 3;
-    color: pvar(--greyForegroundColor);
-    font-size: 16px;
-    display: flex;
-    align-items: center;
-  }
-
-  .actor-counters > *:not(:last-child)::after {
-    content: '•';
-    margin: 0 10px;
-    color: pvar(--mainColor);
   }
 
   .description-html {
@@ -94,6 +85,7 @@ my-subscribe-button {
 
   my-video-miniature {
     @include margin-right(15px);
+
     min-width: $video-thumbnail-medium-width;
     max-width: $video-thumbnail-medium-width;
   }
index 044db953694bc1c3fe575c1e66edebce56ea6343..862da7c18893333822837be417958cb3f1010d6b 100644 (file)
@@ -6,5 +6,15 @@
     h4 {
       margin-bottom: 0;
     }
+
+    .layout-row {
+      display: flex;
+      flex-direction: row;
+    }
+
+    .layout-column {
+      display: flex;
+      flex-direction: column;
+    }
   }
 }
index db5f64ee80bc6b72ed2a8f4c5ee023c1b8185fa7..aa5dbe64360be4e63b87915f75179fc69593e309 100644 (file)
@@ -122,7 +122,13 @@ export class CustomMarkupService {
     const data = el.dataset as ChannelMiniatureMarkupData
     const component = this.dynamicElementService.createElement(ChannelMiniatureMarkupComponent)
 
-    this.dynamicElementService.setModel(component, { name: data.name })
+    const model = {
+      name: data.name,
+      displayLatestVideo: this.buildBoolean(data.displayLatestVideo) ?? true,
+      displayDescription: this.buildBoolean(data.displayDescription) ?? true
+    }
+
+    this.dynamicElementService.setModel(component, model)
 
     return component
   }
@@ -178,7 +184,12 @@ export class CustomMarkupService {
     const data = el.dataset as ContainerMarkupData
 
     const root = document.createElement('div')
-    root.classList.add('peertube-container')
+
+    const layoutClass = data.layout
+      ? 'layout-' + data.layout
+      : 'layout-row'
+
+    root.classList.add('peertube-container', layoutClass)
 
     if (data.width) {
       root.setAttribute('width', data.width)
index da81006b9e80ca9253495f87cdd4d0c0fb269243..2efc56ab2deb1e111b87b715ea898a913f41e555 100644 (file)
@@ -1,8 +1,28 @@
 <div *ngIf="channel" class="channel">
-  <my-actor-avatar [channel]="channel" size="34"></my-actor-avatar>
 
-  <div class="display-name">{{ channel.displayName }}</div>
-  <div class="username">{{ channel.name }}</div>
+  <div class="channel-avatar-row">
+    <my-actor-avatar [channel]="channel" [internalHref]="getVideoChannelLink()" i18n-title title="See this video channel"></my-actor-avatar>
 
-  <div class="description">{{ channel.description }}</div>
+    <h6>
+      <a [routerLink]="getVideoChannelLink()" i18n-title title="See this video channel">
+        {{ channel.displayName }}
+      </a>
+    </h6>
+
+    <div class="actor-counters">
+      <div class="followers" i18n>{channel.followersCount, plural, =1 {1 subscriber} other {{{ channel.followersCount }} subscribers}}</div>
+
+      <span class="videos-count" *ngIf="totalVideos !== undefined" i18n>
+        {totalVideos, plural, =1 {1 videos} other {{{ totalVideos }} videos}}
+      </span>
+    </div>
+
+    <div *ngIf="displayDescription" class="description-html" [innerHTML]="descriptionHTML"></div>
+  </div>
+
+  <div class="video" *ngIf="video && displayLatestVideo">
+    <div i18n class="video-label">Latest published video</div>
+
+    <my-video-miniature-markup [uuid]="video.uuid" [onlyDisplayTitle]="true"></my-video-miniature-markup>
+  </div>
 </div>
index 85018afe2b6d0ec5dc8bd3a4b6baef2d12479f1a..80c36a58bd344d1089fbe6c8b176a45e2129cb5a 100644 (file)
@@ -2,8 +2,58 @@
 @import '_mixins';
 
 .channel {
-  border-radius: 15px;
-  padding: 10px;
-  width: min-content;
-  border: 1px solid pvar(--mainColor);
+  padding: 20px;
+  background-color: pvar(--channelBackgroundColor);
+  margin: 0 30px 30px 0;
+  width: fit-content;
+}
+
+.channel-avatar-row,
+.video {
+  width: 280px;
+}
+
+.channel-avatar-row {
+  display: grid;
+  grid-template-columns: auto 1fr;
+  grid-template-rows: auto auto 1fr;
+  column-gap: 15px;
+
+  a {
+    @include peertube-word-wrap;
+
+    color: pvar(--mainForegroundColor);
+  }
+
+  my-actor-avatar {
+    @include actor-avatar-size(75px);
+
+    grid-column: 1;
+    grid-row: 1 / 4;
+  }
+
+  h6 {
+    grid-column: 2;
+    margin: 0;
+  }
+
+  .actor-counters {
+    @include actor-counters(5px);
+
+    font-size: 13px;
+    grid-column: 2;
+  }
+
+  .description-html {
+    @include fade-text(30px, pvar(--channelBackgroundColor));
+
+    max-height: 60px;
+    grid-column: 2;
+  }
+}
+
+.video-label {
+  font-size: 12px;
+  color: pvar(--greyForegroundColor);
+  margin: 15px 0 5px;
 }
index 25deafb80ff120eac19fbfe8798599c445edf43f..87caec8a5a3c28742def6b33c6799fe96f7439fb 100644 (file)
@@ -1,5 +1,8 @@
+import { map, switchMap } from 'rxjs/operators'
 import { Component, Input, OnInit } from '@angular/core'
-import { VideoChannel, VideoChannelService } from '../../shared-main'
+import { MarkdownService, UserService } from '@app/core'
+import { Video, VideoSortField } from '@shared/models/videos'
+import { VideoChannel, VideoChannelService, VideoService } from '../../shared-main'
 
 /*
  * Markup component that creates a channel miniature only
@@ -12,15 +15,55 @@ import { VideoChannel, VideoChannelService } from '../../shared-main'
 })
 export class ChannelMiniatureMarkupComponent implements OnInit {
   @Input() name: string
+  @Input() displayLatestVideo: boolean
+  @Input() displayDescription: boolean
 
   channel: VideoChannel
+  descriptionHTML: string
+  totalVideos: number
+  video: Video
 
   constructor (
-    private channelService: VideoChannelService
+    private markdown: MarkdownService,
+    private channelService: VideoChannelService,
+    private videoService: VideoService,
+    private userService: UserService
   ) { }
 
   ngOnInit () {
     this.channelService.getVideoChannel(this.name)
-      .subscribe(channel => this.channel = channel)
+      .subscribe(async channel => {
+        this.channel = channel
+
+        this.descriptionHTML = await this.markdown.textMarkdownToHTML(channel.description)
+
+        this.loadVideos()
+      })
+  }
+
+  getVideoChannelLink () {
+    return [ '/c', this.channel.nameWithHost ]
+  }
+
+  private loadVideos () {
+    const videoOptions = {
+      videoChannel: this.channel,
+      videoPagination: {
+        currentPage: 1,
+        itemsPerPage: 1
+      },
+      sort: '-publishedAt' as VideoSortField,
+      count: 1
+    }
+
+    this.userService.getAnonymousOrLoggedUser()
+      .pipe(
+        map(user => user.nsfwPolicy),
+        switchMap(nsfwPolicy => this.videoService.getVideoChannelVideos({ ...videoOptions, nsfwPolicy }))
+      )
+      .subscribe(({ total, data }) => {
+        this.totalVideos = total
+        this.video = data[0]
+      })
   }
 }
index 19454cdb21b8aa04bb0de4e78b38d36eb6efd879..0822e0ca64c55c92b4d02f74aba543fbd0c804d5 100644 (file)
   min-height: $size;
 }
 
+@mixin actor-counters ($separator-margin: 10px) {
+  color: pvar(--greyForegroundColor);
+  font-size: 16px;
+  display: flex;
+  align-items: center;
+
+  > *:not(:last-child)::after {
+    content: '•';
+    margin: 0 $separator-margin;
+    color: pvar(--mainColor);
+  }
+}
+
 @mixin chevron ($size, $border-width) {
   border-style: solid;
   border-width: $border-width $border-width 0 0;
index 085ea7cf6e48ccac0fb6b454987571f30ca8c7b2..f3c23ec2c93aad3b68bc2c266bfefa6e0356bf99 100644 (file)
@@ -18,6 +18,9 @@ export type PlaylistMiniatureMarkupData = {
 export type ChannelMiniatureMarkupData = {
   // Channel name (username)
   name: string
+
+  displayLatestVideo?: string // boolean
+  displayDescription?: string // boolean
 }
 
 export type VideosListMarkupData = {
@@ -43,4 +46,5 @@ export type ContainerMarkupData = {
   width?: string
   title?: string
   description?: string
+  layout?: 'row' | 'column'
 }