1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-18 01:03:35 +00:00

[PM-5266] Create Avatar Service (#7905)

* rename file, move, and update imports

* refactor and implement StateProvider

* remove comments

* add migration

* use 'disk-local' for web

* add JSDoc comments

* move AvatarService before SyncService

* create factory

* replace old method with observable in story

* fix tests

* add tests for migration

* receive most recent avatarColor emission

* move logic to component

* fix CLI dependency

* remove BehaviorSubject

* cleanup

* use UserKeyDefinition

* avoid extra write

* convert to observable

* fix tests
This commit is contained in:
rr-bw
2024-03-14 09:56:48 -07:00
committed by GitHub
parent 10d503c15f
commit 65b7ca7177
25 changed files with 403 additions and 165 deletions

View File

@@ -9,9 +9,9 @@ import {
ViewChild,
ViewEncapsulation,
} from "@angular/core";
import { BehaviorSubject, debounceTime, Subject, takeUntil } from "rxjs";
import { BehaviorSubject, debounceTime, firstValueFrom, Subject, takeUntil } from "rxjs";
import { AvatarUpdateService } from "@bitwarden/common/abstractions/account/avatar-update.service";
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
import { ProfileResponse } from "@bitwarden/common/models/response/profile.response";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { LogService } from "@bitwarden/common/platform/abstractions/log.service";
@@ -55,7 +55,7 @@ export class ChangeAvatarComponent implements OnInit, OnDestroy {
private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService,
private logService: LogService,
private accountUpdateService: AvatarUpdateService,
private avatarService: AvatarService,
) {}
async ngOnInit() {
@@ -73,9 +73,7 @@ export class ChangeAvatarComponent implements OnInit, OnDestroy {
this.currentSelection = color;
});
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
// eslint-disable-next-line @typescript-eslint/no-floating-promises
this.setSelection(await this.accountUpdateService.loadColorFromState());
await this.setSelection(await firstValueFrom(this.avatarService.avatarColor$));
}
async showCustomPicker() {
@@ -93,7 +91,7 @@ export class ChangeAvatarComponent implements OnInit, OnDestroy {
async submit() {
try {
if (Utils.validateHexColor(this.currentSelection) || this.currentSelection == null) {
await this.accountUpdateService.pushUpdate(this.currentSelection);
await this.avatarService.setAvatarColor(this.currentSelection);
this.changeColor.emit(this.currentSelection);
this.platformUtilsService.showToast("success", null, this.i18nService.t("avatarUpdated"));
} else {

View File

@@ -1,7 +1,7 @@
import { Component, Input, OnDestroy } from "@angular/core";
import { Observable, Subject } from "rxjs";
import { Subject } from "rxjs";
import { AvatarUpdateService } from "@bitwarden/common/abstractions/account/avatar-update.service";
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
import { SharedModule } from "../shared";
@@ -29,14 +29,14 @@ export class DynamicAvatarComponent implements OnDestroy {
@Input() text: string;
@Input() title: string;
@Input() size: SizeTypes = "default";
color$: Observable<string | null>;
private destroy$ = new Subject<void>();
constructor(private accountUpdateService: AvatarUpdateService) {
color$ = this.avatarService.avatarColor$;
constructor(private avatarService: AvatarService) {
if (this.text) {
this.text = this.text.toUpperCase();
}
this.color$ = this.accountUpdateService.avatarUpdate$;
}
async ngOnDestroy() {

View File

@@ -1,12 +1,12 @@
import { importProvidersFrom } from "@angular/core";
import { RouterModule } from "@angular/router";
import { applicationConfig, Meta, moduleMetadata, Story } from "@storybook/angular";
import { BehaviorSubject } from "rxjs";
import { BehaviorSubject, of } from "rxjs";
import { AvatarUpdateService } from "@bitwarden/common/abstractions/account/avatar-update.service";
import { SettingsService } from "@bitwarden/common/abstractions/settings.service";
import { OrganizationUserType } from "@bitwarden/common/admin-console/enums";
import { Organization } from "@bitwarden/common/admin-console/models/domain/organization";
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config.service.abstraction";
import { EnvironmentService } from "@bitwarden/common/platform/abstractions/environment.service";
@@ -72,12 +72,10 @@ export default {
} as Partial<SettingsService>,
},
{
provide: AvatarUpdateService,
provide: AvatarService,
useValue: {
async loadColorFromState() {
return "#FF0000";
},
} as Partial<AvatarUpdateService>,
avatarColor$: of("#FF0000"),
} as Partial<AvatarService>,
},
{
provide: TokenService,

View File

@@ -1,6 +1,7 @@
import { Component, Input, OnChanges } from "@angular/core";
import { firstValueFrom } from "rxjs";
import { AvatarUpdateService } from "@bitwarden/common/abstractions/account/avatar-update.service";
import { AvatarService } from "@bitwarden/common/auth/abstractions/avatar.service";
import { TokenService } from "@bitwarden/common/auth/abstractions/token.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { Utils } from "@bitwarden/common/platform/misc/utils";
@@ -24,7 +25,7 @@ export class OrganizationNameBadgeComponent implements OnChanges {
constructor(
private i18nService: I18nService,
private avatarService: AvatarUpdateService,
private avatarService: AvatarService,
private tokenService: TokenService,
) {}
@@ -35,7 +36,7 @@ export class OrganizationNameBadgeComponent implements OnChanges {
if (this.isMe) {
this.name = this.i18nService.t("me");
this.color = await this.avatarService.loadColorFromState();
this.color = await firstValueFrom(this.avatarService.avatarColor$);
if (this.color == null) {
const userId = await this.tokenService.getUserId();
if (userId != null) {