Channel/account page redesign feedbacks

Fix owner default avatar
Semi bold orange inverted button
Max width account description
Increase account's channels padding
Use owner avatar/display name links
Move "view owner account" link on mobile
Try to always display channel in video miniatures
Add small border radius for channel's avatar
Use main foreground color for the magnifying glass
This commit is contained in:
Chocobozzz 2021-03-31 08:59:52 +02:00 committed by Chocobozzz
parent c8e80d1461
commit 733dbc535d
20 changed files with 63 additions and 41 deletions

View File

@ -22,7 +22,7 @@
<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}}
{getTotalVideosOf(videoChannel), plural, =1 {1 videos} other {{{ getTotalVideosOf(videoChannel) }} videos}}
</span>
</div>

View File

@ -9,7 +9,7 @@
.channel {
max-width: $max-channels-width;
background-color: pvar(--channelBackgroundColor);
padding: 15px;
padding: 30px;
margin: 30px 0;
@ -120,6 +120,10 @@ my-subscribe-button {
}
@media screen and (max-width: $mobile-view) {
.channel {
padding: 15px;
}
.channel-avatar-row {
grid-template-columns: auto auto auto 1fr;

View File

@ -52,7 +52,7 @@
<div class="created-at" i18n>Account created on {{ account.createdAt | date }}</div>
</div>
<div *ngIf="!accountDescriptionExpanded" class="show-more" role="button"
<div *ngIf="hasShowMoreDescription()" class="show-more" role="button"
(click)="accountDescriptionExpanded = !accountDescriptionExpanded"
title="Show the complete description" i18n-title i18n
>

View File

@ -62,6 +62,8 @@ my-user-moderation-dropdown,
.description {
grid-column: 1 / 3;
max-width: 1000px;
word-break: break-word;
}
.created-at {

View File

@ -147,6 +147,10 @@ export class AccountsComponent implements OnInit, OnDestroy {
return this.videoChannels.length !== 0
}
hasShowMoreDescription () {
return !this.accountDescriptionExpanded && this.accountDescriptionHTML.length > 100
}
private async onAccount (account: Account) {
this.accountFollowerTitle = $localize`${account.followersCount} direct account followers`

View File

@ -34,7 +34,6 @@
[miniatureDisplayOptions]="miniatureDisplayOptions"
[titlePage]="titlePage"
[getVideosObservableFunction]="getVideosObservableFunction"
[ownerDisplayType]="ownerDisplayType"
[user]="user"
#videosSelection
>

View File

@ -2,12 +2,12 @@ import { concat, Observable, Subject } from 'rxjs'
import { debounceTime, tap, toArray } from 'rxjs/operators'
import { Component, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import { AuthService, ComponentPagination, ConfirmService, Notifier, ScreenService, ServerService, User, UserService } from '@app/core'
import { AuthService, ComponentPagination, ConfirmService, Notifier, ScreenService, ServerService, User } from '@app/core'
import { DisableForReuseHook } from '@app/core/routing/disable-for-reuse-hook'
import { immutableAssign } from '@app/helpers'
import { DropdownAction, Video, VideoService } from '@app/shared/shared-main'
import { LiveStreamInformationComponent } from '@app/shared/shared-video-live'
import { MiniatureDisplayOptions, OwnerDisplayType, SelectionType, VideosSelectionComponent } from '@app/shared/shared-video-miniature'
import { MiniatureDisplayOptions, SelectionType, VideosSelectionComponent } from '@app/shared/shared-video-miniature'
import { VideoSortField } from '@shared/models'
import { VideoChangeOwnershipComponent } from './modals/video-change-ownership.component'
@ -36,7 +36,6 @@ export class MyVideosComponent implements OnInit, DisableForReuseHook {
state: true,
blacklistInfo: true
}
ownerDisplayType: OwnerDisplayType = 'videoChannel'
videoActions: DropdownAction<{ video: Video }>[] = []

View File

@ -17,10 +17,14 @@
<ng-template #ownerTemplate>
<div class="owner-block">
<div class="avatar-row">
<img class="account-avatar" [src]="videoChannel.ownerAvatarUrl" alt="Owner account avatar" />
<a [routerLink]="getAccountUrl()" title="View account" i18n-title>
<img class="account-avatar" [src]="videoChannel.ownerAvatarUrl" alt="Owner account avatar" />
</a>
<div class="actor-info">
<h4>{{ videoChannel.ownerAccount.displayName }}</h4>
<h4>
<a [routerLink]="getAccountUrl()" title="View account" i18n-title>{{ videoChannel.ownerAccount.displayName }}</a>
</h4>
<div class="actor-handle">@{{ videoChannel.ownerBy }}</div>
</div>
@ -30,11 +34,11 @@
<div class="description-html" [innerHTML]="ownerDescriptionHTML"></div>
</div>
<a class="view-account short" [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n>
<a class="view-account short" [routerLink]="getAccountUrl()" i18n>
View account
</a>
<a class="view-account complete" [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n>
<a class="view-account complete" [routerLink]="getAccountUrl()" i18n>
View owner account
</a>
</div>
@ -83,7 +87,7 @@
<div class="created-at" i18n>Channel created on {{ videoChannel.createdAt | date }}</div>
</div>
<div *ngIf="!channelDescriptionExpanded" class="show-more" role="button"
<div *ngIf="hasShowMoreDescription()" class="show-more" role="button"
(click)="channelDescriptionExpanded = !channelDescriptionExpanded"
title="Show the complete description" i18n-title i18n
>

View File

@ -42,6 +42,7 @@
.channel-description {
grid-column: 1;
word-break: break-word;
}
.show-more {
@ -108,6 +109,10 @@
h4 {
font-size: 18px;
margin: 0;
a {
color: pvar(--mainForegroundColor);
}
}
.actor-handle {
@ -118,6 +123,7 @@
.owner-description {
height: 140px;
word-break: break-word;
@include fade-text(120px, pvar(--mainBackgroundColor));
}
@ -217,7 +223,8 @@
}
.view-account.complete {
display: inline-block;
display: block;
text-align: right;
margin-top: 10px;
color: pvar(--mainColor);
}

View File

@ -103,10 +103,18 @@ export class VideoChannelsComponent implements OnInit, OnDestroy {
this.notifier.success($localize`Username copied`)
}
hasShowMoreDescription () {
return !this.channelDescriptionExpanded && this.channelDescriptionHTML.length > 100
}
showSupportModal () {
this.supportModal.show()
}
getAccountUrl () {
return [ '/accounts', this.videoChannel.ownerBy ]
}
private loadChannelVideosCount () {
this.videoService.getVideoChannelVideos({
videoChannel: this.videoChannel,

View File

@ -7,7 +7,7 @@ import { HooksService } from '@app/core/plugins/hooks.service'
import { immutableAssign } from '@app/helpers'
import { VideoService } from '@app/shared/shared-main'
import { UserSubscriptionService } from '@app/shared/shared-user-subscription'
import { AbstractVideoList, OwnerDisplayType } from '@app/shared/shared-video-miniature'
import { AbstractVideoList } from '@app/shared/shared-video-miniature'
import { FeedFormat, VideoSortField } from '@shared/models'
import { environment } from '../../../environments/environment'
import { copyToClipboard } from '../../../root-helpers/utils'
@ -20,7 +20,6 @@ import { copyToClipboard } from '../../../root-helpers/utils'
export class VideoUserSubscriptionsComponent extends AbstractVideoList implements OnInit, OnDestroy {
titlePage: string
sort = '-publishedAt' as VideoSortField
ownerDisplayType: OwnerDisplayType = 'auto'
groupByDate = true
constructor (

View File

@ -26,6 +26,7 @@
top:50%;
left:50%;
transform: translate(-50%,-50%);
border-radius: 5px;
&:not(.channel-avatar) {
border-radius: 50%;

View File

@ -16,7 +16,7 @@ my-global-icon {
}
&[iconName=search] {
color: pvar(--mainColor);
color: pvar(--mainForegroundColor);
}
&[iconName=cross] {

View File

@ -1,4 +1,5 @@
import { VideoChannel as ServerVideoChannel, ViewsPerDate, Account, Avatar } from '@shared/models'
import { Account as ServerAccount, Avatar, VideoChannel as ServerVideoChannel, ViewsPerDate } from '@shared/models'
import { Account } from '../account/account.model'
import { Actor } from '../account/actor.model'
export class VideoChannel extends Actor implements ServerVideoChannel {
@ -9,7 +10,7 @@ export class VideoChannel extends Actor implements ServerVideoChannel {
nameWithHost: string
nameWithHostForced: string
ownerAccount?: Account
ownerAccount?: ServerAccount
ownerBy?: string
ownerAvatarUrl?: string
@ -46,7 +47,7 @@ export class VideoChannel extends Actor implements ServerVideoChannel {
if (hash.ownerAccount) {
this.ownerAccount = hash.ownerAccount
this.ownerBy = Actor.CREATE_BY_STRING(hash.ownerAccount.name, hash.ownerAccount.host)
this.ownerAvatarUrl = VideoChannel.GET_ACTOR_AVATAR_URL(this.ownerAccount)
this.ownerAvatarUrl = Account.GET_ACTOR_AVATAR_URL(this.ownerAccount)
}
}

View File

@ -52,8 +52,7 @@
<div class="video-wrapper">
<my-video-miniature
[fitWidth]="true"
[video]="video" [user]="userMiniature" [ownerDisplayType]="ownerDisplayType"
[fitWidth]="true" [video]="video" [user]="userMiniature"
[displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions"
(videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
>

View File

@ -28,8 +28,8 @@ import { isLastMonth, isLastWeek, isThisMonth, isToday, isYesterday } from '@sha
import { ServerConfig, UserRight, VideoFilter, VideoSortField } from '@shared/models'
import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type'
import { Syndication, Video } from '../shared-main'
import { MiniatureDisplayOptions, OwnerDisplayType } from './video-miniature.component'
import { GenericHeaderComponent, VideoListHeaderComponent } from './video-list-header.component'
import { MiniatureDisplayOptions } from './video-miniature.component'
enum GroupDate {
UNKNOWN = 0,
@ -65,7 +65,6 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, AfterConte
loadOnInit = true
loadUserVideoPreferences = false
ownerDisplayType: OwnerDisplayType = 'auto'
displayModerationBlock = false
titleTooltip: string
displayVideoActions = true

View File

@ -16,7 +16,7 @@ import { Video } from '../shared-main'
import { VideoPlaylistService } from '../shared-video-playlist'
import { VideoActionsDisplayType } from './video-actions-dropdown.component'
export type OwnerDisplayType = 'account' | 'videoChannel' | 'auto'
export type OwnerDisplayType = 'account' | 'videoChannel'
export type MiniatureDisplayOptions = {
date?: boolean
views?: boolean
@ -40,7 +40,6 @@ export class VideoMiniatureComponent implements OnInit {
@Input() user: User
@Input() video: Video
@Input() ownerDisplayType: OwnerDisplayType = 'account'
@Input() displayOptions: MiniatureDisplayOptions = {
date: true,
views: true,
@ -89,7 +88,7 @@ export class VideoMiniatureComponent implements OnInit {
videoHref: string
videoTarget: string
private ownerDisplayTypeChosen: 'account' | 'videoChannel'
private ownerDisplayType: 'account' | 'videoChannel'
constructor (
private screenService: ScreenService,
@ -140,11 +139,11 @@ export class VideoMiniatureComponent implements OnInit {
}
displayOwnerAccount () {
return this.ownerDisplayTypeChosen === 'account'
return this.ownerDisplayType === 'account'
}
displayOwnerVideoChannel () {
return this.ownerDisplayTypeChosen === 'videoChannel'
return this.ownerDisplayType === 'videoChannel'
}
isUnlistedVideo () {
@ -245,21 +244,19 @@ export class VideoMiniatureComponent implements OnInit {
}
private setUpBy () {
if (this.ownerDisplayType === 'account' || this.ownerDisplayType === 'videoChannel') {
this.ownerDisplayTypeChosen = this.ownerDisplayType
return
}
const accountName = this.video.account.name
// If the video channel name is an UUID (not really displayable, we changed this behaviour in v1.0.0-beta.12)
// Or is just a suffix of the account (default created channel)
// Or has not been customized (default created channel display name)
// -> Use the account name
if (
this.video.channel.name === `${this.video.account.name}_channel` ||
this.video.channel.displayName === `Default ${accountName} channel` ||
this.video.channel.displayName === `Main ${accountName} channel` ||
this.video.channel.name.match(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/)
) {
this.ownerDisplayTypeChosen = 'account'
this.ownerDisplayType = 'account'
} else {
this.ownerDisplayTypeChosen = 'videoChannel'
this.ownerDisplayType = 'videoChannel'
}
}

View File

@ -9,8 +9,7 @@
<my-video-miniature
[video]="video" [displayAsRow]="true" [displayOptions]="miniatureDisplayOptions"
[displayVideoActions]="false" [ownerDisplayType]="ownerDisplayType"
[user]="user"
[displayVideoActions]="false" [user]="user"
></my-video-miniature>
<!-- Display only once -->

View File

@ -17,7 +17,7 @@ import { AuthService, ComponentPagination, LocalStorageService, Notifier, Screen
import { ResultList, VideoSortField } from '@shared/models'
import { PeerTubeTemplateDirective, Video } from '../shared-main'
import { AbstractVideoList } from './abstract-video-list'
import { MiniatureDisplayOptions, OwnerDisplayType } from './video-miniature.component'
import { MiniatureDisplayOptions } from './video-miniature.component'
export type SelectionType = { [ id: number ]: boolean }
@ -31,7 +31,6 @@ export class VideosSelectionComponent extends AbstractVideoList implements OnIni
@Input() pagination: ComponentPagination
@Input() titlePage: string
@Input() miniatureDisplayOptions: MiniatureDisplayOptions
@Input() ownerDisplayType: OwnerDisplayType
@Input() getVideosObservableFunction: (page: number, sort?: VideoSortField) => Observable<ResultList<Video>>

View File

@ -152,7 +152,7 @@
@include button-focus(pvar(--mainColorLightest));
border: 2px solid pvar(--mainColor);
font-weight: $font-regular;
font-weight: $font-semibold;
&, &:active, &:focus {
color: pvar(--mainColor);
@ -551,6 +551,7 @@
height: $size;
min-width: $size;
min-height: $size;
border-radius: 5px;
}
@mixin chevron ($size, $border-width) {