|
1 | | -import { computed, Injectable, inject } from '@angular/core'; |
| 1 | +import { Injectable, inject, linkedSignal } from '@angular/core'; |
2 | 2 | import { AuthService } from './auth.service'; |
3 | 3 |
|
| 4 | +interface UserProfile { |
| 5 | + name: string; |
| 6 | + initials: string; |
| 7 | +} |
| 8 | + |
4 | 9 | @Injectable({ |
5 | 10 | providedIn: 'root', |
6 | 11 | }) |
7 | 12 | export class UserProfileService { |
8 | 13 | private readonly authService = inject(AuthService); |
9 | 14 |
|
10 | | - profile = computed(() => { |
11 | | - const userDataResult = this.authService.userData(); |
12 | | - const userData = userDataResult?.userData; |
13 | | - const name = userData?.name ?? userData?.preferred_username; |
| 15 | + // Derive the profile from the auth user data, but keep the last known value |
| 16 | + // while the user data is momentarily empty during a token renewal (which |
| 17 | + // happens when the installed PWA resumes on mobile). A plain computed would |
| 18 | + // blank out and make the avatar disappear; linkedSignal lets us fall back to |
| 19 | + // the previous value instead. |
| 20 | + profile = linkedSignal<unknown, UserProfile | undefined>({ |
| 21 | + source: this.authService.userData, |
| 22 | + computation: (userDataResult, previous) => { |
| 23 | + const userData = ( |
| 24 | + userDataResult as |
| 25 | + | { userData?: { name?: string; preferred_username?: string } } |
| 26 | + | undefined |
| 27 | + )?.userData; |
| 28 | + const name = userData?.name ?? userData?.preferred_username; |
14 | 29 |
|
15 | | - if (!name) { |
16 | | - return undefined; |
17 | | - } |
| 30 | + if (!name) { |
| 31 | + return previous?.value; |
| 32 | + } |
18 | 33 |
|
19 | | - return { |
20 | | - name, |
21 | | - initials: this.getInitials(name), |
22 | | - }; |
| 34 | + return { |
| 35 | + name, |
| 36 | + initials: this.getInitials(name), |
| 37 | + }; |
| 38 | + }, |
23 | 39 | }); |
24 | 40 |
|
25 | | - private getInitials(name: string | undefined): string { |
26 | | - if (!name) return ''; |
27 | | - const initials = name |
| 41 | + private getInitials(name: string): string { |
| 42 | + return name |
28 | 43 | .split(' ') |
29 | | - .map((n) => n[0]) |
30 | | - .join(''); |
31 | | - return initials.toUpperCase(); |
| 44 | + .map((part) => part[0]) |
| 45 | + .join('') |
| 46 | + .toUpperCase(); |
32 | 47 | } |
33 | 48 | } |
0 commit comments