]>
Commit | Line | Data |
---|---|---|
1 | import { Component, Input, OnChanges } from '@angular/core' | |
2 | import { VideoChannel } from '../shared-main' | |
3 | import { Account } from '../shared-main/account/account.model' | |
4 | ||
5 | type ActorInput = { | |
6 | name: string | |
7 | avatars: { width: number, url?: string, path: string }[] | |
8 | url: string | |
9 | } | |
10 | ||
11 | export type ActorAvatarSize = '18' | '25' | '28' | '32' | '34' | '35' | '36' | '40' | '48' | '75' | '80' | '100' | '120' | |
12 | ||
13 | @Component({ | |
14 | selector: 'my-actor-avatar', | |
15 | styleUrls: [ './actor-avatar.component.scss' ], | |
16 | templateUrl: './actor-avatar.component.html' | |
17 | }) | |
18 | export class ActorAvatarComponent implements OnChanges { | |
19 | private _title: string | |
20 | ||
21 | @Input() actor: ActorInput | |
22 | @Input() actorType: 'channel' | 'account' | 'unlogged' | |
23 | ||
24 | @Input() previewImage: string | |
25 | ||
26 | @Input() size: ActorAvatarSize | |
27 | ||
28 | // Use an external link | |
29 | @Input() href: string | |
30 | // Use routerLink | |
31 | @Input() internalHref: string | any[] | |
32 | ||
33 | @Input() set title (value) { | |
34 | this._title = value | |
35 | } | |
36 | ||
37 | get title () { | |
38 | if (this._title) return this._title | |
39 | if (this.isAccount()) return $localize`${this.actor.name} (account page)` | |
40 | if (this.isChannel()) return $localize`${this.actor.name} (channel page)` | |
41 | ||
42 | return '' | |
43 | } | |
44 | ||
45 | classes: string[] = [] | |
46 | ||
47 | get alt () { | |
48 | if (this.isAccount()) return $localize`Account avatar` | |
49 | if (this.isChannel()) return $localize`Channel avatar` | |
50 | ||
51 | return '' | |
52 | } | |
53 | ||
54 | get defaultAvatarUrl () { | |
55 | if (this.isChannel()) return VideoChannel.GET_DEFAULT_AVATAR_URL(this.getSizeNumber()) | |
56 | ||
57 | // account or unlogged | |
58 | return Account.GET_DEFAULT_AVATAR_URL(this.getSizeNumber()) | |
59 | } | |
60 | ||
61 | get avatarUrl () { | |
62 | if (!this.actor) return '' | |
63 | ||
64 | if (this.isAccount()) return Account.GET_ACTOR_AVATAR_URL(this.actor, this.getSizeNumber()) | |
65 | if (this.isChannel()) return VideoChannel.GET_ACTOR_AVATAR_URL(this.actor, this.getSizeNumber()) | |
66 | ||
67 | return '' | |
68 | } | |
69 | ||
70 | ngOnChanges () { | |
71 | this.classes = [ 'avatar' ] | |
72 | ||
73 | if (this.size) { | |
74 | this.classes.push(`avatar-${this.size}`) | |
75 | } | |
76 | ||
77 | if (this.isChannel()) { | |
78 | this.classes.push('channel') | |
79 | } else { | |
80 | this.classes.push('account') | |
81 | } | |
82 | ||
83 | // No avatar, use actor name initial | |
84 | if (this.displayActorInitial()) { | |
85 | this.classes.push('initial') | |
86 | this.classes.push(this.getColorTheme()) | |
87 | } | |
88 | } | |
89 | ||
90 | displayImage () { | |
91 | if (this.actorType === 'unlogged') return true | |
92 | ||
93 | return !!(this.actor && this.avatarUrl) | |
94 | } | |
95 | ||
96 | displayActorInitial () { | |
97 | return this.actor && !this.avatarUrl | |
98 | } | |
99 | ||
100 | displayPlaceholder () { | |
101 | return this.actorType !== 'unlogged' && !this.actor | |
102 | } | |
103 | ||
104 | getActorInitial () { | |
105 | const name = this.actor?.name | |
106 | if (!name) return '' | |
107 | ||
108 | return name.slice(0, 1) | |
109 | } | |
110 | ||
111 | private isAccount () { | |
112 | return this.actorType === 'account' | |
113 | } | |
114 | ||
115 | private isChannel () { | |
116 | return this.actorType === 'channel' | |
117 | } | |
118 | ||
119 | private getSizeNumber () { | |
120 | if (this.size) return +this.size | |
121 | ||
122 | return undefined | |
123 | } | |
124 | ||
125 | private getColorTheme () { | |
126 | const initialLowercase = this.getActorInitial().toLowerCase() | |
127 | ||
128 | // Keep consistency with CSS | |
129 | const themes = { | |
130 | '0123456789abc': 'blue', | |
131 | def: 'green', | |
132 | ghi: 'purple', | |
133 | jkl: 'gray', | |
134 | mno: 'yellow', | |
135 | pqr: 'orange', | |
136 | stvu: 'red', | |
137 | wxyz: 'dark-blue' | |
138 | } | |
139 | ||
140 | const theme = Object.keys(themes) | |
141 | .find(chars => chars.includes(initialLowercase)) | |
142 | ||
143 | return themes[theme] | |
144 | } | |
145 | } |