summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
c8e80d1)
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
20 files changed:
<div class="followers" i18n>{videoChannel.followersCount, plural, =1 {1 subscriber} other {{{ videoChannel.followersCount }} subscribers}}</div>
<span class="videos-count" *ngIf="getTotalVideosOf(videoChannel) !== undefined" i18n>
<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}}
.channel {
max-width: $max-channels-width;
background-color: pvar(--channelBackgroundColor);
.channel {
max-width: $max-channels-width;
background-color: pvar(--channelBackgroundColor);
}
@media screen and (max-width: $mobile-view) {
}
@media screen and (max-width: $mobile-view) {
+ .channel {
+ padding: 15px;
+ }
+
.channel-avatar-row {
grid-template-columns: auto auto auto 1fr;
.channel-avatar-row {
grid-template-columns: auto auto auto 1fr;
<div class="created-at" i18n>Account created on {{ account.createdAt | date }}</div>
</div>
<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
>
(click)="accountDescriptionExpanded = !accountDescriptionExpanded"
title="Show the complete description" i18n-title i18n
>
.description {
grid-column: 1 / 3;
.description {
grid-column: 1 / 3;
+ max-width: 1000px;
+ word-break: break-word;
return this.videoChannels.length !== 0
}
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`
private async onAccount (account: Account) {
this.accountFollowerTitle = $localize`${account.followersCount} direct account followers`
[miniatureDisplayOptions]="miniatureDisplayOptions"
[titlePage]="titlePage"
[getVideosObservableFunction]="getVideosObservableFunction"
[miniatureDisplayOptions]="miniatureDisplayOptions"
[titlePage]="titlePage"
[getVideosObservableFunction]="getVideosObservableFunction"
- [ownerDisplayType]="ownerDisplayType"
[user]="user"
#videosSelection
>
[user]="user"
#videosSelection
>
import { debounceTime, tap, toArray } from 'rxjs/operators'
import { Component, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
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 { 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'
import { VideoSortField } from '@shared/models'
import { VideoChangeOwnershipComponent } from './modals/video-change-ownership.component'
state: true,
blacklistInfo: true
}
state: true,
blacklistInfo: true
}
- ownerDisplayType: OwnerDisplayType = 'videoChannel'
videoActions: DropdownAction<{ video: Video }>[] = []
videoActions: DropdownAction<{ video: Video }>[] = []
<ng-template #ownerTemplate>
<div class="owner-block">
<div class="avatar-row">
<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>
- <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>
<div class="actor-handle">@{{ videoChannel.ownerBy }}</div>
</div>
<div class="description-html" [innerHTML]="ownerDescriptionHTML"></div>
</div>
<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>
- <a class="view-account complete" [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n>
+ <a class="view-account complete" [routerLink]="getAccountUrl()" i18n>
View owner account
</a>
</div>
View owner account
</a>
</div>
<div class="created-at" i18n>Channel created on {{ videoChannel.createdAt | date }}</div>
</div>
<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
>
(click)="channelDescriptionExpanded = !channelDescriptionExpanded"
title="Show the complete description" i18n-title i18n
>
.channel-description {
grid-column: 1;
.channel-description {
grid-column: 1;
+ word-break: break-word;
h4 {
font-size: 18px;
margin: 0;
h4 {
font-size: 18px;
margin: 0;
+
+ a {
+ color: pvar(--mainForegroundColor);
+ }
.owner-description {
height: 140px;
.owner-description {
height: 140px;
+ word-break: break-word;
@include fade-text(120px, pvar(--mainBackgroundColor));
}
@include fade-text(120px, pvar(--mainBackgroundColor));
}
}
.view-account.complete {
}
.view-account.complete {
+ display: block;
+ text-align: right;
margin-top: 10px;
color: pvar(--mainColor);
}
margin-top: 10px;
color: pvar(--mainColor);
}
this.notifier.success($localize`Username copied`)
}
this.notifier.success($localize`Username copied`)
}
+ hasShowMoreDescription () {
+ return !this.channelDescriptionExpanded && this.channelDescriptionHTML.length > 100
+ }
+
showSupportModal () {
this.supportModal.show()
}
showSupportModal () {
this.supportModal.show()
}
+ getAccountUrl () {
+ return [ '/accounts', this.videoChannel.ownerBy ]
+ }
+
private loadChannelVideosCount () {
this.videoService.getVideoChannelVideos({
videoChannel: this.videoChannel,
private loadChannelVideosCount () {
this.videoService.getVideoChannelVideos({
videoChannel: this.videoChannel,
import { immutableAssign } from '@app/helpers'
import { VideoService } from '@app/shared/shared-main'
import { UserSubscriptionService } from '@app/shared/shared-user-subscription'
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'
import { FeedFormat, VideoSortField } from '@shared/models'
import { environment } from '../../../environments/environment'
import { copyToClipboard } from '../../../root-helpers/utils'
export class VideoUserSubscriptionsComponent extends AbstractVideoList implements OnInit, OnDestroy {
titlePage: string
sort = '-publishedAt' as VideoSortField
export class VideoUserSubscriptionsComponent extends AbstractVideoList implements OnInit, OnDestroy {
titlePage: string
sort = '-publishedAt' as VideoSortField
- ownerDisplayType: OwnerDisplayType = 'auto'
groupByDate = true
constructor (
groupByDate = true
constructor (
top:50%;
left:50%;
transform: translate(-50%,-50%);
top:50%;
left:50%;
transform: translate(-50%,-50%);
&:not(.channel-avatar) {
border-radius: 50%;
&:not(.channel-avatar) {
border-radius: 50%;
- color: pvar(--mainColor);
+ color: pvar(--mainForegroundColor);
-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 {
import { Actor } from '../account/actor.model'
export class VideoChannel extends Actor implements ServerVideoChannel {
nameWithHost: string
nameWithHostForced: string
nameWithHost: string
nameWithHostForced: string
+ ownerAccount?: ServerAccount
ownerBy?: string
ownerAvatarUrl?: string
ownerBy?: string
ownerAvatarUrl?: string
if (hash.ownerAccount) {
this.ownerAccount = hash.ownerAccount
this.ownerBy = Actor.CREATE_BY_STRING(hash.ownerAccount.name, hash.ownerAccount.host)
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)
<div class="video-wrapper">
<my-video-miniature
<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)"
>
[displayVideoActions]="displayVideoActions" [displayOptions]="displayOptions"
(videoBlocked)="removeVideoFromArray(video)" (videoRemoved)="removeVideoFromArray(video)"
>
import { ServerConfig, UserRight, VideoFilter, VideoSortField } from '@shared/models'
import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type'
import { Syndication, Video } from '../shared-main'
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 { GenericHeaderComponent, VideoListHeaderComponent } from './video-list-header.component'
+import { MiniatureDisplayOptions } from './video-miniature.component'
enum GroupDate {
UNKNOWN = 0,
enum GroupDate {
UNKNOWN = 0,
loadOnInit = true
loadUserVideoPreferences = false
loadOnInit = true
loadUserVideoPreferences = false
- ownerDisplayType: OwnerDisplayType = 'auto'
displayModerationBlock = false
titleTooltip: string
displayVideoActions = true
displayModerationBlock = false
titleTooltip: string
displayVideoActions = true
import { VideoPlaylistService } from '../shared-video-playlist'
import { VideoActionsDisplayType } from './video-actions-dropdown.component'
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
export type MiniatureDisplayOptions = {
date?: boolean
views?: boolean
@Input() user: User
@Input() video: Video
@Input() user: User
@Input() video: Video
- @Input() ownerDisplayType: OwnerDisplayType = 'account'
@Input() displayOptions: MiniatureDisplayOptions = {
date: true,
views: true,
@Input() displayOptions: MiniatureDisplayOptions = {
date: true,
views: true,
videoHref: string
videoTarget: string
videoHref: string
videoTarget: string
- private ownerDisplayTypeChosen: 'account' | 'videoChannel'
+ private ownerDisplayType: 'account' | 'videoChannel'
constructor (
private screenService: ScreenService,
constructor (
private screenService: ScreenService,
}
displayOwnerAccount () {
}
displayOwnerAccount () {
- return this.ownerDisplayTypeChosen === 'account'
+ return this.ownerDisplayType === 'account'
}
displayOwnerVideoChannel () {
}
displayOwnerVideoChannel () {
- return this.ownerDisplayTypeChosen === 'videoChannel'
+ return this.ownerDisplayType === 'videoChannel'
- 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)
// 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 (
// -> 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.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'
- this.ownerDisplayTypeChosen = 'videoChannel'
+ this.ownerDisplayType = 'videoChannel'
<my-video-miniature
[video]="video" [displayAsRow]="true" [displayOptions]="miniatureDisplayOptions"
<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 -->
></my-video-miniature>
<!-- Display only once -->
import { ResultList, VideoSortField } from '@shared/models'
import { PeerTubeTemplateDirective, Video } from '../shared-main'
import { AbstractVideoList } from './abstract-video-list'
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 }
export type SelectionType = { [ id: number ]: boolean }
@Input() pagination: ComponentPagination
@Input() titlePage: string
@Input() miniatureDisplayOptions: MiniatureDisplayOptions
@Input() pagination: ComponentPagination
@Input() titlePage: string
@Input() miniatureDisplayOptions: MiniatureDisplayOptions
- @Input() ownerDisplayType: OwnerDisplayType
@Input() getVideosObservableFunction: (page: number, sort?: VideoSortField) => Observable<ResultList<Video>>
@Input() getVideosObservableFunction: (page: number, sort?: VideoSortField) => Observable<ResultList<Video>>
@include button-focus(pvar(--mainColorLightest));
border: 2px solid pvar(--mainColor);
@include button-focus(pvar(--mainColorLightest));
border: 2px solid pvar(--mainColor);
- font-weight: $font-regular;
+ font-weight: $font-semibold;
&, &:active, &:focus {
color: pvar(--mainColor);
&, &:active, &:focus {
color: pvar(--mainColor);
height: $size;
min-width: $size;
min-height: $size;
height: $size;
min-width: $size;
min-height: $size;
}
@mixin chevron ($size, $border-width) {
}
@mixin chevron ($size, $border-width) {