aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-04-28 11:49:34 +0200
committerChocobozzz <me@florianbigard.com>2021-04-28 11:49:34 +0200
commit746018f6b81b40e8858303662ac9ec5ce59ac6eb (patch)
tree7b115d12c1926e6283346072fe1c6adbf056abd7 /client/src/app
parentec489ce2f74570f94dffb62266f4ed6f18621b3e (diff)
downloadPeerTube-746018f6b81b40e8858303662ac9ec5ce59ac6eb.tar.gz
PeerTube-746018f6b81b40e8858303662ac9ec5ce59ac6eb.tar.zst
PeerTube-746018f6b81b40e8858303662ac9ec5ce59ac6eb.zip
Refactor actor avatar display
Diffstat (limited to 'client/src/app')
-rw-r--r--client/src/app/+accounts/account-video-channels/account-video-channels.component.html7
-rw-r--r--client/src/app/+accounts/account-video-channels/account-video-channels.component.scss10
-rw-r--r--client/src/app/+accounts/accounts.component.html2
-rw-r--r--client/src/app/+accounts/accounts.module.ts4
-rw-r--r--client/src/app/+admin/admin.module.ts4
-rw-r--r--client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html2
-rw-r--r--client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html2
-rw-r--r--client/src/app/+admin/users/user-list/user-list.component.html2
-rw-r--r--client/src/app/+my-account/my-account.module.ts4
-rw-r--r--client/src/app/+my-library/+my-video-channels/my-video-channels.component.html4
-rw-r--r--client/src/app/+my-library/+my-video-channels/my-video-channels.component.scss4
-rw-r--r--client/src/app/+my-library/+my-video-channels/my-video-channels.module.ts4
-rw-r--r--client/src/app/+my-library/my-library.module.ts4
-rw-r--r--client/src/app/+my-library/my-ownership/my-ownership.component.html2
-rw-r--r--client/src/app/+my-library/my-subscriptions/my-subscriptions.component.html7
-rw-r--r--client/src/app/+my-library/my-subscriptions/my-subscriptions.component.scss19
-rw-r--r--client/src/app/+search/search.component.html11
-rw-r--r--client/src/app/+search/search.component.scss18
-rw-r--r--client/src/app/+search/search.component.ts26
-rw-r--r--client/src/app/+search/search.module.ts2
-rw-r--r--client/src/app/+video-channels/video-channels.component.html20
-rw-r--r--client/src/app/+video-channels/video-channels.component.scss8
-rw-r--r--client/src/app/+video-channels/video-channels.module.ts4
-rw-r--r--client/src/app/+videos/+video-watch/comment/video-comment-add.component.html2
-rw-r--r--client/src/app/+videos/+video-watch/comment/video-comment-add.component.scss3
-rw-r--r--client/src/app/+videos/+video-watch/comment/video-comment.component.html8
-rw-r--r--client/src/app/+videos/+video-watch/comment/video-comment.component.scss10
-rw-r--r--client/src/app/+videos/+video-watch/comment/video-comment.component.ts4
-rw-r--r--client/src/app/+videos/+video-watch/video-avatar-channel.component.html6
-rw-r--r--client/src/app/+videos/+video-watch/video-watch.module.ts4
-rw-r--r--client/src/app/+videos/video-list/overview/video-overview.component.html2
-rw-r--r--client/src/app/+videos/video-list/overview/video-overview.component.scss5
-rw-r--r--client/src/app/+videos/video-list/overview/video-overview.component.ts4
-rw-r--r--client/src/app/+videos/videos.module.ts4
-rw-r--r--client/src/app/app.module.ts4
-rw-r--r--client/src/app/menu/menu.component.html2
-rw-r--r--client/src/app/menu/menu.component.scss2
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-details.component.html4
-rw-r--r--client/src/app/shared/shared-abuse-list/abuse-list-table.component.html2
-rw-r--r--client/src/app/shared/shared-abuse-list/shared-abuse-list.module.ts4
-rw-r--r--client/src/app/shared/shared-account-avatar/account-avatar.component.html18
-rw-r--r--client/src/app/shared/shared-account-avatar/account-avatar.component.ts62
-rw-r--r--client/src/app/shared/shared-account-avatar/index.ts2
-rw-r--r--client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.html3
-rw-r--r--client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.scss10
-rw-r--r--client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts12
-rw-r--r--client/src/app/shared/shared-actor-image-edit/shared-actor-image-edit.module.ts2
-rw-r--r--client/src/app/shared/shared-actor-image/actor-avatar.component.html19
-rw-r--r--client/src/app/shared/shared-actor-image/actor-avatar.component.scss (renamed from client/src/app/shared/shared-account-avatar/account-avatar.component.scss)49
-rw-r--r--client/src/app/shared/shared-actor-image/actor-avatar.component.ts110
-rw-r--r--client/src/app/shared/shared-actor-image/index.ts1
-rw-r--r--client/src/app/shared/shared-actor-image/shared-actor-image.module.ts (renamed from client/src/app/shared/shared-account-avatar/shared-account-avatar.module.ts)8
-rw-r--r--client/src/app/shared/shared-main/users/user-notification.model.ts4
-rw-r--r--client/src/app/shared/shared-main/users/user-notifications.component.scss7
-rw-r--r--client/src/app/shared/shared-main/video-channel/video-channel.model.ts2
-rw-r--r--client/src/app/shared/shared-moderation/account-blocklist.component.html2
-rw-r--r--client/src/app/shared/shared-moderation/shared-moderation.module.ts4
-rw-r--r--client/src/app/shared/shared-video-miniature/shared-video-miniature.module.ts4
-rw-r--r--client/src/app/shared/shared-video-miniature/video-miniature.component.html13
-rw-r--r--client/src/app/shared/shared-video-miniature/video-miniature.component.scss7
60 files changed, 340 insertions, 239 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 19a4b3c9c..922608127 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
@@ -8,9 +8,10 @@
8 <div class="channel" *ngFor="let videoChannel of videoChannels"> 8 <div class="channel" *ngFor="let videoChannel of videoChannels">
9 9
10 <div class="channel-avatar-row"> 10 <div class="channel-avatar-row">
11 <a class="avatar-link" [routerLink]="getVideoChannelLink(videoChannel)" i18n-title title="See this video channel"> 11 <my-actor-avatar
12 <img [src]="videoChannel.avatarUrl" alt="Avatar" /> 12 [channel]="videoChannel" [internalHref]="getVideoChannelLink(videoChannel)"
13 </a> 13 i18n-title title="See this video channel"
14 ></my-actor-avatar>
14 15
15 <h2> 16 <h2>
16 <a [routerLink]="getVideoChannelLink(videoChannel)" i18n-title title="See this video channel"> 17 <a [routerLink]="getVideoChannelLink(videoChannel)" i18n-title title="See this video channel">
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 7e88802f3..0c490ad53 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
@@ -27,14 +27,12 @@
27 grid-template-columns: auto auto 1fr; 27 grid-template-columns: auto auto 1fr;
28 grid-template-rows: auto 1fr; 28 grid-template-rows: auto 1fr;
29 29
30 .avatar-link { 30 my-actor-avatar {
31 @include actor-avatar-size(75px);
32
31 grid-column: 1; 33 grid-column: 1;
32 grid-row: 1 / 3; 34 grid-row: 1 / 3;
33 margin-right: 30px; 35 margin-right: 15px;
34 }
35
36 img {
37 @include channel-avatar(75px);
38 } 36 }
39 37
40 a { 38 a {
diff --git a/client/src/app/+accounts/accounts.component.html b/client/src/app/+accounts/accounts.component.html
index ea7a317eb..350c77f1e 100644
--- a/client/src/app/+accounts/accounts.component.html
+++ b/client/src/app/+accounts/accounts.component.html
@@ -2,7 +2,7 @@
2 <div class="account-info"> 2 <div class="account-info">
3 3
4 <div class="account-avatar-row"> 4 <div class="account-avatar-row">
5 <my-account-avatar [account]="account" size="120"></my-account-avatar> 5 <my-actor-avatar class="main-avatar" [account]="account"></my-actor-avatar>
6 6
7 <div> 7 <div>
8 <div class="section-label" i18n>PEERTUBE ACCOUNT</div> 8 <div class="section-label" i18n>PEERTUBE ACCOUNT</div>
diff --git a/client/src/app/+accounts/accounts.module.ts b/client/src/app/+accounts/accounts.module.ts
index 22cdd0642..1bafc5141 100644
--- a/client/src/app/+accounts/accounts.module.ts
+++ b/client/src/app/+accounts/accounts.module.ts
@@ -10,7 +10,7 @@ import { AccountVideoChannelsComponent } from './account-video-channels/account-
10import { AccountVideosComponent } from './account-videos/account-videos.component' 10import { AccountVideosComponent } from './account-videos/account-videos.component'
11import { AccountsRoutingModule } from './accounts-routing.module' 11import { AccountsRoutingModule } from './accounts-routing.module'
12import { AccountsComponent } from './accounts.component' 12import { AccountsComponent } from './accounts.component'
13import { SharedAccountAvatarModule } from '../shared/shared-account-avatar/shared-account-avatar.module' 13import { SharedActorImageModule } from '../shared/shared-actor-image/shared-actor-image.module'
14 14
15@NgModule({ 15@NgModule({
16 imports: [ 16 imports: [
@@ -22,7 +22,7 @@ import { SharedAccountAvatarModule } from '../shared/shared-account-avatar/share
22 SharedModerationModule, 22 SharedModerationModule,
23 SharedVideoMiniatureModule, 23 SharedVideoMiniatureModule,
24 SharedGlobalIconModule, 24 SharedGlobalIconModule,
25 SharedAccountAvatarModule 25 SharedActorImageModule
26 ], 26 ],
27 27
28 declarations: [ 28 declarations: [
diff --git a/client/src/app/+admin/admin.module.ts b/client/src/app/+admin/admin.module.ts
index 97ce8d1b8..45366f9ec 100644
--- a/client/src/app/+admin/admin.module.ts
+++ b/client/src/app/+admin/admin.module.ts
@@ -9,7 +9,7 @@ import { SharedGlobalIconModule } from '@app/shared/shared-icons'
9import { SharedMainModule } from '@app/shared/shared-main' 9import { SharedMainModule } from '@app/shared/shared-main'
10import { SharedModerationModule } from '@app/shared/shared-moderation' 10import { SharedModerationModule } from '@app/shared/shared-moderation'
11import { SharedVideoCommentModule } from '@app/shared/shared-video-comment' 11import { SharedVideoCommentModule } from '@app/shared/shared-video-comment'
12import { SharedAccountAvatarModule } from '../shared/shared-account-avatar/shared-account-avatar.module' 12import { SharedActorImageModule } from '../shared/shared-actor-image/shared-actor-image.module'
13import { AdminRoutingModule } from './admin-routing.module' 13import { AdminRoutingModule } from './admin-routing.module'
14import { AdminComponent } from './admin.component' 14import { AdminComponent } from './admin.component'
15import { 15import {
@@ -51,7 +51,7 @@ import { UserCreateComponent, UserListComponent, UserPasswordComponent, UsersCom
51 SharedGlobalIconModule, 51 SharedGlobalIconModule,
52 SharedAbuseListModule, 52 SharedAbuseListModule,
53 SharedVideoCommentModule, 53 SharedVideoCommentModule,
54 SharedAccountAvatarModule, 54 SharedActorImageModule,
55 SharedActorImageEditModule, 55 SharedActorImageEditModule,
56 56
57 TableModule, 57 TableModule,
diff --git a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
index f5cf93adb..84ce381cc 100644
--- a/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
+++ b/client/src/app/+admin/moderation/instance-blocklist/instance-account-blocklist.component.html
@@ -34,7 +34,7 @@
34 <td> 34 <td>
35 <a [href]="accountBlock.blockedAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer"> 35 <a [href]="accountBlock.blockedAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
36 <div class="chip two-lines"> 36 <div class="chip two-lines">
37 <my-account-avatar [account]="accountBlock.blockedAccount"></my-account-avatar> 37 <my-actor-avatar [account]="accountBlock.blockedAccount"></my-actor-avatar>
38 <div> 38 <div>
39 {{ accountBlock.blockedAccount.displayName }} 39 {{ accountBlock.blockedAccount.displayName }}
40 <span class="text-muted">{{ accountBlock.blockedAccount.nameWithHost }}</span> 40 <span class="text-muted">{{ accountBlock.blockedAccount.nameWithHost }}</span>
diff --git a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html b/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html
index d360c3c51..b6cec9c51 100644
--- a/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html
+++ b/client/src/app/+admin/moderation/video-comment-list/video-comment-list.component.html
@@ -86,7 +86,7 @@
86 <td> 86 <td>
87 <a [href]="videoComment.account.localUrl" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer"> 87 <a [href]="videoComment.account.localUrl" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
88 <div class="chip two-lines"> 88 <div class="chip two-lines">
89 <my-account-avatar [account]="videoComment.account"></my-account-avatar> 89 <my-actor-avatar [account]="videoComment.account"></my-actor-avatar>
90 <div> 90 <div>
91 {{ videoComment.account.displayName }} 91 {{ videoComment.account.displayName }}
92 <span>{{ videoComment.by }}</span> 92 <span>{{ videoComment.by }}</span>
diff --git a/client/src/app/+admin/users/user-list/user-list.component.html b/client/src/app/+admin/users/user-list/user-list.component.html
index eefb8ea88..f84d3fd0c 100644
--- a/client/src/app/+admin/users/user-list/user-list.component.html
+++ b/client/src/app/+admin/users/user-list/user-list.component.html
@@ -106,7 +106,7 @@
106 <td *ngIf="isSelected('username')"> 106 <td *ngIf="isSelected('username')">
107 <a i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]"> 107 <a i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer" [routerLink]="[ '/accounts/' + user.username ]">
108 <div class="chip two-lines"> 108 <div class="chip two-lines">
109 <my-account-avatar [account]="user?.account" size="32"></my-account-avatar> 109 <my-actor-avatar [account]="user?.account" size="32"></my-actor-avatar>
110 <div> 110 <div>
111 <span class="user-table-primary-text">{{ user.account.displayName }}</span> 111 <span class="user-table-primary-text">{{ user.account.displayName }}</span>
112 <span class="text-muted">{{ user.username }}</span> 112 <span class="text-muted">{{ user.username }}</span>
diff --git a/client/src/app/+my-account/my-account.module.ts b/client/src/app/+my-account/my-account.module.ts
index 36df10edc..4081e4f01 100644
--- a/client/src/app/+my-account/my-account.module.ts
+++ b/client/src/app/+my-account/my-account.module.ts
@@ -10,7 +10,7 @@ import { SharedMainModule } from '@app/shared/shared-main'
10import { SharedModerationModule } from '@app/shared/shared-moderation' 10import { SharedModerationModule } from '@app/shared/shared-moderation'
11import { SharedShareModal } from '@app/shared/shared-share-modal' 11import { SharedShareModal } from '@app/shared/shared-share-modal'
12import { SharedUserInterfaceSettingsModule } from '@app/shared/shared-user-settings' 12import { SharedUserInterfaceSettingsModule } from '@app/shared/shared-user-settings'
13import { SharedAccountAvatarModule } from '../shared/shared-account-avatar/shared-account-avatar.module' 13import { SharedActorImageModule } from '../shared/shared-actor-image/shared-actor-image.module'
14import { MyAccountAbusesListComponent } from './my-account-abuses/my-account-abuses-list.component' 14import { MyAccountAbusesListComponent } from './my-account-abuses/my-account-abuses-list.component'
15import { MyAccountApplicationsComponent } from './my-account-applications/my-account-applications.component' 15import { MyAccountApplicationsComponent } from './my-account-applications/my-account-applications.component'
16import { MyAccountBlocklistComponent } from './my-account-blocklist/my-account-blocklist.component' 16import { MyAccountBlocklistComponent } from './my-account-blocklist/my-account-blocklist.component'
@@ -40,7 +40,7 @@ import { MyAccountComponent } from './my-account.component'
40 SharedGlobalIconModule, 40 SharedGlobalIconModule,
41 SharedAbuseListModule, 41 SharedAbuseListModule,
42 SharedShareModal, 42 SharedShareModal,
43 SharedAccountAvatarModule, 43 SharedActorImageModule,
44 SharedActorImageEditModule 44 SharedActorImageEditModule
45 ], 45 ],
46 46
diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channels.component.html b/client/src/app/+my-library/+my-video-channels/my-video-channels.component.html
index b704a1cc6..a2bdfa31a 100644
--- a/client/src/app/+my-library/+my-video-channels/my-video-channels.component.html
+++ b/client/src/app/+my-library/+my-video-channels/my-video-channels.component.html
@@ -22,9 +22,7 @@
22 22
23<div class="video-channels"> 23<div class="video-channels">
24 <div *ngFor="let videoChannel of videoChannels; let i = index" class="video-channel"> 24 <div *ngFor="let videoChannel of videoChannels; let i = index" class="video-channel">
25 <a [routerLink]="[ '/video-channels', videoChannel.nameWithHost ]"> 25 <my-actor-avatar [channel]="videoChannel" [internalHref]="[ '/video-channels', videoChannel.nameWithHost ]"></my-actor-avatar>
26 <img [src]="videoChannel.avatarUrl" alt="Avatar" />
27 </a>
28 26
29 <div class="video-channel-info"> 27 <div class="video-channel-info">
30 <a [routerLink]="[ '/video-channels', videoChannel.nameWithHost ]" class="video-channel-names" i18n-title title="Channel page"> 28 <a [routerLink]="[ '/video-channels', videoChannel.nameWithHost ]" class="video-channel-names" i18n-title title="Channel page">
diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channels.component.scss b/client/src/app/+my-library/+my-video-channels/my-video-channels.component.scss
index 8804fa95c..dafba925e 100644
--- a/client/src/app/+my-library/+my-video-channels/my-video-channels.component.scss
+++ b/client/src/app/+my-library/+my-video-channels/my-video-channels.component.scss
@@ -20,8 +20,8 @@ input[type=text] {
20 20
21 padding-bottom: 0; 21 padding-bottom: 0;
22 22
23 img { 23 my-actor-avatar {
24 @include channel-avatar(80px); 24 @include actor-avatar-size(80px);
25 25
26 margin-right: 10px; 26 margin-right: 10px;
27 } 27 }
diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channels.module.ts b/client/src/app/+my-library/+my-video-channels/my-video-channels.module.ts
index a23b53ee0..c775bfdee 100644
--- a/client/src/app/+my-library/+my-video-channels/my-video-channels.module.ts
+++ b/client/src/app/+my-library/+my-video-channels/my-video-channels.module.ts
@@ -8,6 +8,7 @@ import { MyVideoChannelCreateComponent } from './my-video-channel-create.compone
8import { MyVideoChannelUpdateComponent } from './my-video-channel-update.component' 8import { MyVideoChannelUpdateComponent } from './my-video-channel-update.component'
9import { MyVideoChannelsRoutingModule } from './my-video-channels-routing.module' 9import { MyVideoChannelsRoutingModule } from './my-video-channels-routing.module'
10import { MyVideoChannelsComponent } from './my-video-channels.component' 10import { MyVideoChannelsComponent } from './my-video-channels.component'
11import { SharedActorImageModule } from '@app/shared/shared-actor-image/shared-actor-image.module'
11 12
12@NgModule({ 13@NgModule({
13 imports: [ 14 imports: [
@@ -18,7 +19,8 @@ import { MyVideoChannelsComponent } from './my-video-channels.component'
18 SharedMainModule, 19 SharedMainModule,
19 SharedFormModule, 20 SharedFormModule,
20 SharedGlobalIconModule, 21 SharedGlobalIconModule,
21 SharedActorImageEditModule 22 SharedActorImageEditModule,
23 SharedActorImageModule
22 ], 24 ],
23 25
24 declarations: [ 26 declarations: [
diff --git a/client/src/app/+my-library/my-library.module.ts b/client/src/app/+my-library/my-library.module.ts
index a1d706f0b..264ad03f7 100644
--- a/client/src/app/+my-library/my-library.module.ts
+++ b/client/src/app/+my-library/my-library.module.ts
@@ -26,7 +26,7 @@ import { MyVideoPlaylistUpdateComponent } from './my-video-playlists/my-video-pl
26import { MyVideoPlaylistsComponent } from './my-video-playlists/my-video-playlists.component' 26import { MyVideoPlaylistsComponent } from './my-video-playlists/my-video-playlists.component'
27import { VideoChangeOwnershipComponent } from './my-videos/modals/video-change-ownership.component' 27import { VideoChangeOwnershipComponent } from './my-videos/modals/video-change-ownership.component'
28import { MyVideosComponent } from './my-videos/my-videos.component' 28import { MyVideosComponent } from './my-videos/my-videos.component'
29import { SharedAccountAvatarModule } from '../shared/shared-account-avatar/shared-account-avatar.module' 29import { SharedActorImageModule } from '../shared/shared-actor-image/shared-actor-image.module'
30 30
31@NgModule({ 31@NgModule({
32 imports: [ 32 imports: [
@@ -47,7 +47,7 @@ import { SharedAccountAvatarModule } from '../shared/shared-account-avatar/share
47 SharedAbuseListModule, 47 SharedAbuseListModule,
48 SharedShareModal, 48 SharedShareModal,
49 SharedVideoLiveModule, 49 SharedVideoLiveModule,
50 SharedAccountAvatarModule 50 SharedActorImageModule
51 ], 51 ],
52 52
53 declarations: [ 53 declarations: [
diff --git a/client/src/app/+my-library/my-ownership/my-ownership.component.html b/client/src/app/+my-library/my-ownership/my-ownership.component.html
index d0eff0521..4c02c78fc 100644
--- a/client/src/app/+my-library/my-ownership/my-ownership.component.html
+++ b/client/src/app/+my-library/my-ownership/my-ownership.component.html
@@ -37,7 +37,7 @@
37 <td> 37 <td>
38 <a [href]="videoChangeOwnership.initiatorAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer"> 38 <a [href]="videoChangeOwnership.initiatorAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
39 <div class="chip two-lines"> 39 <div class="chip two-lines">
40 <my-account-avatar [account]="videoChangeOwnership.initiatorAccount"></my-account-avatar> 40 <my-actor-avatar [account]="videoChangeOwnership.initiatorAccount"></my-actor-avatar>
41 <div> 41 <div>
42 {{ videoChangeOwnership.initiatorAccount.displayName }} 42 {{ videoChangeOwnership.initiatorAccount.displayName }}
43 <span class="text-muted">{{ videoChangeOwnership.initiatorAccount.nameWithHost }}</span> 43 <span class="text-muted">{{ videoChangeOwnership.initiatorAccount.nameWithHost }}</span>
diff --git a/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.html b/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.html
index ff448ad87..853d47fe6 100644
--- a/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.html
+++ b/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.html
@@ -19,9 +19,7 @@
19 19
20<div class="video-channels" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()"> 20<div class="video-channels" myInfiniteScroller [autoInit]="true" (nearOfBottom)="onNearOfBottom()" [dataObservable]="onDataSubject.asObservable()">
21 <div *ngFor="let videoChannel of videoChannels" class="video-channel"> 21 <div *ngFor="let videoChannel of videoChannels" class="video-channel">
22 <a [routerLink]="[ '/video-channels', videoChannel.nameWithHost ]"> 22 <my-actor-avatar [channel]="videoChannel" [internalHref]="[ '/video-channels', videoChannel.nameWithHost ]"></my-actor-avatar>
23 <img [src]="videoChannel.avatarUrl" alt="Avatar" />
24 </a>
25 23
26 <div class="video-channel-info"> 24 <div class="video-channel-info">
27 <a [routerLink]="[ '/video-channels', videoChannel.nameWithHost ]" class="video-channel-names" i18n-title title="Channel page"> 25 <a [routerLink]="[ '/video-channels', videoChannel.nameWithHost ]" class="video-channel-names" i18n-title title="Channel page">
@@ -33,7 +31,8 @@
33 31
34 <a [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n-title title="Owner account page" class="actor-owner"> 32 <a [routerLink]="[ '/accounts', videoChannel.ownerBy ]" i18n-title title="Owner account page" class="actor-owner">
35 <span i18n>Created by {{ videoChannel.ownerBy }}</span> 33 <span i18n>Created by {{ videoChannel.ownerBy }}</span>
36 <img [src]="videoChannel.ownerAvatarUrl" alt="Owner account avatar" /> 34
35 <my-actor-avatar [account]="videoChannel.ownerAccount" size="18"></my-actor-avatar>
37 </a> 36 </a>
38 </div> 37 </div>
39 38
diff --git a/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.scss b/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.scss
index 3c1a4d2ad..53ceaa250 100644
--- a/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.scss
+++ b/client/src/app/+my-library/my-subscriptions/my-subscriptions.component.scss
@@ -8,8 +8,8 @@ input[type=text] {
8.video-channel { 8.video-channel {
9 @include row-blocks; 9 @include row-blocks;
10 10
11 img { 11 > my-actor-avatar {
12 @include channel-avatar(80px); 12 @include actor-avatar-size(80px);
13 13
14 margin-right: 10px; 14 margin-right: 10px;
15 } 15 }
@@ -40,9 +40,20 @@ input[type=text] {
40} 40}
41 41
42.actor-owner { 42.actor-owner {
43 @include actor-owner; 43 @include disable-default-a-behaviour;
44
45 font-size: 13px;
46 color: pvar(--mainForegroundColor);
44 47
45 margin-top: 0; 48 span:hover {
49 opacity: 0.8;
50 }
51
52 my-actor-avatar {
53 margin-left: 7px;
54 display: inline-block;
55 vertical-align: top;
56 }
46} 57}
47 58
48.video-subscriptions-header { 59.video-subscriptions-header {
diff --git a/client/src/app/+search/search.component.html b/client/src/app/+search/search.component.html
index 65d4b6ecd..130be75fc 100644
--- a/client/src/app/+search/search.component.html
+++ b/client/src/app/+search/search.component.html
@@ -33,20 +33,15 @@
33 33
34 <ng-container *ngFor="let result of results"> 34 <ng-container *ngFor="let result of results">
35 <div *ngIf="isVideoChannel(result)" class="entry video-channel"> 35 <div *ngIf="isVideoChannel(result)" class="entry video-channel">
36 <a class="link-avatar" *ngIf="!isExternalChannelUrl()" [routerLink]="getChannelUrl(result)">
37 <img [src]="result.avatarUrl" alt="Avatar" />
38 </a>
39 36
40 <a class="link-avatar" *ngIf="isExternalChannelUrl()" [href]="getChannelUrl(result)" target="_blank"> 37 <my-actor-avatar [channel]="result" [internalHref]="getInternalChannelUrl(result)" [href]="getExternalChannelUrl(result)"></my-actor-avatar>
41 <img [src]="result.avatarUrl" alt="Avatar" />
42 </a>
43 38
44 <div class="video-channel-info"> 39 <div class="video-channel-info">
45 <a *ngIf="!isExternalChannelUrl()" [routerLink]="getChannelUrl(result)" class="video-channel-names"> 40 <a *ngIf="!isExternalChannelUrl()" [routerLink]="getInternalChannelUrl(result)" class="video-channel-names">
46 <ng-container *ngTemplateOutlet="aContent"></ng-container> 41 <ng-container *ngTemplateOutlet="aContent"></ng-container>
47 </a> 42 </a>
48 43
49 <a *ngIf="isExternalChannelUrl()" [href]="getChannelUrl(result)" target="_blank" class="video-channel-names"> 44 <a *ngIf="isExternalChannelUrl()" [href]="getExternalChannelUrl(result)" target="_blank" class="video-channel-names">
50 <ng-container *ngTemplateOutlet="aContent"></ng-container> 45 <ng-container *ngTemplateOutlet="aContent"></ng-container>
51 </a> 46 </a>
52 47
diff --git a/client/src/app/+search/search.component.scss b/client/src/app/+search/search.component.scss
index 91c8272d7..a8002ba88 100644
--- a/client/src/app/+search/search.component.scss
+++ b/client/src/app/+search/search.component.scss
@@ -5,7 +5,7 @@
5 $image-size: min(130px, $video-img-width); 5 $image-size: min(130px, $video-img-width);
6 $margin-size: ($video-img-width - $image-size) / 2; // So we have the same width than the video miniature 6 $margin-size: ($video-img-width - $image-size) / 2; // So we have the same width than the video miniature
7 7
8 @include channel-avatar($image-size); 8 @include actor-avatar-size($image-size);
9 9
10 margin: 0 $margin-size 0 $margin-size; 10 margin: 0 $margin-size 0 $margin-size;
11} 11}
@@ -53,10 +53,8 @@
53 max-width: 800px; 53 max-width: 800px;
54} 54}
55 55
56.video-channel { 56.video-channel my-actor-avatar {
57 img { 57 @include build-channel-img-size($video-thumbnail-width);
58 @include build-channel-img-size($video-thumbnail-width);
59 }
60} 58}
61 59
62.video-channel-info { 60.video-channel-info {
@@ -92,14 +90,12 @@
92 grid-template-columns: auto 1fr; 90 grid-template-columns: auto 1fr;
93 grid-template-rows: auto auto; 91 grid-template-rows: auto auto;
94 92
95 .link-avatar { 93 my-actor-avatar {
94 @include build-channel-img-size($video-thumbnail-medium-width);
95
96 grid-column: 1; 96 grid-column: 1;
97 grid-row: 1 / -1; 97 grid-row: 1 / -1;
98 } 98 }
99
100 img {
101 @include build-channel-img-size($video-thumbnail-medium-width);
102 }
103 } 99 }
104 100
105 .video-channel-info { 101 .video-channel-info {
@@ -115,7 +111,7 @@
115} 111}
116 112
117@include on-mobile-main-col { 113@include on-mobile-main-col {
118 .video-channel img { 114 .video-channel my-actor-avatar {
119 @include build-channel-img-size($video-thumbnail-small-width); 115 @include build-channel-img-size($video-thumbnail-small-width);
120 } 116 }
121} 117}
diff --git a/client/src/app/+search/search.component.ts b/client/src/app/+search/search.component.ts
index 2be952e16..ecede19a3 100644
--- a/client/src/app/+search/search.component.ts
+++ b/client/src/app/+search/search.component.ts
@@ -132,10 +132,6 @@ export class SearchComponent implements OnInit, OnDestroy {
132 return 'internal' 132 return 'internal'
133 } 133 }
134 134
135 isExternalChannelUrl () {
136 return this.getVideoLinkType() === 'external'
137 }
138
139 search () { 135 search () {
140 forkJoin([ 136 forkJoin([
141 this.getVideosObs(), 137 this.getVideosObs(),
@@ -200,17 +196,33 @@ export class SearchComponent implements OnInit, OnDestroy {
200 this.results = this.results.filter(r => !this.isVideo(r) || r.id !== video.id) 196 this.results = this.results.filter(r => !this.isVideo(r) || r.id !== video.id)
201 } 197 }
202 198
203 getChannelUrl (channel: VideoChannel) { 199 isExternalChannelUrl () {
200 return this.getVideoLinkType() === 'external'
201 }
202
203 getExternalChannelUrl (channel: VideoChannel) {
204 // Same algorithm than videos 204 // Same algorithm than videos
205 if (this.getVideoLinkType() === 'external') { 205 if (this.getVideoLinkType() === 'external') {
206 return channel.url 206 return channel.url
207 } 207 }
208 208
209 if (this.getVideoLinkType() === 'internal') { 209 // lazy-load or internal
210 return undefined
211 }
212
213 getInternalChannelUrl (channel: VideoChannel) {
214 const linkType = this.getVideoLinkType()
215
216 if (linkType === 'internal') {
210 return [ '/video-channels', channel.nameWithHost ] 217 return [ '/video-channels', channel.nameWithHost ]
211 } 218 }
212 219
213 return [ '/search/lazy-load-channel', { url: channel.url } ] 220 if (linkType === 'lazy-load') {
221 return [ '/search/lazy-load-channel', { url: channel.url } ]
222 }
223
224 // external
225 return undefined
214 } 226 }
215 227
216 hideActions () { 228 hideActions () {
diff --git a/client/src/app/+search/search.module.ts b/client/src/app/+search/search.module.ts
index e85ae07d0..390833abc 100644
--- a/client/src/app/+search/search.module.ts
+++ b/client/src/app/+search/search.module.ts
@@ -1,4 +1,5 @@
1import { NgModule } from '@angular/core' 1import { NgModule } from '@angular/core'
2import { SharedActorImageModule } from '@app/shared/shared-actor-image/shared-actor-image.module'
2import { SharedFormModule } from '@app/shared/shared-forms' 3import { SharedFormModule } from '@app/shared/shared-forms'
3import { SharedMainModule } from '@app/shared/shared-main' 4import { SharedMainModule } from '@app/shared/shared-main'
4import { SharedSearchModule } from '@app/shared/shared-search' 5import { SharedSearchModule } from '@app/shared/shared-search'
@@ -18,6 +19,7 @@ import { VideoLazyLoadResolver } from './video-lazy-load.resolver'
18 SharedMainModule, 19 SharedMainModule,
19 SharedSearchModule, 20 SharedSearchModule,
20 SharedFormModule, 21 SharedFormModule,
22 SharedActorImageModule,
21 SharedUserSubscriptionModule, 23 SharedUserSubscriptionModule,
22 SharedVideoMiniatureModule 24 SharedVideoMiniatureModule
23 ], 25 ],
diff --git a/client/src/app/+video-channels/video-channels.component.html b/client/src/app/+video-channels/video-channels.component.html
index 9308d5bb6..b4d81fe39 100644
--- a/client/src/app/+video-channels/video-channels.component.html
+++ b/client/src/app/+video-channels/video-channels.component.html
@@ -6,16 +6,16 @@
6 <div class="channel-info"> 6 <div class="channel-info">
7 7
8 <ng-template #buttonsTemplate> 8 <ng-template #buttonsTemplate>
9 <a *ngIf="isManageable()" [routerLink]="[ '/my-library/video-channels/update', videoChannel.nameWithHost ]" class="peertube-button-link orange-button" i18n> 9 <a *ngIf="isManageable()" [routerLink]="[ '/my-library/video-channels/update', videoChannel.nameWithHost ]" class="peertube-button-link orange-button" i18n>
10 Manage channel 10 Manage channel
11 </a> 11 </a>
12 12
13 <my-subscribe-button *ngIf="!isManageable()" #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button> 13 <my-subscribe-button *ngIf="!isManageable()" #subscribeButton [videoChannels]="[videoChannel]"></my-subscribe-button>
14 14
15 <button *ngIf="videoChannel.support" (click)="showSupportModal()" class="support-button peertube-button orange-button-inverted"> 15 <button *ngIf="videoChannel.support" (click)="showSupportModal()" class="support-button peertube-button orange-button-inverted">
16 <my-global-icon iconName="support" aria-hidden="true"></my-global-icon> 16 <my-global-icon iconName="support" aria-hidden="true"></my-global-icon>
17 <span class="icon-text" i18n>Support</span> 17 <span class="icon-text" i18n>Support</span>
18 </button> 18 </button>
19 </ng-template> 19 </ng-template>
20 20
21 <ng-template #ownerTemplate> 21 <ng-template #ownerTemplate>
@@ -23,7 +23,7 @@
23 <div class="section-label" i18n>OWNER ACCOUNT</div> 23 <div class="section-label" i18n>OWNER ACCOUNT</div>
24 24
25 <div class="avatar-row"> 25 <div class="avatar-row">
26 <my-account-avatar [account]="videoChannel.ownerAccount" [internalHref]="getAccountUrl()" size="120"></my-account-avatar> 26 <my-actor-avatar class="account-avatar" [account]="videoChannel.ownerAccount" [internalHref]="getAccountUrl()"></my-actor-avatar>
27 27
28 <div class="actor-info"> 28 <div class="actor-info">
29 <h4> 29 <h4>
@@ -49,7 +49,7 @@
49 </ng-template> 49 </ng-template>
50 50
51 <div class="channel-avatar-row"> 51 <div class="channel-avatar-row">
52 <img class="channel-avatar" [src]="videoChannel.avatarUrl" alt="Avatar" /> 52 <my-actor-avatar class="main-avatar" [channel]="videoChannel"></my-actor-avatar>
53 53
54 <div> 54 <div>
55 <div class="section-label" i18n>VIDEO CHANNEL</div> 55 <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 e946707ef..360a99342 100644
--- a/client/src/app/+video-channels/video-channels.component.scss
+++ b/client/src/app/+video-channels/video-channels.component.scss
@@ -107,8 +107,8 @@
107 display: flex; 107 display: flex;
108 margin-bottom: 15px; 108 margin-bottom: 15px;
109 109
110 img { 110 .account-avatar {
111 @include avatar(48px); 111 @include actor-avatar-size(48px);
112 } 112 }
113 113
114 .actor-info { 114 .actor-info {
@@ -289,8 +289,8 @@
289 margin-top: -5px; 289 margin-top: -5px;
290 } 290 }
291 291
292 img { 292 .account-avatar {
293 @include channel-avatar(64px); 293 @include actor-avatar-size(64px);
294 294
295 margin: -30px 0 0 15px; 295 margin: -30px 0 0 15px;
296 } 296 }
diff --git a/client/src/app/+video-channels/video-channels.module.ts b/client/src/app/+video-channels/video-channels.module.ts
index 2e387f401..35c39cc2e 100644
--- a/client/src/app/+video-channels/video-channels.module.ts
+++ b/client/src/app/+video-channels/video-channels.module.ts
@@ -10,7 +10,7 @@ import { VideoChannelPlaylistsComponent } from './video-channel-playlists/video-
10import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component' 10import { VideoChannelVideosComponent } from './video-channel-videos/video-channel-videos.component'
11import { VideoChannelsRoutingModule } from './video-channels-routing.module' 11import { VideoChannelsRoutingModule } from './video-channels-routing.module'
12import { VideoChannelsComponent } from './video-channels.component' 12import { VideoChannelsComponent } from './video-channels.component'
13import { SharedAccountAvatarModule } from '../shared/shared-account-avatar/shared-account-avatar.module' 13import { SharedActorImageModule } from '../shared/shared-actor-image/shared-actor-image.module'
14 14
15@NgModule({ 15@NgModule({
16 imports: [ 16 imports: [
@@ -23,7 +23,7 @@ import { SharedAccountAvatarModule } from '../shared/shared-account-avatar/share
23 SharedUserSubscriptionModule, 23 SharedUserSubscriptionModule,
24 SharedGlobalIconModule, 24 SharedGlobalIconModule,
25 SharedSupportModal, 25 SharedSupportModal,
26 SharedAccountAvatarModule 26 SharedActorImageModule
27 ], 27 ],
28 28
29 declarations: [ 29 declarations: [
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment-add.component.html b/client/src/app/+videos/+video-watch/comment/video-comment-add.component.html
index 7bd9b7c90..42adfed8d 100644
--- a/client/src/app/+videos/+video-watch/comment/video-comment-add.component.html
+++ b/client/src/app/+videos/+video-watch/comment/video-comment-add.component.html
@@ -1,6 +1,6 @@
1<form novalidate [formGroup]="form" (ngSubmit)="formValidated()"> 1<form novalidate [formGroup]="form" (ngSubmit)="formValidated()">
2 <div class="avatar-and-textarea"> 2 <div class="avatar-and-textarea">
3 <my-account-avatar [account]="user?.account" size="25"></my-account-avatar> 3 <my-actor-avatar [account]="user?.account" size="25"></my-actor-avatar>
4 4
5 <div class="form-group"> 5 <div class="form-group">
6 <textarea i18n-placeholder placeholder="Add comment..." myAutoResize 6 <textarea i18n-placeholder placeholder="Add comment..." myAutoResize
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment-add.component.scss b/client/src/app/+videos/+video-watch/comment/video-comment-add.component.scss
index 1aa9255c2..54e61eac4 100644
--- a/client/src/app/+videos/+video-watch/comment/video-comment-add.component.scss
+++ b/client/src/app/+videos/+video-watch/comment/video-comment-add.component.scss
@@ -13,8 +13,7 @@ form {
13 display: flex; 13 display: flex;
14 margin-bottom: 10px; 14 margin-bottom: 10px;
15 15
16 my-account-avatar { 16 my-actor-avatar {
17 vertical-align: top;
18 margin-right: 10px; 17 margin-right: 10px;
19 } 18 }
20 19
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment.component.html b/client/src/app/+videos/+video-watch/comment/video-comment.component.html
index 2b0739261..d7ba40ef6 100644
--- a/client/src/app/+videos/+video-watch/comment/video-comment.component.html
+++ b/client/src/app/+videos/+video-watch/comment/video-comment.component.html
@@ -1,12 +1,10 @@
1<div *ngIf="isCommentDisplayed()" class="root-comment"> 1<div *ngIf="isCommentDisplayed()" class="root-comment" [ngClass]="{ 'is-child': isChild() }">
2 <div class="left"> 2 <div class="left">
3 <my-account-avatar *ngIf="!comment.isDeleted" [href]="comment.account.url" [account]="comment.account"></my-account-avatar> 3 <my-actor-avatar *ngIf="!comment.isDeleted" [href]="comment.account.url" [account]="comment.account"></my-actor-avatar>
4 <div class="vertical-border"></div> 4 <div class="vertical-border"></div>
5 </div> 5 </div>
6 6
7 <div class="right" [ngClass]="{ 'mb-3': firstInThread }"> 7 <div class="right" [ngClass]="{ 'mb-3': firstInThread }">
8 <span *ngIf="comment.isDeleted" class="comment-avatar"></span>
9
10 <div class="comment"> 8 <div class="comment">
11 <ng-container *ngIf="!comment.isDeleted"> 9 <ng-container *ngIf="!comment.isDeleted">
12 <div *ngIf="highlightedComment === true" class="highlighted-comment" i18n>Highlighted comment</div> 10 <div *ngIf="highlightedComment === true" class="highlighted-comment" i18n>Highlighted comment</div>
@@ -68,7 +66,7 @@
68 [textValue]="redraftValue" 66 [textValue]="redraftValue"
69 ></my-video-comment-add> 67 ></my-video-comment-add>
70 68
71 <div *ngIf="commentTree" class="children"> 69 <div *ngIf="commentTree">
72 <div *ngFor="let commentChild of commentTree.children"> 70 <div *ngFor="let commentChild of commentTree.children">
73 <my-video-comment 71 <my-video-comment
74 [comment]="commentChild.comment" 72 [comment]="commentChild.comment"
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment.component.scss b/client/src/app/+videos/+video-watch/comment/video-comment.component.scss
index cf33a5b0e..f0dcc08b8 100644
--- a/client/src/app/+videos/+video-watch/comment/video-comment.component.scss
+++ b/client/src/app/+videos/+video-watch/comment/video-comment.component.scss
@@ -24,6 +24,10 @@
24 } 24 }
25} 25}
26 26
27my-actor-avatar {
28 @include actor-avatar-size(36px);
29}
30
27.comment { 31.comment {
28 flex-grow: 1; 32 flex-grow: 1;
29 // Fix word-wrap with flex 33 // Fix word-wrap with flex
@@ -148,10 +152,10 @@ my-video-comment-add {
148 } 152 }
149} 153}
150 154
151.children { 155.is-child {
152 // Reduce avatars size for replies 156 // Reduce avatars size for replies
153 .comment-avatar { 157 my-actor-avatar {
154 @include avatar(25px); 158 @include actor-avatar-size(25px);
155 } 159 }
156 160
157 .left { 161 .left {
diff --git a/client/src/app/+videos/+video-watch/comment/video-comment.component.ts b/client/src/app/+videos/+video-watch/comment/video-comment.component.ts
index dd3db0c65..fd379e80e 100644
--- a/client/src/app/+videos/+video-watch/comment/video-comment.component.ts
+++ b/client/src/app/+videos/+video-watch/comment/video-comment.component.ts
@@ -138,6 +138,10 @@ export class VideoCommentComponent implements OnInit, OnChanges {
138 (this.commentTree?.hasDisplayedChildren) // Or this is a reply that have other replies 138 (this.commentTree?.hasDisplayedChildren) // Or this is a reply that have other replies
139 } 139 }
140 140
141 isChild () {
142 return this.parentComments.length !== 0
143 }
144
141 private getUserIfNeeded (account: Account) { 145 private getUserIfNeeded (account: Account) {
142 if (!account.userId) return 146 if (!account.userId) return
143 if (!this.authService.isLoggedIn()) return 147 if (!this.authService.isLoggedIn()) return
diff --git a/client/src/app/+videos/+video-watch/video-avatar-channel.component.html b/client/src/app/+videos/+video-watch/video-avatar-channel.component.html
index a02373f2d..b8b5d7843 100644
--- a/client/src/app/+videos/+video-watch/video-avatar-channel.component.html
+++ b/client/src/app/+videos/+video-watch/video-avatar-channel.component.html
@@ -4,11 +4,11 @@
4 <img [src]="video.videoChannelAvatarUrl" i18n-alt alt="Channel avatar" class="channel-avatar" /> 4 <img [src]="video.videoChannelAvatarUrl" i18n-alt alt="Channel avatar" class="channel-avatar" />
5 </a> 5 </a>
6 6
7 <my-account-avatar [account]="video.account" [title]="accountLinkTitle" [internalHref]="[ '/accounts', video.byAccount ]"></my-account-avatar> 7 <my-actor-avatar [account]="video.account" [title]="accountLinkTitle" [internalHref]="[ '/accounts', video.byAccount ]"></my-actor-avatar>
8</ng-container> 8</ng-container>
9 9
10 <ng-container *ngIf="!isChannelAvatarNull() && genericChannel"> 10 <ng-container *ngIf="!isChannelAvatarNull() && genericChannel">
11 <my-account-avatar [account]="video.account" [title]="accountLinkTitle" [internalHref]="[ '/accounts', video.byAccount ]"></my-account-avatar> 11 <my-actor-avatar [account]="video.account" [title]="accountLinkTitle" [internalHref]="[ '/accounts', video.byAccount ]"></my-actor-avatar>
12 12
13 <a [routerLink]="[ '/video-channels', video.byVideoChannel ]" [title]="channelLinkTitle"> 13 <a [routerLink]="[ '/video-channels', video.byVideoChannel ]" [title]="channelLinkTitle">
14 <img [src]="video.videoChannelAvatarUrl" i18n-alt alt="Channel avatar" class="channel-avatar" /> 14 <img [src]="video.videoChannelAvatarUrl" i18n-alt alt="Channel avatar" class="channel-avatar" />
@@ -16,6 +16,6 @@
16 </ng-container> 16 </ng-container>
17 17
18 <ng-container *ngIf="isChannelAvatarNull()"> 18 <ng-container *ngIf="isChannelAvatarNull()">
19 <my-account-avatar [account]="video.account" [title]="accountLinkTitle" [internalHref]="[ '/accounts', video.byAccount ]"></my-account-avatar> 19 <my-actor-avatar [account]="video.account" [title]="accountLinkTitle" [internalHref]="[ '/accounts', video.byAccount ]"></my-actor-avatar>
20 </ng-container> 20 </ng-container>
21</div> 21</div>
diff --git a/client/src/app/+videos/+video-watch/video-watch.module.ts b/client/src/app/+videos/+video-watch/video-watch.module.ts
index cf6afd852..62ce7be2d 100644
--- a/client/src/app/+videos/+video-watch/video-watch.module.ts
+++ b/client/src/app/+videos/+video-watch/video-watch.module.ts
@@ -20,7 +20,7 @@ import { TimestampRouteTransformerDirective } from './timestamp-route-transforme
20import { VideoWatchPlaylistComponent } from './video-watch-playlist.component' 20import { VideoWatchPlaylistComponent } from './video-watch-playlist.component'
21import { VideoWatchRoutingModule } from './video-watch-routing.module' 21import { VideoWatchRoutingModule } from './video-watch-routing.module'
22import { VideoWatchComponent } from './video-watch.component' 22import { VideoWatchComponent } from './video-watch.component'
23import { SharedAccountAvatarModule } from '../../shared/shared-account-avatar/shared-account-avatar.module' 23import { SharedActorImageModule } from '../../shared/shared-actor-image/shared-actor-image.module'
24import { VideoAvatarChannelComponent } from './video-avatar-channel.component' 24import { VideoAvatarChannelComponent } from './video-avatar-channel.component'
25 25
26@NgModule({ 26@NgModule({
@@ -39,7 +39,7 @@ import { VideoAvatarChannelComponent } from './video-avatar-channel.component'
39 SharedShareModal, 39 SharedShareModal,
40 SharedVideoModule, 40 SharedVideoModule,
41 SharedSupportModal, 41 SharedSupportModal,
42 SharedAccountAvatarModule 42 SharedActorImageModule
43 ], 43 ],
44 44
45 declarations: [ 45 declarations: [
diff --git a/client/src/app/+videos/video-list/overview/video-overview.component.html b/client/src/app/+videos/video-list/overview/video-overview.component.html
index 639a96c43..e21bffb6c 100644
--- a/client/src/app/+videos/video-list/overview/video-overview.component.html
+++ b/client/src/app/+videos/video-list/overview/video-overview.component.html
@@ -33,7 +33,7 @@
33 <div class="section channel videos" *ngFor="let object of overview.channels"> 33 <div class="section channel videos" *ngFor="let object of overview.channels">
34 <div class="section-title"> 34 <div class="section-title">
35 <a [routerLink]="[ '/video-channels', buildVideoChannelBy(object) ]"> 35 <a [routerLink]="[ '/video-channels', buildVideoChannelBy(object) ]">
36 <img [src]="buildVideoChannelAvatarUrl(object)" alt="Avatar" /> 36 <my-actor-avatar [channel]="buildVideoChannel(object)"></my-actor-avatar>
37 37
38 <h2 class="section-title">{{ object.channel.displayName }}</h2> 38 <h2 class="section-title">{{ object.channel.displayName }}</h2>
39 </a> 39 </a>
diff --git a/client/src/app/+videos/video-list/overview/video-overview.component.scss b/client/src/app/+videos/video-list/overview/video-overview.component.scss
index ec73c628c..251eae456 100644
--- a/client/src/app/+videos/video-list/overview/video-overview.component.scss
+++ b/client/src/app/+videos/video-list/overview/video-overview.component.scss
@@ -49,9 +49,10 @@
49 width: fit-content; 49 width: fit-content;
50 align-items: center; 50 align-items: center;
51 51
52 img { 52 my-actor-avatar {
53 @include channel-avatar(28px); 53 @include actor-avatar-size(28px);
54 54
55 font-size: initial;
55 margin-right: 8px; 56 margin-right: 8px;
56 } 57 }
57 } 58 }
diff --git a/client/src/app/+videos/video-list/overview/video-overview.component.ts b/client/src/app/+videos/video-list/overview/video-overview.component.ts
index b3be1d7b5..14532ca1e 100644
--- a/client/src/app/+videos/video-list/overview/video-overview.component.ts
+++ b/client/src/app/+videos/video-list/overview/video-overview.component.ts
@@ -45,8 +45,8 @@ export class VideoOverviewComponent implements OnInit {
45 return object.videos[0].byVideoChannel 45 return object.videos[0].byVideoChannel
46 } 46 }
47 47
48 buildVideoChannelAvatarUrl (object: { videos: Video[] }) { 48 buildVideoChannel (object: { videos: Video[] }) {
49 return object.videos[0].videoChannelAvatarUrl 49 return object.videos[0].channel
50 } 50 }
51 51
52 buildVideos (videos: Video[]) { 52 buildVideos (videos: Video[]) {
diff --git a/client/src/app/+videos/videos.module.ts b/client/src/app/+videos/videos.module.ts
index 61d012d63..8a35015d6 100644
--- a/client/src/app/+videos/videos.module.ts
+++ b/client/src/app/+videos/videos.module.ts
@@ -1,4 +1,5 @@
1import { NgModule } from '@angular/core' 1import { NgModule } from '@angular/core'
2import { SharedActorImageModule } from '@app/shared/shared-actor-image/shared-actor-image.module'
2import { SharedFormModule } from '@app/shared/shared-forms' 3import { SharedFormModule } from '@app/shared/shared-forms'
3import { SharedGlobalIconModule } from '@app/shared/shared-icons' 4import { SharedGlobalIconModule } from '@app/shared/shared-icons'
4import { SharedMainModule } from '@app/shared/shared-main' 5import { SharedMainModule } from '@app/shared/shared-main'
@@ -21,7 +22,8 @@ import { VideosComponent } from './videos.component'
21 SharedFormModule, 22 SharedFormModule,
22 SharedVideoMiniatureModule, 23 SharedVideoMiniatureModule,
23 SharedUserSubscriptionModule, 24 SharedUserSubscriptionModule,
24 SharedGlobalIconModule 25 SharedGlobalIconModule,
26 SharedActorImageModule
25 ], 27 ],
26 28
27 declarations: [ 29 declarations: [
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts
index 41c59cc86..3cec6d739 100644
--- a/client/src/app/app.module.ts
+++ b/client/src/app/app.module.ts
@@ -24,7 +24,7 @@ import { SharedGlobalIconModule } from './shared/shared-icons'
24import { SharedInstanceModule } from './shared/shared-instance' 24import { SharedInstanceModule } from './shared/shared-instance'
25import { SharedMainModule } from './shared/shared-main' 25import { SharedMainModule } from './shared/shared-main'
26import { SharedUserInterfaceSettingsModule } from './shared/shared-user-settings' 26import { SharedUserInterfaceSettingsModule } from './shared/shared-user-settings'
27import { SharedAccountAvatarModule } from './shared/shared-account-avatar/shared-account-avatar.module' 27import { SharedActorImageModule } from './shared/shared-actor-image/shared-actor-image.module'
28 28
29registerLocaleData(localeOc, 'oc') 29registerLocaleData(localeOc, 'oc')
30 30
@@ -60,7 +60,7 @@ registerLocaleData(localeOc, 'oc')
60 SharedUserInterfaceSettingsModule, 60 SharedUserInterfaceSettingsModule,
61 SharedGlobalIconModule, 61 SharedGlobalIconModule,
62 SharedInstanceModule, 62 SharedInstanceModule,
63 SharedAccountAvatarModule, 63 SharedActorImageModule,
64 64
65 MetaModule.forRoot({ 65 MetaModule.forRoot({
66 provide: MetaLoader, 66 provide: MetaLoader,
diff --git a/client/src/app/menu/menu.component.html b/client/src/app/menu/menu.component.html
index df5c7971d..2e07deca2 100644
--- a/client/src/app/menu/menu.component.html
+++ b/client/src/app/menu/menu.component.html
@@ -5,7 +5,7 @@
5 <div> 5 <div>
6 <div class="logged-in-more" ngbDropdown #dropdown="ngbDropdown" placement="bottom-left" [container]="dropdownContainer" (openChange)="onDropdownOpenChange($event)" autoClose="outside"> 6 <div class="logged-in-more" ngbDropdown #dropdown="ngbDropdown" placement="bottom-left" [container]="dropdownContainer" (openChange)="onDropdownOpenChange($event)" autoClose="outside">
7 <div ngbDropdownToggle> 7 <div ngbDropdownToggle>
8 <my-account-avatar [account]="user.account" size="34"></my-account-avatar> 8 <my-actor-avatar [account]="user.account" size="34"></my-actor-avatar>
9 <div class="logged-in-info"> 9 <div class="logged-in-info">
10 <div class="logged-in-display-name">{{ user.account?.displayName }}</div> 10 <div class="logged-in-display-name">{{ user.account?.displayName }}</div>
11 11
diff --git a/client/src/app/menu/menu.component.scss b/client/src/app/menu/menu.component.scss
index 00d1a1f69..c84a08b1d 100644
--- a/client/src/app/menu/menu.component.scss
+++ b/client/src/app/menu/menu.component.scss
@@ -177,7 +177,7 @@ my-notification {
177 } 177 }
178} 178}
179 179
180my-account-avatar { 180my-actor-avatar {
181 margin-right: 10px; 181 margin-right: 10px;
182} 182}
183 183
diff --git a/client/src/app/shared/shared-abuse-list/abuse-details.component.html b/client/src/app/shared/shared-abuse-list/abuse-details.component.html
index 658d42537..f2eaeb32f 100644
--- a/client/src/app/shared/shared-abuse-list/abuse-details.component.html
+++ b/client/src/app/shared/shared-abuse-list/abuse-details.component.html
@@ -10,7 +10,7 @@
10 <a [routerLink]="[ baseRoute ]" [queryParams]="{ 'search': 'reporter:&quot;' + abuse.reporterAccount.displayName + '&quot;' }" 10 <a [routerLink]="[ baseRoute ]" [queryParams]="{ 'search': 'reporter:&quot;' + abuse.reporterAccount.displayName + '&quot;' }"
11 class="chip" 11 class="chip"
12 > 12 >
13 <my-account-avatar [account]="abuse.reporterAccount"></my-account-avatar> 13 <my-actor-avatar [account]="abuse.reporterAccount"></my-actor-avatar>
14 <div> 14 <div>
15 <span class="text-muted">{{ abuse.reporterAccount.nameWithHost }}</span> 15 <span class="text-muted">{{ abuse.reporterAccount.nameWithHost }}</span>
16 </div> 16 </div>
@@ -30,7 +30,7 @@
30 <a [routerLink]="[ baseRoute ]" [queryParams]="{ 'search': 'reportee:&quot;' +abuse.flaggedAccount.displayName + '&quot;' }" 30 <a [routerLink]="[ baseRoute ]" [queryParams]="{ 'search': 'reportee:&quot;' +abuse.flaggedAccount.displayName + '&quot;' }"
31 class="chip" 31 class="chip"
32 > 32 >
33 <my-account-avatar [account]="abuse.flaggedAccount"></my-account-avatar> 33 <my-actor-avatar [account]="abuse.flaggedAccount"></my-actor-avatar>
34 <div> 34 <div>
35 <span class="text-muted">{{ abuse.flaggedAccount ? abuse.flaggedAccount.nameWithHost : '' }}</span> 35 <span class="text-muted">{{ abuse.flaggedAccount ? abuse.flaggedAccount.nameWithHost : '' }}</span>
36 </div> 36 </div>
diff --git a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html
index 29b51f09c..b41bc75d4 100644
--- a/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html
+++ b/client/src/app/shared/shared-abuse-list/abuse-list-table.component.html
@@ -65,7 +65,7 @@
65 <td *ngIf="isAdminView()"> 65 <td *ngIf="isAdminView()">
66 <a *ngIf="abuse.reporterAccount" [href]="abuse.reporterAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer"> 66 <a *ngIf="abuse.reporterAccount" [href]="abuse.reporterAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
67 <div class="chip two-lines"> 67 <div class="chip two-lines">
68 <my-account-avatar [account]="abuse.reporterAccount"></my-account-avatar> 68 <my-actor-avatar [account]="abuse.reporterAccount"></my-actor-avatar>
69 <div> 69 <div>
70 {{ abuse.reporterAccount.displayName }} 70 {{ abuse.reporterAccount.displayName }}
71 <span>{{ abuse.reporterAccount.nameWithHost }}</span> 71 <span>{{ abuse.reporterAccount.nameWithHost }}</span>
diff --git a/client/src/app/shared/shared-abuse-list/shared-abuse-list.module.ts b/client/src/app/shared/shared-abuse-list/shared-abuse-list.module.ts
index 19b6d456d..8f3830a17 100644
--- a/client/src/app/shared/shared-abuse-list/shared-abuse-list.module.ts
+++ b/client/src/app/shared/shared-abuse-list/shared-abuse-list.module.ts
@@ -10,7 +10,7 @@ import { AbuseDetailsComponent } from './abuse-details.component'
10import { AbuseListTableComponent } from './abuse-list-table.component' 10import { AbuseListTableComponent } from './abuse-list-table.component'
11import { AbuseMessageModalComponent } from './abuse-message-modal.component' 11import { AbuseMessageModalComponent } from './abuse-message-modal.component'
12import { ModerationCommentModalComponent } from './moderation-comment-modal.component' 12import { ModerationCommentModalComponent } from './moderation-comment-modal.component'
13import { SharedAccountAvatarModule } from '../shared-account-avatar/shared-account-avatar.module' 13import { SharedActorImageModule } from '../shared-actor-image/shared-actor-image.module'
14 14
15@NgModule({ 15@NgModule({
16 imports: [ 16 imports: [
@@ -21,7 +21,7 @@ import { SharedAccountAvatarModule } from '../shared-account-avatar/shared-accou
21 SharedModerationModule, 21 SharedModerationModule,
22 SharedGlobalIconModule, 22 SharedGlobalIconModule,
23 SharedVideoCommentModule, 23 SharedVideoCommentModule,
24 SharedAccountAvatarModule 24 SharedActorImageModule
25 ], 25 ],
26 26
27 declarations: [ 27 declarations: [
diff --git a/client/src/app/shared/shared-account-avatar/account-avatar.component.html b/client/src/app/shared/shared-account-avatar/account-avatar.component.html
deleted file mode 100644
index 083daccfb..000000000
--- a/client/src/app/shared/shared-account-avatar/account-avatar.component.html
+++ /dev/null
@@ -1,18 +0,0 @@
1<ng-template #img>
2 <img *ngIf="avatarUrl || !initial" [class]="class" [src]="avatarUrl || defaultAvatarUrl" i18n-alt alt="Account avatar" />
3 <div *ngIf="!avatarUrl && initial" [class]="class">
4 <span>{{ initial }}</span>
5 </div>
6</ng-template>
7
8<a *ngIf="account && href" [href]="href" target="_blank" rel="noopener noreferrer" [title]="title">
9 <ng-template *ngTemplateOutlet="img"></ng-template>
10</a>
11
12<a *ngIf="account && internalHref" [routerLink]="internalHref" [title]="title">
13 <ng-template *ngTemplateOutlet="img"></ng-template>
14</a>
15
16<ng-container *ngIf="!account || (!href && !internalHref)">
17 <ng-template *ngTemplateOutlet="img"></ng-template>
18</ng-container>
diff --git a/client/src/app/shared/shared-account-avatar/account-avatar.component.ts b/client/src/app/shared/shared-account-avatar/account-avatar.component.ts
deleted file mode 100644
index 76b696566..000000000
--- a/client/src/app/shared/shared-account-avatar/account-avatar.component.ts
+++ /dev/null
@@ -1,62 +0,0 @@
1import { Component, Input } from '@angular/core'
2import { Account } from '../shared-main/account/account.model'
3
4@Component({
5 selector: 'my-account-avatar',
6 styleUrls: [ './account-avatar.component.scss' ],
7 templateUrl: './account-avatar.component.html'
8})
9export class AccountAvatarComponent {
10 @Input() account: {
11 name: string
12 avatar?: { url?: string, path: string }
13 url: string
14 }
15 @Input() size: '25' | '32' | '34' | '36' | '40' | '120' = '36'
16
17 // Use an external link
18 @Input() href: string
19 // Use routerLink
20 @Input() internalHref: string | string[]
21
22 @Input() set title (value) {
23 this._title = value
24 }
25
26 defaultAvatarUrl = Account.GET_DEFAULT_AVATAR_URL()
27
28 private _title: string
29
30 get title () {
31 return this._title || $localize`${this.account.name} (account page)`
32 }
33
34 get class () {
35 return `avatar avatar-${this.size}` + (this.avatarUrl ? '' : ` initial ${this.getColorTheme()}`)
36 }
37
38 get avatarUrl () {
39 return Account.GET_ACTOR_AVATAR_URL(this.account)
40 }
41
42 get initial () {
43 return this.account?.name.slice(0, 1)
44 }
45
46 private getColorTheme () {
47 const themes = {
48 abc: 'blue',
49 def: 'green',
50 ghi: 'purple',
51 jkl: 'gray',
52 mno: 'yellow',
53 pqr: 'orange',
54 stv: 'red',
55 wxyz: 'dark-blue'
56 }
57
58 const theme = Object.keys(themes).find(chars => chars.includes(this.initial))
59
60 return themes[theme]
61 }
62}
diff --git a/client/src/app/shared/shared-account-avatar/index.ts b/client/src/app/shared/shared-account-avatar/index.ts
deleted file mode 100644
index 40c742ba5..000000000
--- a/client/src/app/shared/shared-account-avatar/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
1export * from './account-avatar.component'
2export * from './shared-account-avatar.module' \ No newline at end of file
diff --git a/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.html b/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.html
index 0829263f4..e9c5fadcf 100644
--- a/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.html
+++ b/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.html
@@ -1,6 +1,6 @@
1<div class="actor" *ngIf="actor"> 1<div class="actor" *ngIf="actor">
2 <div class="d-flex"> 2 <div class="d-flex">
3 <img [ngClass]="{ channel: isChannel() }" [src]="preview || actor.avatarUrl" alt="Avatar" /> 3 <my-actor-avatar [channel]="getChannel()" [account]="getAccount()" [previewImage]="preview" size="100"></my-actor-avatar>
4 4
5 <div class="actor-img-edit-container"> 5 <div class="actor-img-edit-container">
6 6
@@ -34,6 +34,7 @@
34 <span for="avatarfile" i18n>Upload a new avatar</span> 34 <span for="avatarfile" i18n>Upload a new avatar</span>
35 <input #avatarfileInput type="file" name="avatarfile" id="avatarfile" [accept]="avatarExtensions" (change)="onAvatarChange(avatarfileInput)"/> 35 <input #avatarfileInput type="file" name="avatarfile" id="avatarfile" [accept]="avatarExtensions" (change)="onAvatarChange(avatarfileInput)"/>
36 </div> 36 </div>
37
37 <div class="dropdown-item c-hand" (click)="deleteAvatar()" (key.enter)="deleteAvatar()"> 38 <div class="dropdown-item c-hand" (click)="deleteAvatar()" (key.enter)="deleteAvatar()">
38 <my-global-icon iconName="delete"></my-global-icon> 39 <my-global-icon iconName="delete"></my-global-icon>
39 <span i18n>Remove avatar</span> 40 <span i18n>Remove avatar</span>
diff --git a/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.scss b/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.scss
index 8b0172315..08e80c3b4 100644
--- a/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.scss
+++ b/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.scss
@@ -4,16 +4,8 @@
4.actor { 4.actor {
5 display: flex; 5 display: flex;
6 6
7 img { 7 my-actor-avatar {
8 margin-right: 15px; 8 margin-right: 15px;
9
10 &:not(.channel) {
11 @include avatar(100px);
12 }
13
14 &.channel {
15 @include channel-avatar(100px);
16 }
17 } 9 }
18 10
19 .actor-info { 11 .actor-info {
diff --git a/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts b/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts
index d0d269489..840946690 100644
--- a/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts
+++ b/client/src/app/shared/shared-actor-image-edit/actor-avatar-edit.component.ts
@@ -80,4 +80,16 @@ export class ActorAvatarEditComponent implements OnInit {
80 isChannel () { 80 isChannel () {
81 return !!(this.actor as VideoChannel).ownerAccount 81 return !!(this.actor as VideoChannel).ownerAccount
82 } 82 }
83
84 getChannel (): VideoChannel {
85 if (this.isChannel()) return this.actor as VideoChannel
86
87 return undefined
88 }
89
90 getAccount (): Account {
91 if (this.isChannel()) return undefined
92
93 return this.actor as Account
94 }
83} 95}
diff --git a/client/src/app/shared/shared-actor-image-edit/shared-actor-image-edit.module.ts b/client/src/app/shared/shared-actor-image-edit/shared-actor-image-edit.module.ts
index c9c6472b9..f6a397d5c 100644
--- a/client/src/app/shared/shared-actor-image-edit/shared-actor-image-edit.module.ts
+++ b/client/src/app/shared/shared-actor-image-edit/shared-actor-image-edit.module.ts
@@ -1,6 +1,7 @@
1 1
2import { CommonModule } from '@angular/common' 2import { CommonModule } from '@angular/common'
3import { NgModule } from '@angular/core' 3import { NgModule } from '@angular/core'
4import { SharedActorImageModule } from '../shared-actor-image/shared-actor-image.module'
4import { SharedGlobalIconModule } from '../shared-icons' 5import { SharedGlobalIconModule } from '../shared-icons'
5import { SharedMainModule } from '../shared-main' 6import { SharedMainModule } from '../shared-main'
6import { ActorAvatarEditComponent } from './actor-avatar-edit.component' 7import { ActorAvatarEditComponent } from './actor-avatar-edit.component'
@@ -11,6 +12,7 @@ import { ActorBannerEditComponent } from './actor-banner-edit.component'
11 CommonModule, 12 CommonModule,
12 13
13 SharedMainModule, 14 SharedMainModule,
15 SharedActorImageModule,
14 SharedGlobalIconModule 16 SharedGlobalIconModule
15 ], 17 ],
16 18
diff --git a/client/src/app/shared/shared-actor-image/actor-avatar.component.html b/client/src/app/shared/shared-actor-image/actor-avatar.component.html
new file mode 100644
index 000000000..607f28e5b
--- /dev/null
+++ b/client/src/app/shared/shared-actor-image/actor-avatar.component.html
@@ -0,0 +1,19 @@
1<ng-template #img>
2 <img *ngIf="previewImage || avatarUrl || !initial" [class]="class" [src]="previewImage || avatarUrl || defaultAvatarUrl" [alt]="alt" />
3
4 <div *ngIf="!avatarUrl && initial" [class]="class">
5 <span>{{ initial }}</span>
6 </div>
7</ng-template>
8
9<a *ngIf="hasActor() && href" [href]="href" target="_blank" rel="noopener noreferrer" [title]="title">
10 <ng-template *ngTemplateOutlet="img"></ng-template>
11</a>
12
13<a *ngIf="hasActor() && internalHref" [routerLink]="internalHref" [title]="title">
14 <ng-template *ngTemplateOutlet="img"></ng-template>
15</a>
16
17<ng-container *ngIf="!hasActor() || (!href && !internalHref)">
18 <ng-template *ngTemplateOutlet="img"></ng-template>
19</ng-container>
diff --git a/client/src/app/shared/shared-account-avatar/account-avatar.component.scss b/client/src/app/shared/shared-actor-image/actor-avatar.component.scss
index 75a4cbf86..f014dec48 100644
--- a/client/src/app/shared/shared-account-avatar/account-avatar.component.scss
+++ b/client/src/app/shared/shared-actor-image/actor-avatar.component.scss
@@ -1,32 +1,58 @@
1@import '_variables'; 1@import '_variables';
2@import '_mixins'; 2@import '_mixins';
3 3
4.avatar {
5 --avatarSize: 100%;
6 --initialFontSize: 22px;
7
8 width: var(--avatarSize);
9 height: var(--avatarSize);
10 min-width: var(--avatarSize);
11 min-height: var(--avatarSize);
12
13 &.account {
14 object-fit: cover;
15 border-radius: 50%;
16 }
17
18 &.channel {
19 border-radius: 5px;
20 }
21}
22
23.avatar-18 {
24 --avatarSize: 18px;
25 --initialFontSize: 13px;
26}
27
4.avatar-25 { 28.avatar-25 {
5 @include avatar(25px); 29 --avatarSize: 25px;
6} 30}
7 31
8.avatar-32 { 32.avatar-32 {
9 @include avatar(32px); 33 --avatarSize: 32px;
10} 34}
11 35
12.avatar-34 { 36.avatar-34 {
13 @include avatar(34px); 37 --avatarSize: 34px;
14} 38}
15 39
16.avatar-36 { 40.avatar-36 {
17 @include avatar(36px); 41 --avatarSize: 36px;
18} 42}
19 43
20.avatar-40 { 44.avatar-40 {
21 @include avatar(40px); 45 --avatarSize: 40px;
22} 46}
23 47
24.avatar-120 { 48.avatar-100 {
25 @include avatar(120px); 49 --avatarSize: 100px;
50 --initialFontSize: 40px;
51 }
26 52
27 &.initial { 53.avatar-120 {
28 font-size: 46px; 54 --avatarSize: 120px;
29 } 55 --initialFontSize: 46px;
30} 56}
31 57
32a:hover { 58a:hover {
@@ -39,8 +65,7 @@ a:hover {
39 display: flex; 65 display: flex;
40 align-items: center; 66 align-items: center;
41 justify-content: center; 67 justify-content: center;
42 font-size: 22px; 68 font-size: var(--initialFontSize);
43 border-radius: 50%;
44 69
45 &.blue { 70 &.blue {
46 background-color: #009FD4; 71 background-color: #009FD4;
diff --git a/client/src/app/shared/shared-actor-image/actor-avatar.component.ts b/client/src/app/shared/shared-actor-image/actor-avatar.component.ts
new file mode 100644
index 000000000..6bb3b65fa
--- /dev/null
+++ b/client/src/app/shared/shared-actor-image/actor-avatar.component.ts
@@ -0,0 +1,110 @@
1import { Component, Input } from '@angular/core'
2import { SafeResourceUrl } from '@angular/platform-browser'
3import { VideoChannel } from '../shared-main'
4import { Account } from '../shared-main/account/account.model'
5
6type ActorInput = {
7 name: string
8 avatar?: { url?: string, path: string }
9 url: string
10}
11
12@Component({
13 selector: 'my-actor-avatar',
14 styleUrls: [ './actor-avatar.component.scss' ],
15 templateUrl: './actor-avatar.component.html'
16})
17export class ActorAvatarComponent {
18 @Input() account: ActorInput
19 @Input() channel: ActorInput
20
21 @Input() previewImage: SafeResourceUrl
22
23 @Input() size: '18' | '25' | '32' | '34' | '36' | '40' | '100' | '120'
24
25 // Use an external link
26 @Input() href: string
27 // Use routerLink
28 @Input() internalHref: string | any[]
29
30 @Input() set title (value) {
31 this._title = value
32 }
33
34 private _title: string
35
36 get title () {
37 if (this._title) return this._title
38 if (this.account) return $localize`${this.account.name} (account page)`
39 if (this.channel) return $localize`${this.channel.name} (channel page)`
40
41 return ''
42 }
43
44 get alt () {
45 if (this.account) return $localize`Account avatar`
46 if (this.channel) return $localize`Channel avatar`
47
48 return ''
49 }
50
51 get class () {
52 const base = [ 'avatar' ]
53
54 if (this.size) base.push(`avatar-${this.size}`)
55
56 if (this.account) base.push('account')
57 else base.push('channel')
58
59 if (this.initial) {
60 base.push('initial')
61 base.push(this.getColorTheme())
62 }
63
64 return base
65 }
66
67 get defaultAvatarUrl () {
68 if (this.account) Account.GET_DEFAULT_AVATAR_URL()
69 if (this.channel) return VideoChannel.GET_DEFAULT_AVATAR_URL()
70
71 return ''
72 }
73
74 get avatarUrl () {
75 if (this.account) return Account.GET_ACTOR_AVATAR_URL(this.account)
76 if (this.channel) return VideoChannel.GET_ACTOR_AVATAR_URL(this.account)
77
78 return ''
79 }
80
81 get initial () {
82 const name = this.account?.name
83 if (!name) return ''
84
85 return name.slice(0, 1)
86 }
87
88 hasActor () {
89 return !!this.account || !!this.channel
90 }
91
92 private getColorTheme () {
93 // Keep consistency with CSS
94 const themes = {
95 abc: 'blue',
96 def: 'green',
97 ghi: 'purple',
98 jkl: 'gray',
99 mno: 'yellow',
100 pqr: 'orange',
101 stv: 'red',
102 wxyz: 'dark-blue'
103 }
104
105 const theme = Object.keys(themes)
106 .find(chars => chars.includes(this.initial))
107
108 return themes[theme]
109 }
110}
diff --git a/client/src/app/shared/shared-actor-image/index.ts b/client/src/app/shared/shared-actor-image/index.ts
new file mode 100644
index 000000000..18a9038eb
--- /dev/null
+++ b/client/src/app/shared/shared-actor-image/index.ts
@@ -0,0 +1 @@
export * from './shared-actor-image.module'
diff --git a/client/src/app/shared/shared-account-avatar/shared-account-avatar.module.ts b/client/src/app/shared/shared-actor-image/shared-actor-image.module.ts
index 17b27589f..8ea4bb2bf 100644
--- a/client/src/app/shared/shared-account-avatar/shared-account-avatar.module.ts
+++ b/client/src/app/shared/shared-actor-image/shared-actor-image.module.ts
@@ -2,7 +2,7 @@
2import { NgModule } from '@angular/core' 2import { NgModule } from '@angular/core'
3import { SharedGlobalIconModule } from '../shared-icons' 3import { SharedGlobalIconModule } from '../shared-icons'
4import { SharedMainModule } from '../shared-main/shared-main.module' 4import { SharedMainModule } from '../shared-main/shared-main.module'
5import { AccountAvatarComponent } from './account-avatar.component' 5import { ActorAvatarComponent } from './actor-avatar.component'
6 6
7@NgModule({ 7@NgModule({
8 imports: [ 8 imports: [
@@ -11,13 +11,13 @@ import { AccountAvatarComponent } from './account-avatar.component'
11 ], 11 ],
12 12
13 declarations: [ 13 declarations: [
14 AccountAvatarComponent 14 ActorAvatarComponent
15 ], 15 ],
16 16
17 exports: [ 17 exports: [
18 AccountAvatarComponent 18 ActorAvatarComponent
19 ], 19 ],
20 20
21 providers: [ ] 21 providers: [ ]
22}) 22})
23export class SharedAccountAvatarModule { } 23export class SharedActorImageModule { }
diff --git a/client/src/app/shared/shared-main/users/user-notification.model.ts b/client/src/app/shared/shared-main/users/user-notification.model.ts
index 88a4811da..ed5791794 100644
--- a/client/src/app/shared/shared-main/users/user-notification.model.ts
+++ b/client/src/app/shared/shared-main/users/user-notification.model.ts
@@ -258,10 +258,10 @@ export class UserNotification implements UserNotificationServer {
258 } 258 }
259 259
260 private setAccountAvatarUrl (actor: { avatarUrl?: string, avatar?: { url?: string, path: string } }) { 260 private setAccountAvatarUrl (actor: { avatarUrl?: string, avatar?: { url?: string, path: string } }) {
261 actor.avatarUrl = Account.GET_ACTOR_AVATAR_URL(actor) 261 actor.avatarUrl = Account.GET_ACTOR_AVATAR_URL(actor) || Account.GET_DEFAULT_AVATAR_URL()
262 } 262 }
263 263
264 private setVideoChannelAvatarUrl (actor: { avatarUrl?: string, avatar?: { url?: string, path: string } }) { 264 private setVideoChannelAvatarUrl (actor: { avatarUrl?: string, avatar?: { url?: string, path: string } }) {
265 actor.avatarUrl = VideoChannel.GET_ACTOR_AVATAR_URL(actor) 265 actor.avatarUrl = VideoChannel.GET_ACTOR_AVATAR_URL(actor) || VideoChannel.GET_DEFAULT_AVATAR_URL()
266 } 266 }
267} 267}
diff --git a/client/src/app/shared/shared-main/users/user-notifications.component.scss b/client/src/app/shared/shared-main/users/user-notifications.component.scss
index 5166bd559..fa9c55ec9 100644
--- a/client/src/app/shared/shared-main/users/user-notifications.component.scss
+++ b/client/src/app/shared/shared-main/users/user-notifications.component.scss
@@ -29,8 +29,11 @@
29 } 29 }
30 30
31 .avatar { 31 .avatar {
32 @include avatar(30px); 32 width: 30px;
33 33 height: 30px;
34 min-width: 30px;
35 min-height: 30px;
36 border-radius: 5px;
34 margin-right: 10px; 37 margin-right: 10px;
35 } 38 }
36 39
diff --git a/client/src/app/shared/shared-main/video-channel/video-channel.model.ts b/client/src/app/shared/shared-main/video-channel/video-channel.model.ts
index 1ba3fcc0e..548725e04 100644
--- a/client/src/app/shared/shared-main/video-channel/video-channel.model.ts
+++ b/client/src/app/shared/shared-main/video-channel/video-channel.model.ts
@@ -25,7 +25,7 @@ export class VideoChannel extends Actor implements ServerVideoChannel {
25 viewsPerDay?: ViewsPerDate[] 25 viewsPerDay?: ViewsPerDate[]
26 26
27 static GET_ACTOR_AVATAR_URL (actor: object) { 27 static GET_ACTOR_AVATAR_URL (actor: object) {
28 return Actor.GET_ACTOR_AVATAR_URL(actor) || this.GET_DEFAULT_AVATAR_URL() 28 return Actor.GET_ACTOR_AVATAR_URL(actor)
29 } 29 }
30 30
31 static GET_ACTOR_BANNER_URL (channel: ServerVideoChannel) { 31 static GET_ACTOR_BANNER_URL (channel: ServerVideoChannel) {
diff --git a/client/src/app/shared/shared-moderation/account-blocklist.component.html b/client/src/app/shared/shared-moderation/account-blocklist.component.html
index 3f2f55559..e914a7c3c 100644
--- a/client/src/app/shared/shared-moderation/account-blocklist.component.html
+++ b/client/src/app/shared/shared-moderation/account-blocklist.component.html
@@ -38,7 +38,7 @@
38 <td> 38 <td>
39 <a [href]="accountBlock.blockedAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer"> 39 <a [href]="accountBlock.blockedAccount.url" i18n-title title="Open account in a new tab" target="_blank" rel="noopener noreferrer">
40 <div class="chip two-lines"> 40 <div class="chip two-lines">
41 <my-account-avatar [account]="accountBlock.blockedAccount"></my-account-avatar> 41 <my-actor-avatar [account]="accountBlock.blockedAccount"></my-actor-avatar>
42 <div> 42 <div>
43 {{ accountBlock.blockedAccount.displayName }} 43 {{ accountBlock.blockedAccount.displayName }}
44 <span class="text-muted">{{ accountBlock.blockedAccount.nameWithHost }}</span> 44 <span class="text-muted">{{ accountBlock.blockedAccount.nameWithHost }}</span>
diff --git a/client/src/app/shared/shared-moderation/shared-moderation.module.ts b/client/src/app/shared/shared-moderation/shared-moderation.module.ts
index c7e201792..95213e2bd 100644
--- a/client/src/app/shared/shared-moderation/shared-moderation.module.ts
+++ b/client/src/app/shared/shared-moderation/shared-moderation.module.ts
@@ -13,7 +13,7 @@ import { UserBanModalComponent } from './user-ban-modal.component'
13import { UserModerationDropdownComponent } from './user-moderation-dropdown.component' 13import { UserModerationDropdownComponent } from './user-moderation-dropdown.component'
14import { VideoBlockComponent } from './video-block.component' 14import { VideoBlockComponent } from './video-block.component'
15import { VideoBlockService } from './video-block.service' 15import { VideoBlockService } from './video-block.service'
16import { SharedAccountAvatarModule } from '../shared-account-avatar/shared-account-avatar.module' 16import { SharedActorImageModule } from '../shared-actor-image/shared-actor-image.module'
17 17
18@NgModule({ 18@NgModule({
19 imports: [ 19 imports: [
@@ -21,7 +21,7 @@ import { SharedAccountAvatarModule } from '../shared-account-avatar/shared-accou
21 SharedFormModule, 21 SharedFormModule,
22 SharedGlobalIconModule, 22 SharedGlobalIconModule,
23 SharedVideoCommentModule, 23 SharedVideoCommentModule,
24 SharedAccountAvatarModule 24 SharedActorImageModule
25 ], 25 ],
26 26
27 declarations: [ 27 declarations: [
diff --git a/client/src/app/shared/shared-video-miniature/shared-video-miniature.module.ts b/client/src/app/shared/shared-video-miniature/shared-video-miniature.module.ts
index 32cfdfd68..03be6d2ff 100644
--- a/client/src/app/shared/shared-video-miniature/shared-video-miniature.module.ts
+++ b/client/src/app/shared/shared-video-miniature/shared-video-miniature.module.ts
@@ -13,7 +13,7 @@ import { VideoDownloadComponent } from './video-download.component'
13import { VideoMiniatureComponent } from './video-miniature.component' 13import { VideoMiniatureComponent } from './video-miniature.component'
14import { VideosSelectionComponent } from './videos-selection.component' 14import { VideosSelectionComponent } from './videos-selection.component'
15import { VideoListHeaderComponent } from './video-list-header.component' 15import { VideoListHeaderComponent } from './video-list-header.component'
16import { SharedAccountAvatarModule } from '../shared-account-avatar/shared-account-avatar.module' 16import { SharedActorImageModule } from '../shared-actor-image/shared-actor-image.module'
17 17
18@NgModule({ 18@NgModule({
19 imports: [ 19 imports: [
@@ -25,7 +25,7 @@ import { SharedAccountAvatarModule } from '../shared-account-avatar/shared-accou
25 SharedGlobalIconModule, 25 SharedGlobalIconModule,
26 SharedVideoLiveModule, 26 SharedVideoLiveModule,
27 SharedVideoModule, 27 SharedVideoModule,
28 SharedAccountAvatarModule 28 SharedActorImageModule
29 ], 29 ],
30 30
31 declarations: [ 31 declarations: [
diff --git a/client/src/app/shared/shared-video-miniature/video-miniature.component.html b/client/src/app/shared/shared-video-miniature/video-miniature.component.html
index bc19127aa..7c4fcc491 100644
--- a/client/src/app/shared/shared-video-miniature/video-miniature.component.html
+++ b/client/src/app/shared/shared-video-miniature/video-miniature.component.html
@@ -10,14 +10,15 @@
10 <div class="video-bottom"> 10 <div class="video-bottom">
11 <div class="video-miniature-information"> 11 <div class="video-miniature-information">
12 <div class="d-flex video-miniature-meta"> 12 <div class="d-flex video-miniature-meta">
13 <a *ngIf="displayOptions.avatar && displayOwnerVideoChannel()" class="channel-avatar" [routerLink]="[ '/video-channels', video.byVideoChannel ]" [title]="channelLinkTitle"> 13 <my-actor-avatar
14 <img [src]="getAvatarUrl()" alt="" /> 14 *ngIf="displayOptions.avatar && displayOwnerVideoChannel()" [title]="channelLinkTitle"
15 </a> 15 [channel]="video.channel" size="40" [internalHref]="[ '/video-channels', video.byVideoChannel ]"
16 ></my-actor-avatar>
16 17
17 <my-account-avatar 18 <my-actor-avatar
18 *ngIf="displayOptions.avatar && displayOwnerAccount()" [title]="channelLinkTitle" 19 *ngIf="displayOptions.avatar && displayOwnerAccount()" [title]="channelLinkTitle"
19 [account]="video.account" size="40" [internalHref]="'/video-channels/' + video.byVideoChannel" 20 [account]="video.account" size="40" [internalHref]="[ '/video-channels', video.byVideoChannel ]"
20 ></my-account-avatar> 21 ></my-actor-avatar>
21 22
22 <div class="w-100 d-flex flex-column"> 23 <div class="w-100 d-flex flex-column">
23 <a *ngIf="!videoHref" tabindex="-1" class="video-miniature-name" 24 <a *ngIf="!videoHref" tabindex="-1" class="video-miniature-name"
diff --git a/client/src/app/shared/shared-video-miniature/video-miniature.component.scss b/client/src/app/shared/shared-video-miniature/video-miniature.component.scss
index f6f2925f0..c142e2e93 100644
--- a/client/src/app/shared/shared-video-miniature/video-miniature.component.scss
+++ b/client/src/app/shared/shared-video-miniature/video-miniature.component.scss
@@ -12,15 +12,10 @@ $more-button-width: 40px;
12 width: calc(100% - #{$more-button-width}); 12 width: calc(100% - #{$more-button-width});
13} 13}
14 14
15my-account-avatar, 15my-actor-avatar {
16.channel-avatar {
17 margin: 10px 10px 0 0; 16 margin: 10px 10px 0 0;
18} 17}
19 18
20.channel-avatar img{
21 @include channel-avatar(40px);
22}
23
24.video-miniature-created-at-views { 19.video-miniature-created-at-views {
25 font-size: 13px; 20 font-size: 13px;
26} 21}