Skip to content

Commit f2be150

Browse files
[PM-9552] add a toggle for the routing animation (#10005)
* add a toggle for the routing animation * add missing period (thanks mat) * rename routingAnimation to enableRoutingAnimation for consistency * move animation-control.service.ts into abstractions * simplify config option * fixup! simplify config option remove dead aria reference --------- Co-authored-by: Shane Melton <smelton@bitwarden.com>
1 parent c2829cd commit f2be150

File tree

7 files changed

+88
-1
lines changed

7 files changed

+88
-1
lines changed

apps/browser/src/_locales/en/messages.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3987,6 +3987,9 @@
39873987
}
39883988
}
39893989
},
3990+
"enableAnimations": {
3991+
"message": "Enable animations"
3992+
},
39903993
"addAccount": {
39913994
"message": "Add account"
39923995
},

apps/browser/src/popup/app.component.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { LogoutReason } from "@bitwarden/auth/common";
66
import { AccountService } from "@bitwarden/common/auth/abstractions/account.service";
77
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
88
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
9+
import { AnimationControlService } from "@bitwarden/common/platform/abstractions/animation-control.service";
910
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
1011
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
1112
import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
@@ -39,6 +40,7 @@ export class AppComponent implements OnInit, OnDestroy {
3940
private lastActivity: Date;
4041
private activeUserId: UserId;
4142
private recordActivitySubject = new Subject<void>();
43+
private routerAnimations = false;
4244

4345
private destroy$ = new Subject<void>();
4446

@@ -57,6 +59,7 @@ export class AppComponent implements OnInit, OnDestroy {
5759
private messageListener: MessageListener,
5860
private toastService: ToastService,
5961
private accountService: AccountService,
62+
private animationControlService: AnimationControlService,
6063
) {}
6164

6265
async ngOnInit() {
@@ -173,6 +176,12 @@ export class AppComponent implements OnInit, OnDestroy {
173176
}
174177
}
175178
});
179+
180+
this.animationControlService.enableRoutingAnimation$
181+
.pipe(takeUntil(this.destroy$))
182+
.subscribe((state) => {
183+
this.routerAnimations = state;
184+
});
176185
}
177186

