1- import { ChangeDetectionStrategy , Component , NgZone , OnDestroy } from '@angular/core' ;
2- import { BehaviorSubject , Observable , Subscription } from 'rxjs' ;
1+ import {
2+ ChangeDetectionStrategy ,
3+ Component ,
4+ NgZone ,
5+ OnDestroy ,
6+ } from '@angular/core' ;
7+ import { DomSanitizer , SafeUrl } from '@angular/platform-browser' ;
8+ import { BehaviorSubject , Observable , Subscription , combineLatest } from 'rxjs' ;
39import { filter , map , pluck , startWith } from 'rxjs/operators' ;
410import { Player } from 'src/app/models/player' ;
511import { ClientService } from 'src/app/services/client.service' ;
@@ -15,14 +21,26 @@ import { PlayerListService } from 'src/app/services/player-list.service';
1521} )
1622export class PartyMenuComponent implements OnDestroy {
1723 isLoading$ = this . loadingService . getLoading ( ) ;
18- members$ = this . groupService . selectMembers ( ) ;
24+ members$ = combineLatest ( [
25+ this . groupService . selectMembers ( ) ,
26+ this . clientService . localPlayerIdChange ,
27+ ] ) . pipe (
28+ map ( ( [ members , localId ] ) =>
29+ members . filter ( member => member . id !== localId ) ,
30+ ) ,
31+ ) ;
1932 memberCount$ = this . groupService . selectMembersLength ( true ) ;
2033 group$ = this . groupService . group . asObservable ( ) ;
2134 isLaunchPartyDisabled$ : Observable < boolean > ;
2235 invitations$ : Observable < Player [ ] > ;
2336 isPartyLeader$ : Observable < boolean > ;
24- readonly defaultAvatar = 'assets/images/group/avatar-placeholder.png' ;
25- profilePreview$ = new BehaviorSubject < string | null > ( null ) ;
37+ readonly defaultAvatarPath = 'assets/images/group/avatar-placeholder.png' ;
38+ readonly defaultAvatar : SafeUrl ;
39+ private readonly profilePreviewSubject = new BehaviorSubject < string | null > (
40+ null ,
41+ ) ;
42+ profilePreview$ = this . profilePreviewSubject . asObservable ( ) ;
43+ profilePreviewSafeUrl$ : Observable < SafeUrl > ;
2644 uploadError$ = new BehaviorSubject < string | null > ( null ) ;
2745 private readonly subscriptions = new Subscription ( ) ;
2846 private readonly targetImageSize = 128 ;
@@ -35,7 +53,19 @@ export class PartyMenuComponent implements OnDestroy {
3553 private readonly playerListService : PlayerListService ,
3654 private readonly clientService : ClientService ,
3755 private readonly zone : NgZone ,
56+ private readonly sanitizer : DomSanitizer ,
3857 ) {
58+ this . defaultAvatar = this . sanitizer . bypassSecurityTrustUrl (
59+ this . defaultAvatarPath ,
60+ ) ;
61+ this . profilePreviewSafeUrl$ = this . profilePreviewSubject . pipe (
62+ map ( preview =>
63+ preview
64+ ? this . sanitizer . bypassSecurityTrustUrl ( preview )
65+ : this . defaultAvatar ,
66+ ) ,
67+ ) ;
68+
3969 this . invitations$ = this . playerListService . playerList . asObservable ( ) . pipe (
4070 filter ( playerlist => ! ! playerlist ) ,
4171 pluck ( 'players' ) ,
@@ -63,23 +93,23 @@ export class PartyMenuComponent implements OnDestroy {
6393
6494 const localPlayer = list . players . find ( player => player . id === localId ) ;
6595 if ( localPlayer ) {
66- this . profilePreview$ . next ( localPlayer . avatar || null ) ;
96+ this . profilePreviewSubject . next ( localPlayer . avatar || null ) ;
6797 }
6898 } ) ,
6999 ) ;
70100
71101 this . subscriptions . add (
72102 this . clientService . avatarChange . subscribe ( player => {
73103 if ( player . id === this . clientService . localPlayerId ) {
74- this . profilePreview$ . next ( player . avatar || null ) ;
104+ this . profilePreviewSubject . next ( player . avatar || null ) ;
75105 }
76106 } ) ,
77107 ) ;
78108
79109 this . subscriptions . add (
80110 this . clientService . connectionStateChange . subscribe ( isConnected => {
81111 if ( ! isConnected ) {
82- this . profilePreview$ . next ( null ) ;
112+ this . profilePreviewSubject . next ( null ) ;
83113 }
84114 } ) ,
85115 ) ;
@@ -125,29 +155,20 @@ export class PartyMenuComponent implements OnDestroy {
125155 const allowedExtensions = [ 'png' , 'jpg' , 'jpeg' ] ;
126156
127157 if ( file . size > this . maxUploadBytes ) {
128- this . uploadError$ . next (
129- 'COMPONENT.PARTY_MENU.PROFILE_PICTURE.ERROR_SIZE' ,
130- ) ;
158+ this . uploadError$ . next ( 'COMPONENT.PARTY_MENU.PROFILE_PICTURE.ERROR_SIZE' ) ;
131159 input . value = '' ;
132160 return ;
133161 }
134162
135- if (
136- file . type &&
137- ! allowedMimeTypes . includes ( file . type . toLowerCase ( ) )
138- ) {
139- this . uploadError$ . next (
140- 'COMPONENT.PARTY_MENU.PROFILE_PICTURE.ERROR_TYPE' ,
141- ) ;
163+ if ( file . type && ! allowedMimeTypes . includes ( file . type . toLowerCase ( ) ) ) {
164+ this . uploadError$ . next ( 'COMPONENT.PARTY_MENU.PROFILE_PICTURE.ERROR_TYPE' ) ;
142165 input . value = '' ;
143166 return ;
144167 }
145168
146169 const extension = file . name . split ( '.' ) . pop ( ) ?. toLowerCase ( ) ;
147170 if ( ! file . type && extension && ! allowedExtensions . includes ( extension ) ) {
148- this . uploadError$ . next (
149- 'COMPONENT.PARTY_MENU.PROFILE_PICTURE.ERROR_TYPE' ,
150- ) ;
171+ this . uploadError$ . next ( 'COMPONENT.PARTY_MENU.PROFILE_PICTURE.ERROR_TYPE' ) ;
151172 input . value = '' ;
152173 return ;
153174 }
@@ -174,7 +195,7 @@ export class PartyMenuComponent implements OnDestroy {
174195 }
175196
176197 this . uploadError$ . next ( null ) ;
177- this . profilePreview$ . next ( normalized ) ;
198+ this . profilePreviewSubject . next ( normalized ) ;
178199 this . clientService . setProfilePicture ( normalized ) ;
179200 } )
180201 . catch ( ( ) => {
@@ -197,7 +218,7 @@ export class PartyMenuComponent implements OnDestroy {
197218
198219 public clearProfilePicture ( ) {
199220 this . uploadError$ . next ( null ) ;
200- this . profilePreview$ . next ( null ) ;
221+ this . profilePreviewSubject . next ( null ) ;
201222 this . clientService . setProfilePicture ( '' ) ;
202223 }
203224
0 commit comments