diff options
12 files changed, 296 insertions, 71 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 @@ | |||
1 | <h1 class="sr-only" i18n>Video channels</h1> | 1 | <h1 class="sr-only" i18n>Video channels</h1> |
2 | |||
2 | <div class="margin-content"> | 3 | <div class="margin-content"> |
3 | 4 | ||
4 | <div class="no-results" i18n *ngIf="channelPagination.totalItems === 0">This account does not have channels.</div> | 5 | <div class="no-results" i18n *ngIf="channelPagination.totalItems === 0">This account does not have channels.</div> |
5 | 6 | ||
6 | <div class="channels" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onChannelDataSubject.asObservable()"> | 7 | <div class="channels" myInfiniteScroller (nearOfBottom)="onNearOfBottom()" [autoInit]="true" [dataObservable]="onChannelDataSubject.asObservable()"> |
7 | <div class="section channel" *ngFor="let videoChannel of videoChannels"> | 8 | <div class="channel" *ngFor="let videoChannel of videoChannels"> |
8 | <div class="section-title"> | 9 | |
9 | <a [routerLink]="getVideoChannelLink(videoChannel)" i18n-title title="See this video channel"> | 10 | <div class="channel-avatar-row"> |
11 | <a class="avatar-link" [routerLink]="getVideoChannelLink(videoChannel)" i18n-title title="See this video channel"> | ||
10 | <img [src]="videoChannel.avatarUrl" alt="Avatar" /> | 12 | <img [src]="videoChannel.avatarUrl" alt="Avatar" /> |
13 | </a> | ||
11 | 14 | ||
12 | <h2 class="section-title">{{ videoChannel.displayName }}</h2> | 15 | <h2> |
16 | <a [routerLink]="getVideoChannelLink(videoChannel)" i18n-title title="See this video channel"> | ||
17 | {{ videoChannel.displayName }} | ||
18 | </a> | ||
19 | </h2> | ||
20 | |||
21 | <div class="actor-counters"> | ||
13 | <div class="followers" i18n>{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div> | 22 | <div class="followers" i18n>{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div> |
14 | </a> | ||
15 | 23 | ||
16 | <my-subscribe-button [videoChannels]="[videoChannel]"></my-subscribe-button> | 24 | <span class="videos-count" *ngIf="getTotalVideosOf(videoChannel) !== undefined" i18n> |
25 | {getTotalVideosOf(videoChannel), splural, =1 {1 videos} other {{{ getTotalVideosOf(videoChannel) }} videos}} | ||
26 | </span> | ||
27 | </div> | ||
28 | |||
29 | <div class="description-html" [innerHTML]="getChannelDescription(videoChannel)"></div> | ||
17 | </div> | 30 | </div> |
18 | 31 | ||
19 | <div *ngIf="getVideosOf(videoChannel)" class="videos"> | 32 | <my-subscribe-button [videoChannels]="[videoChannel]"></my-subscribe-button> |
20 | <div class="no-results my-5" i18n *ngIf="getVideosOf(videoChannel).length === 0">This channel doesn't have any videos.</div> | 33 | |
34 | <a i18n class="button-show-channel peertube-button-link orange-button-inverted" [routerLink]="getVideoChannelLink(videoChannel)">Show this channel</a> | ||
35 | |||
36 | <div class="videos"> | ||
37 | <div class="no-results" i18n *ngIf="getTotalVideosOf(videoChannel) === 0">This channel doesn't have any videos.</div> | ||
21 | 38 | ||
22 | <my-video-miniature | 39 | <my-video-miniature |
23 | *ngFor="let video of getVideosOf(videoChannel)" | 40 | *ngFor="let video of getVideosOf(videoChannel)" |
24 | [video]="video" [user]="userMiniature" [displayVideoActions]="true" | 41 | [video]="video" [user]="userMiniature" [displayVideoActions]="true" [displayOptions]="miniatureDisplayOptions" |
25 | ></my-video-miniature> | 42 | ></my-video-miniature> |
26 | </div> | ||
27 | 43 | ||
28 | <a *ngIf="getVideosOf(videoChannel).length !== 0" class="show-more" i18n [routerLink]="getVideoChannelLink(videoChannel)"> | 44 | <div *ngIf="getTotalVideosOf(videoChannel)" class="miniature-show-channel"> |
29 | SHOW THIS CHANNEL | 45 | <a i18n [routerLink]="getVideoChannelLink(videoChannel)">SHOW THIS CHANNEL ></a> |
30 | </a> | 46 | </div> |
47 | </div> | ||
31 | </div> | 48 | </div> |
32 | </div> | 49 | </div> |
33 | </div> | 50 | </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 @@ | |||
3 | @import '_miniature'; | 3 | @import '_miniature'; |
4 | 4 | ||
5 | .margin-content { | 5 | .margin-content { |
6 | @include fluid-videos-miniature-layout; | 6 | @include fluid-videos-miniature-margins; |
7 | } | 7 | } |
8 | 8 | ||
9 | .section { | 9 | .channel { |
10 | @include miniature-rows; | 10 | max-width: $max-channels-width; |
11 | background-color: pvar(--channelBackgroundColor); | ||
12 | padding: 15px; | ||
11 | 13 | ||
12 | padding-top: 0 !important; | 14 | margin: 30px 0; |
13 | 15 | ||
14 | .section-title { | 16 | display: grid; |
17 | grid-template-columns: 1fr auto; | ||
18 | grid-template-rows: auto auto; | ||
19 | column-gap: 15px; | ||
20 | } | ||
21 | |||
22 | .channel-avatar-row { | ||
23 | grid-column: 1; | ||
24 | grid-row: 1; | ||
25 | |||
26 | display: grid; | ||
27 | grid-template-columns: auto auto 1fr; | ||
28 | grid-template-rows: auto 1fr; | ||
29 | |||
30 | .avatar-link { | ||
31 | grid-column: 1; | ||
32 | grid-row: 1 / 3; | ||
33 | margin-right: 30px; | ||
34 | } | ||
35 | |||
36 | img { | ||
37 | @include channel-avatar(75px); | ||
38 | } | ||
39 | |||
40 | a { | ||
41 | color: pvar(--mainForegroundColor); | ||
42 | } | ||
43 | |||
44 | h2 { | ||
45 | grid-row: 1; | ||
46 | grid-column: 2; | ||
47 | font-size: 20px; | ||
48 | line-height: 1; | ||
49 | font-weight: $font-bold; | ||
50 | margin: 0; | ||
51 | } | ||
52 | |||
53 | .actor-counters { | ||
54 | grid-row: 1; | ||
55 | grid-column: 3; | ||
56 | color: pvar(--greyForegroundColor); | ||
57 | font-size: 16px; | ||
58 | display: flex; | ||
15 | align-items: center; | 59 | align-items: center; |
60 | margin-left: 15px; | ||
16 | } | 61 | } |
17 | 62 | ||
18 | .videos { | 63 | .actor-counters > *:not(:last-child)::after { |
19 | overflow: hidden; | 64 | content: '•'; |
65 | margin: 0 10px; | ||
66 | color: pvar(--mainColor); | ||
67 | } | ||
20 | 68 | ||
21 | .no-results { | 69 | .description-html { |
22 | height: 50px; | 70 | grid-column: 2 / 4; |
23 | } | 71 | grid-row: 2; |
72 | |||
73 | max-height: 80px; | ||
74 | font-size: 16px; | ||
75 | |||
76 | @include fade-text(30px, pvar(--channelBackgroundColor)); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | my-subscribe-button { | ||
81 | grid-row: 1; | ||
82 | grid-column: 2; | ||
83 | } | ||
84 | |||
85 | .videos { | ||
86 | display: flex; | ||
87 | grid-column: 1 / 3; | ||
88 | grid-row: 2; | ||
89 | margin-top: 30px; | ||
90 | |||
91 | position: relative; | ||
92 | overflow: hidden; | ||
93 | |||
94 | my-video-miniature { | ||
95 | margin-right: 15px; | ||
24 | } | 96 | } |
25 | 97 | ||
26 | my-video-miniature ::ng-deep my-video-actions-dropdown > my-action-dropdown { | 98 | .no-results { |
27 | // Fix our overflow | 99 | height: auto; |
28 | position: absolute; | ||
29 | } | 100 | } |
30 | } | 101 | } |
31 | 102 | ||
103 | .miniature-show-channel { | ||
104 | height: 100%; | ||
105 | position: absolute; | ||
106 | right: 0; | ||
107 | background: linear-gradient(90deg, transparent 0, pvar(--channelBackgroundColor) 45px); | ||
108 | padding: ($video-thumbnail-height / 2 - 10px) 15px 0 60px; | ||
109 | z-index: z(miniature) + 1; | ||
110 | |||
111 | a { | ||
112 | color: pvar(--mainColor); | ||
113 | font-size: 16px; | ||
114 | font-weight: $font-semibold; | ||
115 | } | ||
116 | } | ||
117 | |||
118 | .button-show-channel { | ||
119 | display: none; | ||
120 | } | ||
121 | |||
32 | @media screen and (max-width: $mobile-view) { | 122 | @media screen and (max-width: $mobile-view) { |
33 | .section { | 123 | .channel-avatar-row { |
34 | .section-title { | 124 | grid-template-columns: auto auto auto 1fr; |
35 | flex-direction: column; | 125 | |
36 | align-items: normal; | 126 | .avatar-link { |
127 | grid-row: 1 / 4; | ||
128 | } | ||
129 | |||
130 | h2 { | ||
131 | font-size: 16px; | ||
132 | } | ||
133 | |||
134 | .actor-counters { | ||
135 | margin: 0; | ||
136 | font-size: 13px; | ||
137 | grid-row: 2; | ||
138 | grid-column: 2 / 4; | ||
139 | } | ||
140 | |||
141 | .description-html { | ||
142 | grid-row: 3; | ||
143 | font-size: 14px; | ||
37 | } | 144 | } |
38 | } | 145 | } |
146 | |||
147 | .show-channel a { | ||
148 | @include peertube-button-link; | ||
149 | @include orange-button-inverted; | ||
150 | } | ||
151 | |||
152 | .videos { | ||
153 | display: none; | ||
154 | } | ||
155 | |||
156 | my-subscribe-button, | ||
157 | .button-show-channel { | ||
158 | grid-column: 1 / 4; | ||
159 | grid-row: 3; | ||
160 | margin-top: 15px; | ||
161 | } | ||
162 | |||
163 | my-subscribe-button { | ||
164 | justify-self: start; | ||
165 | } | ||
166 | |||
167 | .button-show-channel { | ||
168 | display: block; | ||
169 | justify-self: end; | ||
170 | } | ||
39 | } | 171 | } |
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 @@ | |||
1 | import { from, Subject, Subscription } from 'rxjs' | 1 | import { from, Subject, Subscription } from 'rxjs' |
2 | import { concatMap, map, switchMap, tap } from 'rxjs/operators' | 2 | import { concatMap, map, switchMap, tap } from 'rxjs/operators' |
3 | import { Component, OnDestroy, OnInit } from '@angular/core' | 3 | import { Component, OnDestroy, OnInit } from '@angular/core' |
4 | import { ComponentPagination, hasMoreItems, ScreenService, User, UserService } from '@app/core' | 4 | import { ComponentPagination, hasMoreItems, MarkdownService, ScreenService, User, UserService } from '@app/core' |
5 | import { Account, AccountService, Video, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main' | 5 | import { Account, AccountService, Video, VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main' |
6 | import { NSFWPolicyType, VideoSortField } from '@shared/models' | 6 | import { NSFWPolicyType, VideoSortField } from '@shared/models' |
7 | import { MiniatureDisplayOptions } from '@app/shared/shared-video-miniature' | ||
7 | 8 | ||
8 | @Component({ | 9 | @Component({ |
9 | selector: 'my-account-video-channels', | 10 | selector: 'my-account-video-channels', |
@@ -13,7 +14,10 @@ import { NSFWPolicyType, VideoSortField } from '@shared/models' | |||
13 | export class AccountVideoChannelsComponent implements OnInit, OnDestroy { | 14 | export class AccountVideoChannelsComponent implements OnInit, OnDestroy { |
14 | account: Account | 15 | account: Account |
15 | videoChannels: VideoChannel[] = [] | 16 | videoChannels: VideoChannel[] = [] |
16 | videos: { [id: number]: Video[] } = {} | 17 | |
18 | videos: { [id: number]: { total: number, videos: Video[] } } = {} | ||
19 | |||
20 | channelsDescriptionHTML: { [ id: number ]: string } = {} | ||
17 | 21 | ||
18 | channelPagination: ComponentPagination = { | 22 | channelPagination: ComponentPagination = { |
19 | currentPage: 1, | 23 | currentPage: 1, |
@@ -23,7 +27,7 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy { | |||
23 | 27 | ||
24 | videosPagination: ComponentPagination = { | 28 | videosPagination: ComponentPagination = { |
25 | currentPage: 1, | 29 | currentPage: 1, |
26 | itemsPerPage: 12, | 30 | itemsPerPage: 5, |
27 | totalItems: null | 31 | totalItems: null |
28 | } | 32 | } |
29 | videosSort: VideoSortField = '-publishedAt' | 33 | videosSort: VideoSortField = '-publishedAt' |
@@ -32,6 +36,16 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy { | |||
32 | 36 | ||
33 | userMiniature: User | 37 | userMiniature: User |
34 | nsfwPolicy: NSFWPolicyType | 38 | nsfwPolicy: NSFWPolicyType |
39 | miniatureDisplayOptions: MiniatureDisplayOptions = { | ||
40 | date: true, | ||
41 | views: true, | ||
42 | by: false, | ||
43 | avatar: false, | ||
44 | privacyLabel: false, | ||
45 | privacyText: false, | ||
46 | state: false, | ||
47 | blacklistInfo: false | ||
48 | } | ||
35 | 49 | ||
36 | private accountSub: Subscription | 50 | private accountSub: Subscription |
37 | 51 | ||
@@ -39,7 +53,7 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy { | |||
39 | private accountService: AccountService, | 53 | private accountService: AccountService, |
40 | private videoChannelService: VideoChannelService, | 54 | private videoChannelService: VideoChannelService, |
41 | private videoService: VideoService, | 55 | private videoService: VideoService, |
42 | private screenService: ScreenService, | 56 | private markdown: MarkdownService, |
43 | private userService: UserService | 57 | private userService: UserService |
44 | ) { } | 58 | ) { } |
45 | 59 | ||
@@ -78,23 +92,36 @@ export class AccountVideoChannelsComponent implements OnInit, OnDestroy { | |||
78 | } | 92 | } |
79 | 93 | ||
80 | return this.videoService.getVideoChannelVideos(options) | 94 | return this.videoService.getVideoChannelVideos(options) |
81 | .pipe(map(data => ({ videoChannel, videos: data.data }))) | 95 | .pipe(map(data => ({ videoChannel, videos: data.data, total: data.total }))) |
82 | }) | 96 | }) |
83 | ) | 97 | ) |
84 | .subscribe(({ videoChannel, videos }) => { | 98 | .subscribe(async ({ videoChannel, videos, total }) => { |
99 | this.channelsDescriptionHTML[videoChannel.id] = await this.markdown.textMarkdownToHTML(videoChannel.description) | ||
100 | |||
85 | this.videoChannels.push(videoChannel) | 101 | this.videoChannels.push(videoChannel) |
86 | 102 | ||
87 | this.videos[videoChannel.id] = videos | 103 | this.videos[videoChannel.id] = { videos, total } |
88 | 104 | ||
89 | this.onChannelDataSubject.next([ videoChannel ]) | 105 | this.onChannelDataSubject.next([ videoChannel ]) |
90 | }) | 106 | }) |
91 | } | 107 | } |
92 | 108 | ||
93 | getVideosOf (videoChannel: VideoChannel) { | 109 | getVideosOf (videoChannel: VideoChannel) { |
94 | const numberOfVideos = this.screenService.getNumberOfAvailableMiniatures() | 110 | const obj = this.videos[ videoChannel.id ] |
111 | if (!obj) return [] | ||
112 | |||
113 | return obj.videos | ||
114 | } | ||
115 | |||
116 | getTotalVideosOf (videoChannel: VideoChannel) { | ||
117 | const obj = this.videos[ videoChannel.id ] | ||
118 | if (!obj) return undefined | ||
119 | |||
120 | return obj.total | ||
121 | } | ||
95 | 122 | ||
96 | // 2 rows | 123 | getChannelDescription (videoChannel: VideoChannel) { |
97 | return this.videos[ videoChannel.id ].slice(0, numberOfVideos * 2) | 124 | return this.channelsDescriptionHTML[videoChannel.id] |
98 | } | 125 | } |
99 | 126 | ||
100 | onNearOfBottom () { | 127 | 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 @@ | |||
60 | </div> | 60 | </div> |
61 | 61 | ||
62 | <div class="buttons"> | 62 | <div class="buttons"> |
63 | <a *ngIf="isManageable() && !isInSmallView()" routerLink="/my-account" class="peertube-button-link orange-button" i18n> | 63 | <a *ngIf="isManageable()" routerLink="/my-account" class="peertube-button-link orange-button" i18n> |
64 | Manage account | 64 | Manage account |
65 | </a> | 65 | </a> |
66 | 66 | ||
67 | <my-subscribe-button *ngIf="videoChannels" [account]="account" [videoChannels]="videoChannels"></my-subscribe-button> | 67 | <my-subscribe-button *ngIf="hasVideoChannels() && !isManageable()" [account]="account" [videoChannels]="videoChannels"></my-subscribe-button> |
68 | </div> | 68 | </div> |
69 | </div> | 69 | </div> |
70 | 70 | ||
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 @@ | |||
4 | @import '_miniature'; | 4 | @import '_miniature'; |
5 | 5 | ||
6 | .root { | 6 | .root { |
7 | --myGlobalPadding: 60px; | 7 | --myGlobalTopPadding: 60px; |
8 | --myImgMargin: 30px; | 8 | --myImgMargin: 30px; |
9 | --myFontSize: 16px; | 9 | --myFontSize: 16px; |
10 | --myGreyFontSize: 16px; | 10 | --myGreyFontSize: 16px; |
@@ -15,12 +15,16 @@ | |||
15 | } | 15 | } |
16 | 16 | ||
17 | .links { | 17 | .links { |
18 | @include fluid-videos-miniature-layout; | 18 | @include fluid-videos-miniature-margins; |
19 | 19 | ||
20 | display: flex; | 20 | display: flex; |
21 | justify-content: space-between; | 21 | justify-content: space-between; |
22 | align-items: center; | 22 | align-items: center; |
23 | max-width: 800px; | 23 | max-width: $max-channels-width; |
24 | |||
25 | simple-search-input { | ||
26 | margin-left: auto; | ||
27 | } | ||
24 | } | 28 | } |
25 | 29 | ||
26 | my-user-moderation-dropdown, | 30 | my-user-moderation-dropdown, |
@@ -40,13 +44,15 @@ my-user-moderation-dropdown, | |||
40 | } | 44 | } |
41 | 45 | ||
42 | .account-info { | 46 | .account-info { |
47 | @include fluid-videos-miniature-margins(false, 15px); | ||
48 | |||
43 | display: grid; | 49 | display: grid; |
44 | grid-template-columns: 1fr min-content; | 50 | grid-template-columns: 1fr min-content; |
45 | grid-template-rows: auto auto; | 51 | grid-template-rows: auto auto; |
46 | 52 | ||
47 | background-color: pvar(--submenuColor); | 53 | background-color: pvar(--submenuColor); |
48 | margin-bottom: 45px; | 54 | margin-bottom: 45px; |
49 | padding: var(--myGlobalPadding) var(--myGlobalPadding) 0 var(--myGlobalPadding); | 55 | padding-top: var(--myGlobalTopPadding); |
50 | font-size: var(--myFontSize); | 56 | font-size: var(--myFontSize); |
51 | } | 57 | } |
52 | 58 | ||
@@ -83,11 +89,15 @@ my-user-moderation-dropdown, | |||
83 | > *:not(:last-child) { | 89 | > *:not(:last-child) { |
84 | margin-bottom: 15px; | 90 | margin-bottom: 15px; |
85 | } | 91 | } |
92 | |||
93 | > a { | ||
94 | white-space: nowrap; | ||
95 | } | ||
86 | } | 96 | } |
87 | 97 | ||
88 | @media screen and (max-width: $small-view) { | 98 | @media screen and (max-width: $small-view) { |
89 | .root { | 99 | .root { |
90 | --myGlobalPadding: 45px; | 100 | --myGlobalTopPadding: 45px; |
91 | --myChannelImgMargin: 15px; | 101 | --myChannelImgMargin: 15px; |
92 | } | 102 | } |
93 | 103 | ||
@@ -113,7 +123,7 @@ my-user-moderation-dropdown, | |||
113 | 123 | ||
114 | @media screen and (max-width: $mobile-view) { | 124 | @media screen and (max-width: $mobile-view) { |
115 | .root { | 125 | .root { |
116 | --myGlobalPadding: 15px; | 126 | --myGlobalTopPadding: 15px; |
117 | --myFontSize: 14px; | 127 | --myFontSize: 14px; |
118 | --myGreyFontSize: 13px; | 128 | --myGreyFontSize: 13px; |
119 | } | 129 | } |
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 { | |||
143 | this.hideMenu = this.isInSmallView() && displayed | 143 | this.hideMenu = this.isInSmallView() && displayed |
144 | } | 144 | } |
145 | 145 | ||
146 | hasVideoChannels () { | ||
147 | return this.videoChannels.length !== 0 | ||
148 | } | ||
149 | |||
146 | private async onAccount (account: Account) { | 150 | private async onAccount (account: Account) { |
147 | this.accountFollowerTitle = $localize`${account.followersCount} direct account followers` | 151 | this.accountFollowerTitle = $localize`${account.followersCount} direct account followers` |
148 | 152 | ||
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' | |||
5 | import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core' | 5 | import { AuthService, ConfirmService, LocalStorageService, Notifier, ScreenService, ServerService, UserService } from '@app/core' |
6 | import { immutableAssign } from '@app/helpers' | 6 | import { immutableAssign } from '@app/helpers' |
7 | import { VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main' | 7 | import { VideoChannel, VideoChannelService, VideoService } from '@app/shared/shared-main' |
8 | import { AbstractVideoList } from '@app/shared/shared-video-miniature' | 8 | import { AbstractVideoList, MiniatureDisplayOptions } from '@app/shared/shared-video-miniature' |
9 | import { VideoFilter } from '@shared/models' | 9 | import { VideoFilter } from '@shared/models' |
10 | 10 | ||
11 | @Component({ | 11 | @Component({ |
@@ -22,6 +22,17 @@ export class VideoChannelVideosComponent extends AbstractVideoList implements On | |||
22 | 22 | ||
23 | filter: VideoFilter = null | 23 | filter: VideoFilter = null |
24 | 24 | ||
25 | displayOptions: MiniatureDisplayOptions = { | ||
26 | date: true, | ||
27 | views: true, | ||
28 | by: false, | ||
29 | avatar: false, | ||
30 | privacyLabel: true, | ||
31 | privacyText: false, | ||
32 | state: false, | ||
33 | blacklistInfo: false | ||
34 | } | ||
35 | |||
25 | private videoChannel: VideoChannel | 36 | private videoChannel: VideoChannel |
26 | private videoChannelSub: Subscription | 37 | private videoChannelSub: Subscription |
27 | 38 | ||
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 @@ | |||
2 | <div class="channel-info"> | 2 | <div class="channel-info"> |
3 | 3 | ||
4 | <ng-template #buttonsTemplate> | 4 | <ng-template #buttonsTemplate> |
5 | <a *ngIf="isManageable() && !isInSmallView()" [routerLink]="[ '/my-library/video-channels/update', videoChannel.nameWithHost ]" class="peertube-button-link orange-button" i18n> | 5 | <a *ngIf="isManageable()" [routerLink]="[ '/my-library/video-channels/update', videoChannel.nameWithHost ]" class="peertube-button-link orange-button" i18n> |
6 | Manage channel | 6 | Manage channel |
7 | </a> | 7 | </a> |
8 | 8 | ||
9 | <my-subscribe-button #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button> | 9 | <my-subscribe-button *ngIf="!isManageable()" #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button> |
10 | </ng-template> | 10 | </ng-template> |
11 | 11 | ||
12 | <ng-template #ownerTemplate> | 12 | <ng-template #ownerTemplate> |
13 | <div class="owner-block"> | 13 | <div class="owner-block"> |
14 | <div class="avatar-row"> | 14 | <div class="avatar-row"> |
15 | <img class="channel-avatar" [src]="videoChannel.ownerAvatarUrl" alt="Owner account avatar" /> | 15 | <img class="account-avatar" [src]="videoChannel.ownerAvatarUrl" alt="Owner account avatar" /> |
16 | 16 | ||
17 | <div class="actor-info"> | 17 | <div class="actor-info"> |
18 | <h4>{{ videoChannel.ownerAccount.displayName }}</h4> | 18 | <h4>{{ videoChannel.ownerAccount.displayName }}</h4> |
@@ -36,7 +36,7 @@ | |||
36 | </ng-template> | 36 | </ng-template> |
37 | 37 | ||
38 | <div class="channel-avatar-row"> | 38 | <div class="channel-avatar-row"> |
39 | <img [src]="videoChannel.avatarUrl" alt="Avatar" /> | 39 | <img class="channel-avatar" [src]="videoChannel.avatarUrl" alt="Avatar" /> |
40 | 40 | ||
41 | <div> | 41 | <div> |
42 | <div class="section-label" i18n>VIDEO CHANNEL</div> | 42 | <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 @@ | |||
4 | @import '_miniature'; | 4 | @import '_miniature'; |
5 | 5 | ||
6 | .root { | 6 | .root { |
7 | --myGlobalPadding: 60px; | 7 | --myGlobalTopPadding: 60px; |
8 | --myChannelImgMargin: 30px; | 8 | --myChannelImgMargin: 30px; |
9 | --myFontSize: 16px; | 9 | --myFontSize: 16px; |
10 | --myGreyChannelFontSize: 16px; | 10 | --myGreyChannelFontSize: 16px; |
@@ -16,17 +16,19 @@ | |||
16 | } | 16 | } |
17 | 17 | ||
18 | .links { | 18 | .links { |
19 | @include fluid-videos-miniature-layout; | 19 | @include fluid-videos-miniature-margins; |
20 | } | 20 | } |
21 | 21 | ||
22 | .channel-info { | 22 | .channel-info { |
23 | @include fluid-videos-miniature-margins(false, 15px); | ||
24 | |||
23 | display: grid; | 25 | display: grid; |
24 | grid-template-columns: 1fr auto; | 26 | grid-template-columns: 1fr auto; |
25 | grid-template-rows: auto auto; | 27 | grid-template-rows: auto auto; |
26 | 28 | ||
27 | background-color: pvar(--channelBackgroundColor); | 29 | background-color: pvar(--channelBackgroundColor); |
28 | margin-bottom: 45px; | 30 | margin-bottom: 45px; |
29 | padding: var(--myGlobalPadding) var(--myGlobalPadding) 0 var(--myGlobalPadding); | 31 | padding-top: var(--myGlobalTopPadding); |
30 | font-size: var(--myFontSize); | 32 | font-size: var(--myFontSize); |
31 | } | 33 | } |
32 | 34 | ||
@@ -146,7 +148,7 @@ | |||
146 | 148 | ||
147 | @media screen and (max-width: 1100px) { | 149 | @media screen and (max-width: 1100px) { |
148 | .root { | 150 | .root { |
149 | --myGlobalPadding: 45px; | 151 | --myGlobalTopPadding: 45px; |
150 | --myChannelImgMargin: 15px; | 152 | --myChannelImgMargin: 15px; |
151 | } | 153 | } |
152 | 154 | ||
@@ -184,7 +186,7 @@ | |||
184 | display: block; | 186 | display: block; |
185 | width: 100%; | 187 | width: 100%; |
186 | border-bottom: 2px solid $separator-border-color; | 188 | border-bottom: 2px solid $separator-border-color; |
187 | padding: var(--myGlobalPadding) 45px; | 189 | padding: var(--myGlobalTopPadding) 45px; |
188 | margin-bottom: 60px; | 190 | margin-bottom: 60px; |
189 | } | 191 | } |
190 | 192 | ||
@@ -223,7 +225,7 @@ | |||
223 | 225 | ||
224 | @media screen and (max-width: $mobile-view) { | 226 | @media screen and (max-width: $mobile-view) { |
225 | .root { | 227 | .root { |
226 | --myGlobalPadding: 15px; | 228 | --myGlobalTopPadding: 15px; |
227 | --myFontSize: 14px; | 229 | --myFontSize: 14px; |
228 | --myGreyChannelFontSize: 13px; | 230 | --myGreyChannelFontSize: 13px; |
229 | --myGreyOwnerFontSize: 13px; | 231 | --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 @@ | |||
6 | } | 6 | } |
7 | 7 | ||
8 | my-global-icon { | 8 | my-global-icon { |
9 | height: 26px; | 9 | height: 28px; |
10 | width: 26px; | 10 | width: 28px; |
11 | margin-left: 10px; | 11 | margin-left: 10px; |
12 | cursor: pointer; | 12 | cursor: pointer; |
13 | 13 | ||
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; | |||
176 | } | 176 | } |
177 | } | 177 | } |
178 | 178 | ||
179 | @mixin fluid-videos-miniature-layout { | 179 | // Use margin by default, or padding if $margin is false |
180 | margin-left: $not-expanded-horizontal-margins !important; | 180 | @mixin fluid-videos-miniature-margins ($margin: true, $min-margin: 0) { |
181 | margin-right: $not-expanded-horizontal-margins !important; | 181 | @if $margin { |
182 | margin-left: $not-expanded-horizontal-margins !important; | ||
183 | margin-right: $not-expanded-horizontal-margins !important; | ||
184 | } @else { | ||
185 | padding-left: $not-expanded-horizontal-margins !important; | ||
186 | padding-right: $not-expanded-horizontal-margins !important; | ||
187 | } | ||
182 | 188 | ||
183 | @media screen and (max-width: $mobile-view) { | 189 | @media screen and (max-width: $mobile-view) { |
184 | width: auto; | 190 | width: auto; |
185 | margin: 0 !important; | ||
186 | 191 | ||
192 | @if $margin { | ||
193 | margin: $min-margin !important; | ||
194 | } @else { | ||
195 | padding: $min-margin !important; | ||
196 | } | ||
197 | } | ||
198 | |||
199 | @media screen and (min-width: #{breakpoint(fhd)}) { | ||
200 | @if $margin { | ||
201 | margin-left: 6vw !important; | ||
202 | margin-right: 6vw !important; | ||
203 | } @else { | ||
204 | padding-left: 6vw !important; | ||
205 | padding-right: 6vw !important; | ||
206 | } | ||
207 | } | ||
208 | } | ||
209 | |||
210 | @mixin fluid-videos-miniature-layout { | ||
211 | @include fluid-videos-miniature-margins; | ||
212 | |||
213 | @media screen and (max-width: $mobile-view) { | ||
187 | .videos { | 214 | .videos { |
188 | text-align: center; | 215 | text-align: center; |
189 | 216 | ||
@@ -209,13 +236,7 @@ $play-overlay-width: 18px; | |||
209 | } | 236 | } |
210 | } | 237 | } |
211 | 238 | ||
212 | @media screen and (min-width: #{breakpoint(fhd)}) { | ||
213 | margin-left: 6vw !important; | ||
214 | margin-right: 6vw !important; | ||
215 | } | ||
216 | |||
217 | @media screen and (min-width: $mobile-view) { | 239 | @media screen and (min-width: $mobile-view) { |
218 | |||
219 | .videos { | 240 | .videos { |
220 | --miniature-min-width: #{$video-thumbnail-width - 15px}; | 241 | --miniature-min-width: #{$video-thumbnail-width - 15px}; |
221 | --miniature-max-width: #{$video-thumbnail-width}; | 242 | --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; | |||
52 | $sub-menu-height: 81px; | 52 | $sub-menu-height: 81px; |
53 | 53 | ||
54 | $channel-background-color: #f6ede8; | 54 | $channel-background-color: #f6ede8; |
55 | $max-channels-width: 1200px; | ||
55 | 56 | ||
56 | $footer-height: 30px; | 57 | $footer-height: 30px; |
57 | $footer-margin: 30px; | 58 | $footer-margin: 30px; |