1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-12-21 16:18:28 +01:00

[PM-12345] Add cipher type settings for inline autofill menu (#11260)

* add inline menu identity and card visibility settings state to autofill settings service

* add inline menu identity and card visibility settings to autofill settings view component

* add inline menu identity and card visibility settings to legacy autofill settings view component

* do not show inline menu card and identity visibility settings if inline-menu-positioning-improvements feature flag is off

* show card and identity inline menus based on their visibility settings

* do not show identities in account creation username/email fields if user setting disallows it

* reload local tab settings for inline menu visibility when an inline visibility setting value changes

* take out tabSendMessageData call for inline menu visibility sub-settings

---------

Co-authored-by: Cesar Gonzalez <cesar.a.gonzalezcs@gmail.com>
This commit is contained in:
Jonathan Prusik 2024-10-15 11:07:52 -04:00 committed by GitHub
parent 40ab96a7ce
commit 1c2cb4440b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 291 additions and 29 deletions

View File

@ -1408,6 +1408,12 @@
"showInlineMenuLabel": {
"message": "Show autofill suggestions on form fields"
},
"showInlineMenuIdentitiesLabel": {
"message": "Display identities as suggestions"
},
"showInlineMenuCardsLabel": {
"message": "Display cards as suggestions"
},
"showInlineMenuOnIconSelectionLabel": {
"message": "Display suggestions when icon is selected"
},

View File

@ -188,6 +188,8 @@ export type OverlayBackgroundExtensionMessageHandlers = {
updateIsFieldCurrentlyFilling: ({ message }: BackgroundMessageParam) => void;
checkIsFieldCurrentlyFilling: () => boolean;
getAutofillInlineMenuVisibility: () => void;
getInlineMenuCardsVisibility: () => void;
getInlineMenuIdentitiesVisibility: () => void;
openAutofillInlineMenu: () => void;
closeAutofillInlineMenu: ({ message, sender }: BackgroundOnMessageHandlerParams) => void;
checkAutofillInlineMenuFocused: ({ sender }: BackgroundSenderParam) => void;

View File

@ -132,6 +132,8 @@ export class OverlayBackground implements OverlayBackgroundInterface {
updateIsFieldCurrentlyFilling: ({ message }) => this.updateIsFieldCurrentlyFilling(message),
checkIsFieldCurrentlyFilling: () => this.checkIsFieldCurrentlyFilling(),
getAutofillInlineMenuVisibility: () => this.getInlineMenuVisibility(),
getInlineMenuCardsVisibility: () => this.getInlineMenuCardsVisibility(),
getInlineMenuIdentitiesVisibility: () => this.getInlineMenuIdentitiesVisibility(),
openAutofillInlineMenu: () => this.openInlineMenu(false),
closeAutofillInlineMenu: ({ message, sender }) => this.closeInlineMenu(sender, message),
checkAutofillInlineMenuFocused: ({ sender }) => this.checkInlineMenuFocused(sender),
@ -1483,6 +1485,20 @@ export class OverlayBackground implements OverlayBackgroundInterface {
return await firstValueFrom(this.autofillSettingsService.inlineMenuVisibility$);
}
/**
* Gets the inline menu's visibility setting for Cards from the settings service.
*/
private async getInlineMenuCardsVisibility(): Promise<boolean> {
return await firstValueFrom(this.autofillSettingsService.showInlineMenuCards$);
}
/**
* Gets the inline menu's visibility setting for Identities from the settings service.
*/
private async getInlineMenuIdentitiesVisibility(): Promise<boolean> {
return await firstValueFrom(this.autofillSettingsService.showInlineMenuIdentities$);
}
/**
* Gets the user's authentication status from the auth service.
*/

View File

@ -1,4 +1,5 @@
import { AuthenticationStatus } from "@bitwarden/common/auth/enums/authentication-status";
import { InlineMenuVisibilitySetting } from "@bitwarden/common/autofill/types";
import { CipherType } from "@bitwarden/common/vault/enums";
import { AutofillOverlayElementType } from "../../enums/autofill-overlay.enum";
@ -23,7 +24,7 @@ export type AutofillExtensionMessage = {
data?: {
direction?: "previous" | "next" | "current";
forceCloseInlineMenu?: boolean;
inlineMenuVisibility?: number;
newSettingValue?: InlineMenuVisibilitySetting;
};
};

View File

@ -46,6 +46,32 @@
</div>
</div>
</div>
<div class="box tw-mb-5" *ngIf="inlineMenuPositioningImprovementsEnabled && inlineMenuIsEnabled">
<div class="box-content">
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="show-inline-menu-identities" class="!tw-mr-0">{{
"showInlineMenuIdentitiesLabel" | i18n
}}</label>
<input
id="show-inline-menu-identities"
type="checkbox"
(change)="updateShowInlineMenuIdentities()"
[(ngModel)]="showInlineMenuIdentities"
/>
</div>
<div class="box-content-row box-content-row-checkbox" appBoxRow>
<label for="show-inline-menu-cards" class="!tw-mr-0">{{
"showInlineMenuCardsLabel" | i18n
}}</label>
<input
id="show-inline-menu-cards"
type="checkbox"
(change)="updateShowInlineMenuCards()"
[(ngModel)]="showInlineMenuCards"
/>
</div>
</div>
</div>
<div class="box">
<div class="box-content" *ngIf="canOverrideBrowserAutofillSetting">
<div class="box-content-row box-content-row-checkbox" appBoxRow>

View File

@ -8,10 +8,12 @@ import {
InlineMenuVisibilitySetting,
ClearClipboardDelaySetting,
} from "@bitwarden/common/autofill/types";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import {
UriMatchStrategy,
UriMatchStrategySetting,
} from "@bitwarden/common/models/domain/domain-service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -20,7 +22,6 @@ import { DialogService } from "@bitwarden/components";
import { BrowserApi } from "../../../platform/browser/browser-api";
import { enableAccountSwitching } from "../../../platform/flags";
import { AutofillService } from "../../services/abstractions/autofill.service";
@Component({
selector: "app-autofill-v1",
@ -32,6 +33,10 @@ export class AutofillV1Component implements OnInit {
protected autoFillOverlayVisibility: InlineMenuVisibilitySetting;
protected autoFillOverlayVisibilityOptions: any[];
protected disablePasswordManagerLink: string;
protected inlineMenuPositioningImprovementsEnabled: boolean = false;
protected showInlineMenuIdentities: boolean = true;
protected showInlineMenuCards: boolean = true;
inlineMenuIsEnabled: boolean = false;
enableAutoFillOnPageLoad = false;
autoFillOnPageLoadDefault = false;
autoFillOnPageLoadOptions: any[];
@ -50,7 +55,7 @@ export class AutofillV1Component implements OnInit {
private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService,
private domainSettingsService: DomainSettingsService,
private autofillService: AutofillService,
private configService: ConfigService,
private dialogService: DialogService,
private autofillSettingsService: AutofillSettingsServiceAbstraction,
private messagingService: MessagingService,
@ -109,6 +114,20 @@ export class AutofillV1Component implements OnInit {
this.autofillSettingsService.inlineMenuVisibility$,
);
this.inlineMenuPositioningImprovementsEnabled = await this.configService.getFeatureFlag(
FeatureFlag.InlineMenuPositioningImprovements,
);
this.inlineMenuIsEnabled = this.isInlineMenuEnabled();
this.showInlineMenuIdentities =
this.inlineMenuPositioningImprovementsEnabled &&
(await firstValueFrom(this.autofillSettingsService.showInlineMenuIdentities$));
this.showInlineMenuCards =
this.inlineMenuPositioningImprovementsEnabled &&
(await firstValueFrom(this.autofillSettingsService.showInlineMenuCards$));
this.enableAutoFillOnPageLoad = await firstValueFrom(
this.autofillSettingsService.autofillOnPageLoad$,
);
@ -140,9 +159,18 @@ export class AutofillV1Component implements OnInit {
);
}
isInlineMenuEnabled() {
return (
this.autoFillOverlayVisibility === AutofillOverlayVisibility.OnFieldFocus ||
this.autoFillOverlayVisibility === AutofillOverlayVisibility.OnButtonClick
);
}
async updateAutoFillOverlayVisibility() {
await this.autofillSettingsService.setInlineMenuVisibility(this.autoFillOverlayVisibility);
await this.requestPrivacyPermission();
this.inlineMenuIsEnabled = this.isInlineMenuEnabled();
}
async updateAutoFillOnPageLoad() {
@ -298,4 +326,12 @@ export class AutofillV1Component implements OnInit {
async updateShowIdentitiesCurrentTab() {
await this.vaultSettingsService.setShowIdentitiesCurrentTab(this.showIdentitiesCurrentTab);
}
async updateShowInlineMenuCards() {
await this.autofillSettingsService.setShowInlineMenuCards(this.showInlineMenuCards);
}
async updateShowInlineMenuIdentities() {
await this.autofillSettingsService.setShowInlineMenuIdentities(this.showInlineMenuIdentities);
}
}

View File

@ -27,7 +27,37 @@
{{ "showInlineMenuOnFormFieldsDescAlt" | i18n }}
</bit-hint>
</bit-form-control>
<bit-form-control *ngIf="enableInlineMenu" class="tw-pl-5">
<bit-form-control
*ngIf="inlineMenuPositioningImprovementsEnabled && enableInlineMenu"
class="tw-ml-5"
>
<input
bitCheckbox
id="show-inline-menu-identities"
type="checkbox"
(change)="updateShowInlineMenuIdentities()"
[(ngModel)]="showInlineMenuIdentities"
/>
<bit-label for="show-inline-menu-identities">
{{ "showInlineMenuIdentitiesLabel" | i18n }}
</bit-label>
</bit-form-control>
<bit-form-control
*ngIf="inlineMenuPositioningImprovementsEnabled && enableInlineMenu"
class="tw-ml-5"
>
<input
bitCheckbox
id="show-inline-menu-cards"
type="checkbox"
(change)="updateShowInlineMenuCards()"
[(ngModel)]="showInlineMenuCards"
/>
<bit-label for="show-inline-menu-cards">
{{ "showInlineMenuCardsLabel" | i18n }}
</bit-label>
</bit-form-control>
<bit-form-control *ngIf="enableInlineMenu" class="tw-ml-5">
<input
bitCheckbox
id="show-autofill-suggestions-on-icon"

View File

@ -21,10 +21,12 @@ import {
DisablePasswordManagerUri,
InlineMenuVisibilitySetting,
} from "@bitwarden/common/autofill/types";
import { FeatureFlag } from "@bitwarden/common/enums/feature-flag.enum";
import {
UriMatchStrategy,
UriMatchStrategySetting,
} from "@bitwarden/common/models/domain/domain-service";
import { ConfigService } from "@bitwarden/common/platform/abstractions/config/config.service";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
@ -82,6 +84,7 @@ export class AutofillComponent implements OnInit {
protected defaultBrowserAutofillDisabled: boolean = false;
protected inlineMenuVisibility: InlineMenuVisibilitySetting =
AutofillOverlayVisibility.OnFieldFocus;
protected inlineMenuPositioningImprovementsEnabled: boolean = false;
protected browserClientVendor: BrowserClientVendor = BrowserClientVendors.Unknown;
protected disablePasswordManagerURI: DisablePasswordManagerUri =
DisablePasswordManagerUris.Unknown;
@ -93,6 +96,8 @@ export class AutofillComponent implements OnInit {
enableAutofillOnPageLoad: boolean = false;
enableInlineMenu: boolean = false;
enableInlineMenuOnIconSelect: boolean = false;
showInlineMenuIdentities: boolean = true;
showInlineMenuCards: boolean = true;
autofillOnPageLoadDefault: boolean = false;
autofillOnPageLoadOptions: { name: string; value: boolean }[];
enableContextMenuItem: boolean = false;
@ -114,6 +119,7 @@ export class AutofillComponent implements OnInit {
private autofillSettingsService: AutofillSettingsServiceAbstraction,
private messagingService: MessagingService,
private vaultSettingsService: VaultSettingsService,
private configService: ConfigService,
) {
this.autofillOnPageLoadOptions = [
{ name: i18nService.t("autoFillOnPageLoadYes"), value: true },
@ -151,6 +157,18 @@ export class AutofillComponent implements OnInit {
this.autofillSettingsService.inlineMenuVisibility$,
);
this.inlineMenuPositioningImprovementsEnabled = await this.configService.getFeatureFlag(
FeatureFlag.InlineMenuPositioningImprovements,
);
this.showInlineMenuIdentities =
this.inlineMenuPositioningImprovementsEnabled &&
(await firstValueFrom(this.autofillSettingsService.showInlineMenuIdentities$));
this.showInlineMenuCards =
this.inlineMenuPositioningImprovementsEnabled &&
(await firstValueFrom(this.autofillSettingsService.showInlineMenuCards$));
this.enableInlineMenuOnIconSelect =
this.inlineMenuVisibility === AutofillOverlayVisibility.OnButtonClick;
@ -381,4 +399,12 @@ export class AutofillComponent implements OnInit {
async updateShowIdentitiesCurrentTab() {
await this.vaultSettingsService.setShowIdentitiesCurrentTab(this.showIdentitiesCurrentTab);
}
async updateShowInlineMenuCards() {
await this.autofillSettingsService.setShowInlineMenuCards(this.showInlineMenuCards);
}
async updateShowInlineMenuIdentities() {
await this.autofillSettingsService.setShowInlineMenuIdentities(this.showInlineMenuIdentities);
}
}

View File

@ -2238,7 +2238,7 @@ describe("AutofillOverlayContentService", () => {
it("updates the inlineMenuVisibility property", () => {
sendMockExtensionMessage({
command: "updateAutofillInlineMenuVisibility",
data: { inlineMenuVisibility: AutofillOverlayVisibility.OnButtonClick },
data: { newSettingValue: AutofillOverlayVisibility.OnButtonClick },
});
expect(autofillOverlayContentService["inlineMenuVisibility"]).toEqual(

View File

@ -9,6 +9,7 @@ import {
AUTOFILL_OVERLAY_HANDLE_REPOSITION,
AUTOFILL_TRIGGER_FORM_FIELD_SUBMIT,
} from "@bitwarden/common/autofill/constants";
import { InlineMenuVisibilitySetting } from "@bitwarden/common/autofill/types";
import { CipherType } from "@bitwarden/common/vault/enums";
import {
@ -51,7 +52,9 @@ import { AutoFillConstants } from "./autofill-constants";
export class AutofillOverlayContentService implements AutofillOverlayContentServiceInterface {
pageDetailsUpdateRequired = false;
inlineMenuVisibility: number;
inlineMenuVisibility: InlineMenuVisibilitySetting;
private showInlineMenuIdentities: boolean;
private showInlineMenuCards: boolean;
private readonly findTabs = tabbable;
private readonly sendExtensionMessage = sendExtensionMessage;
private formFieldElements: Map<ElementWithOpId<FormFieldElement>, AutofillField> = new Map();
@ -183,6 +186,18 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
autofillFieldData: AutofillField,
pageDetails: AutofillPageDetails,
) {
if (!this.inlineMenuVisibility) {
await this.getInlineMenuVisibility();
}
if (this.showInlineMenuCards == null) {
await this.getInlineMenuCardsVisibility();
}
if (this.showInlineMenuIdentities == null) {
await this.getInlineMenuIdentitiesVisibility();
}
if (
this.formFieldElements.has(formFieldElement) ||
this.isIgnoredField(autofillFieldData, pageDetails)
@ -1019,10 +1034,16 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
const { width, height, top, left } =
await this.getMostRecentlyFocusedFieldRects(formFieldElement);
const autofillFieldData = this.formFieldElements.get(formFieldElement);
let accountCreationFieldType = null;
if (
// user setting allows display of identities in inline menu
this.showInlineMenuIdentities &&
// `showInlineMenuAccountCreation` has been set or field is filled by Login cipher
(autofillFieldData?.showInlineMenuAccountCreation ||
autofillFieldData?.filledByCipherType === CipherType.Login) &&
// field is a username field, which is relevant to both Identity and Login ciphers
this.inlineMenuFieldQualificationService.isUsernameField(autofillFieldData)
) {
accountCreationFieldType = this.inlineMenuFieldQualificationService.isEmailField(
@ -1125,6 +1146,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
}
if (
this.showInlineMenuCards &&
this.inlineMenuFieldQualificationService.isFieldForCreditCardForm(
autofillFieldData,
pageDetails,
@ -1135,6 +1157,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
}
if (
this.showInlineMenuIdentities &&
this.inlineMenuFieldQualificationService.isFieldForAccountCreationForm(
autofillFieldData,
pageDetails,
@ -1146,6 +1169,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
}
if (
this.showInlineMenuIdentities &&
this.inlineMenuFieldQualificationService.isFieldForIdentityForm(
autofillFieldData,
pageDetails,
@ -1244,6 +1268,7 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
autofillFieldData.readonly = getAttributeBoolean(formFieldElement, "disabled");
autofillFieldData.disabled = getAttributeBoolean(formFieldElement, "disabled");
autofillFieldData.viewable = true;
void this.setupOverlayListenersOnQualifiedField(formFieldElement, autofillFieldData);
}
@ -1266,10 +1291,6 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
await this.updateMostRecentlyFocusedField(formFieldElement);
}
if (!this.inlineMenuVisibility) {
await this.getInlineMenuVisibility();
}
this.setupFormFieldElementEventListeners(formFieldElement);
this.setupFormSubmissionEventListeners(formFieldElement, autofillFieldData);
@ -1291,6 +1312,30 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
this.inlineMenuVisibility = inlineMenuVisibility || AutofillOverlayVisibility.OnFieldFocus;
}
/**
* Queries the background script for the autofill inline menu's Cards visibility setting.
* If the setting is not found, a default value of true will be used
* @private
*/
private async getInlineMenuCardsVisibility() {
const inlineMenuCardsVisibility = await this.sendExtensionMessage(
"getInlineMenuCardsVisibility",
);
this.showInlineMenuCards = inlineMenuCardsVisibility ?? true;
}
/**
* Queries the background script for the autofill inline menu's Identities visibility setting.
* If the setting is not found, a default value of true will be used
* @private
*/
private async getInlineMenuIdentitiesVisibility() {
const inlineMenuIdentitiesVisibility = await this.sendExtensionMessage(
"getInlineMenuIdentitiesVisibility",
);
this.showInlineMenuIdentities = inlineMenuIdentitiesVisibility ?? true;
}
/**
* Returns a value that indicates if we should hide the inline menu list due to a filled field.
*
@ -1318,8 +1363,10 @@ export class AutofillOverlayContentService implements AutofillOverlayContentServ
* @param data - The data object from the extension message.
*/
private updateInlineMenuVisibility({ data }: AutofillExtensionMessage) {
if (!isNaN(data?.inlineMenuVisibility)) {
this.inlineMenuVisibility = data.inlineMenuVisibility;
const newSettingValue = data?.newSettingValue;
if (!isNaN(newSettingValue)) {
this.inlineMenuVisibility = newSettingValue;
}
}

View File

@ -75,6 +75,8 @@ describe("AutofillService", () => {
let autofillService: AutofillService;
const cipherService = mock<CipherService>();
let inlineMenuVisibilityMock$!: BehaviorSubject<InlineMenuVisibilitySetting>;
let showInlineMenuCardsMock$!: BehaviorSubject<boolean>;
let showInlineMenuIdentitiesMock$!: BehaviorSubject<boolean>;
let autofillSettingsService: MockProxy<AutofillSettingsServiceAbstraction>;
const mockUserId = Utils.newGuid() as UserId;
const accountService: FakeAccountService = mockAccountServiceWith(mockUserId);
@ -98,8 +100,12 @@ describe("AutofillService", () => {
beforeEach(() => {
scriptInjectorService = new BrowserScriptInjectorService(platformUtilsService, logService);
inlineMenuVisibilityMock$ = new BehaviorSubject(AutofillOverlayVisibility.OnFieldFocus);
showInlineMenuCardsMock$ = new BehaviorSubject(false);
showInlineMenuIdentitiesMock$ = new BehaviorSubject(false);
autofillSettingsService = mock<AutofillSettingsServiceAbstraction>();
autofillSettingsService.inlineMenuVisibility$ = inlineMenuVisibilityMock$;
autofillSettingsService.showInlineMenuCards$ = showInlineMenuCardsMock$;
autofillSettingsService.showInlineMenuIdentities$ = showInlineMenuIdentitiesMock$;
activeAccountStatusMock$ = new BehaviorSubject(AuthenticationStatus.Unlocked);
authService = mock<AuthService>();
authService.activeAccountStatus$ = activeAccountStatusMock$;
@ -291,12 +297,12 @@ describe("AutofillService", () => {
expect(BrowserApi.tabSendMessageData).toHaveBeenCalledWith(
tab1,
"updateAutofillInlineMenuVisibility",
{ inlineMenuVisibility: AutofillOverlayVisibility.OnButtonClick },
{ newSettingValue: AutofillOverlayVisibility.OnButtonClick },
);
expect(BrowserApi.tabSendMessageData).toHaveBeenCalledWith(
tab2,
"updateAutofillInlineMenuVisibility",
{ inlineMenuVisibility: AutofillOverlayVisibility.OnButtonClick },
{ newSettingValue: AutofillOverlayVisibility.OnButtonClick },
);
});
@ -308,12 +314,12 @@ describe("AutofillService", () => {
expect(BrowserApi.tabSendMessageData).toHaveBeenCalledWith(
tab1,
"updateAutofillInlineMenuVisibility",
{ inlineMenuVisibility: AutofillOverlayVisibility.OnFieldFocus },
{ newSettingValue: AutofillOverlayVisibility.OnFieldFocus },
);
expect(BrowserApi.tabSendMessageData).toHaveBeenCalledWith(
tab2,
"updateAutofillInlineMenuVisibility",
{ inlineMenuVisibility: AutofillOverlayVisibility.OnFieldFocus },
{ newSettingValue: AutofillOverlayVisibility.OnFieldFocus },
);
});
});

View File

@ -130,10 +130,23 @@ export default class AutofillService implements AutofillServiceInterface {
async loadAutofillScriptsOnInstall() {
BrowserApi.addListener(chrome.runtime.onConnect, this.handleInjectedScriptPortConnection);
void this.injectAutofillScriptsInAllTabs();
this.autofillSettingsService.inlineMenuVisibility$
.pipe(startWith(undefined), pairwise())
.subscribe(([previousSetting, currentSetting]) =>
this.handleInlineMenuVisibilityChange(previousSetting, currentSetting),
this.handleInlineMenuVisibilitySettingsChange(previousSetting, currentSetting),
);
this.autofillSettingsService.showInlineMenuCards$
.pipe(startWith(undefined), pairwise())
.subscribe(([previousSetting, currentSetting]) =>
this.handleInlineMenuVisibilitySettingsChange(previousSetting, currentSetting),
);
this.autofillSettingsService.showInlineMenuIdentities$
.pipe(startWith(undefined), pairwise())
.subscribe(([previousSetting, currentSetting]) =>
this.handleInlineMenuVisibilitySettingsChange(previousSetting, currentSetting),
);
}
@ -3043,27 +3056,36 @@ export default class AutofillService implements AutofillServiceInterface {
}
/**
* Updates the autofill inline menu visibility setting in all active tabs
* when the InlineMenuVisibilitySetting observable is updated.
* Updates the autofill inline menu visibility settings in all active tabs
* when the inlineMenuVisibility, showInlineMenuCards, or showInlineMenuIdentities
* observables are updated.
*
* @param previousSetting - The previous setting value
* @param currentSetting - The current setting value
* @param oldSettingValue - The previous setting value
* @param newSettingValue - The current setting value
* @param cipherType - The cipher type of the changed inline menu setting
*/
private async handleInlineMenuVisibilityChange(
previousSetting: InlineMenuVisibilitySetting,
currentSetting: InlineMenuVisibilitySetting,
private async handleInlineMenuVisibilitySettingsChange(
oldSettingValue: InlineMenuVisibilitySetting | boolean,
newSettingValue: InlineMenuVisibilitySetting | boolean,
) {
if (previousSetting === undefined || previousSetting === currentSetting) {
if (oldSettingValue === undefined || oldSettingValue === newSettingValue) {
return;
}
const inlineMenuPreviouslyDisabled = previousSetting === AutofillOverlayVisibility.Off;
const inlineMenuCurrentlyDisabled = currentSetting === AutofillOverlayVisibility.Off;
if (!inlineMenuPreviouslyDisabled && !inlineMenuCurrentlyDisabled) {
const isInlineMenuVisibilitySubSetting =
typeof oldSettingValue === "boolean" || typeof newSettingValue === "boolean";
const inlineMenuPreviouslyDisabled = oldSettingValue === AutofillOverlayVisibility.Off;
const inlineMenuCurrentlyDisabled = newSettingValue === AutofillOverlayVisibility.Off;
if (
!isInlineMenuVisibilitySubSetting &&
!inlineMenuPreviouslyDisabled &&
!inlineMenuCurrentlyDisabled
) {
const tabs = await BrowserApi.tabsQuery({});
tabs.forEach((tab) =>
BrowserApi.tabSendMessageData(tab, "updateAutofillInlineMenuVisibility", {
inlineMenuVisibility: currentSetting,
newSettingValue,
}),
);
return;

View File

@ -59,6 +59,24 @@ const INLINE_MENU_VISIBILITY = new KeyDefinition(
},
);
const SHOW_INLINE_MENU_IDENTITIES = new UserKeyDefinition(
AUTOFILL_SETTINGS_DISK,
"showInlineMenuIdentities",
{
deserializer: (value: boolean) => value ?? true,
clearOn: [],
},
);
const SHOW_INLINE_MENU_CARDS = new UserKeyDefinition(
AUTOFILL_SETTINGS_DISK,
"showInlineMenuCards",
{
deserializer: (value: boolean) => value ?? true,
clearOn: [],
},
);
const ENABLE_CONTEXT_MENU = new KeyDefinition(AUTOFILL_SETTINGS_DISK, "enableContextMenu", {
deserializer: (value: boolean) => value ?? true,
});
@ -86,6 +104,10 @@ export abstract class AutofillSettingsServiceAbstraction {
setAutoCopyTotp: (newValue: boolean) => Promise<void>;
inlineMenuVisibility$: Observable<InlineMenuVisibilitySetting>;
setInlineMenuVisibility: (newValue: InlineMenuVisibilitySetting) => Promise<void>;
showInlineMenuIdentities$: Observable<boolean>;
setShowInlineMenuIdentities: (newValue: boolean) => Promise<void>;
showInlineMenuCards$: Observable<boolean>;
setShowInlineMenuCards: (newValue: boolean) => Promise<void>;
enableContextMenu$: Observable<boolean>;
setEnableContextMenu: (newValue: boolean) => Promise<void>;
clearClipboardDelay$: Observable<ClearClipboardDelaySetting>;
@ -113,6 +135,12 @@ export class AutofillSettingsService implements AutofillSettingsServiceAbstracti
private inlineMenuVisibilityState: GlobalState<InlineMenuVisibilitySetting>;
readonly inlineMenuVisibility$: Observable<InlineMenuVisibilitySetting>;
private showInlineMenuIdentitiesState: ActiveUserState<boolean>;
readonly showInlineMenuIdentities$: Observable<boolean>;
private showInlineMenuCardsState: ActiveUserState<boolean>;
readonly showInlineMenuCards$: Observable<boolean>;
private enableContextMenuState: GlobalState<boolean>;
readonly enableContextMenu$: Observable<boolean>;
@ -157,6 +185,14 @@ export class AutofillSettingsService implements AutofillSettingsServiceAbstracti
map((x) => x ?? AutofillOverlayVisibility.Off),
);
this.showInlineMenuIdentitiesState = this.stateProvider.getActive(SHOW_INLINE_MENU_IDENTITIES);
this.showInlineMenuIdentities$ = this.showInlineMenuIdentitiesState.state$.pipe(
map((x) => x ?? true),
);
this.showInlineMenuCardsState = this.stateProvider.getActive(SHOW_INLINE_MENU_CARDS);
this.showInlineMenuCards$ = this.showInlineMenuCardsState.state$.pipe(map((x) => x ?? true));
this.enableContextMenuState = this.stateProvider.getGlobal(ENABLE_CONTEXT_MENU);
this.enableContextMenu$ = this.enableContextMenuState.state$.pipe(map((x) => x ?? true));
@ -190,6 +226,14 @@ export class AutofillSettingsService implements AutofillSettingsServiceAbstracti
await this.inlineMenuVisibilityState.update(() => newValue);
}
async setShowInlineMenuIdentities(newValue: boolean): Promise<void> {
await this.showInlineMenuIdentitiesState.update(() => newValue);
}
async setShowInlineMenuCards(newValue: boolean): Promise<void> {
await this.showInlineMenuCardsState.update(() => newValue);
}
async setEnableContextMenu(newValue: boolean): Promise<void> {
await this.enableContextMenuState.update(() => newValue);
}