178187
ngOnDestroy(): void {
@@ -181,7 +190,9 @@ export class AppComponent implements OnInit, OnDestroy {
181190
}
182191

183192
getState(outlet: RouterOutlet) {
184-
if (outlet.activatedRouteData.state === "ciphers") {
193+
if (!this.routerAnimations) {
194+
return;
195+
} else if (outlet.activatedRouteData.state === "ciphers") {
185196
const routeDirection =
186197
(window as any).routeDirection != null ? (window as any).routeDirection : "";
187198
return (

apps/browser/src/popup/services/services.module.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ import {
4141
} from "@bitwarden/common/autofill/services/user-notification-settings.service";
4242
import { BillingAccountProfileStateService } from "@bitwarden/common/billing/abstractions/account/billing-account-profile-state.service";
4343
import { ClientType } from "@bitwarden/common/enums";
44+
import {
45+
AnimationControlService,
46+
DefaultAnimationControlService,
47+
} from "@bitwarden/common/platform/abstractions/animation-control.service";
4448
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
4549
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
4650
import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
@@ -527,6 +531,11 @@ const safeProviders: SafeProvider[] = [
527531
useClass: Fido2UserVerificationService,
528532
deps: [PasswordRepromptService, UserVerificationService, DialogService],
529533
}),
534+
safeProvider({
535+
provide: AnimationControlService,
536+
useClass: DefaultAnimationControlService,
537+
deps: [GlobalStateProvider],
538+
}),
530539
safeProvider({
531540
provide: TaskSchedulerService,
532541
useExisting: ForegroundTaskSchedulerService,

apps/browser/src/vault/popup/settings/appearance.component.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,4 +64,17 @@ <h1 class="center">
6464
{{ accountSwitcherEnabled ? ("faviconDescAlt" | i18n) : ("faviconDesc" | i18n) }}
6565
</div>
6666
</div>
67+
<div class="box">
68+
<div class="box-content">
69+
<div class="box-content-row box-content-row-checkbox" appBoxRow>
70+
<label for="routing">{{ "enableAnimations" | i18n }}</label>
71+
<input
72+
id="routing"
73+
type="checkbox"
74+
(change)="updateRoutingAnimation()"
75+
[(ngModel)]="enableRoutingAnimation"
76+
/>
77+
</div>
78+
</div>
79+
</div>
6780
</main>

apps/browser/src/vault/popup/settings/appearance.component.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { firstValueFrom } from "rxjs";
33

44
import { BadgeSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/badge-settings.service";
55
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
6+
import { AnimationControlService } from "@bitwarden/common/platform/abstractions/animation-control.service";
67
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
78
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
89
import { ThemeType } from "@bitwarden/common/platform/enums";
@@ -20,13 +21,15 @@ export class AppearanceComponent implements OnInit {
2021
theme: ThemeType;
2122
themeOptions: any[];
2223
accountSwitcherEnabled = false;
24+
enableRoutingAnimation: boolean;
2325

2426
constructor(
2527
private messagingService: MessagingService,
2628
private domainSettingsService: DomainSettingsService,
2729
private badgeSettingsService: BadgeSettingsServiceAbstraction,
2830
i18nService: I18nService,
2931
private themeStateService: ThemeStateService,
32+
private animationControlService: AnimationControlService,
3033
) {
3134
this.themeOptions = [
3235
{ name: i18nService.t("default"), value: ThemeType.System },
@@ -40,13 +43,21 @@ export class AppearanceComponent implements OnInit {
4043
}
4144

4245
async ngOnInit() {
46+
this.enableRoutingAnimation = await firstValueFrom(
47+
this.animationControlService.enableRoutingAnimation$,
48+
);
49+
4350
this.enableFavicon = await firstValueFrom(this.domainSettingsService.showFavicons$);
4451

4552
this.enableBadgeCounter = await firstValueFrom(this.badgeSettingsService.enableBadgeCounter$);
4653

4754
this.theme = await firstValueFrom(this.themeStateService.selectedTheme$);
4855
}
4956

57+
async updateRoutingAnimation() {
58+
await this.animationControlService.setEnableRoutingAnimation(this.enableRoutingAnimation);
59+
}
60+
5061
async updateFavicon() {
5162
await this.domainSettingsService.setShowFavicons(this.enableFavicon);
5263
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Observable, map } from "rxjs";
2+
3+
import { GlobalStateProvider, KeyDefinition, ANIMATION_DISK } from "../state";
4+
5+
export abstract class AnimationControlService {
6+
/**
7+
* The routing animation toggle.
8+
*/
9+
abstract enableRoutingAnimation$: Observable<boolean>;
10+
11+
/**
12+
* A method for updating the state of the animation toggle.
13+
* @param theme The new state.
14+
*/
15+
abstract setEnableRoutingAnimation(state: boolean): Promise<void>;
16+
}
17+
18+
const ROUTING_ANIMATION = new KeyDefinition<boolean>(ANIMATION_DISK, "routing", {
19+
deserializer: (s) => s,
20+
});
21+
22+
export class DefaultAnimationControlService implements AnimationControlService {
23+
private readonly enableRoutingAnimationState = this.globalStateProvider.get(ROUTING_ANIMATION);
24+
25+
enableRoutingAnimation$ = this.enableRoutingAnimationState.state$.pipe(
26+
map((state) => state ?? this.defaultEnableRoutingAnimation),
27+
);
28+
29+
constructor(
30+
private globalStateProvider: GlobalStateProvider,
31+
private defaultEnableRoutingAnimation: boolean = true,
32+
) {}
33+
34+
async setEnableRoutingAnimation(state: boolean): Promise<void> {
35+
await this.enableRoutingAnimationState.update(() => state, {
36+
shouldUpdate: (currentState) => currentState !== state,
37+
});
38+
}
39+
}

libs/common/src/platform/state/state-definitions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ export const POPUP_VIEW_MEMORY = new StateDefinition("popupView", "memory", {
117117
export const SYNC_DISK = new StateDefinition("sync", "disk", { web: "memory" });
118118
export const THEMING_DISK = new StateDefinition("theming", "disk", { web: "disk-local" });
119119
export const TRANSLATION_DISK = new StateDefinition("translation", "disk", { web: "disk-local" });
120+
export const ANIMATION_DISK = new StateDefinition("animation", "disk");
120121
export const TASK_SCHEDULER_DISK = new StateDefinition("taskScheduler", "disk");
121122

122123
// Secrets Manager

0 commit comments

Comments
 (0)