diff --git a/apps/browser/src/autofill/background/service_factories/badge-settings-service.factory.ts b/apps/browser/src/autofill/background/service_factories/badge-settings-service.factory.ts new file mode 100644 index 00000000000..c51a9b31b01 --- /dev/null +++ b/apps/browser/src/autofill/background/service_factories/badge-settings-service.factory.ts @@ -0,0 +1,25 @@ +import { BadgeSettingsService } from "@bitwarden/common/autofill/services/badge-settings.service"; + +import { + CachedServices, + factory, + FactoryOptions, +} from "../../../platform/background/service-factories/factory-options"; +import { + stateProviderFactory, + StateProviderInitOptions, +} from "../../../platform/background/service-factories/state-provider.factory"; + +export type BadgeSettingsServiceInitOptions = FactoryOptions & StateProviderInitOptions; + +export function badgeSettingsServiceFactory( + cache: { badgeSettingsService?: BadgeSettingsService } & CachedServices, + opts: BadgeSettingsServiceInitOptions, +): Promise { + return factory( + cache, + "badgeSettingsService", + opts, + async () => new BadgeSettingsService(await stateProviderFactory(cache, opts)), + ); +} diff --git a/apps/browser/src/background/main.background.ts b/apps/browser/src/background/main.background.ts index a3d1e40ac4d..724c2ee9949 100644 --- a/apps/browser/src/background/main.background.ts +++ b/apps/browser/src/background/main.background.ts @@ -49,6 +49,10 @@ import { AutofillSettingsServiceAbstraction, AutofillSettingsService, } from "@bitwarden/common/autofill/services/autofill-settings.service"; +import { + BadgeSettingsServiceAbstraction, + BadgeSettingsService, +} from "@bitwarden/common/autofill/services/badge-settings.service"; import { AppIdService as AppIdServiceAbstraction } from "@bitwarden/common/platform/abstractions/app-id.service"; import { ConfigApiServiceAbstraction } from "@bitwarden/common/platform/abstractions/config/config-api.service.abstraction"; import { CryptoFunctionService as CryptoFunctionServiceAbstraction } from "@bitwarden/common/platform/abstractions/crypto-function.service"; @@ -243,6 +247,7 @@ export default class MainBackground { notificationsService: NotificationsServiceAbstraction; stateService: StateServiceAbstraction; autofillSettingsService: AutofillSettingsServiceAbstraction; + badgeSettingsService: BadgeSettingsServiceAbstraction; systemService: SystemServiceAbstraction; eventCollectionService: EventCollectionServiceAbstraction; eventUploadService: EventUploadServiceAbstraction; @@ -482,6 +487,7 @@ export default class MainBackground { this.stateProvider, this.policyService, ); + this.badgeSettingsService = new BadgeSettingsService(this.stateProvider); this.policyApiService = new PolicyApiService( this.policyService, this.apiService, @@ -1079,7 +1085,10 @@ export default class MainBackground { this.keyConnectorService.clear(), this.vaultFilterService.clear(), this.biometricStateService.logout(userId), - // We intentionally do not clear the autofillSettingsService + /* We intentionally do not clear: + * - autofillSettingsService + * - badgeSettingsService + */ ]); //Needs to be checked before state is cleaned diff --git a/apps/browser/src/platform/listeners/update-badge.ts b/apps/browser/src/platform/listeners/update-badge.ts index 9cc9c9b5108..ee9996a28bf 100644 --- a/apps/browser/src/platform/listeners/update-badge.ts +++ b/apps/browser/src/platform/listeners/update-badge.ts @@ -1,5 +1,8 @@ +import { firstValueFrom } from "rxjs"; + import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service"; import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status"; +import { BadgeSettingsService } from "@bitwarden/common/autofill/services/badge-settings.service"; import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service"; import { EncryptService } from "@bitwarden/common/platform/abstractions/encrypt.service"; import { StateFactory } from "@bitwarden/common/platform/factories/state-factory"; @@ -9,9 +12,8 @@ import { ContainerService } from "@bitwarden/common/platform/services/container. import { CipherService } from "@bitwarden/common/vault/abstractions/cipher.service"; import { authServiceFactory } from "../../auth/background/service-factories/auth-service.factory"; +import { badgeSettingsServiceFactory } from "../../autofill/background/service_factories/badge-settings-service.factory"; import { Account } from "../../models/account"; -import { stateServiceFactory } from "../../platform/background/service-factories/state-service.factory"; -import { BrowserStateService } from "../../platform/services/abstractions/browser-state.service"; import IconDetails from "../../vault/background/models/icon-details"; import { cipherServiceFactory } from "../../vault/background/service_factories/cipher-service.factory"; import { BrowserApi } from "../browser/browser-api"; @@ -24,7 +26,7 @@ export type BadgeOptions = { export class UpdateBadge { private authService: AuthService; - private stateService: BrowserStateService; + private badgeSettingsService: BadgeSettingsService; private cipherService: CipherService; private badgeAction: typeof chrome.action | typeof chrome.browserAction; private sidebarAction: OperaSidebarAction | FirefoxSidebarAction; @@ -152,8 +154,8 @@ export class UpdateBadge { await this.setBadgeIcon(""); - const disableBadgeCounter = await this.stateService.getDisableBadgeCounter(); - if (disableBadgeCounter) { + const enableBadgeCounter = await firstValueFrom(this.badgeSettingsService.enableBadgeCounter$); + if (!enableBadgeCounter) { return; } @@ -290,7 +292,7 @@ export class UpdateBadge { systemLanguage: BrowserApi.getUILanguage(), }, }; - this.stateService = await stateServiceFactory(serviceCache, opts); + this.badgeSettingsService = await badgeSettingsServiceFactory(serviceCache, opts); this.authService = await authServiceFactory(serviceCache, opts); this.cipherService = await cipherServiceFactory(serviceCache, opts); diff --git a/apps/browser/src/popup/settings/options.component.ts b/apps/browser/src/popup/settings/options.component.ts index ecdd6d13c25..2a68fe73ac0 100644 --- a/apps/browser/src/popup/settings/options.component.ts +++ b/apps/browser/src/popup/settings/options.component.ts @@ -4,6 +4,7 @@ import { firstValueFrom } from "rxjs"; import { AbstractThemingService } from "@bitwarden/angular/platform/services/theming/theming.service.abstraction"; import { SettingsService } from "@bitwarden/common/abstractions/settings.service"; import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service"; +import { BadgeSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/badge-settings.service"; import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service"; import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service"; import { StateService } from "@bitwarden/common/platform/abstractions/state.service"; @@ -20,7 +21,7 @@ import { enableAccountSwitching } from "../../platform/flags"; }) export class OptionsComponent implements OnInit { enableFavicon = false; - enableBadgeCounter = false; + enableBadgeCounter = true; enableAutoFillOnPageLoad = false; autoFillOnPageLoadDefault = false; autoFillOnPageLoadOptions: any[]; @@ -47,6 +48,7 @@ export class OptionsComponent implements OnInit { private messagingService: MessagingService, private stateService: StateService, private autofillSettingsService: AutofillSettingsServiceAbstraction, + private badgeSettingsService: BadgeSettingsServiceAbstraction, i18nService: I18nService, private themingService: AbstractThemingService, private settingsService: SettingsService, @@ -107,7 +109,7 @@ export class OptionsComponent implements OnInit { this.enableFavicon = !this.settingsService.getDisableFavicon(); - this.enableBadgeCounter = !(await this.stateService.getDisableBadgeCounter()); + this.enableBadgeCounter = await firstValueFrom(this.badgeSettingsService.enableBadgeCounter$); this.enablePasskeys = await firstValueFrom(this.vaultSettingsService.enablePasskeys$); @@ -155,7 +157,7 @@ export class OptionsComponent implements OnInit { } async updateBadgeCounter() { - await this.stateService.setDisableBadgeCounter(!this.enableBadgeCounter); + await this.badgeSettingsService.setEnableBadgeCounter(this.enableBadgeCounter); this.messagingService.send("bgUpdateContextMenu"); } diff --git a/libs/angular/src/services/jslib-services.module.ts b/libs/angular/src/services/jslib-services.module.ts index 8dcfcb207d7..a08b75ff57c 100644 --- a/libs/angular/src/services/jslib-services.module.ts +++ b/libs/angular/src/services/jslib-services.module.ts @@ -86,6 +86,10 @@ import { AutofillSettingsServiceAbstraction, AutofillSettingsService, } from "@bitwarden/common/autofill/services/autofill-settings.service"; +import { + BadgeSettingsServiceAbstraction, + BadgeSettingsService, +} from "@bitwarden/common/autofill/services/badge-settings.service"; import { BillingApiServiceAbstraction } from "@bitwarden/common/billing/abstractions/billilng-api.service.abstraction"; import { BillingBannerServiceAbstraction } from "@bitwarden/common/billing/abstractions/billing-banner.service.abstraction"; import { OrganizationBillingServiceAbstraction } from "@bitwarden/common/billing/abstractions/organization-billing.service"; @@ -936,6 +940,11 @@ import { ModalService } from "./modal.service"; useClass: AutofillSettingsService, deps: [StateProvider, PolicyServiceAbstraction], }, + { + provide: BadgeSettingsServiceAbstraction, + useClass: BadgeSettingsService, + deps: [StateProvider], + }, { provide: BiometricStateService, useClass: DefaultBiometricStateService, diff --git a/libs/common/src/autofill/services/badge-settings.service.ts b/libs/common/src/autofill/services/badge-settings.service.ts new file mode 100644 index 00000000000..dcd266f8856 --- /dev/null +++ b/libs/common/src/autofill/services/badge-settings.service.ts @@ -0,0 +1,31 @@ +import { map, Observable } from "rxjs"; + +import { + BADGE_SETTINGS_DISK, + ActiveUserState, + KeyDefinition, + StateProvider, +} from "../../platform/state"; + +const ENABLE_BADGE_COUNTER = new KeyDefinition(BADGE_SETTINGS_DISK, "enableBadgeCounter", { + deserializer: (value: boolean) => value ?? true, +}); + +export abstract class BadgeSettingsServiceAbstraction { + enableBadgeCounter$: Observable; + setEnableBadgeCounter: (newValue: boolean) => Promise; +} + +export class BadgeSettingsService implements BadgeSettingsServiceAbstraction { + private enableBadgeCounterState: ActiveUserState; + readonly enableBadgeCounter$: Observable; + + constructor(private stateProvider: StateProvider) { + this.enableBadgeCounterState = this.stateProvider.getActive(ENABLE_BADGE_COUNTER); + this.enableBadgeCounter$ = this.enableBadgeCounterState.state$.pipe(map((x) => x ?? true)); + } + + async setEnableBadgeCounter(newValue: boolean): Promise { + await this.enableBadgeCounterState.update(() => newValue); + } +} diff --git a/libs/common/src/platform/abstractions/state.service.ts b/libs/common/src/platform/abstractions/state.service.ts index 505595eb29f..24da0dd3daa 100644 --- a/libs/common/src/platform/abstractions/state.service.ts +++ b/libs/common/src/platform/abstractions/state.service.ts @@ -204,8 +204,6 @@ export abstract class StateService { setDefaultUriMatch: (value: UriMatchType, options?: StorageOptions) => Promise; getDisableAddLoginNotification: (options?: StorageOptions) => Promise; setDisableAddLoginNotification: (value: boolean, options?: StorageOptions) => Promise; - getDisableBadgeCounter: (options?: StorageOptions) => Promise; - setDisableBadgeCounter: (value: boolean, options?: StorageOptions) => Promise; getDisableChangedPasswordNotification: (options?: StorageOptions) => Promise; setDisableChangedPasswordNotification: ( value: boolean, diff --git a/libs/common/src/platform/models/domain/account.ts b/libs/common/src/platform/models/domain/account.ts index e75efd34cd1..5fa1039fe36 100644 --- a/libs/common/src/platform/models/domain/account.ts +++ b/libs/common/src/platform/models/domain/account.ts @@ -202,7 +202,6 @@ export class AccountSettings { autoConfirmFingerPrints?: boolean; biometricUnlock?: boolean; defaultUriMatch?: UriMatchType; - disableBadgeCounter?: boolean; disableGa?: boolean; dontShowCardsCurrentTab?: boolean; dontShowIdentitiesCurrentTab?: boolean; diff --git a/libs/common/src/platform/services/state.service.ts b/libs/common/src/platform/services/state.service.ts index 0e45c94228d..3db3809d246 100644 --- a/libs/common/src/platform/services/state.service.ts +++ b/libs/common/src/platform/services/state.service.ts @@ -889,24 +889,6 @@ export class StateService< ); } - async getDisableBadgeCounter(options?: StorageOptions): Promise { - return ( - (await this.getAccount(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) - ?.settings?.disableBadgeCounter ?? false - ); - } - - async setDisableBadgeCounter(value: boolean, options?: StorageOptions): Promise { - const account = await this.getAccount( - this.reconcileOptions(options, await this.defaultOnDiskOptions()), - ); - account.settings.disableBadgeCounter = value; - await this.saveAccount( - account, - this.reconcileOptions(options, await this.defaultOnDiskOptions()), - ); - } - async getDisableChangedPasswordNotification(options?: StorageOptions): Promise { return ( (await this.getGlobals(this.reconcileOptions(options, await this.defaultOnDiskOptions()))) diff --git a/libs/common/src/platform/state/state-definitions.ts b/libs/common/src/platform/state/state-definitions.ts index 861ff639878..0962e7b37aa 100644 --- a/libs/common/src/platform/state/state-definitions.ts +++ b/libs/common/src/platform/state/state-definitions.ts @@ -53,6 +53,9 @@ export const VAULT_SETTINGS_DISK = new StateDefinition("vaultSettings", "disk", export const COLLECTION_DATA = new StateDefinition("collection", "disk", { web: "memory", }); + +export const BADGE_SETTINGS_DISK = new StateDefinition("badgeSettings", "disk"); + export const AUTOFILL_SETTINGS_DISK = new StateDefinition("autofillSettings", "disk"); export const AUTOFILL_SETTINGS_DISK_LOCAL = new StateDefinition("autofillSettingsLocal", "disk", { web: "disk-local", diff --git a/libs/common/src/state-migrations/migrate.ts b/libs/common/src/state-migrations/migrate.ts index 182ca4ea6af..bec8e0241f6 100644 --- a/libs/common/src/state-migrations/migrate.ts +++ b/libs/common/src/state-migrations/migrate.ts @@ -20,6 +20,7 @@ import { CollapsedGroupingsMigrator } from "./migrations/22-move-collapsed-group import { MoveBiometricPromptsToStateProviders } from "./migrations/23-move-biometric-prompts-to-state-providers"; import { SmOnboardingTasksMigrator } from "./migrations/24-move-sm-onboarding-key-to-state-providers"; import { ClearClipboardDelayMigrator } from "./migrations/25-move-clear-clipboard-to-autofill-settings-state-provider"; +import { BadgeSettingsMigrator } from "./migrations/26-move-badge-settings-to-state-providers"; import { FixPremiumMigrator } from "./migrations/3-fix-premium"; import { RemoveEverBeenUnlockedMigrator } from "./migrations/4-remove-ever-been-unlocked"; import { AddKeyTypeToOrgKeysMigrator } from "./migrations/5-add-key-type-to-org-keys"; @@ -30,7 +31,7 @@ import { MoveBrowserSettingsToGlobal } from "./migrations/9-move-browser-setting import { MinVersionMigrator } from "./migrations/min-version"; export const MIN_VERSION = 2; -export const CURRENT_VERSION = 25; +export const CURRENT_VERSION = 26; export type MinVersion = typeof MIN_VERSION; export function createMigrationBuilder() { @@ -58,7 +59,8 @@ export function createMigrationBuilder() { .with(CollapsedGroupingsMigrator, 21, 22) .with(MoveBiometricPromptsToStateProviders, 22, 23) .with(SmOnboardingTasksMigrator, 23, 24) - .with(ClearClipboardDelayMigrator, 24, CURRENT_VERSION); + .with(ClearClipboardDelayMigrator, 24, 25) + .with(BadgeSettingsMigrator, 25, CURRENT_VERSION); } export async function currentVersion( diff --git a/libs/common/src/state-migrations/migrations/18-move-autofill-settings-to-state-providers.spec.ts b/libs/common/src/state-migrations/migrations/18-move-autofill-settings-to-state-providers.spec.ts index 84ca11fde17..2ca58fc31f9 100644 --- a/libs/common/src/state-migrations/migrations/18-move-autofill-settings-to-state-providers.spec.ts +++ b/libs/common/src/state-migrations/migrations/18-move-autofill-settings-to-state-providers.spec.ts @@ -73,7 +73,7 @@ const autofillSettingsStateDefinition: { }, }; -describe("ProviderKeysMigrator", () => { +describe("AutofillSettingsKeyMigrator", () => { let helper: MockProxy; let sut: AutofillSettingsKeyMigrator; diff --git a/libs/common/src/state-migrations/migrations/25-move-clear-clipboard-to-autofill-settings-state-provider.spec.ts b/libs/common/src/state-migrations/migrations/25-move-clear-clipboard-to-autofill-settings-state-provider.spec.ts index 083c1fb0303..c9507c846a9 100644 --- a/libs/common/src/state-migrations/migrations/25-move-clear-clipboard-to-autofill-settings-state-provider.spec.ts +++ b/libs/common/src/state-migrations/migrations/25-move-clear-clipboard-to-autofill-settings-state-provider.spec.ts @@ -82,7 +82,7 @@ const autofillSettingsLocalStateDefinition: { }, }; -describe("ProviderKeysMigrator", () => { +describe("ClearClipboardDelayMigrator", () => { let helper: MockProxy; let sut: ClearClipboardDelayMigrator; diff --git a/libs/common/src/state-migrations/migrations/26-move-badge-settings-to-state-providers.spec.ts b/libs/common/src/state-migrations/migrations/26-move-badge-settings-to-state-providers.spec.ts new file mode 100644 index 00000000000..599cbf14b81 --- /dev/null +++ b/libs/common/src/state-migrations/migrations/26-move-badge-settings-to-state-providers.spec.ts @@ -0,0 +1,166 @@ +import { any, MockProxy } from "jest-mock-extended"; + +import { StateDefinitionLike, MigrationHelper } from "../migration-helper"; +import { mockMigrationHelper } from "../migration-helper.spec"; + +import { BadgeSettingsMigrator } from "./26-move-badge-settings-to-state-providers"; + +function exampleJSON() { + return { + global: { + otherStuff: "otherStuff1", + }, + authenticatedAccounts: ["user-1", "user-2", "user-3"], + "user-1": { + settings: { + disableBadgeCounter: true, + otherStuff: "otherStuff2", + }, + otherStuff: "otherStuff3", + }, + "user-2": { + settings: { + disableBadgeCounter: false, + otherStuff: "otherStuff4", + }, + otherStuff: "otherStuff5", + }, + "user-3": { + settings: { + otherStuff: "otherStuff6", + }, + otherStuff: "otherStuff7", + }, + }; +} + +function rollbackJSON() { + return { + "user_user-1_badgeSettings_enableBadgeCounter": false, + "user_user-2_badgeSettings_enableBadgeCounter": true, + global: { + otherStuff: "otherStuff1", + }, + authenticatedAccounts: ["user-1", "user-2", "user-3"], + "user-1": { + settings: { + otherStuff: "otherStuff2", + }, + otherStuff: "otherStuff3", + }, + "user-2": { + settings: { + otherStuff: "otherStuff4", + }, + otherStuff: "otherStuff5", + }, + "user-3": { + settings: { + otherStuff: "otherStuff6", + }, + otherStuff: "otherStuff7", + }, + }; +} + +const badgeSettingsStateDefinition: { + stateDefinition: StateDefinitionLike; +} = { + stateDefinition: { + name: "badgeSettings", + }, +}; + +describe("BadgeSettingsMigrator", () => { + let helper: MockProxy; + let sut: BadgeSettingsMigrator; + + describe("migrate", () => { + beforeEach(() => { + helper = mockMigrationHelper(exampleJSON(), 25); + sut = new BadgeSettingsMigrator(25, 26); + }); + + it("should remove disableBadgeCounter setting from all accounts", async () => { + await sut.migrate(helper); + expect(helper.set).toHaveBeenCalledTimes(2); + expect(helper.set).toHaveBeenCalledWith("user-1", { + settings: { + otherStuff: "otherStuff2", + }, + otherStuff: "otherStuff3", + }); + expect(helper.set).toHaveBeenCalledWith("user-2", { + settings: { + otherStuff: "otherStuff4", + }, + otherStuff: "otherStuff5", + }); + }); + + it("should set badge setting values for each account", async () => { + await sut.migrate(helper); + + expect(helper.setToUser).toHaveBeenCalledTimes(2); + expect(helper.setToUser).toHaveBeenCalledWith( + "user-1", + { ...badgeSettingsStateDefinition, key: "enableBadgeCounter" }, + false, + ); + expect(helper.setToUser).toHaveBeenCalledWith( + "user-2", + { ...badgeSettingsStateDefinition, key: "enableBadgeCounter" }, + true, + ); + }); + }); + + describe("rollback", () => { + beforeEach(() => { + helper = mockMigrationHelper(rollbackJSON(), 24); + sut = new BadgeSettingsMigrator(25, 26); + }); + + it("should null out new values for each account", async () => { + await sut.rollback(helper); + + expect(helper.setToUser).toHaveBeenCalledTimes(2); + expect(helper.setToUser).toHaveBeenCalledWith( + "user-1", + { ...badgeSettingsStateDefinition, key: "enableBadgeCounter" }, + null, + ); + expect(helper.setToUser).toHaveBeenCalledWith( + "user-2", + { ...badgeSettingsStateDefinition, key: "enableBadgeCounter" }, + null, + ); + }); + + it("should add explicit value back to accounts", async () => { + await sut.rollback(helper); + + expect(helper.set).toHaveBeenCalledTimes(2); + expect(helper.set).toHaveBeenCalledWith("user-1", { + settings: { + disableBadgeCounter: true, + otherStuff: "otherStuff2", + }, + otherStuff: "otherStuff3", + }); + expect(helper.set).toHaveBeenCalledWith("user-2", { + settings: { + disableBadgeCounter: false, + otherStuff: "otherStuff4", + }, + otherStuff: "otherStuff5", + }); + }); + + it("should not try to restore values to missing accounts", async () => { + await sut.rollback(helper); + + expect(helper.set).not.toHaveBeenCalledWith("user-3", any()); + }); + }); +}); diff --git a/libs/common/src/state-migrations/migrations/26-move-badge-settings-to-state-providers.ts b/libs/common/src/state-migrations/migrations/26-move-badge-settings-to-state-providers.ts new file mode 100644 index 00000000000..090cb5a7900 --- /dev/null +++ b/libs/common/src/state-migrations/migrations/26-move-badge-settings-to-state-providers.ts @@ -0,0 +1,71 @@ +import { KeyDefinitionLike, MigrationHelper } from "../migration-helper"; +import { Migrator } from "../migrator"; + +type ExpectedAccountState = { + settings?: { + disableBadgeCounter?: boolean; + }; +}; + +const enableBadgeCounterKeyDefinition: KeyDefinitionLike = { + stateDefinition: { + name: "badgeSettings", + }, + key: "enableBadgeCounter", +}; + +export class BadgeSettingsMigrator extends Migrator<25, 26> { + async migrate(helper: MigrationHelper): Promise { + // account state (e.g. account settings -> state provider framework keys) + const accounts = await helper.getAccounts(); + + await Promise.all([...accounts.map(({ userId, account }) => migrateAccount(userId, account))]); + + // migrate account state + async function migrateAccount(userId: string, account: ExpectedAccountState): Promise { + const accountSettings = account?.settings; + + if (accountSettings?.disableBadgeCounter != undefined) { + await helper.setToUser( + userId, + enableBadgeCounterKeyDefinition, + !accountSettings.disableBadgeCounter, + ); + delete account.settings.disableBadgeCounter; + + // update the state account settings with the migrated values deleted + await helper.set(userId, account); + } + } + } + + async rollback(helper: MigrationHelper): Promise { + // account state (e.g. state provider framework keys -> account settings) + const accounts = await helper.getAccounts(); + + await Promise.all([...accounts.map(({ userId, account }) => rollbackAccount(userId, account))]); + + // rollback account state + async function rollbackAccount(userId: string, account: ExpectedAccountState): Promise { + let settings = account?.settings || {}; + + const enableBadgeCounter: boolean = await helper.getFromUser( + userId, + enableBadgeCounterKeyDefinition, + ); + + // update new settings and remove the account state provider framework keys for the rolled back values + if (enableBadgeCounter != undefined) { + settings = { ...settings, disableBadgeCounter: !enableBadgeCounter }; + + await helper.setToUser(userId, enableBadgeCounterKeyDefinition, null); + + // commit updated settings to state + await helper.set(userId, { + ...account, + settings, + }); + } + } + } +}