Add channel/account avatars in miniature (#2838)
* add small avatar to miniature * fix svg size for trending and search icons in plugins view * parametrize avatar in miniature display options
This commit is contained in:
parent
c87d45df9b
commit
c2caa99b94
|
@ -1,8 +1,8 @@
|
||||||
<div class="wrapper">
|
<div class="wrapper" [ngClass]="'avatar-' + size">
|
||||||
<a [routerLink]="[ '/video-channels', video.byVideoChannel ]" i18n-title title="Go the channel page">
|
<a [routerLink]="[ '/video-channels', video.byVideoChannel ]" [title]="channelLinkTitle">
|
||||||
<img [src]="video.videoChannelAvatarUrl" alt="Channel avatar" />
|
<img [src]="video.videoChannelAvatarUrl" alt="Channel avatar" />
|
||||||
</a>
|
</a>
|
||||||
<a [routerLink]="[ '/accounts', video.byAccount ]" i18n-title title="Go to the account page">
|
<a [routerLink]="[ '/accounts', video.byAccount ]" [title]="accountLinkTitle">
|
||||||
<img [src]="video.accountAvatarUrl" alt="Account avatar" />
|
<img [src]="video.accountAvatarUrl" alt="Account avatar" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
@import '_mixins';
|
@import '_mixins';
|
||||||
|
|
||||||
.wrapper {
|
.wrapper {
|
||||||
width: 35px;
|
$avatar-size: 35px;
|
||||||
height: 35px;
|
|
||||||
min-width: 35px;
|
width: $avatar-size;
|
||||||
min-height: 35px;
|
height: $avatar-size;
|
||||||
position: relative;
|
position: relative;
|
||||||
margin-right: 5px;
|
margin-right: 5px;
|
||||||
|
|
||||||
|
&.avatar-sm {
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
@include disable-outline;
|
@include disable-outline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,31 @@
|
||||||
import { Component, Input } from '@angular/core'
|
import { Component, Input, OnInit } from '@angular/core'
|
||||||
import { VideoDetails } from '../video/video-details.model'
|
import { Video } from '../video/video.model'
|
||||||
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'avatar-channel',
|
selector: 'avatar-channel',
|
||||||
templateUrl: './avatar.component.html',
|
templateUrl: './avatar.component.html',
|
||||||
styleUrls: [ './avatar.component.scss' ]
|
styleUrls: [ './avatar.component.scss' ]
|
||||||
})
|
})
|
||||||
export class AvatarComponent {
|
export class AvatarComponent implements OnInit {
|
||||||
@Input() video: VideoDetails
|
@Input() video: Video
|
||||||
|
@Input() size: 'md' | 'sm' = 'md'
|
||||||
|
|
||||||
|
channelLinkTitle = ''
|
||||||
|
accountLinkTitle = ''
|
||||||
|
|
||||||
|
constructor (
|
||||||
|
private i18n: I18n
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit () {
|
||||||
|
this.channelLinkTitle = this.i18n(
|
||||||
|
'Go to the channel page of {{name}} ({{handle}})',
|
||||||
|
{ name: this.video.channel.name, handle: this.video.byVideoChannel }
|
||||||
|
)
|
||||||
|
this.accountLinkTitle = this.i18n(
|
||||||
|
'Go to the account page of {{name}} ({{handle}})',
|
||||||
|
{ name: this.video.account.name, handle: this.video.byAccount }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@ export abstract class AbstractVideoList implements OnInit, OnDestroy, DisableFor
|
||||||
date: true,
|
date: true,
|
||||||
views: true,
|
views: true,
|
||||||
by: true,
|
by: true,
|
||||||
|
avatar: true,
|
||||||
privacyLabel: true,
|
privacyLabel: true,
|
||||||
privacyText: false,
|
privacyText: false,
|
||||||
state: false,
|
state: false,
|
||||||
|
|
|
@ -15,26 +15,32 @@
|
||||||
[routerLink]="[ '/videos/watch', video.uuid ]" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur }"
|
[routerLink]="[ '/videos/watch', video.uuid ]" [attr.title]="video.name" [ngClass]="{ 'blur-filter': isVideoBlur }"
|
||||||
>{{ video.name }}</a>
|
>{{ video.name }}</a>
|
||||||
|
|
||||||
<span class="video-miniature-created-at-views">
|
<div class="d-inline-flex">
|
||||||
<my-date-toggle *ngIf="displayOptions.date" [date]="video.publishedAt"></my-date-toggle>
|
<avatar-channel *ngIf="displayOptions.avatar" class="mr-1 pt-1" [video]="video" size="sm"></avatar-channel>
|
||||||
|
|
||||||
<span class="views">
|
<div class="d-flex flex-column">
|
||||||
<ng-container *ngIf="displayOptions.date && displayOptions.views"> • </ng-container>
|
<span class="video-miniature-created-at-views">
|
||||||
<ng-container i18n *ngIf="displayOptions.views">{video.views, plural, =1 {1 view} other {{{ video.views | myNumberFormatter }} views}}</ng-container>
|
<my-date-toggle *ngIf="displayOptions.date" [date]="video.publishedAt"></my-date-toggle>
|
||||||
</span>
|
|
||||||
</span>
|
<span class="views">
|
||||||
|
<ng-container *ngIf="displayOptions.date && displayOptions.views"> • </ng-container>
|
||||||
<a tabindex="-1" *ngIf="displayOptions.by && displayOwnerAccount()" class="video-miniature-account" [routerLink]="[ '/accounts', video.byAccount ]">
|
<ng-container i18n *ngIf="displayOptions.views">{video.views, plural, =1 {1 view} other {{{ video.views | myNumberFormatter }} views}}</ng-container>
|
||||||
{{ video.byAccount }}
|
</span>
|
||||||
</a>
|
</span>
|
||||||
<a tabindex="-1" *ngIf="displayOptions.by && displayOwnerVideoChannel()" class="video-miniature-channel" [routerLink]="[ '/video-channels', video.byVideoChannel ]">
|
|
||||||
{{ video.byVideoChannel }}
|
<a tabindex="-1" *ngIf="displayOptions.by && displayOwnerAccount()" class="video-miniature-account" [routerLink]="[ '/accounts', video.byAccount ]">
|
||||||
</a>
|
{{ video.byAccount }}
|
||||||
|
</a>
|
||||||
<div class="video-info-privacy">
|
<a tabindex="-1" *ngIf="displayOptions.by && displayOwnerVideoChannel()" class="video-miniature-channel" [routerLink]="[ '/video-channels', video.byVideoChannel ]">
|
||||||
<ng-container *ngIf="displayOptions.privacyText">{{ video.privacy.label }}</ng-container>
|
{{ video.byVideoChannel }}
|
||||||
<ng-container *ngIf="displayOptions.privacyText && displayOptions.state && getStateLabel(video)"> - </ng-container>
|
</a>
|
||||||
<ng-container *ngIf="displayOptions.state">{{ getStateLabel(video) }}</ng-container>
|
|
||||||
|
<div class="video-info-privacy">
|
||||||
|
<ng-container *ngIf="displayOptions.privacyText">{{ video.privacy.label }}</ng-container>
|
||||||
|
<ng-container *ngIf="displayOptions.privacyText && displayOptions.state && getStateLabel(video)"> - </ng-container>
|
||||||
|
<ng-container *ngIf="displayOptions.state">{{ getStateLabel(video) }}</ng-container>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="displayOptions.blacklistInfo && video.blacklisted" class="video-info-blacklisted">
|
<div *ngIf="displayOptions.blacklistInfo && video.blacklisted" class="video-info-blacklisted">
|
||||||
|
|
|
@ -24,6 +24,7 @@ export type MiniatureDisplayOptions = {
|
||||||
date?: boolean
|
date?: boolean
|
||||||
views?: boolean
|
views?: boolean
|
||||||
by?: boolean
|
by?: boolean
|
||||||
|
avatar?: boolean
|
||||||
privacyLabel?: boolean
|
privacyLabel?: boolean
|
||||||
privacyText?: boolean
|
privacyText?: boolean
|
||||||
state?: boolean
|
state?: boolean
|
||||||
|
@ -46,6 +47,7 @@ export class VideoMiniatureComponent implements OnInit {
|
||||||
date: true,
|
date: true,
|
||||||
views: true,
|
views: true,
|
||||||
by: true,
|
by: true,
|
||||||
|
avatar: false,
|
||||||
privacyLabel: false,
|
privacyLabel: false,
|
||||||
privacyText: false,
|
privacyText: false,
|
||||||
state: false,
|
state: false,
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngFor="let video of (videos$ | async); let i = index; let length = count">
|
<div *ngFor="let video of (videos$ | async); let i = index; let length = count">
|
||||||
<my-video-miniature [video]="video" [user]="user" (videoBlacklisted)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()">
|
<my-video-miniature [displayOptions]="displayOptions" [video]="video" [user]="user" (videoBlacklisted)="onVideoRemoved()" (videoRemoved)="onVideoRemoved()">
|
||||||
</my-video-miniature>
|
</my-video-miniature>
|
||||||
|
|
||||||
<hr *ngIf="!playlist && i == 0 && length > 1" />
|
<hr *ngIf="!playlist && i == 0 && length > 1" />
|
||||||
|
|
|
@ -9,6 +9,7 @@ import { AuthService, Notifier } from '@app/core'
|
||||||
import { UserService } from '@app/shared/users/user.service'
|
import { UserService } from '@app/shared/users/user.service'
|
||||||
import { I18n } from '@ngx-translate/i18n-polyfill'
|
import { I18n } from '@ngx-translate/i18n-polyfill'
|
||||||
import { SessionStorageService } from '@app/shared/misc/storage.service'
|
import { SessionStorageService } from '@app/shared/misc/storage.service'
|
||||||
|
import { MiniatureDisplayOptions } from '@app/shared/video/video-miniature.component'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-recommended-videos',
|
selector: 'my-recommended-videos',
|
||||||
|
@ -24,6 +25,13 @@ export class RecommendedVideosComponent implements OnChanges {
|
||||||
autoPlayNextVideo: boolean
|
autoPlayNextVideo: boolean
|
||||||
autoPlayNextVideoTooltip: string
|
autoPlayNextVideoTooltip: string
|
||||||
|
|
||||||
|
displayOptions: MiniatureDisplayOptions = {
|
||||||
|
date: true,
|
||||||
|
views: true,
|
||||||
|
by: true,
|
||||||
|
avatar: true
|
||||||
|
}
|
||||||
|
|
||||||
readonly hasVideos$: Observable<boolean>
|
readonly hasVideos$: Observable<boolean>
|
||||||
readonly videos$: Observable<Video[]>
|
readonly videos$: Observable<Video[]>
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" width="24px" viewBox="0 0 24 24">
|
||||||
<defs/>
|
<defs/>
|
||||||
<g fill="none" fill-rule="evenodd" stroke="#000" stroke-width="2">
|
<g fill="none" fill-rule="evenodd" stroke="#000" stroke-width="2">
|
||||||
<circle cx="10" cy="10" r="7"/>
|
<circle cx="10" cy="10" r="7"/>
|
||||||
|
|
Before Width: | Height: | Size: 264 B After Width: | Height: | Size: 291 B |
|
@ -1,4 +1,4 @@
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" width="24px" viewBox="0 0 24 24">
|
||||||
<defs/>
|
<defs/>
|
||||||
<g fill="none" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
|
<g fill="none" fill-rule="evenodd" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
|
||||||
<path d="M3 3v18h18"/>
|
<path d="M3 3v18h18"/>
|
||||||
|
|
Before Width: | Height: | Size: 290 B After Width: | Height: | Size: 317 B |
Loading…
Reference in New Issue
Block a user