aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--client/src/app/+accounts/account-video-channels/account-video-channels.component.scss12
-rw-r--r--client/src/app/shared/shared-custom-markup/custom-markup-container.component.scss10
-rw-r--r--client/src/app/shared/shared-custom-markup/custom-markup.service.ts15
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.html28
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.scss58
-rw-r--r--client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts49
-rw-r--r--client/src/sass/include/_mixins.scss13
-rw-r--r--shared/models/custom-markup/custom-markup-data.model.ts4
8 files changed, 166 insertions, 23 deletions
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 da3751b47..60914ec12 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
@@ -52,19 +52,10 @@
52 52
53 .actor-counters { 53 .actor-counters {
54 @include margin-left(15px); 54 @include margin-left(15px);
55 @include actor-counters;
55 56
56 grid-row: 1; 57 grid-row: 1;
57 grid-column: 3; 58 grid-column: 3;
58 color: pvar(--greyForegroundColor);
59 font-size: 16px;
60 display: flex;
61 align-items: center;
62 }
63
64 .actor-counters > *:not(:last-child)::after {
65 content: '•';
66 margin: 0 10px;
67 color: pvar(--mainColor);
68 } 59 }
69 60
70 .description-html { 61 .description-html {
@@ -94,6 +85,7 @@ my-subscribe-button {
94 85
95 my-video-miniature { 86 my-video-miniature {
96 @include margin-right(15px); 87 @include margin-right(15px);
88
97 min-width: $video-thumbnail-medium-width; 89 min-width: $video-thumbnail-medium-width;
98 max-width: $video-thumbnail-medium-width; 90 max-width: $video-thumbnail-medium-width;
99 } 91 }
diff --git a/client/src/app/shared/shared-custom-markup/custom-markup-container.component.scss b/client/src/app/shared/shared-custom-markup/custom-markup-container.component.scss
index 044db9536..862da7c18 100644
--- a/client/src/app/shared/shared-custom-markup/custom-markup-container.component.scss
+++ b/client/src/app/shared/shared-custom-markup/custom-markup-container.component.scss
@@ -6,5 +6,15 @@
6 h4 { 6 h4 {
7 margin-bottom: 0; 7 margin-bottom: 0;
8 } 8 }
9
10 .layout-row {
11 display: flex;
12 flex-direction: row;
13 }
14
15 .layout-column {
16 display: flex;
17 flex-direction: column;
18 }
9 } 19 }
10} 20}
diff --git a/client/src/app/shared/shared-custom-markup/custom-markup.service.ts b/client/src/app/shared/shared-custom-markup/custom-markup.service.ts
index db5f64ee8..aa5dbe643 100644
--- a/client/src/app/shared/shared-custom-markup/custom-markup.service.ts
+++ b/client/src/app/shared/shared-custom-markup/custom-markup.service.ts
@@ -122,7 +122,13 @@ export class CustomMarkupService {
122 const data = el.dataset as ChannelMiniatureMarkupData 122 const data = el.dataset as ChannelMiniatureMarkupData
123 const component = this.dynamicElementService.createElement(ChannelMiniatureMarkupComponent) 123 const component = this.dynamicElementService.createElement(ChannelMiniatureMarkupComponent)
124 124
125 this.dynamicElementService.setModel(component, { name: data.name }) 125 const model = {
126 name: data.name,
127 displayLatestVideo: this.buildBoolean(data.displayLatestVideo) ?? true,
128 displayDescription: this.buildBoolean(data.displayDescription) ?? true
129 }
130
131 this.dynamicElementService.setModel(component, model)
126 132
127 return component 133 return component
128 } 134 }
@@ -178,7 +184,12 @@ export class CustomMarkupService {
178 const data = el.dataset as ContainerMarkupData 184 const data = el.dataset as ContainerMarkupData
179 185
180 const root = document.createElement('div') 186 const root = document.createElement('div')
181 root.classList.add('peertube-container') 187
188 const layoutClass = data.layout
189 ? 'layout-' + data.layout
190 : 'layout-row'
191
192 root.classList.add('peertube-container', layoutClass)
182 193
183 if (data.width) { 194 if (data.width) {
184 root.setAttribute('width', data.width) 195 root.setAttribute('width', data.width)
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.html b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.html
index da81006b9..2efc56ab2 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.html
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.html
@@ -1,8 +1,28 @@
1<div *ngIf="channel" class="channel"> 1<div *ngIf="channel" class="channel">
2 <my-actor-avatar [channel]="channel" size="34"></my-actor-avatar>
3 2
4 <div class="display-name">{{ channel.displayName }}</div> 3 <div class="channel-avatar-row">
5 <div class="username">{{ channel.name }}</div> 4 <my-actor-avatar [channel]="channel" [internalHref]="getVideoChannelLink()" i18n-title title="See this video channel"></my-actor-avatar>
6 5
7 <div class="description">{{ channel.description }}</div> 6 <h6>
7 <a [routerLink]="getVideoChannelLink()" i18n-title title="See this video channel">
8 {{ channel.displayName }}
9 </a>
10 </h6>
11
12 <div class="actor-counters">
13 <div class="followers" i18n>{channel.followersCount, plural, =1 {1 subscriber} other {{{ channel.followersCount }} subscribers}}</div>
14
15 <span class="videos-count" *ngIf="totalVideos !== undefined" i18n>
16 {totalVideos, plural, =1 {1 videos} other {{{ totalVideos }} videos}}
17 </span>
18 </div>
19
20 <div *ngIf="displayDescription" class="description-html" [innerHTML]="descriptionHTML"></div>
21 </div>
22
23 <div class="video" *ngIf="video && displayLatestVideo">
24 <div i18n class="video-label">Latest published video</div>
25
26 <my-video-miniature-markup [uuid]="video.uuid" [onlyDisplayTitle]="true"></my-video-miniature-markup>
27 </div>
8</div> 28</div>
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.scss b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.scss
index 85018afe2..80c36a58b 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.scss
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.scss
@@ -2,8 +2,58 @@
2@import '_mixins'; 2@import '_mixins';
3 3
4.channel { 4.channel {
5 border-radius: 15px; 5 padding: 20px;
6 padding: 10px; 6 background-color: pvar(--channelBackgroundColor);
7 width: min-content; 7 margin: 0 30px 30px 0;
8 border: 1px solid pvar(--mainColor); 8 width: fit-content;
9}
10
11.channel-avatar-row,
12.video {
13 width: 280px;
14}
15
16.channel-avatar-row {
17 display: grid;
18 grid-template-columns: auto 1fr;
19 grid-template-rows: auto auto 1fr;
20 column-gap: 15px;
21
22 a {
23 @include peertube-word-wrap;
24
25 color: pvar(--mainForegroundColor);
26 }
27
28 my-actor-avatar {
29 @include actor-avatar-size(75px);
30
31 grid-column: 1;
32 grid-row: 1 / 4;
33 }
34
35 h6 {
36 grid-column: 2;
37 margin: 0;
38 }
39
40 .actor-counters {
41 @include actor-counters(5px);
42
43 font-size: 13px;
44 grid-column: 2;
45 }
46
47 .description-html {
48 @include fade-text(30px, pvar(--channelBackgroundColor));
49
50 max-height: 60px;
51 grid-column: 2;
52 }
53}
54
55.video-label {
56 font-size: 12px;
57 color: pvar(--greyForegroundColor);
58 margin: 15px 0 5px;
9} 59}
diff --git a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts
index 25deafb80..87caec8a5 100644
--- a/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts
+++ b/client/src/app/shared/shared-custom-markup/peertube-custom-tags/channel-miniature-markup.component.ts
@@ -1,5 +1,8 @@
1import { map, switchMap } from 'rxjs/operators'
1import { Component, Input, OnInit } from '@angular/core' 2import { Component, Input, OnInit } from '@angular/core'
2import { VideoChannel, VideoChannelService } from '../../shared-main' 3import { MarkdownService, UserService } from '@app/core'
4import { Video, VideoSortField } from '@shared/models/videos'
5import { VideoChannel, VideoChannelService, VideoService } from '../../shared-main'
3 6
4/* 7/*
5 * Markup component that creates a channel miniature only 8 * Markup component that creates a channel miniature only
@@ -12,15 +15,55 @@ import { VideoChannel, VideoChannelService } from '../../shared-main'
12}) 15})
13export class ChannelMiniatureMarkupComponent implements OnInit { 16export class ChannelMiniatureMarkupComponent implements OnInit {
14 @Input() name: string 17 @Input() name: string
18 @Input() displayLatestVideo: boolean
19 @Input() displayDescription: boolean
15 20
16 channel: VideoChannel 21 channel: VideoChannel
22 descriptionHTML: string
23 totalVideos: number
24 video: Video
17 25
18 constructor ( 26 constructor (
19 private channelService: VideoChannelService 27 private markdown: MarkdownService,
28 private channelService: VideoChannelService,
29 private videoService: VideoService,
30 private userService: UserService
20 ) { } 31 ) { }
21 32
22 ngOnInit () { 33 ngOnInit () {
23 this.channelService.getVideoChannel(this.name) 34 this.channelService.getVideoChannel(this.name)
24 .subscribe(channel => this.channel = channel) 35 .subscribe(async channel => {
36 this.channel = channel
37
38 this.descriptionHTML = await this.markdown.textMarkdownToHTML(channel.description)
39
40 this.loadVideos()
41 })
42 }
43
44 getVideoChannelLink () {
45 return [ '/c', this.channel.nameWithHost ]
46 }
47
48 private loadVideos () {
49 const videoOptions = {
50 videoChannel: this.channel,
51 videoPagination: {
52 currentPage: 1,
53 itemsPerPage: 1
54 },
55 sort: '-publishedAt' as VideoSortField,
56 count: 1
57 }
58
59 this.userService.getAnonymousOrLoggedUser()
60 .pipe(
61 map(user => user.nsfwPolicy),
62 switchMap(nsfwPolicy => this.videoService.getVideoChannelVideos({ ...videoOptions, nsfwPolicy }))
63 )
64 .subscribe(({ total, data }) => {
65 this.totalVideos = total
66 this.video = data[0]
67 })
25 } 68 }
26} 69}
diff --git a/client/src/sass/include/_mixins.scss b/client/src/sass/include/_mixins.scss
index 19454cdb2..0822e0ca6 100644
--- a/client/src/sass/include/_mixins.scss
+++ b/client/src/sass/include/_mixins.scss
@@ -569,6 +569,19 @@
569 min-height: $size; 569 min-height: $size;
570} 570}
571 571
572@mixin actor-counters ($separator-margin: 10px) {
573 color: pvar(--greyForegroundColor);
574 font-size: 16px;
575 display: flex;
576 align-items: center;
577
578 > *:not(:last-child)::after {
579 content: '•';
580 margin: 0 $separator-margin;
581 color: pvar(--mainColor);
582 }
583}
584
572@mixin chevron ($size, $border-width) { 585@mixin chevron ($size, $border-width) {
573 border-style: solid; 586 border-style: solid;
574 border-width: $border-width $border-width 0 0; 587 border-width: $border-width $border-width 0 0;
diff --git a/shared/models/custom-markup/custom-markup-data.model.ts b/shared/models/custom-markup/custom-markup-data.model.ts
index 085ea7cf6..f3c23ec2c 100644
--- a/shared/models/custom-markup/custom-markup-data.model.ts
+++ b/shared/models/custom-markup/custom-markup-data.model.ts
@@ -18,6 +18,9 @@ export type PlaylistMiniatureMarkupData = {
18export type ChannelMiniatureMarkupData = { 18export type ChannelMiniatureMarkupData = {
19 // Channel name (username) 19 // Channel name (username)
20 name: string 20 name: string
21
22 displayLatestVideo?: string // boolean
23 displayDescription?: string // boolean
21} 24}
22 25
23export type VideosListMarkupData = { 26export type VideosListMarkupData = {
@@ -43,4 +46,5 @@ export type ContainerMarkupData = {
43 width?: string 46 width?: string
44 title?: string 47 title?: string
45 description?: string 48 description?: string
49 layout?: 'row' | 'column'
46} 50}