mirror of
https://github.com/bitwarden/browser
synced 2025-12-13 06:43:35 +00:00
Pm 22882 display simple dialog when advanced matching strategy selected for global setting (#15531)
* PM-22882 * add bit hints * export dialog and implement in autofill component * remove unnecessary non null assertion * set to previous on cancel * add advanced options message to web and desktop * tweak styling * add warning capitalized to web and desktop
This commit is contained in:
@@ -262,10 +262,15 @@
|
|||||||
*ngFor="let option of uriMatchOptions"
|
*ngFor="let option of uriMatchOptions"
|
||||||
[label]="option.name"
|
[label]="option.name"
|
||||||
[value]="option.value"
|
[value]="option.value"
|
||||||
|
[disabled]="option.disabled"
|
||||||
></bit-option>
|
></bit-option>
|
||||||
</bit-select>
|
</bit-select>
|
||||||
<bit-hint class="tw-text-sm" id="defaultUriMatchHelp">
|
<bit-hint *ngIf="getMatchHints() as hints">
|
||||||
{{ "defaultUriMatchDetectionDesc" | i18n }}
|
{{ hints[0] | i18n }}
|
||||||
|
<ng-container *ngIf="hints.length > 1">
|
||||||
|
<b>{{ "warningCapitalized" | i18n }}:</b>
|
||||||
|
{{ hints[1] | i18n }}
|
||||||
|
</ng-container>
|
||||||
</bit-hint>
|
</bit-hint>
|
||||||
</bit-form-field>
|
</bit-form-field>
|
||||||
</bit-card>
|
</bit-card>
|
||||||
|
|||||||
@@ -11,7 +11,17 @@ import {
|
|||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
} from "@angular/forms";
|
} from "@angular/forms";
|
||||||
import { RouterModule } from "@angular/router";
|
import { RouterModule } from "@angular/router";
|
||||||
import { filter, firstValueFrom, map, Observable, shareReplay, switchMap } from "rxjs";
|
import {
|
||||||
|
concatMap,
|
||||||
|
filter,
|
||||||
|
firstValueFrom,
|
||||||
|
map,
|
||||||
|
Observable,
|
||||||
|
pairwise,
|
||||||
|
shareReplay,
|
||||||
|
startWith,
|
||||||
|
switchMap,
|
||||||
|
} from "rxjs";
|
||||||
|
|
||||||
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
import { NudgesService, NudgeType } from "@bitwarden/angular/vault";
|
import { NudgesService, NudgeType } from "@bitwarden/angular/vault";
|
||||||
@@ -59,6 +69,7 @@ import {
|
|||||||
SelectModule,
|
SelectModule,
|
||||||
TypographyModule,
|
TypographyModule,
|
||||||
} from "@bitwarden/components";
|
} from "@bitwarden/components";
|
||||||
|
import { AdvancedUriOptionDialogComponent } from "@bitwarden/vault";
|
||||||
|
|
||||||
import { AutofillBrowserSettingsService } from "../../../autofill/services/autofill-browser-settings.service";
|
import { AutofillBrowserSettingsService } from "../../../autofill/services/autofill-browser-settings.service";
|
||||||
import { BrowserApi } from "../../../platform/browser/browser-api";
|
import { BrowserApi } from "../../../platform/browser/browser-api";
|
||||||
@@ -131,6 +142,7 @@ export class AutofillComponent implements OnInit {
|
|||||||
defaultUriMatch: new FormControl(),
|
defaultUriMatch: new FormControl(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
advancedOptionWarningMap: Partial<Record<UriMatchStrategySetting, string>>;
|
||||||
enableAutofillOnPageLoad: boolean = false;
|
enableAutofillOnPageLoad: boolean = false;
|
||||||
enableInlineMenu: boolean = false;
|
enableInlineMenu: boolean = false;
|
||||||
enableInlineMenuOnIconSelect: boolean = false;
|
enableInlineMenuOnIconSelect: boolean = false;
|
||||||
@@ -143,7 +155,7 @@ export class AutofillComponent implements OnInit {
|
|||||||
clearClipboard: ClearClipboardDelaySetting;
|
clearClipboard: ClearClipboardDelaySetting;
|
||||||
clearClipboardOptions: { name: string; value: ClearClipboardDelaySetting }[];
|
clearClipboardOptions: { name: string; value: ClearClipboardDelaySetting }[];
|
||||||
defaultUriMatch: UriMatchStrategySetting = UriMatchStrategy.Domain;
|
defaultUriMatch: UriMatchStrategySetting = UriMatchStrategy.Domain;
|
||||||
uriMatchOptions: { name: string; value: UriMatchStrategySetting }[];
|
uriMatchOptions: { name: string; value: UriMatchStrategySetting; disabled?: boolean }[];
|
||||||
showCardsCurrentTab: boolean = true;
|
showCardsCurrentTab: boolean = true;
|
||||||
showIdentitiesCurrentTab: boolean = true;
|
showIdentitiesCurrentTab: boolean = true;
|
||||||
autofillKeyboardHelperText: string;
|
autofillKeyboardHelperText: string;
|
||||||
@@ -181,11 +193,16 @@ export class AutofillComponent implements OnInit {
|
|||||||
this.uriMatchOptions = [
|
this.uriMatchOptions = [
|
||||||
{ name: i18nService.t("baseDomainOptionRecommended"), value: UriMatchStrategy.Domain },
|
{ name: i18nService.t("baseDomainOptionRecommended"), value: UriMatchStrategy.Domain },
|
||||||
{ name: i18nService.t("host"), value: UriMatchStrategy.Host },
|
{ name: i18nService.t("host"), value: UriMatchStrategy.Host },
|
||||||
{ name: i18nService.t("startsWith"), value: UriMatchStrategy.StartsWith },
|
|
||||||
{ name: i18nService.t("regEx"), value: UriMatchStrategy.RegularExpression },
|
|
||||||
{ name: i18nService.t("exact"), value: UriMatchStrategy.Exact },
|
{ name: i18nService.t("exact"), value: UriMatchStrategy.Exact },
|
||||||
{ name: i18nService.t("never"), value: UriMatchStrategy.Never },
|
{ name: i18nService.t("never"), value: UriMatchStrategy.Never },
|
||||||
|
{ name: this.i18nService.t("uriAdvancedOption"), value: null, disabled: true },
|
||||||
|
{ name: i18nService.t("startsWith"), value: UriMatchStrategy.StartsWith },
|
||||||
|
{ name: i18nService.t("regEx"), value: UriMatchStrategy.RegularExpression },
|
||||||
];
|
];
|
||||||
|
this.advancedOptionWarningMap = {
|
||||||
|
[UriMatchStrategy.StartsWith]: "startsWithAdvancedOptionWarning",
|
||||||
|
[UriMatchStrategy.RegularExpression]: "regExAdvancedOptionWarning",
|
||||||
|
};
|
||||||
|
|
||||||
this.browserClientVendor = BrowserApi.getBrowserClientVendor(window);
|
this.browserClientVendor = BrowserApi.getBrowserClientVendor(window);
|
||||||
this.disablePasswordManagerURI = DisablePasswordManagerUris[this.browserClientVendor];
|
this.disablePasswordManagerURI = DisablePasswordManagerUris[this.browserClientVendor];
|
||||||
@@ -319,10 +336,13 @@ export class AutofillComponent implements OnInit {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.additionalOptionsForm.controls.defaultUriMatch.valueChanges
|
this.additionalOptionsForm.controls.defaultUriMatch.valueChanges
|
||||||
.pipe(takeUntilDestroyed(this.destroyRef))
|
.pipe(
|
||||||
.subscribe((value) => {
|
startWith(this.defaultUriMatch),
|
||||||
void this.domainSettingsService.setDefaultUriMatchStrategy(value);
|
pairwise(),
|
||||||
});
|
concatMap(([previous, current]) => this.handleAdvancedMatch(previous, current)),
|
||||||
|
takeUntilDestroyed(this.destroyRef),
|
||||||
|
)
|
||||||
|
.subscribe();
|
||||||
|
|
||||||
const command = await this.platformUtilsService.getAutofillKeyboardShortcut();
|
const command = await this.platformUtilsService.getAutofillKeyboardShortcut();
|
||||||
await this.setAutofillKeyboardHelperText(command);
|
await this.setAutofillKeyboardHelperText(command);
|
||||||
@@ -510,6 +530,29 @@ export class AutofillComponent implements OnInit {
|
|||||||
await this.updateDefaultBrowserAutofillDisabled();
|
await this.updateDefaultBrowserAutofillDisabled();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private async handleAdvancedMatch(
|
||||||
|
previous: UriMatchStrategySetting | null,
|
||||||
|
current: UriMatchStrategySetting | null,
|
||||||
|
): Promise<void> {
|
||||||
|
const valueChange = previous !== current;
|
||||||
|
const isAdvanced =
|
||||||
|
current === UriMatchStrategy.StartsWith || current === UriMatchStrategy.RegularExpression;
|
||||||
|
if (!valueChange || !isAdvanced) {
|
||||||
|
return await this.domainSettingsService.setDefaultUriMatchStrategy(current);
|
||||||
|
}
|
||||||
|
AdvancedUriOptionDialogComponent.open(this.dialogService, {
|
||||||
|
contentKey: this.advancedOptionWarningMap[current],
|
||||||
|
onContinue: async () => {
|
||||||
|
this.additionalOptionsForm.controls.defaultUriMatch.setValue(current);
|
||||||
|
await this.domainSettingsService.setDefaultUriMatchStrategy(current);
|
||||||
|
},
|
||||||
|
onCancel: async () => {
|
||||||
|
this.additionalOptionsForm.controls.defaultUriMatch.setValue(previous);
|
||||||
|
await this.domainSettingsService.setDefaultUriMatchStrategy(previous);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async privacyPermissionGranted(): Promise<boolean> {
|
async privacyPermissionGranted(): Promise<boolean> {
|
||||||
return await BrowserApi.permissionsGranted(["privacy"]);
|
return await BrowserApi.permissionsGranted(["privacy"]);
|
||||||
}
|
}
|
||||||
@@ -529,4 +572,17 @@ export class AutofillComponent implements OnInit {
|
|||||||
async updateShowInlineMenuIdentities() {
|
async updateShowInlineMenuIdentities() {
|
||||||
await this.autofillSettingsService.setShowInlineMenuIdentities(this.showInlineMenuIdentities);
|
await this.autofillSettingsService.setShowInlineMenuIdentities(this.showInlineMenuIdentities);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMatchHints() {
|
||||||
|
const hints = ["uriMatchDefaultStrategyHint"];
|
||||||
|
const strategy = this.additionalOptionsForm.get("defaultUriMatch")
|
||||||
|
?.value as UriMatchStrategySetting;
|
||||||
|
if (
|
||||||
|
strategy === UriMatchStrategy.StartsWith ||
|
||||||
|
strategy === UriMatchStrategy.RegularExpression
|
||||||
|
) {
|
||||||
|
hints.push(this.advancedOptionWarningMap[strategy]);
|
||||||
|
}
|
||||||
|
return hints;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3565,6 +3565,14 @@
|
|||||||
"uriMatchWarningDialogLink": {
|
"uriMatchWarningDialogLink": {
|
||||||
"message": "More about match detection",
|
"message": "More about match detection",
|
||||||
"description": "Link to match detection docs on warning dialog for advance match strategy"
|
"description": "Link to match detection docs on warning dialog for advance match strategy"
|
||||||
|
},
|
||||||
|
"uriAdvancedOption":{
|
||||||
|
"message": "Advanced options",
|
||||||
|
"description": "Advanced option placeholder for uri option component"
|
||||||
|
},
|
||||||
|
"warningCapitalized": {
|
||||||
|
"message": "Warning",
|
||||||
|
"description": "Warning (should maintain locale-relevant capitalization)"
|
||||||
},
|
},
|
||||||
"success": {
|
"success": {
|
||||||
"message": "Success"
|
"message": "Success"
|
||||||
|
|||||||
@@ -8941,6 +8941,14 @@
|
|||||||
"uriMatchWarningDialogLink": {
|
"uriMatchWarningDialogLink": {
|
||||||
"message": "More about match detection",
|
"message": "More about match detection",
|
||||||
"description": "Link to match detection docs on warning dialog for advance match strategy"
|
"description": "Link to match detection docs on warning dialog for advance match strategy"
|
||||||
|
},
|
||||||
|
"uriAdvancedOption":{
|
||||||
|
"message": "Advanced options",
|
||||||
|
"description": "Advanced option placeholder for uri option component"
|
||||||
|
},
|
||||||
|
"warningCapitalized": {
|
||||||
|
"message": "Warning",
|
||||||
|
"description": "Warning (should maintain locale-relevant capitalization)"
|
||||||
},
|
},
|
||||||
"maintainYourSubscription": {
|
"maintainYourSubscription": {
|
||||||
"message": "To maintain your subscription for $ORG$, ",
|
"message": "To maintain your subscription for $ORG$, ",
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
<span bitDialogTitle>
|
<span bitDialogTitle>
|
||||||
{{ "warningCapitalized" | i18n }}
|
{{ "warningCapitalized" | i18n }}
|
||||||
</span>
|
</span>
|
||||||
<div bitDialogContent>
|
<div bitDialogContent class="tw-mb-1">
|
||||||
<p>
|
<p class="tw-mb-1 tw-hyphens-none">
|
||||||
{{ contentKey | i18n }}
|
{{ contentKey | i18n }}
|
||||||
<br />
|
<br />
|
||||||
<button bitLink type="button" linkType="primary" (click)="openLink($event)">
|
<button bitLink type="button" linkType="primary" (click)="openLink($event)">
|
||||||
|
|||||||
@@ -11,3 +11,4 @@ export { DefaultCipherFormConfigService } from "./services/default-cipher-form-c
|
|||||||
export { CipherFormGeneratorComponent } from "./components/cipher-generator/cipher-form-generator.component";
|
export { CipherFormGeneratorComponent } from "./components/cipher-generator/cipher-form-generator.component";
|
||||||
export { CipherFormContainer } from "../cipher-form/cipher-form-container";
|
export { CipherFormContainer } from "../cipher-form/cipher-form-container";
|
||||||
export { CipherFormComponent } from "./components/cipher-form.component";
|
export { CipherFormComponent } from "./components/cipher-form.component";
|
||||||
|
export { AdvancedUriOptionDialogComponent } from "./components/autofill-options/advanced-uri-option-dialog.component";
|
||||||
|
|||||||
Reference in New Issue
Block a user