1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-12 10:14:10 +01:00

[PM-11306] Disable Animation Setting (#11157)

* add appearance option to disable animations

* add check to only show the form after it's populated to avoid flash of inaccurate values

* switch to form loading while waiting for form values
This commit is contained in:
Nick Krantz 2024-09-23 11:56:09 -05:00 committed by GitHub
parent 2b462b6fd6
commit bcddf575a1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 48 additions and 3 deletions

View File

@ -4201,6 +4201,9 @@
"enableAnimations": { "enableAnimations": {
"message": "Enable animations" "message": "Enable animations"
}, },
"showAnimations": {
"message": "Show animations"
},
"addAccount": { "addAccount": {
"message": "Add account" "message": "Add account"
}, },

View File

@ -1,4 +1,4 @@
<popup-page> <popup-page [loading]="formLoading">
<popup-header slot="header" [pageTitle]="'appearance' | i18n" showBackButton> <popup-header slot="header" [pageTitle]="'appearance' | i18n" showBackButton>
<ng-container slot="end"> <ng-container slot="end">
<app-pop-out></app-pop-out> <app-pop-out></app-pop-out>
@ -23,10 +23,15 @@
<bit-label>{{ "showNumberOfAutofillSuggestions" | i18n }}</bit-label> <bit-label>{{ "showNumberOfAutofillSuggestions" | i18n }}</bit-label>
</bit-form-control> </bit-form-control>
<bit-form-control disableMargin> <bit-form-control>
<input bitCheckbox formControlName="enableFavicon" type="checkbox" /> <input bitCheckbox formControlName="enableFavicon" type="checkbox" />
<bit-label>{{ "enableFavicon" | i18n }}</bit-label> <bit-label>{{ "enableFavicon" | i18n }}</bit-label>
</bit-form-control> </bit-form-control>
<bit-form-control disableMargin>
<input bitCheckbox formControlName="enableAnimations" type="checkbox" />
<bit-label>{{ "showAnimations" | i18n }}</bit-label>
</bit-form-control>
</bit-card> </bit-card>
</form> </form>
</popup-page> </popup-page>

View File

@ -5,6 +5,7 @@ import { BehaviorSubject } from "rxjs";
import { BadgeSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/badge-settings.service"; import { BadgeSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/badge-settings.service";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service"; import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { AnimationControlService } from "@bitwarden/common/platform/abstractions/animation-control.service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service"; import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
@ -41,14 +42,17 @@ describe("AppearanceV2Component", () => {
const showFavicons$ = new BehaviorSubject<boolean>(true); const showFavicons$ = new BehaviorSubject<boolean>(true);
const enableBadgeCounter$ = new BehaviorSubject<boolean>(true); const enableBadgeCounter$ = new BehaviorSubject<boolean>(true);
const selectedTheme$ = new BehaviorSubject<ThemeType>(ThemeType.Nord); const selectedTheme$ = new BehaviorSubject<ThemeType>(ThemeType.Nord);
const enableRoutingAnimation$ = new BehaviorSubject<boolean>(true);
const setSelectedTheme = jest.fn().mockResolvedValue(undefined); const setSelectedTheme = jest.fn().mockResolvedValue(undefined);
const setShowFavicons = jest.fn().mockResolvedValue(undefined); const setShowFavicons = jest.fn().mockResolvedValue(undefined);
const setEnableBadgeCounter = jest.fn().mockResolvedValue(undefined); const setEnableBadgeCounter = jest.fn().mockResolvedValue(undefined);
const setEnableRoutingAnimation = jest.fn().mockResolvedValue(undefined);
beforeEach(async () => { beforeEach(async () => {
setSelectedTheme.mockClear(); setSelectedTheme.mockClear();
setShowFavicons.mockClear(); setShowFavicons.mockClear();
setEnableBadgeCounter.mockClear(); setEnableBadgeCounter.mockClear();
setEnableRoutingAnimation.mockClear();
await TestBed.configureTestingModule({ await TestBed.configureTestingModule({
imports: [AppearanceV2Component], imports: [AppearanceV2Component],
@ -58,11 +62,15 @@ describe("AppearanceV2Component", () => {
{ provide: MessagingService, useValue: mock<MessagingService>() }, { provide: MessagingService, useValue: mock<MessagingService>() },
{ provide: I18nService, useValue: { t: (key: string) => key } }, { provide: I18nService, useValue: { t: (key: string) => key } },
{ provide: DomainSettingsService, useValue: { showFavicons$, setShowFavicons } }, { provide: DomainSettingsService, useValue: { showFavicons$, setShowFavicons } },
{ provide: ThemeStateService, useValue: { selectedTheme$, setSelectedTheme } },
{
provide: AnimationControlService,
useValue: { enableRoutingAnimation$, setEnableRoutingAnimation },
},
{ {
provide: BadgeSettingsServiceAbstraction, provide: BadgeSettingsServiceAbstraction,
useValue: { enableBadgeCounter$, setEnableBadgeCounter }, useValue: { enableBadgeCounter$, setEnableBadgeCounter },
}, },
{ provide: ThemeStateService, useValue: { selectedTheme$, setSelectedTheme } },
], ],
}) })
.overrideComponent(AppearanceV2Component, { .overrideComponent(AppearanceV2Component, {
@ -82,6 +90,7 @@ describe("AppearanceV2Component", () => {
it("populates the form with the user's current settings", () => { it("populates the form with the user's current settings", () => {
expect(component.appearanceForm.value).toEqual({ expect(component.appearanceForm.value).toEqual({
enableAnimations: true,
enableFavicon: true, enableFavicon: true,
enableBadgeCounter: true, enableBadgeCounter: true,
theme: ThemeType.Nord, theme: ThemeType.Nord,
@ -106,5 +115,11 @@ describe("AppearanceV2Component", () => {
expect(setEnableBadgeCounter).toHaveBeenCalledWith(false); expect(setEnableBadgeCounter).toHaveBeenCalledWith(false);
}); });
it("updates the animation setting", () => {
component.appearanceForm.controls.enableAnimations.setValue(false);
expect(setEnableRoutingAnimation).toHaveBeenCalledWith(false);
});
}); });
}); });

View File

@ -7,6 +7,7 @@ import { firstValueFrom } from "rxjs";
import { JslibModule } from "@bitwarden/angular/jslib.module"; import { JslibModule } from "@bitwarden/angular/jslib.module";
import { BadgeSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/badge-settings.service"; import { BadgeSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/badge-settings.service";
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service"; import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
import { AnimationControlService } from "@bitwarden/common/platform/abstractions/animation-control.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { ThemeType } from "@bitwarden/common/platform/enums"; import { ThemeType } from "@bitwarden/common/platform/enums";
@ -41,8 +42,12 @@ export class AppearanceV2Component implements OnInit {
enableFavicon: false, enableFavicon: false,
enableBadgeCounter: true, enableBadgeCounter: true,
theme: ThemeType.System, theme: ThemeType.System,
enableAnimations: true,
}); });
/** To avoid flashes of inaccurate values, only show the form after the entire form is populated. */
formLoading = true;
/** Available theme options */ /** Available theme options */
themeOptions: { name: string; value: ThemeType }[]; themeOptions: { name: string; value: ThemeType }[];
@ -53,6 +58,7 @@ export class AppearanceV2Component implements OnInit {
private themeStateService: ThemeStateService, private themeStateService: ThemeStateService,
private formBuilder: FormBuilder, private formBuilder: FormBuilder,
private destroyRef: DestroyRef, private destroyRef: DestroyRef,
private animationControlService: AnimationControlService,
i18nService: I18nService, i18nService: I18nService,
) { ) {
this.themeOptions = [ this.themeOptions = [
@ -66,14 +72,20 @@ export class AppearanceV2Component implements OnInit {
const enableFavicon = await firstValueFrom(this.domainSettingsService.showFavicons$); const enableFavicon = await firstValueFrom(this.domainSettingsService.showFavicons$);
const enableBadgeCounter = await firstValueFrom(this.badgeSettingsService.enableBadgeCounter$); const enableBadgeCounter = await firstValueFrom(this.badgeSettingsService.enableBadgeCounter$);
const theme = await firstValueFrom(this.themeStateService.selectedTheme$); const theme = await firstValueFrom(this.themeStateService.selectedTheme$);
const enableAnimations = await firstValueFrom(
this.animationControlService.enableRoutingAnimation$,
);
// Set initial values for the form // Set initial values for the form
this.appearanceForm.setValue({ this.appearanceForm.setValue({
enableFavicon, enableFavicon,
enableBadgeCounter, enableBadgeCounter,
theme, theme,
enableAnimations,
}); });
this.formLoading = false;
this.appearanceForm.controls.theme.valueChanges this.appearanceForm.controls.theme.valueChanges
.pipe(takeUntilDestroyed(this.destroyRef)) .pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((newTheme) => { .subscribe((newTheme) => {
@ -91,6 +103,12 @@ export class AppearanceV2Component implements OnInit {
.subscribe((enableBadgeCounter) => { .subscribe((enableBadgeCounter) => {
void this.updateBadgeCounter(enableBadgeCounter); void this.updateBadgeCounter(enableBadgeCounter);
}); });
this.appearanceForm.controls.enableAnimations.valueChanges
.pipe(takeUntilDestroyed(this.destroyRef))
.subscribe((enableBadgeCounter) => {
void this.updateAnimations(enableBadgeCounter);
});
} }
async updateFavicon(enableFavicon: boolean) { async updateFavicon(enableFavicon: boolean) {
@ -105,4 +123,8 @@ export class AppearanceV2Component implements OnInit {
async saveTheme(newTheme: ThemeType) { async saveTheme(newTheme: ThemeType) {
await this.themeStateService.setSelectedTheme(newTheme); await this.themeStateService.setSelectedTheme(newTheme);
} }
async updateAnimations(enableAnimations: boolean) {
await this.animationControlService.setEnableRoutingAnimation(enableAnimations);
}
} }