aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app
diff options
context:
space:
mode:
authorChocobozzz <me@florianbigard.com>2021-04-08 12:09:54 +0200
committerChocobozzz <me@florianbigard.com>2021-04-08 13:38:04 +0200
commit27ec473f5306621643fcb169be7cfe6b15136265 (patch)
treebc4a8d81c5baa58ae1af6434731644da7c2df109 /client/src/app
parent84531547bc0934a2abda586d539f7455b455d488 (diff)
downloadPeerTube-27ec473f5306621643fcb169be7cfe6b15136265.tar.gz
PeerTube-27ec473f5306621643fcb169be7cfe6b15136265.tar.zst
PeerTube-27ec473f5306621643fcb169be7cfe6b15136265.zip
Set channel banner/avatar in creation form
Diffstat (limited to 'client/src/app')
-rw-r--r--client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts70
-rw-r--r--client/src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html28
-rw-r--r--client/src/app/+my-library/+my-video-channels/my-video-channel-edit.ts9
-rw-r--r--client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts22
-rw-r--r--client/src/app/shared/shared-actor-image/actor-avatar-edit.component.html2
-rw-r--r--client/src/app/shared/shared-actor-image/actor-avatar-edit.component.ts12
-rw-r--r--client/src/app/shared/shared-actor-image/actor-banner-edit.component.html2
-rw-r--r--client/src/app/shared/shared-actor-image/actor-banner-edit.component.ts12
-rw-r--r--client/src/app/shared/shared-main/account/actor.model.ts8
-rw-r--r--client/src/app/shared/shared-main/video-channel/video-channel.model.ts4
10 files changed, 112 insertions, 57 deletions
diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts b/client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts
index a625493de..b3265210f 100644
--- a/client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts
+++ b/client/src/app/+my-library/+my-video-channels/my-video-channel-create.component.ts
@@ -8,10 +8,12 @@ import {
8 VIDEO_CHANNEL_SUPPORT_VALIDATOR 8 VIDEO_CHANNEL_SUPPORT_VALIDATOR
9} from '@app/shared/form-validators/video-channel-validators' 9} from '@app/shared/form-validators/video-channel-validators'
10import { FormValidatorService } from '@app/shared/shared-forms' 10import { FormValidatorService } from '@app/shared/shared-forms'
11import { VideoChannelService } from '@app/shared/shared-main' 11import { VideoChannel, VideoChannelService } from '@app/shared/shared-main'
12import { VideoChannelCreate } from '@shared/models' 12import { VideoChannelCreate } from '@shared/models'
13import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' 13import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes'
14import { MyVideoChannelEdit } from './my-video-channel-edit' 14import { MyVideoChannelEdit } from './my-video-channel-edit'
15import { switchMap } from 'rxjs/operators'
16import { of } from 'rxjs'
15 17
16@Component({ 18@Component({
17 templateUrl: './my-video-channel-edit.component.html', 19 templateUrl: './my-video-channel-edit.component.html',
@@ -19,6 +21,10 @@ import { MyVideoChannelEdit } from './my-video-channel-edit'
19}) 21})
20export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements OnInit { 22export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements OnInit {
21 error: string 23 error: string
24 videoChannel = new VideoChannel({})
25
26 private avatar: FormData
27 private banner: FormData
22 28
23 constructor ( 29 constructor (
24 protected formValidatorService: FormValidatorService, 30 protected formValidatorService: FormValidatorService,
@@ -50,23 +56,43 @@ export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements
50 support: body.support || null 56 support: body.support || null
51 } 57 }
52 58
53 this.videoChannelService.createVideoChannel(videoChannelCreate).subscribe( 59 this.videoChannelService.createVideoChannel(videoChannelCreate)
54 () => { 60 .pipe(
55 this.authService.refreshUserInformation() 61 switchMap(() => this.uploadAvatar()),
62 switchMap(() => this.uploadBanner())
63 ).subscribe(
64 () => {
65 this.authService.refreshUserInformation()
66
67 this.notifier.success($localize`Video channel ${videoChannelCreate.displayName} created.`)
68 this.router.navigate(['/my-library', 'video-channels'])
69 },
56 70
57 this.notifier.success($localize`Video channel ${videoChannelCreate.displayName} created.`) 71 err => {
58 this.router.navigate([ '/my-library', 'video-channels' ]) 72 if (err.status === HttpStatusCode.CONFLICT_409) {
59 }, 73 this.error = $localize`This name already exists on this instance.`
74 return
75 }
60 76
61 err => { 77 this.error = err.message
62 if (err.status === HttpStatusCode.CONFLICT_409) {
63 this.error = $localize`This name already exists on this instance.`
64 return
65 } 78 }
79 )
80 }
81
82 onAvatarChange (formData: FormData) {
83 this.avatar = formData
84 }
85
86 onAvatarDelete () {
87 this.avatar = null
88 }
89
90 onBannerChange (formData: FormData) {
91 this.banner = formData
92 }
66 93
67 this.error = err.message 94 onBannerDelete () {
68 } 95 this.banner = null
69 )
70 } 96 }
71 97
72 isCreation () { 98 isCreation () {
@@ -76,4 +102,20 @@ export class MyVideoChannelCreateComponent extends MyVideoChannelEdit implements
76 getFormButtonTitle () { 102 getFormButtonTitle () {
77 return $localize`Create` 103 return $localize`Create`
78 } 104 }
105
106 getUsername () {
107 return this.form.value.name
108 }
109
110 private uploadAvatar () {
111 if (!this.avatar) return of(undefined)
112
113 return this.videoChannelService.changeVideoChannelImage(this.getUsername(), this.avatar, 'avatar')
114 }
115
116 private uploadBanner () {
117 if (!this.banner) return of(undefined)
118
119 return this.videoChannelService.changeVideoChannelImage(this.getUsername(), this.banner, 'banner')
120 }
79} 121}
diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html b/client/src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html
index 7b8928907..2910dffad 100644
--- a/client/src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html
+++ b/client/src/app/+my-library/+my-video-channels/my-video-channel-edit.component.html
@@ -10,7 +10,7 @@
10 <ng-container *ngIf="!isCreation()"> 10 <ng-container *ngIf="!isCreation()">
11 <li class="breadcrumb-item active" i18n>Edit</li> 11 <li class="breadcrumb-item active" i18n>Edit</li>
12 <li class="breadcrumb-item active" aria-current="page"> 12 <li class="breadcrumb-item active" aria-current="page">
13 <a *ngIf="videoChannelToUpdate" [routerLink]="[ '/my-library/video-channels/update', videoChannelToUpdate?.nameWithHost ]">{{ videoChannelToUpdate?.displayName }}</a> 13 <a *ngIf="videoChannel" [routerLink]="[ '/my-library/video-channels/update', videoChannel?.nameWithHost ]">{{ videoChannel?.displayName }}</a>
14 </li> 14 </li>
15 </ng-container> 15 </ng-container>
16 </ol> 16 </ol>
@@ -23,10 +23,22 @@
23 <div class="form-row"> <!-- channel grid --> 23 <div class="form-row"> <!-- channel grid -->
24 <div class="form-group col-12 col-lg-4 col-xl-3"> 24 <div class="form-group col-12 col-lg-4 col-xl-3">
25 <div *ngIf="isCreation()" class="video-channel-title" i18n>NEW CHANNEL</div> 25 <div *ngIf="isCreation()" class="video-channel-title" i18n>NEW CHANNEL</div>
26 <div *ngIf="!isCreation() && videoChannelToUpdate" class="video-channel-title" i18n>CHANNEL</div> 26 <div *ngIf="!isCreation() && videoChannel" class="video-channel-title" i18n>CHANNEL</div>
27 </div> 27 </div>
28 28
29 <div class="form-group col-12 col-lg-8 col-xl-9"> 29 <div class="form-group col-12 col-lg-8 col-xl-9">
30 <h6 i18n>Banner image of your channel</h6>
31
32 <my-actor-banner-edit
33 *ngIf="videoChannel" [previewImage]="isCreation()"
34 [actor]="videoChannel" (bannerChange)="onBannerChange($event)" (bannerDelete)="onBannerDelete()"
35 ></my-actor-banner-edit>
36
37 <my-actor-avatar-edit
38 *ngIf="videoChannel" [previewImage]="isCreation()"
39 [actor]="videoChannel" (avatarChange)="onAvatarChange($event)" (avatarDelete)="onAvatarDelete()"
40 [displayUsername]="!isCreation()" [displaySubscribers]="!isCreation()"
41 ></my-actor-avatar-edit>
30 42
31 <div class="form-group" *ngIf="isCreation()"> 43 <div class="form-group" *ngIf="isCreation()">
32 <label i18n for="name">Name</label> 44 <label i18n for="name">Name</label>
@@ -44,18 +56,6 @@
44 </div> 56 </div>
45 </div> 57 </div>
46 58
47 <h6 i18n>Banner image of your channel</h6>
48
49 <my-actor-banner-edit
50 *ngIf="!isCreation() && videoChannelToUpdate"
51 [actor]="videoChannelToUpdate" (bannerChange)="onBannerChange($event)" (bannerDelete)="onBannerDelete()"
52 ></my-actor-banner-edit>
53
54 <my-actor-avatar-edit
55 *ngIf="!isCreation() && videoChannelToUpdate"
56 [actor]="videoChannelToUpdate" (avatarChange)="onAvatarChange($event)" (avatarDelete)="onAvatarDelete()"
57 ></my-actor-avatar-edit>
58
59 <div class="form-group"> 59 <div class="form-group">
60 <label i18n for="display-name">Display name</label> 60 <label i18n for="display-name">Display name</label>
61 <input 61 <input
diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channel-edit.ts b/client/src/app/+my-library/+my-video-channels/my-video-channel-edit.ts
index 0cdf2fe34..33bb90f14 100644
--- a/client/src/app/+my-library/+my-video-channels/my-video-channel-edit.ts
+++ b/client/src/app/+my-library/+my-video-channels/my-video-channel-edit.ts
@@ -2,8 +2,7 @@ import { FormReactive } from '@app/shared/shared-forms'
2import { VideoChannel } from '@app/shared/shared-main' 2import { VideoChannel } from '@app/shared/shared-main'
3 3
4export abstract class MyVideoChannelEdit extends FormReactive { 4export abstract class MyVideoChannelEdit extends FormReactive {
5 // We need it even in the create component because it's used in the edit template 5 videoChannel: VideoChannel
6 videoChannelToUpdate: VideoChannel
7 6
8 abstract isCreation (): boolean 7 abstract isCreation (): boolean
9 abstract getFormButtonTitle (): string 8 abstract getFormButtonTitle (): string
@@ -12,12 +11,6 @@ export abstract class MyVideoChannelEdit extends FormReactive {
12 return window.location.host 11 return window.location.host
13 } 12 }
14 13
15 // We need this method so angular does not complain in child template that doesn't need this
16 onAvatarChange (formData: FormData) { /* empty */ }
17 onAvatarDelete () { /* empty */ }
18 onBannerChange (formData: FormData) { /* empty */ }
19 onBannerDelete () { /* empty */ }
20
21 // Should be implemented by the child 14 // Should be implemented by the child
22 isBulkUpdateVideosDisplayed () { 15 isBulkUpdateVideosDisplayed () {
23 return false 16 return false
diff --git a/client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts b/client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts
index 22935a87a..a29af176c 100644
--- a/client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts
+++ b/client/src/app/+my-library/+my-video-channels/my-video-channel-update.component.ts
@@ -21,7 +21,7 @@ import { MyVideoChannelEdit } from './my-video-channel-edit'
21}) 21})
22export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements OnInit, OnDestroy { 22export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements OnInit, OnDestroy {
23 error: string 23 error: string
24 videoChannelToUpdate: VideoChannel 24 videoChannel: VideoChannel
25 25
26 private paramsSub: Subscription 26 private paramsSub: Subscription
27 private oldSupportField: string 27 private oldSupportField: string
@@ -56,7 +56,7 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
56 56
57 this.videoChannelService.getVideoChannel(videoChannelId).subscribe( 57 this.videoChannelService.getVideoChannel(videoChannelId).subscribe(
58 videoChannelToUpdate => { 58 videoChannelToUpdate => {
59 this.videoChannelToUpdate = videoChannelToUpdate 59 this.videoChannel = videoChannelToUpdate
60 60
61 this.oldSupportField = videoChannelToUpdate.support 61 this.oldSupportField = videoChannelToUpdate.support
62 62
@@ -87,7 +87,7 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
87 bulkVideosSupportUpdate: body.bulkVideosSupportUpdate || false 87 bulkVideosSupportUpdate: body.bulkVideosSupportUpdate || false
88 } 88 }
89 89
90 this.videoChannelService.updateVideoChannel(this.videoChannelToUpdate.name, videoChannelUpdate).subscribe( 90 this.videoChannelService.updateVideoChannel(this.videoChannel.name, videoChannelUpdate).subscribe(
91 () => { 91 () => {
92 this.authService.refreshUserInformation() 92 this.authService.refreshUserInformation()
93 93
@@ -101,12 +101,12 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
101 } 101 }
102 102
103 onAvatarChange (formData: FormData) { 103 onAvatarChange (formData: FormData) {
104 this.videoChannelService.changeVideoChannelImage(this.videoChannelToUpdate.name, formData, 'avatar') 104 this.videoChannelService.changeVideoChannelImage(this.videoChannel.name, formData, 'avatar')
105 .subscribe( 105 .subscribe(
106 data => { 106 data => {
107 this.notifier.success($localize`Avatar changed.`) 107 this.notifier.success($localize`Avatar changed.`)
108 108
109 this.videoChannelToUpdate.updateAvatar(data.avatar) 109 this.videoChannel.updateAvatar(data.avatar)
110 }, 110 },
111 111
112 (err: HttpErrorResponse) => uploadErrorHandler({ 112 (err: HttpErrorResponse) => uploadErrorHandler({
@@ -118,12 +118,12 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
118 } 118 }
119 119
120 onAvatarDelete () { 120 onAvatarDelete () {
121 this.videoChannelService.deleteVideoChannelImage(this.videoChannelToUpdate.name, 'avatar') 121 this.videoChannelService.deleteVideoChannelImage(this.videoChannel.name, 'avatar')
122 .subscribe( 122 .subscribe(
123 data => { 123 data => {
124 this.notifier.success($localize`Avatar deleted.`) 124 this.notifier.success($localize`Avatar deleted.`)
125 125
126 this.videoChannelToUpdate.resetAvatar() 126 this.videoChannel.resetAvatar()
127 }, 127 },
128 128
129 err => this.notifier.error(err.message) 129 err => this.notifier.error(err.message)
@@ -131,12 +131,12 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
131 } 131 }
132 132
133 onBannerChange (formData: FormData) { 133 onBannerChange (formData: FormData) {
134 this.videoChannelService.changeVideoChannelImage(this.videoChannelToUpdate.name, formData, 'banner') 134 this.videoChannelService.changeVideoChannelImage(this.videoChannel.name, formData, 'banner')
135 .subscribe( 135 .subscribe(
136 data => { 136 data => {
137 this.notifier.success($localize`Banner changed.`) 137 this.notifier.success($localize`Banner changed.`)
138 138
139 this.videoChannelToUpdate.updateBanner(data.banner) 139 this.videoChannel.updateBanner(data.banner)
140 }, 140 },
141 141
142 (err: HttpErrorResponse) => uploadErrorHandler({ 142 (err: HttpErrorResponse) => uploadErrorHandler({
@@ -148,12 +148,12 @@ export class MyVideoChannelUpdateComponent extends MyVideoChannelEdit implements
148 } 148 }
149 149
150 onBannerDelete () { 150 onBannerDelete () {
151 this.videoChannelService.deleteVideoChannelImage(this.videoChannelToUpdate.name, 'banner') 151 this.videoChannelService.deleteVideoChannelImage(this.videoChannel.name, 'banner')
152 .subscribe( 152 .subscribe(
153 data => { 153 data => {
154 this.notifier.success($localize`Banner deleted.`) 154 this.notifier.success($localize`Banner deleted.`)
155 155
156 this.videoChannelToUpdate.resetBanner() 156 this.videoChannel.resetBanner()
157 }, 157 },
158 158
159 err => this.notifier.error(err.message) 159 err => this.notifier.error(err.message)
diff --git a/client/src/app/shared/shared-actor-image/actor-avatar-edit.component.html b/client/src/app/shared/shared-actor-image/actor-avatar-edit.component.html
index 10f2ef262..0829263f4 100644
--- a/client/src/app/shared/shared-actor-image/actor-avatar-edit.component.html
+++ b/client/src/app/shared/shared-actor-image/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]="actor.avatarUrl" alt="Avatar" /> 3 <img [ngClass]="{ channel: isChannel() }" [src]="preview || actor.avatarUrl" alt="Avatar" />
4 4
5 <div class="actor-img-edit-container"> 5 <div class="actor-img-edit-container">
6 6
diff --git a/client/src/app/shared/shared-actor-image/actor-avatar-edit.component.ts b/client/src/app/shared/shared-actor-image/actor-avatar-edit.component.ts
index 6f76172e9..d0d269489 100644
--- a/client/src/app/shared/shared-actor-image/actor-avatar-edit.component.ts
+++ b/client/src/app/shared/shared-actor-image/actor-avatar-edit.component.ts
@@ -1,4 +1,5 @@
1import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core' 1import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core'
2import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'
2import { Notifier, ServerService } from '@app/core' 3import { Notifier, ServerService } from '@app/core'
3import { Account, VideoChannel } from '@app/shared/shared-main' 4import { Account, VideoChannel } from '@app/shared/shared-main'
4import { NgbPopover } from '@ng-bootstrap/ng-bootstrap' 5import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
@@ -20,6 +21,7 @@ export class ActorAvatarEditComponent implements OnInit {
20 @Input() editable = true 21 @Input() editable = true
21 @Input() displaySubscribers = true 22 @Input() displaySubscribers = true
22 @Input() displayUsername = true 23 @Input() displayUsername = true
24 @Input() previewImage = false
23 25
24 @Output() avatarChange = new EventEmitter<FormData>() 26 @Output() avatarChange = new EventEmitter<FormData>()
25 @Output() avatarDelete = new EventEmitter<void>() 27 @Output() avatarDelete = new EventEmitter<void>()
@@ -28,7 +30,10 @@ export class ActorAvatarEditComponent implements OnInit {
28 maxAvatarSize = 0 30 maxAvatarSize = 0
29 avatarExtensions = '' 31 avatarExtensions = ''
30 32
33 preview: SafeResourceUrl
34
31 constructor ( 35 constructor (
36 private sanitizer: DomSanitizer,
32 private serverService: ServerService, 37 private serverService: ServerService,
33 private notifier: Notifier 38 private notifier: Notifier
34 ) { } 39 ) { }
@@ -57,14 +62,19 @@ export class ActorAvatarEditComponent implements OnInit {
57 formData.append('avatarfile', avatarfile) 62 formData.append('avatarfile', avatarfile)
58 this.avatarPopover?.close() 63 this.avatarPopover?.close()
59 this.avatarChange.emit(formData) 64 this.avatarChange.emit(formData)
65
66 if (this.previewImage) {
67 this.preview = this.sanitizer.bypassSecurityTrustResourceUrl(URL.createObjectURL(avatarfile))
68 }
60 } 69 }
61 70
62 deleteAvatar () { 71 deleteAvatar () {
72 this.preview = undefined
63 this.avatarDelete.emit() 73 this.avatarDelete.emit()
64 } 74 }
65 75
66 hasAvatar () { 76 hasAvatar () {
67 return !!this.actor.avatar 77 return !!this.preview || !!this.actor.avatar
68 } 78 }
69 79
70 isChannel () { 80 isChannel () {
diff --git a/client/src/app/shared/shared-actor-image/actor-banner-edit.component.html b/client/src/app/shared/shared-actor-image/actor-banner-edit.component.html
index eb1b66422..266fc26c5 100644
--- a/client/src/app/shared/shared-actor-image/actor-banner-edit.component.html
+++ b/client/src/app/shared/shared-actor-image/actor-banner-edit.component.html
@@ -1,7 +1,7 @@
1<div class="actor" *ngIf="actor"> 1<div class="actor" *ngIf="actor">
2 <div class="actor-img-edit-container"> 2 <div class="actor-img-edit-container">
3 <div class="banner-placeholder"> 3 <div class="banner-placeholder">
4 <img *ngIf="hasBanner()" [src]="actor.bannerUrl" alt="Banner" /> 4 <img *ngIf="hasBanner()" [src]="preview || actor.bannerUrl" alt="Banner" />
5 </div> 5 </div>
6 6
7 <div *ngIf="!hasBanner()" class="actor-img-edit-button" [ngbTooltip]="bannerFormat" placement="right" container="body"> 7 <div *ngIf="!hasBanner()" class="actor-img-edit-button" [ngbTooltip]="bannerFormat" placement="right" container="body">
diff --git a/client/src/app/shared/shared-actor-image/actor-banner-edit.component.ts b/client/src/app/shared/shared-actor-image/actor-banner-edit.component.ts
index 48451744c..8c12d3c4c 100644
--- a/client/src/app/shared/shared-actor-image/actor-banner-edit.component.ts
+++ b/client/src/app/shared/shared-actor-image/actor-banner-edit.component.ts
@@ -1,4 +1,5 @@
1import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core' 1import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild } from '@angular/core'
2import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser'
2import { Notifier, ServerService } from '@app/core' 3import { Notifier, ServerService } from '@app/core'
3import { VideoChannel } from '@app/shared/shared-main' 4import { VideoChannel } from '@app/shared/shared-main'
4import { NgbPopover } from '@ng-bootstrap/ng-bootstrap' 5import { NgbPopover } from '@ng-bootstrap/ng-bootstrap'
@@ -17,6 +18,7 @@ export class ActorBannerEditComponent implements OnInit {
17 @ViewChild('bannerPopover') bannerPopover: NgbPopover 18 @ViewChild('bannerPopover') bannerPopover: NgbPopover
18 19
19 @Input() actor: VideoChannel 20 @Input() actor: VideoChannel
21 @Input() previewImage = false
20 22
21 @Output() bannerChange = new EventEmitter<FormData>() 23 @Output() bannerChange = new EventEmitter<FormData>()
22 @Output() bannerDelete = new EventEmitter<void>() 24 @Output() bannerDelete = new EventEmitter<void>()
@@ -25,7 +27,10 @@ export class ActorBannerEditComponent implements OnInit {
25 maxBannerSize = 0 27 maxBannerSize = 0
26 bannerExtensions = '' 28 bannerExtensions = ''
27 29
30 preview: SafeResourceUrl
31
28 constructor ( 32 constructor (
33 private sanitizer: DomSanitizer,
29 private serverService: ServerService, 34 private serverService: ServerService,
30 private notifier: Notifier 35 private notifier: Notifier
31 ) { } 36 ) { }
@@ -54,13 +59,18 @@ export class ActorBannerEditComponent implements OnInit {
54 formData.append('bannerfile', bannerfile) 59 formData.append('bannerfile', bannerfile)
55 this.bannerPopover?.close() 60 this.bannerPopover?.close()
56 this.bannerChange.emit(formData) 61 this.bannerChange.emit(formData)
62
63 if (this.previewImage) {
64 this.preview = this.sanitizer.bypassSecurityTrustResourceUrl(URL.createObjectURL(bannerfile))
65 }
57 } 66 }
58 67
59 deleteBanner () { 68 deleteBanner () {
69 this.preview = undefined
60 this.bannerDelete.emit() 70 this.bannerDelete.emit()
61 } 71 }
62 72
63 hasBanner () { 73 hasBanner () {
64 return !!this.actor.bannerUrl 74 return !!this.preview || !!this.actor.bannerUrl
65 } 75 }
66} 76}
diff --git a/client/src/app/shared/shared-main/account/actor.model.ts b/client/src/app/shared/shared-main/account/actor.model.ts
index 670823060..1ee0c297e 100644
--- a/client/src/app/shared/shared-main/account/actor.model.ts
+++ b/client/src/app/shared/shared-main/account/actor.model.ts
@@ -47,11 +47,11 @@ export abstract class Actor implements ActorServer {
47 return host.trim() === thisHost 47 return host.trim() === thisHost
48 } 48 }
49 49
50 protected constructor (hash: ActorServer) { 50 protected constructor (hash: Partial<ActorServer>) {
51 this.id = hash.id 51 this.id = hash.id
52 this.url = hash.url 52 this.url = hash.url ?? ''
53 this.name = hash.name 53 this.name = hash.name ?? ''
54 this.host = hash.host 54 this.host = hash.host ?? ''
55 this.followingCount = hash.followingCount 55 this.followingCount = hash.followingCount
56 this.followersCount = hash.followersCount 56 this.followersCount = hash.followersCount
57 57
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 d8be42eef..1ba3fcc0e 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
@@ -44,7 +44,7 @@ export class VideoChannel extends Actor implements ServerVideoChannel {
44 return `${window.location.origin}/client/assets/images/default-avatar-videochannel.png` 44 return `${window.location.origin}/client/assets/images/default-avatar-videochannel.png`
45 } 45 }
46 46
47 constructor (hash: ServerVideoChannel) { 47 constructor (hash: Partial<ServerVideoChannel>) {
48 super(hash) 48 super(hash)
49 49
50 this.displayName = hash.displayName 50 this.displayName = hash.displayName
@@ -93,7 +93,7 @@ export class VideoChannel extends Actor implements ServerVideoChannel {
93 this.updateBanner(null) 93 this.updateBanner(null)
94 } 94 }
95 95
96 private updateComputedAttributes () { 96 updateComputedAttributes () {
97 this.avatarUrl = VideoChannel.GET_ACTOR_AVATAR_URL(this) 97 this.avatarUrl = VideoChannel.GET_ACTOR_AVATAR_URL(this)
98 this.bannerUrl = VideoChannel.GET_ACTOR_BANNER_URL(this) 98 this.bannerUrl = VideoChannel.GET_ACTOR_BANNER_URL(this)
99 } 99 }