[PM-8338] New Autofill Settings Components (#10184)
* add v2 autofill settings component * add and update entries in message catalog for new autofill settings view * add confirmation dialogs ahead of new tabs for browser settings from autofill settings * fix autofill on page load warning styling and improper concatenation * code cleanup
This commit is contained in:
parent
d2afe221f0
commit
0ff62a5cc3
|
@ -108,7 +108,7 @@
|
||||||
"message": "Copy security code"
|
"message": "Copy security code"
|
||||||
},
|
},
|
||||||
"autoFill": {
|
"autoFill": {
|
||||||
"message": "Auto-fill"
|
"message": "Autofill"
|
||||||
},
|
},
|
||||||
"autoFillLogin": {
|
"autoFillLogin": {
|
||||||
"message": "Auto-fill login"
|
"message": "Auto-fill login"
|
||||||
|
@ -789,12 +789,18 @@
|
||||||
"addLoginNotificationDescAlt": {
|
"addLoginNotificationDescAlt": {
|
||||||
"message": "Ask to add an item if one isn't found in your vault. Applies to all logged in accounts."
|
"message": "Ask to add an item if one isn't found in your vault. Applies to all logged in accounts."
|
||||||
},
|
},
|
||||||
|
"showCardsInVaultView": {
|
||||||
|
"message": "Show cards as Autofill suggestions on Vault view"
|
||||||
|
},
|
||||||
"showCardsCurrentTab": {
|
"showCardsCurrentTab": {
|
||||||
"message": "Show cards on Tab page"
|
"message": "Show cards on Tab page"
|
||||||
},
|
},
|
||||||
"showCardsCurrentTabDesc": {
|
"showCardsCurrentTabDesc": {
|
||||||
"message": "List card items on the Tab page for easy auto-fill."
|
"message": "List card items on the Tab page for easy auto-fill."
|
||||||
},
|
},
|
||||||
|
"showIdentitiesInVaultView": {
|
||||||
|
"message": "Show identifies as Autofill suggestions on Vault view"
|
||||||
|
},
|
||||||
"showIdentitiesCurrentTab": {
|
"showIdentitiesCurrentTab": {
|
||||||
"message": "Show identities on Tab page"
|
"message": "Show identities on Tab page"
|
||||||
},
|
},
|
||||||
|
@ -1227,11 +1233,20 @@
|
||||||
"message": "Show auto-fill menu on form fields",
|
"message": "Show auto-fill menu on form fields",
|
||||||
"description": "Represents the message for allowing the user to enable the auto-fill overlay"
|
"description": "Represents the message for allowing the user to enable the auto-fill overlay"
|
||||||
},
|
},
|
||||||
"showAutoFillMenuOnFormFieldsDescAlt": {
|
"autofillSuggestionsSectionTitle": {
|
||||||
|
"message": "Autofill suggestions"
|
||||||
|
},
|
||||||
|
"showInlineMenuLabel": {
|
||||||
|
"message": "Show autofill suggestions on form fields"
|
||||||
|
},
|
||||||
|
"showInlineMenuOnIconSelectionLabel": {
|
||||||
|
"message": "Display suggestions when icon is selected"
|
||||||
|
},
|
||||||
|
"showInlineMenuOnFormFieldsDescAlt": {
|
||||||
"message": "Applies to all logged in accounts."
|
"message": "Applies to all logged in accounts."
|
||||||
},
|
},
|
||||||
"turnOffBrowserBuiltInPasswordManagerSettings": {
|
"turnOffBrowserBuiltInPasswordManagerSettings": {
|
||||||
"message": "Turn off your browser’s built in password manager settings to avoid conflicts."
|
"message": "Turn off your browser's built in password manager settings to avoid conflicts."
|
||||||
},
|
},
|
||||||
"turnOffBrowserBuiltInPasswordManagerSettingsLink": {
|
"turnOffBrowserBuiltInPasswordManagerSettingsLink": {
|
||||||
"message": "Edit browser settings."
|
"message": "Edit browser settings."
|
||||||
|
@ -1248,23 +1263,43 @@
|
||||||
"message": "When auto-fill icon is selected",
|
"message": "When auto-fill icon is selected",
|
||||||
"description": "Overlay appearance select option for showing the field on click of the overlay icon"
|
"description": "Overlay appearance select option for showing the field on click of the overlay icon"
|
||||||
},
|
},
|
||||||
|
"enableAutoFillOnPageLoadSectionTitle": {
|
||||||
|
"message": "Autofill on page load"
|
||||||
|
},
|
||||||
"enableAutoFillOnPageLoad": {
|
"enableAutoFillOnPageLoad": {
|
||||||
"message": "Auto-fill on page load"
|
"message": "Autofill on page load"
|
||||||
},
|
},
|
||||||
"enableAutoFillOnPageLoadDesc": {
|
"enableAutoFillOnPageLoadDesc": {
|
||||||
"message": "If a login form is detected, auto-fill when the web page loads."
|
"message": "If a login form is detected, autofill when the web page loads."
|
||||||
|
},
|
||||||
|
"autofillOnPageLoadWarning": {
|
||||||
|
"message": "$OPENTAG$Warning:$CLOSETAG$ Compromised or untrusted websites can exploit autofill on page load.",
|
||||||
|
"placeholders": {
|
||||||
|
"openTag": {
|
||||||
|
"content": "$1",
|
||||||
|
"example": "<b>"
|
||||||
|
},
|
||||||
|
"closeTag": {
|
||||||
|
"content": "$2",
|
||||||
|
"example": "</b>"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"experimentalFeature": {
|
"experimentalFeature": {
|
||||||
"message": "Compromised or untrusted websites can exploit auto-fill on page load."
|
"message": "Compromised or untrusted websites can exploit autofill on page load."
|
||||||
|
},
|
||||||
|
"learnMoreAboutAutofillOnPageLoadLinkText": {
|
||||||
|
"message": "Learn more about risks"
|
||||||
},
|
},
|
||||||
"learnMoreAboutAutofill": {
|
"learnMoreAboutAutofill": {
|
||||||
"message": "Learn more about auto-fill"
|
"message": "Learn more about autofill"
|
||||||
},
|
},
|
||||||
"defaultAutoFillOnPageLoad": {
|
"defaultAutoFillOnPageLoad": {
|
||||||
"message": "Default autofill setting for login items"
|
"message": "Default autofill setting for login items"
|
||||||
},
|
},
|
||||||
"defaultAutoFillOnPageLoadDesc": {
|
"defaultAutoFillOnPageLoadDesc": {
|
||||||
"message": "You can turn off auto-fill on page load for individual login items from the item's Edit view."
|
"message": "You can turn off autofill on page load for individual login items from the item's Edit view."
|
||||||
},
|
},
|
||||||
"itemAutoFillOnPageLoad": {
|
"itemAutoFillOnPageLoad": {
|
||||||
"message": "Auto-fill on page load (if set up in Options)"
|
"message": "Auto-fill on page load (if set up in Options)"
|
||||||
|
@ -1273,10 +1308,10 @@
|
||||||
"message": "Use default setting"
|
"message": "Use default setting"
|
||||||
},
|
},
|
||||||
"autoFillOnPageLoadYes": {
|
"autoFillOnPageLoadYes": {
|
||||||
"message": "Auto-fill on page load"
|
"message": "Autofill on page load"
|
||||||
},
|
},
|
||||||
"autoFillOnPageLoadNo": {
|
"autoFillOnPageLoadNo": {
|
||||||
"message": "Do not auto-fill on page load"
|
"message": "Do not autofill on page load"
|
||||||
},
|
},
|
||||||
"commandOpenPopup": {
|
"commandOpenPopup": {
|
||||||
"message": "Open vault popup"
|
"message": "Open vault popup"
|
||||||
|
@ -2004,7 +2039,7 @@
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"domain": {
|
"domain": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
"example": "google.com"
|
"example": "duckduckgo.com"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -2706,14 +2741,20 @@
|
||||||
"autofillSettings": {
|
"autofillSettings": {
|
||||||
"message": "Auto-fill settings"
|
"message": "Auto-fill settings"
|
||||||
},
|
},
|
||||||
|
"autofillKeyboardShortcutSectionTitle": {
|
||||||
|
"message": "Autofill shortcut"
|
||||||
|
},
|
||||||
|
"autofillKeyboardShortcutUpdateLabel": {
|
||||||
|
"message": "Change shortcut"
|
||||||
|
},
|
||||||
"autofillShortcut": {
|
"autofillShortcut": {
|
||||||
"message": "Auto-fill keyboard shortcut"
|
"message": "Autofill keyboard shortcut"
|
||||||
},
|
},
|
||||||
"autofillShortcutNotSet": {
|
"autofillShortcutNotSet": {
|
||||||
"message": "The auto-fill shortcut is not set. Change this in the browser's settings."
|
"message": "The autofill shortcut is not set. Change this in the browser's settings."
|
||||||
},
|
},
|
||||||
"autofillShortcutText": {
|
"autofillShortcutText": {
|
||||||
"message": "The auto-fill shortcut is: $COMMAND$. Change this in the browser's settings.",
|
"message": "The autofill shortcut is: $COMMAND$. Change this in the browser's settings.",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"command": {
|
"command": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
|
@ -3369,7 +3410,7 @@
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"domain": {
|
"domain": {
|
||||||
"content": "$1",
|
"content": "$1",
|
||||||
"example": "google.com"
|
"example": "duckduckgo.com"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -3377,12 +3418,36 @@
|
||||||
"message": "Common formats",
|
"message": "Common formats",
|
||||||
"description": "Label indicating the most common import formats"
|
"description": "Label indicating the most common import formats"
|
||||||
},
|
},
|
||||||
|
"confirmContinueToBrowserSettingsTitle": {
|
||||||
|
"message": "Continue to browser settings?",
|
||||||
|
"description": "Title for dialog which asks if the user wants to proceed to a relevant browser settings page"
|
||||||
|
},
|
||||||
|
"confirmContinueToHelpCenter": {
|
||||||
|
"message": "Continue to Help Center?",
|
||||||
|
"description": "Title for dialog which asks if the user wants to proceed to a relevant Help Center page"
|
||||||
|
},
|
||||||
|
"confirmContinueToHelpCenterPasswordManagementContent": {
|
||||||
|
"message": "Change your browser's autofill and password management settings.",
|
||||||
|
"description": "Body content for dialog which asks if the user wants to proceed to the Help Center's page about browser password management settings"
|
||||||
|
},
|
||||||
|
"confirmContinueToHelpCenterKeyboardShortcutsContent": {
|
||||||
|
"message": "You can view and set extension shortcuts in your browser's settings.",
|
||||||
|
"description": "Body content for dialog which asks if the user wants to proceed to the Help Center's page about browser keyboard shortcut settings"
|
||||||
|
},
|
||||||
|
"confirmContinueToBrowserPasswordManagementSettingsContent": {
|
||||||
|
"message": "Change your browser's autofill and password management settings.",
|
||||||
|
"description": "Body content for dialog which asks if the user wants to proceed to the browser's password management settings page"
|
||||||
|
},
|
||||||
|
"confirmContinueToBrowserKeyboardShortcutSettingsContent": {
|
||||||
|
"message": "You can view and set extension shortcuts in your browser's settings.",
|
||||||
|
"description": "Body content for dialog which asks if the user wants to proceed to the browser's keyboard shortcut settings page"
|
||||||
|
},
|
||||||
"overrideDefaultBrowserAutofillTitle": {
|
"overrideDefaultBrowserAutofillTitle": {
|
||||||
"message": "Make Bitwarden your default password manager?",
|
"message": "Make Bitwarden your default password manager?",
|
||||||
"description": "Dialog title facilitating the ability to override a chrome browser's default autofill behavior"
|
"description": "Dialog title facilitating the ability to override a chrome browser's default autofill behavior"
|
||||||
},
|
},
|
||||||
"overrideDefaultBrowserAutofillDescription": {
|
"overrideDefaultBrowserAutofillDescription": {
|
||||||
"message": "Ignoring this option may cause conflicts between the Bitwarden auto-fill menu and your browser's.",
|
"message": "Ignoring this option may cause conflicts between Bitwarden autofill suggestions and your browser's.",
|
||||||
"description": "Dialog message facilitating the ability to override a chrome browser's default autofill behavior"
|
"description": "Dialog message facilitating the ability to override a chrome browser's default autofill behavior"
|
||||||
},
|
},
|
||||||
"overrideDefaultBrowserAutoFillSettings": {
|
"overrideDefaultBrowserAutoFillSettings": {
|
||||||
|
|
|
@ -0,0 +1,221 @@
|
||||||
|
<header>
|
||||||
|
<div class="left">
|
||||||
|
<button type="button" routerLink="/tabs/settings">
|
||||||
|
<span class="header-icon"><i class="bwi bwi-angle-left" aria-hidden="true"></i></span>
|
||||||
|
<span>{{ "back" | i18n }}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<h1 class="center">
|
||||||
|
<span class="title">{{ "autofill" | i18n }}</span>
|
||||||
|
</h1>
|
||||||
|
<div class="right"></div>
|
||||||
|
</header>
|
||||||
|
<main tabindex="-1">
|
||||||
|
<div class="box tw-mt-4">
|
||||||
|
<div class="box-content">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="box-content-row box-content-row-link box-content-row-flex"
|
||||||
|
(click)="commandSettings()"
|
||||||
|
>
|
||||||
|
<div class="row-main">{{ "autofillShortcut" | i18n }}</div>
|
||||||
|
<i class="bwi bwi-external-link bwi-lg bwi-fw" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div id="autofillKeyboardHelp" class="box-footer">
|
||||||
|
{{ autofillKeyboardHelperText }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row" appBoxRow>
|
||||||
|
<label for="autofill-overlay-settings">{{ "showAutoFillMenuOnFormFields" | i18n }}</label>
|
||||||
|
<select
|
||||||
|
id="autofill-overlay-settings"
|
||||||
|
name="autofill-overlay-settings"
|
||||||
|
[(ngModel)]="autoFillOverlayVisibility"
|
||||||
|
(change)="updateAutoFillOverlayVisibility()"
|
||||||
|
>
|
||||||
|
<option *ngFor="let o of autoFillOverlayVisibilityOptions" [ngValue]="o.value">
|
||||||
|
{{ o.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer" *ngIf="accountSwitcherEnabled && canOverrideBrowserAutofillSetting">
|
||||||
|
{{ "showInlineMenuOnFormFieldsDescAlt" | i18n }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-content" *ngIf="canOverrideBrowserAutofillSetting">
|
||||||
|
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||||
|
<label for="overrideBrowserAutofill" class="!tw-mr-0">{{
|
||||||
|
"overrideDefaultBrowserAutoFillSettings" | i18n
|
||||||
|
}}</label>
|
||||||
|
<input
|
||||||
|
id="overrideBrowserAutofill"
|
||||||
|
type="checkbox"
|
||||||
|
(change)="updateDefaultBrowserAutofillDisabled()"
|
||||||
|
[(ngModel)]="defaultBrowserAutofillDisabled"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-footer">
|
||||||
|
<span *ngIf="accountSwitcherEnabled">{{ "showInlineMenuOnFormFieldsDescAlt" | i18n }}</span>
|
||||||
|
{{ "turnOffBrowserBuiltInPasswordManagerSettings" | i18n }}
|
||||||
|
<a
|
||||||
|
[attr.href]="disablePasswordManagerLink"
|
||||||
|
(click)="openDisablePasswordManagerLink($event)"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
{{ "turnOffBrowserBuiltInPasswordManagerSettingsLink" | i18n }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box tw-mt-4">
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||||
|
<label for="autofill">{{ "enableAutoFillOnPageLoad" | i18n }}</label>
|
||||||
|
<input
|
||||||
|
id="autofill"
|
||||||
|
type="checkbox"
|
||||||
|
aria-describedby="autofillHelp"
|
||||||
|
(change)="updateAutoFillOnPageLoad()"
|
||||||
|
[(ngModel)]="enableAutoFillOnPageLoad"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="autofillHelp" class="box-footer">
|
||||||
|
{{ "enableAutoFillOnPageLoadDesc" | i18n }}
|
||||||
|
<b>{{ "warning" | i18n }}</b
|
||||||
|
>: {{ "experimentalFeature" | i18n }}
|
||||||
|
<a href="https://bitwarden.com/help/auto-fill-browser/" target="_blank" rel="noreferrer">
|
||||||
|
{{ "learnMoreAboutAutofill" | i18n }}.
|
||||||
|
<i
|
||||||
|
[attr.aria-label]="'opensInANewWindow' | i18n"
|
||||||
|
class="bwi bwi-external-link bwi-sm bwi-fw"
|
||||||
|
></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row" appBoxRow>
|
||||||
|
<label for="defaultAutofill">{{ "defaultAutoFillOnPageLoad" | i18n }}</label>
|
||||||
|
<select
|
||||||
|
id="defaultAutofill"
|
||||||
|
name="DefaultAutofill"
|
||||||
|
aria-describedby="defaultAutofillHelp"
|
||||||
|
[(ngModel)]="autoFillOnPageLoadDefault"
|
||||||
|
(change)="updateAutoFillOnPageLoadDefault()"
|
||||||
|
[disabled]="!enableAutoFillOnPageLoad"
|
||||||
|
>
|
||||||
|
<option *ngFor="let o of autoFillOnPageLoadOptions" [ngValue]="o.value">
|
||||||
|
{{ o.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="defaultAutofillHelp" class="box-footer">
|
||||||
|
{{ "defaultAutoFillOnPageLoadDesc" | i18n }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box">
|
||||||
|
<h2 class="box-header">{{ "additionalOptions" | i18n }}</h2>
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||||
|
<label for="context-menu">{{ "enableContextMenuItem" | i18n }}</label>
|
||||||
|
<input
|
||||||
|
id="context-menu"
|
||||||
|
type="checkbox"
|
||||||
|
aria-describedby="context-menuHelp"
|
||||||
|
(change)="updateContextMenuItem()"
|
||||||
|
[(ngModel)]="enableContextMenuItem"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="context-menuHelp" class="box-footer">
|
||||||
|
{{
|
||||||
|
accountSwitcherEnabled ? ("contextMenuItemDescAlt" | i18n) : ("contextMenuItemDesc" | i18n)
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||||
|
<label for="totp">{{ "enableAutoTotpCopy" | i18n }}</label>
|
||||||
|
<input
|
||||||
|
id="totp"
|
||||||
|
type="checkbox"
|
||||||
|
aria-describedby="totpHelp"
|
||||||
|
(change)="updateAutoTotpCopy()"
|
||||||
|
[(ngModel)]="enableAutoTotpCopy"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="totpHelp" class="box-footer">{{ "disableAutoTotpCopyDesc" | i18n }}</div>
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row" appBoxRow>
|
||||||
|
<label for="clearClipboard">{{ "clearClipboard" | i18n }}</label>
|
||||||
|
<select
|
||||||
|
id="clearClipboard"
|
||||||
|
name="ClearClipboard"
|
||||||
|
aria-describedby="clearClipboardHelp"
|
||||||
|
[(ngModel)]="clearClipboard"
|
||||||
|
(change)="saveClearClipboard()"
|
||||||
|
>
|
||||||
|
<option *ngFor="let o of clearClipboardOptions" [ngValue]="o.value">
|
||||||
|
{{ o.name }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="clearClipboardHelp" class="box-footer">{{ "clearClipboardDesc" | i18n }}</div>
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row" appBoxRow>
|
||||||
|
<label for="defaultUriMatch">{{ "defaultUriMatchDetection" | i18n }}</label>
|
||||||
|
<select
|
||||||
|
id="defaultUriMatch"
|
||||||
|
name="DefaultUriMatch"
|
||||||
|
aria-describedby="defaultUriMatchHelp"
|
||||||
|
[(ngModel)]="defaultUriMatch"
|
||||||
|
(change)="saveDefaultUriMatch()"
|
||||||
|
>
|
||||||
|
<option *ngFor="let o of uriMatchOptions" [ngValue]="o.value">{{ o.name }}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="defaultUriMatchHelp" class="box-footer">
|
||||||
|
{{ "defaultUriMatchDetectionDesc" | i18n }}
|
||||||
|
</div>
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||||
|
<label for="showCardsCurrentTab">{{ "showCardsCurrentTab" | i18n }}</label>
|
||||||
|
<input
|
||||||
|
id="showCardsCurrentTab"
|
||||||
|
type="checkbox"
|
||||||
|
aria-describedby="showCardsCurrentTabHelp"
|
||||||
|
(change)="updateShowCardsCurrentTab()"
|
||||||
|
[(ngModel)]="showCardsCurrentTab"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="showCardsCurrentTabHelp" class="box-footer">
|
||||||
|
{{ "showCardsCurrentTabDesc" | i18n }}
|
||||||
|
</div>
|
||||||
|
<div class="box-content">
|
||||||
|
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
||||||
|
<label for="showIdentitiesCurrentTab">{{ "showIdentitiesCurrentTab" | i18n }}</label>
|
||||||
|
<input
|
||||||
|
id="showIdentitiesCurrentTab"
|
||||||
|
type="checkbox"
|
||||||
|
aria-describedby="showIdentitiesCurrentTabHelp"
|
||||||
|
(change)="updateShowIdentitiesCurrentTab()"
|
||||||
|
[(ngModel)]="showIdentitiesCurrentTab"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="showIdentitiesCurrentTabHelp" class="box-footer">
|
||||||
|
{{ "showIdentitiesCurrentTabDesc" | i18n }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
|
@ -0,0 +1,301 @@
|
||||||
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
|
import { AutofillOverlayVisibility } from "@bitwarden/common/autofill/constants";
|
||||||
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
|
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
|
import {
|
||||||
|
InlineMenuVisibilitySetting,
|
||||||
|
ClearClipboardDelaySetting,
|
||||||
|
} from "@bitwarden/common/autofill/types";
|
||||||
|
import {
|
||||||
|
UriMatchStrategy,
|
||||||
|
UriMatchStrategySetting,
|
||||||
|
} from "@bitwarden/common/models/domain/domain-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";
|
||||||
|
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
||||||
|
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",
|
||||||
|
templateUrl: "autofill-v1.component.html",
|
||||||
|
})
|
||||||
|
export class AutofillV1Component implements OnInit {
|
||||||
|
protected canOverrideBrowserAutofillSetting = false;
|
||||||
|
protected defaultBrowserAutofillDisabled = false;
|
||||||
|
protected autoFillOverlayVisibility: InlineMenuVisibilitySetting;
|
||||||
|
protected autoFillOverlayVisibilityOptions: any[];
|
||||||
|
protected disablePasswordManagerLink: string;
|
||||||
|
enableAutoFillOnPageLoad = false;
|
||||||
|
autoFillOnPageLoadDefault = false;
|
||||||
|
autoFillOnPageLoadOptions: any[];
|
||||||
|
enableContextMenuItem = false;
|
||||||
|
enableAutoTotpCopy = false; // TODO: Does it matter if this is set to false or true?
|
||||||
|
clearClipboard: ClearClipboardDelaySetting;
|
||||||
|
clearClipboardOptions: any[];
|
||||||
|
defaultUriMatch: UriMatchStrategySetting = UriMatchStrategy.Domain;
|
||||||
|
uriMatchOptions: any[];
|
||||||
|
showCardsCurrentTab = false;
|
||||||
|
showIdentitiesCurrentTab = false;
|
||||||
|
autofillKeyboardHelperText: string;
|
||||||
|
accountSwitcherEnabled = false;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private i18nService: I18nService,
|
||||||
|
private platformUtilsService: PlatformUtilsService,
|
||||||
|
private domainSettingsService: DomainSettingsService,
|
||||||
|
private autofillService: AutofillService,
|
||||||
|
private dialogService: DialogService,
|
||||||
|
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||||
|
private messagingService: MessagingService,
|
||||||
|
private vaultSettingsService: VaultSettingsService,
|
||||||
|
) {
|
||||||
|
this.autoFillOverlayVisibilityOptions = [
|
||||||
|
{
|
||||||
|
name: i18nService.t("autofillOverlayVisibilityOff"),
|
||||||
|
value: AutofillOverlayVisibility.Off,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18nService.t("autofillOverlayVisibilityOnFieldFocus"),
|
||||||
|
value: AutofillOverlayVisibility.OnFieldFocus,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: i18nService.t("autofillOverlayVisibilityOnButtonClick"),
|
||||||
|
value: AutofillOverlayVisibility.OnButtonClick,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
this.autoFillOnPageLoadOptions = [
|
||||||
|
{ name: i18nService.t("autoFillOnPageLoadYes"), value: true },
|
||||||
|
{ name: i18nService.t("autoFillOnPageLoadNo"), value: false },
|
||||||
|
];
|
||||||
|
this.clearClipboardOptions = [
|
||||||
|
{ name: i18nService.t("never"), value: null },
|
||||||
|
{ name: i18nService.t("tenSeconds"), value: 10 },
|
||||||
|
{ name: i18nService.t("twentySeconds"), value: 20 },
|
||||||
|
{ name: i18nService.t("thirtySeconds"), value: 30 },
|
||||||
|
{ name: i18nService.t("oneMinute"), value: 60 },
|
||||||
|
{ name: i18nService.t("twoMinutes"), value: 120 },
|
||||||
|
{ name: i18nService.t("fiveMinutes"), value: 300 },
|
||||||
|
];
|
||||||
|
this.uriMatchOptions = [
|
||||||
|
{ name: i18nService.t("baseDomain"), value: UriMatchStrategy.Domain },
|
||||||
|
{ 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("never"), value: UriMatchStrategy.Never },
|
||||||
|
];
|
||||||
|
|
||||||
|
this.accountSwitcherEnabled = enableAccountSwitching();
|
||||||
|
this.disablePasswordManagerLink = this.getDisablePasswordManagerLink();
|
||||||
|
}
|
||||||
|
|
||||||
|
async ngOnInit() {
|
||||||
|
this.canOverrideBrowserAutofillSetting =
|
||||||
|
this.platformUtilsService.isChrome() ||
|
||||||
|
this.platformUtilsService.isEdge() ||
|
||||||
|
this.platformUtilsService.isOpera() ||
|
||||||
|
this.platformUtilsService.isVivaldi();
|
||||||
|
|
||||||
|
this.defaultBrowserAutofillDisabled = await this.browserAutofillSettingCurrentlyOverridden();
|
||||||
|
|
||||||
|
this.autoFillOverlayVisibility = await firstValueFrom(
|
||||||
|
this.autofillSettingsService.inlineMenuVisibility$,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.enableAutoFillOnPageLoad = await firstValueFrom(
|
||||||
|
this.autofillSettingsService.autofillOnPageLoad$,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.autoFillOnPageLoadDefault = await firstValueFrom(
|
||||||
|
this.autofillSettingsService.autofillOnPageLoadDefault$,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.enableContextMenuItem = await firstValueFrom(
|
||||||
|
this.autofillSettingsService.enableContextMenu$,
|
||||||
|
);
|
||||||
|
|
||||||
|
this.enableAutoTotpCopy = await firstValueFrom(this.autofillSettingsService.autoCopyTotp$);
|
||||||
|
|
||||||
|
this.clearClipboard = await firstValueFrom(this.autofillSettingsService.clearClipboardDelay$);
|
||||||
|
|
||||||
|
const defaultUriMatch = await firstValueFrom(
|
||||||
|
this.domainSettingsService.defaultUriMatchStrategy$,
|
||||||
|
);
|
||||||
|
this.defaultUriMatch = defaultUriMatch == null ? UriMatchStrategy.Domain : defaultUriMatch;
|
||||||
|
|
||||||
|
const command = await this.platformUtilsService.getAutofillKeyboardShortcut();
|
||||||
|
await this.setAutofillKeyboardHelperText(command);
|
||||||
|
|
||||||
|
this.showCardsCurrentTab = await firstValueFrom(this.vaultSettingsService.showCardsCurrentTab$);
|
||||||
|
|
||||||
|
this.showIdentitiesCurrentTab = await firstValueFrom(
|
||||||
|
this.vaultSettingsService.showIdentitiesCurrentTab$,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateAutoFillOverlayVisibility() {
|
||||||
|
await this.autofillSettingsService.setInlineMenuVisibility(this.autoFillOverlayVisibility);
|
||||||
|
await this.requestPrivacyPermission();
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateAutoFillOnPageLoad() {
|
||||||
|
await this.autofillSettingsService.setAutofillOnPageLoad(this.enableAutoFillOnPageLoad);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateAutoFillOnPageLoadDefault() {
|
||||||
|
await this.autofillSettingsService.setAutofillOnPageLoadDefault(this.autoFillOnPageLoadDefault);
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveDefaultUriMatch() {
|
||||||
|
await this.domainSettingsService.setDefaultUriMatchStrategy(this.defaultUriMatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async setAutofillKeyboardHelperText(command: string) {
|
||||||
|
if (command) {
|
||||||
|
this.autofillKeyboardHelperText = this.i18nService.t("autofillShortcutText", command);
|
||||||
|
} else {
|
||||||
|
this.autofillKeyboardHelperText = this.i18nService.t("autofillShortcutNotSet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async commandSettings() {
|
||||||
|
if (this.platformUtilsService.isChrome()) {
|
||||||
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
BrowserApi.createNewTab("chrome://extensions/shortcuts");
|
||||||
|
} else if (this.platformUtilsService.isOpera()) {
|
||||||
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
BrowserApi.createNewTab("opera://extensions/shortcuts");
|
||||||
|
} else if (this.platformUtilsService.isEdge()) {
|
||||||
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
BrowserApi.createNewTab("edge://extensions/shortcuts");
|
||||||
|
} else if (this.platformUtilsService.isVivaldi()) {
|
||||||
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
BrowserApi.createNewTab("vivaldi://extensions/shortcuts");
|
||||||
|
} else {
|
||||||
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
BrowserApi.createNewTab("https://bitwarden.com/help/keyboard-shortcuts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private getDisablePasswordManagerLink(): string {
|
||||||
|
if (this.platformUtilsService.isChrome()) {
|
||||||
|
return "chrome://settings/autofill";
|
||||||
|
}
|
||||||
|
if (this.platformUtilsService.isOpera()) {
|
||||||
|
return "opera://settings/autofill";
|
||||||
|
}
|
||||||
|
if (this.platformUtilsService.isEdge()) {
|
||||||
|
return "edge://settings/passwords";
|
||||||
|
}
|
||||||
|
if (this.platformUtilsService.isVivaldi()) {
|
||||||
|
return "vivaldi://settings/autofill";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "https://bitwarden.com/help/disable-browser-autofill/";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected openDisablePasswordManagerLink(event: Event) {
|
||||||
|
event.preventDefault();
|
||||||
|
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
BrowserApi.createNewTab(this.disablePasswordManagerLink);
|
||||||
|
}
|
||||||
|
|
||||||
|
async requestPrivacyPermission() {
|
||||||
|
if (
|
||||||
|
this.autoFillOverlayVisibility === AutofillOverlayVisibility.Off ||
|
||||||
|
!this.canOverrideBrowserAutofillSetting ||
|
||||||
|
(await this.browserAutofillSettingCurrentlyOverridden())
|
||||||
|
) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.dialogService.openSimpleDialog({
|
||||||
|
title: { key: "overrideDefaultBrowserAutofillTitle" },
|
||||||
|
content: { key: "overrideDefaultBrowserAutofillDescription" },
|
||||||
|
acceptButtonText: { key: "makeDefault" },
|
||||||
|
acceptAction: async () => await this.handleOverrideDialogAccept(),
|
||||||
|
cancelButtonText: { key: "ignore" },
|
||||||
|
type: "info",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateDefaultBrowserAutofillDisabled() {
|
||||||
|
const privacyPermissionGranted = await this.privacyPermissionGranted();
|
||||||
|
if (!this.defaultBrowserAutofillDisabled && !privacyPermissionGranted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!privacyPermissionGranted &&
|
||||||
|
!(await BrowserApi.requestPermission({ permissions: ["privacy"] }))
|
||||||
|
) {
|
||||||
|
await this.dialogService.openSimpleDialog({
|
||||||
|
title: { key: "privacyPermissionAdditionNotGrantedTitle" },
|
||||||
|
content: { key: "privacyPermissionAdditionNotGrantedDescription" },
|
||||||
|
acceptButtonText: { key: "ok" },
|
||||||
|
cancelButtonText: null,
|
||||||
|
type: "warning",
|
||||||
|
});
|
||||||
|
this.defaultBrowserAutofillDisabled = false;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BrowserApi.updateDefaultBrowserAutofillSettings(!this.defaultBrowserAutofillDisabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleOverrideDialogAccept = async () => {
|
||||||
|
this.defaultBrowserAutofillDisabled = true;
|
||||||
|
await this.updateDefaultBrowserAutofillDisabled();
|
||||||
|
};
|
||||||
|
|
||||||
|
async browserAutofillSettingCurrentlyOverridden() {
|
||||||
|
if (!this.canOverrideBrowserAutofillSetting) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(await this.privacyPermissionGranted())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await BrowserApi.browserAutofillSettingsOverridden();
|
||||||
|
}
|
||||||
|
|
||||||
|
async privacyPermissionGranted(): Promise<boolean> {
|
||||||
|
return await BrowserApi.permissionsGranted(["privacy"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateContextMenuItem() {
|
||||||
|
await this.autofillSettingsService.setEnableContextMenu(this.enableContextMenuItem);
|
||||||
|
this.messagingService.send("bgUpdateContextMenu");
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateAutoTotpCopy() {
|
||||||
|
await this.autofillSettingsService.setAutoCopyTotp(this.enableAutoTotpCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
async saveClearClipboard() {
|
||||||
|
await this.autofillSettingsService.setClearClipboardDelay(this.clearClipboard);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateShowCardsCurrentTab() {
|
||||||
|
await this.vaultSettingsService.setShowCardsCurrentTab(this.showCardsCurrentTab);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateShowIdentitiesCurrentTab() {
|
||||||
|
await this.vaultSettingsService.setShowIdentitiesCurrentTab(this.showIdentitiesCurrentTab);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,221 +1,234 @@
|
||||||
<header>
|
<popup-page>
|
||||||
<div class="left">
|
<popup-header slot="header" pageTitle="{{ 'autofill' | i18n }}" showBackButton>
|
||||||
<button type="button" routerLink="/tabs/settings">
|
<ng-container slot="end">
|
||||||
<span class="header-icon"><i class="bwi bwi-angle-left" aria-hidden="true"></i></span>
|
<app-pop-out></app-pop-out>
|
||||||
<span>{{ "back" | i18n }}</span>
|
</ng-container>
|
||||||
</button>
|
</popup-header>
|
||||||
|
|
||||||
|
<div class="tw-bg-background-alt tw-p-2">
|
||||||
|
<bit-section>
|
||||||
|
<bit-section-header>
|
||||||
|
<h2 bitTypography="h5">{{ "autofillSuggestionsSectionTitle" | i18n }}</h2>
|
||||||
|
</bit-section-header>
|
||||||
|
<bit-card>
|
||||||
|
<bit-form-control>
|
||||||
|
<input
|
||||||
|
bitCheckbox
|
||||||
|
id="show-inline-menu"
|
||||||
|
type="checkbox"
|
||||||
|
(change)="updateInlineMenuVisibility()"
|
||||||
|
[(ngModel)]="enableInlineMenu"
|
||||||
|
/>
|
||||||
|
<bit-label for="show-inline-menu">{{ "showInlineMenuLabel" | i18n }}</bit-label>
|
||||||
|
<bit-hint
|
||||||
|
*ngIf="accountSwitcherEnabled && canOverrideBrowserAutofillSetting"
|
||||||
|
class="tw-text-sm"
|
||||||
|
>
|
||||||
|
{{ "showInlineMenuOnFormFieldsDescAlt" | i18n }}
|
||||||
|
</bit-hint>
|
||||||
|
</bit-form-control>
|
||||||
|
<bit-form-control *ngIf="enableInlineMenu" class="tw-pl-5">
|
||||||
|
<input
|
||||||
|
bitCheckbox
|
||||||
|
id="show-autofill-suggestions-on-icon"
|
||||||
|
type="checkbox"
|
||||||
|
(change)="updateInlineMenuVisibility()"
|
||||||
|
[(ngModel)]="enableInlineMenuOnIconSelect"
|
||||||
|
/>
|
||||||
|
<bit-label for="show-autofill-suggestions-on-icon">
|
||||||
|
{{ "showInlineMenuOnIconSelectionLabel" | i18n }}
|
||||||
|
</bit-label>
|
||||||
|
<bit-hint class="tw-text-sm" *ngIf="!canOverrideBrowserAutofillSetting">
|
||||||
|
{{ "turnOffBrowserBuiltInPasswordManagerSettings" | i18n }}
|
||||||
|
<a
|
||||||
|
bitLink
|
||||||
|
class="tw-no-underline"
|
||||||
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
(click)="openURI($event, disablePasswordManagerURI)"
|
||||||
|
[attr.href]="disablePasswordManagerURI"
|
||||||
|
>
|
||||||
|
{{ "turnOffBrowserBuiltInPasswordManagerSettingsLink" | i18n }}
|
||||||
|
</a>
|
||||||
|
</bit-hint>
|
||||||
|
</bit-form-control>
|
||||||
|
<bit-form-control *ngIf="canOverrideBrowserAutofillSetting">
|
||||||
|
<input
|
||||||
|
bitCheckbox
|
||||||
|
id="overrideBrowserAutofill"
|
||||||
|
type="checkbox"
|
||||||
|
(change)="updateDefaultBrowserAutofillDisabled()"
|
||||||
|
[(ngModel)]="defaultBrowserAutofillDisabled"
|
||||||
|
/>
|
||||||
|
<bit-label for="overrideBrowserAutofill">{{
|
||||||
|
"overrideDefaultBrowserAutoFillSettings" | i18n
|
||||||
|
}}</bit-label>
|
||||||
|
<bit-hint class="tw-text-sm">
|
||||||
|
{{ "turnOffBrowserBuiltInPasswordManagerSettings" | i18n }}
|
||||||
|
<a
|
||||||
|
bitLink
|
||||||
|
class="tw-no-underline"
|
||||||
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
(click)="openURI($event, disablePasswordManagerURI)"
|
||||||
|
[attr.href]="disablePasswordManagerURI"
|
||||||
|
>
|
||||||
|
{{ "turnOffBrowserBuiltInPasswordManagerSettingsLink" | i18n }}
|
||||||
|
</a>
|
||||||
|
</bit-hint>
|
||||||
|
</bit-form-control>
|
||||||
|
<bit-form-control>
|
||||||
|
<input
|
||||||
|
bitCheckbox
|
||||||
|
id="showCardsSuggestions"
|
||||||
|
type="checkbox"
|
||||||
|
(change)="updateShowCardsCurrentTab()"
|
||||||
|
[(ngModel)]="showCardsCurrentTab"
|
||||||
|
/>
|
||||||
|
<bit-label for="showCardsSuggestions">{{ "showCardsInVaultView" | i18n }}</bit-label>
|
||||||
|
</bit-form-control>
|
||||||
|
<bit-form-control>
|
||||||
|
<input
|
||||||
|
bitCheckbox
|
||||||
|
id="showIdentitiesSuggestions"
|
||||||
|
type="checkbox"
|
||||||
|
(change)="updateShowIdentitiesCurrentTab()"
|
||||||
|
[(ngModel)]="showIdentitiesCurrentTab"
|
||||||
|
/>
|
||||||
|
<bit-label for="showIdentitiesSuggestions" class="tw-whitespace-normal">
|
||||||
|
{{ "showIdentitiesInVaultView" | i18n }}
|
||||||
|
</bit-label>
|
||||||
|
</bit-form-control>
|
||||||
|
</bit-card>
|
||||||
|
</bit-section>
|
||||||
|
<bit-section>
|
||||||
|
<bit-section-header>
|
||||||
|
<h2 bitTypography="h5">{{ "autofillKeyboardShortcutSectionTitle" | i18n }}</h2>
|
||||||
|
</bit-section-header>
|
||||||
|
<bit-item>
|
||||||
|
<button bit-item-content type="button" (click)="openURI($event, browserShortcutsURI)">
|
||||||
|
<h3 bitTypography="h5">{{ "autofillKeyboardShortcutUpdateLabel" | i18n }}</h3>
|
||||||
|
<bit-hint slot="secondary" class="tw-text-sm tw-whitespace-normal">
|
||||||
|
{{ autofillKeyboardHelperText }}
|
||||||
|
</bit-hint>
|
||||||
|
<i
|
||||||
|
appA11yTitle="{{ 'opensInANewWindow' | i18n }}"
|
||||||
|
aria-hidden="true"
|
||||||
|
class="bwi bwi-fw bwi-external-link bwi-lg tw-text-muted"
|
||||||
|
slot="end"
|
||||||
|
></i>
|
||||||
|
</button>
|
||||||
|
</bit-item>
|
||||||
|
</bit-section>
|
||||||
|
<bit-section>
|
||||||
|
<bit-section-header>
|
||||||
|
<h2 bitTypography="h5">{{ "enableAutoFillOnPageLoadSectionTitle" | i18n }}</h2>
|
||||||
|
</bit-section-header>
|
||||||
|
<bit-card>
|
||||||
|
<bit-hint class="tw-mb-6 tw-text-sm">
|
||||||
|
{{ "enableAutoFillOnPageLoadDesc" | i18n }}
|
||||||
|
<span [innerHTML]="'autofillOnPageLoadWarning' | i18n: '\<b>' : '\</b>'"></span>
|
||||||
|
<a
|
||||||
|
bitLink
|
||||||
|
class="tw-no-underline"
|
||||||
|
href="https://bitwarden.com/help/auto-fill-browser/"
|
||||||
|
rel="noreferrer"
|
||||||
|
target="_blank"
|
||||||
|
>
|
||||||
|
{{ "learnMoreAboutAutofillOnPageLoadLinkText" | i18n }}
|
||||||
|
</a>
|
||||||
|
</bit-hint>
|
||||||
|
<bit-form-control>
|
||||||
|
<input
|
||||||
|
bitCheckbox
|
||||||
|
id="autofillOnPageLoad"
|
||||||
|
type="checkbox"
|
||||||
|
(change)="updateAutofillOnPageLoad()"
|
||||||
|
[(ngModel)]="enableAutofillOnPageLoad"
|
||||||
|
/>
|
||||||
|
<bit-label for="autofillOnPageLoad">{{ "enableAutoFillOnPageLoad" | i18n }}</bit-label>
|
||||||
|
</bit-form-control>
|
||||||
|
<bit-form-field>
|
||||||
|
<bit-label for="defaultAutofill">{{ "defaultAutoFillOnPageLoad" | i18n }}</bit-label>
|
||||||
|
<select
|
||||||
|
bitInput
|
||||||
|
id="defaultAutofill"
|
||||||
|
(change)="updateAutofillOnPageLoadDefault()"
|
||||||
|
[(ngModel)]="autofillOnPageLoadDefault"
|
||||||
|
[disabled]="!enableAutofillOnPageLoad"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
*ngFor="let o of autofillOnPageLoadOptions"
|
||||||
|
[value]="o.value"
|
||||||
|
[label]="o.name"
|
||||||
|
></option>
|
||||||
|
</select>
|
||||||
|
<bit-hint class="tw-text-sm">
|
||||||
|
{{ "defaultAutoFillOnPageLoadDesc" | i18n }}
|
||||||
|
</bit-hint>
|
||||||
|
</bit-form-field>
|
||||||
|
</bit-card>
|
||||||
|
</bit-section>
|
||||||
|
<bit-section>
|
||||||
|
<bit-section-header>
|
||||||
|
<h2 bitTypography="h5">{{ "additionalOptions" | i18n }}</h2>
|
||||||
|
</bit-section-header>
|
||||||
|
<bit-card>
|
||||||
|
<bit-form-control>
|
||||||
|
<input
|
||||||
|
bitCheckbox
|
||||||
|
id="context-menu"
|
||||||
|
type="checkbox"
|
||||||
|
(change)="updateContextMenuItem()"
|
||||||
|
[(ngModel)]="enableContextMenuItem"
|
||||||
|
/>
|
||||||
|
<bit-label for="context-menu">{{ "enableContextMenuItem" | i18n }}</bit-label>
|
||||||
|
</bit-form-control>
|
||||||
|
<bit-form-control>
|
||||||
|
<input
|
||||||
|
bitCheckbox
|
||||||
|
id="totp"
|
||||||
|
type="checkbox"
|
||||||
|
(change)="updateAutoTotpCopy()"
|
||||||
|
[(ngModel)]="enableAutoTotpCopy"
|
||||||
|
/>
|
||||||
|
<bit-label for="totp">{{ "enableAutoTotpCopy" | i18n }}</bit-label>
|
||||||
|
</bit-form-control>
|
||||||
|
<bit-form-field>
|
||||||
|
<bit-label for="clearClipboard">{{ "clearClipboard" | i18n }}</bit-label>
|
||||||
|
<select
|
||||||
|
aria-describedby="clearClipboardHelp"
|
||||||
|
bitInput
|
||||||
|
id="clearClipboard"
|
||||||
|
(change)="saveClearClipboard()"
|
||||||
|
[(ngModel)]="clearClipboard"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
*ngFor="let o of clearClipboardOptions"
|
||||||
|
[label]="o.name"
|
||||||
|
[value]="o.value"
|
||||||
|
></option>
|
||||||
|
</select>
|
||||||
|
<bit-hint class="tw-text-sm" id="clearClipboardHelp">
|
||||||
|
{{ "clearClipboardDesc" | i18n }}
|
||||||
|
</bit-hint>
|
||||||
|
</bit-form-field>
|
||||||
|
<bit-form-field>
|
||||||
|
<bit-label for="defaultUriMatch">{{ "defaultUriMatchDetection" | i18n }}</bit-label>
|
||||||
|
<select
|
||||||
|
aria-describedby="defaultUriMatchHelp"
|
||||||
|
bitInput
|
||||||
|
id="defaultUriMatch"
|
||||||
|
(change)="saveDefaultUriMatch()"
|
||||||
|
[(ngModel)]="defaultUriMatch"
|
||||||
|
>
|
||||||
|
<option *ngFor="let o of uriMatchOptions" [label]="o.name" [value]="o.value"></option>
|
||||||
|
</select>
|
||||||
|
<bit-hint class="tw-text-sm" id="defaultUriMatchHelp">
|
||||||
|
{{ "defaultUriMatchDetectionDesc" | i18n }}
|
||||||
|
</bit-hint>
|
||||||
|
</bit-form-field>
|
||||||
|
</bit-card>
|
||||||
|
</bit-section>
|
||||||
</div>
|
</div>
|
||||||
<h1 class="center">
|
</popup-page>
|
||||||
<span class="title">{{ "autofill" | i18n }}</span>
|
|
||||||
</h1>
|
|
||||||
<div class="right"></div>
|
|
||||||
</header>
|
|
||||||
<main tabindex="-1">
|
|
||||||
<div class="box tw-mt-4">
|
|
||||||
<div class="box-content">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class="box-content-row box-content-row-link box-content-row-flex"
|
|
||||||
(click)="commandSettings()"
|
|
||||||
>
|
|
||||||
<div class="row-main">{{ "autofillShortcut" | i18n }}</div>
|
|
||||||
<i class="bwi bwi-external-link bwi-lg bwi-fw" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div id="autofillKeyboardHelp" class="box-footer">
|
|
||||||
{{ autofillKeyboardHelperText }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box">
|
|
||||||
<div class="box-content">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="autofill-overlay-settings">{{ "showAutoFillMenuOnFormFields" | i18n }}</label>
|
|
||||||
<select
|
|
||||||
id="autofill-overlay-settings"
|
|
||||||
name="autofill-overlay-settings"
|
|
||||||
[(ngModel)]="autoFillOverlayVisibility"
|
|
||||||
(change)="updateAutoFillOverlayVisibility()"
|
|
||||||
>
|
|
||||||
<option *ngFor="let o of autoFillOverlayVisibilityOptions" [ngValue]="o.value">
|
|
||||||
{{ o.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div class="box-footer" *ngIf="accountSwitcherEnabled && canOverrideBrowserAutofillSetting">
|
|
||||||
{{ "showAutoFillMenuOnFormFieldsDescAlt" | i18n }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box">
|
|
||||||
<div class="box-content" *ngIf="canOverrideBrowserAutofillSetting">
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="overrideBrowserAutofill" class="!tw-mr-0">{{
|
|
||||||
"overrideDefaultBrowserAutoFillSettings" | i18n
|
|
||||||
}}</label>
|
|
||||||
<input
|
|
||||||
id="overrideBrowserAutofill"
|
|
||||||
type="checkbox"
|
|
||||||
(change)="updateDefaultBrowserAutofillDisabled()"
|
|
||||||
[(ngModel)]="defaultBrowserAutofillDisabled"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box-footer">
|
|
||||||
<span *ngIf="accountSwitcherEnabled">{{ "showAutoFillMenuOnFormFieldsDescAlt" | i18n }}</span>
|
|
||||||
{{ "turnOffBrowserBuiltInPasswordManagerSettings" | i18n }}
|
|
||||||
<a
|
|
||||||
[attr.href]="disablePasswordManagerLink"
|
|
||||||
(click)="openDisablePasswordManagerLink($event)"
|
|
||||||
target="_blank"
|
|
||||||
rel="noreferrer"
|
|
||||||
>
|
|
||||||
{{ "turnOffBrowserBuiltInPasswordManagerSettingsLink" | i18n }}
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box tw-mt-4">
|
|
||||||
<div class="box-content">
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="autofill">{{ "enableAutoFillOnPageLoad" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="autofill"
|
|
||||||
type="checkbox"
|
|
||||||
aria-describedby="autofillHelp"
|
|
||||||
(change)="updateAutoFillOnPageLoad()"
|
|
||||||
[(ngModel)]="enableAutoFillOnPageLoad"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="autofillHelp" class="box-footer">
|
|
||||||
{{ "enableAutoFillOnPageLoadDesc" | i18n }}
|
|
||||||
<b>{{ "warning" | i18n }}</b
|
|
||||||
>: {{ "experimentalFeature" | i18n }}
|
|
||||||
<a href="https://bitwarden.com/help/auto-fill-browser/" target="_blank" rel="noreferrer">
|
|
||||||
{{ "learnMoreAboutAutofill" | i18n }}.
|
|
||||||
<i
|
|
||||||
[attr.aria-label]="'opensInANewWindow' | i18n"
|
|
||||||
class="bwi bwi-external-link bwi-sm bwi-fw"
|
|
||||||
></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box">
|
|
||||||
<div class="box-content">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="defaultAutofill">{{ "defaultAutoFillOnPageLoad" | i18n }}</label>
|
|
||||||
<select
|
|
||||||
id="defaultAutofill"
|
|
||||||
name="DefaultAutofill"
|
|
||||||
aria-describedby="defaultAutofillHelp"
|
|
||||||
[(ngModel)]="autoFillOnPageLoadDefault"
|
|
||||||
(change)="updateAutoFillOnPageLoadDefault()"
|
|
||||||
[disabled]="!enableAutoFillOnPageLoad"
|
|
||||||
>
|
|
||||||
<option *ngFor="let o of autoFillOnPageLoadOptions" [ngValue]="o.value">
|
|
||||||
{{ o.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="defaultAutofillHelp" class="box-footer">
|
|
||||||
{{ "defaultAutoFillOnPageLoadDesc" | i18n }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="box">
|
|
||||||
<h2 class="box-header">{{ "additionalOptions" | i18n }}</h2>
|
|
||||||
<div class="box-content">
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="context-menu">{{ "enableContextMenuItem" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="context-menu"
|
|
||||||
type="checkbox"
|
|
||||||
aria-describedby="context-menuHelp"
|
|
||||||
(change)="updateContextMenuItem()"
|
|
||||||
[(ngModel)]="enableContextMenuItem"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="context-menuHelp" class="box-footer">
|
|
||||||
{{
|
|
||||||
accountSwitcherEnabled ? ("contextMenuItemDescAlt" | i18n) : ("contextMenuItemDesc" | i18n)
|
|
||||||
}}
|
|
||||||
</div>
|
|
||||||
<div class="box-content">
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="totp">{{ "enableAutoTotpCopy" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="totp"
|
|
||||||
type="checkbox"
|
|
||||||
aria-describedby="totpHelp"
|
|
||||||
(change)="updateAutoTotpCopy()"
|
|
||||||
[(ngModel)]="enableAutoTotpCopy"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="totpHelp" class="box-footer">{{ "disableAutoTotpCopyDesc" | i18n }}</div>
|
|
||||||
<div class="box-content">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="clearClipboard">{{ "clearClipboard" | i18n }}</label>
|
|
||||||
<select
|
|
||||||
id="clearClipboard"
|
|
||||||
name="ClearClipboard"
|
|
||||||
aria-describedby="clearClipboardHelp"
|
|
||||||
[(ngModel)]="clearClipboard"
|
|
||||||
(change)="saveClearClipboard()"
|
|
||||||
>
|
|
||||||
<option *ngFor="let o of clearClipboardOptions" [ngValue]="o.value">
|
|
||||||
{{ o.name }}
|
|
||||||
</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="clearClipboardHelp" class="box-footer">{{ "clearClipboardDesc" | i18n }}</div>
|
|
||||||
<div class="box-content">
|
|
||||||
<div class="box-content-row" appBoxRow>
|
|
||||||
<label for="defaultUriMatch">{{ "defaultUriMatchDetection" | i18n }}</label>
|
|
||||||
<select
|
|
||||||
id="defaultUriMatch"
|
|
||||||
name="DefaultUriMatch"
|
|
||||||
aria-describedby="defaultUriMatchHelp"
|
|
||||||
[(ngModel)]="defaultUriMatch"
|
|
||||||
(change)="saveDefaultUriMatch()"
|
|
||||||
>
|
|
||||||
<option *ngFor="let o of uriMatchOptions" [ngValue]="o.value">{{ o.name }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="defaultUriMatchHelp" class="box-footer">
|
|
||||||
{{ "defaultUriMatchDetectionDesc" | i18n }}
|
|
||||||
</div>
|
|
||||||
<div class="box-content">
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="showCardsCurrentTab">{{ "showCardsCurrentTab" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="showCardsCurrentTab"
|
|
||||||
type="checkbox"
|
|
||||||
aria-describedby="showCardsCurrentTabHelp"
|
|
||||||
(change)="updateShowCardsCurrentTab()"
|
|
||||||
[(ngModel)]="showCardsCurrentTab"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="showCardsCurrentTabHelp" class="box-footer">
|
|
||||||
{{ "showCardsCurrentTabDesc" | i18n }}
|
|
||||||
</div>
|
|
||||||
<div class="box-content">
|
|
||||||
<div class="box-content-row box-content-row-checkbox" appBoxRow>
|
|
||||||
<label for="showIdentitiesCurrentTab">{{ "showIdentitiesCurrentTab" | i18n }}</label>
|
|
||||||
<input
|
|
||||||
id="showIdentitiesCurrentTab"
|
|
||||||
type="checkbox"
|
|
||||||
aria-describedby="showIdentitiesCurrentTabHelp"
|
|
||||||
(change)="updateShowIdentitiesCurrentTab()"
|
|
||||||
[(ngModel)]="showIdentitiesCurrentTab"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="showIdentitiesCurrentTabHelp" class="box-footer">
|
|
||||||
{{ "showIdentitiesCurrentTabDesc" | i18n }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
|
|
|
@ -1,12 +1,25 @@
|
||||||
|
import { CommonModule } from "@angular/common";
|
||||||
import { Component, OnInit } from "@angular/core";
|
import { Component, OnInit } from "@angular/core";
|
||||||
|
import { FormsModule } from "@angular/forms";
|
||||||
|
import { RouterModule } from "@angular/router";
|
||||||
import { firstValueFrom } from "rxjs";
|
import { firstValueFrom } from "rxjs";
|
||||||
|
|
||||||
import { AutofillOverlayVisibility } from "@bitwarden/common/autofill/constants";
|
import { JslibModule } from "@bitwarden/angular/jslib.module";
|
||||||
|
import {
|
||||||
|
AutofillOverlayVisibility,
|
||||||
|
BrowserClientVendors,
|
||||||
|
BrowserShortcutsUris,
|
||||||
|
ClearClipboardDelay,
|
||||||
|
DisablePasswordManagerUris,
|
||||||
|
} from "@bitwarden/common/autofill/constants";
|
||||||
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
import { AutofillSettingsServiceAbstraction } from "@bitwarden/common/autofill/services/autofill-settings.service";
|
||||||
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
import { DomainSettingsService } from "@bitwarden/common/autofill/services/domain-settings.service";
|
||||||
import {
|
import {
|
||||||
InlineMenuVisibilitySetting,
|
BrowserClientVendor,
|
||||||
|
BrowserShortcutsUri,
|
||||||
ClearClipboardDelaySetting,
|
ClearClipboardDelaySetting,
|
||||||
|
DisablePasswordManagerUri,
|
||||||
|
InlineMenuVisibilitySetting,
|
||||||
} from "@bitwarden/common/autofill/types";
|
} from "@bitwarden/common/autofill/types";
|
||||||
import {
|
import {
|
||||||
UriMatchStrategy,
|
UriMatchStrategy,
|
||||||
|
@ -16,33 +29,77 @@ import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.servic
|
||||||
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
import { MessagingService } from "@bitwarden/common/platform/abstractions/messaging.service";
|
||||||
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
import { PlatformUtilsService } from "@bitwarden/common/platform/abstractions/platform-utils.service";
|
||||||
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
import { VaultSettingsService } from "@bitwarden/common/vault/abstractions/vault-settings/vault-settings.service";
|
||||||
import { DialogService } from "@bitwarden/components";
|
import {
|
||||||
|
CardComponent,
|
||||||
|
CheckboxModule,
|
||||||
|
DialogService,
|
||||||
|
FormFieldModule,
|
||||||
|
IconButtonModule,
|
||||||
|
ItemModule,
|
||||||
|
LinkModule,
|
||||||
|
SectionComponent,
|
||||||
|
SectionHeaderComponent,
|
||||||
|
SelectModule,
|
||||||
|
TypographyModule,
|
||||||
|
} from "@bitwarden/components";
|
||||||
|
|
||||||
import { BrowserApi } from "../../../platform/browser/browser-api";
|
import { BrowserApi } from "../../../platform/browser/browser-api";
|
||||||
import { enableAccountSwitching } from "../../../platform/flags";
|
import { PopOutComponent } from "../../../platform/popup/components/pop-out.component";
|
||||||
import { AutofillService } from "../../services/abstractions/autofill.service";
|
import { PopupFooterComponent } from "../../../platform/popup/layout/popup-footer.component";
|
||||||
|
import { PopupHeaderComponent } from "../../../platform/popup/layout/popup-header.component";
|
||||||
|
import { PopupPageComponent } from "../../../platform/popup/layout/popup-page.component";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: "app-autofill",
|
|
||||||
templateUrl: "autofill.component.html",
|
templateUrl: "autofill.component.html",
|
||||||
|
standalone: true,
|
||||||
|
imports: [
|
||||||
|
CardComponent,
|
||||||
|
CheckboxModule,
|
||||||
|
CommonModule,
|
||||||
|
FormFieldModule,
|
||||||
|
FormsModule,
|
||||||
|
IconButtonModule,
|
||||||
|
ItemModule,
|
||||||
|
JslibModule,
|
||||||
|
LinkModule,
|
||||||
|
PopOutComponent,
|
||||||
|
PopupFooterComponent,
|
||||||
|
PopupHeaderComponent,
|
||||||
|
PopupPageComponent,
|
||||||
|
RouterModule,
|
||||||
|
SectionComponent,
|
||||||
|
SectionHeaderComponent,
|
||||||
|
SelectModule,
|
||||||
|
TypographyModule,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class AutofillComponent implements OnInit {
|
export class AutofillComponent implements OnInit {
|
||||||
|
/*
|
||||||
|
* Default values set here are used in component state operations
|
||||||
|
* until corresponding stored settings have loaded on init.
|
||||||
|
*/
|
||||||
protected canOverrideBrowserAutofillSetting = false;
|
protected canOverrideBrowserAutofillSetting = false;
|
||||||
protected defaultBrowserAutofillDisabled = false;
|
protected defaultBrowserAutofillDisabled = false;
|
||||||
protected autoFillOverlayVisibility: InlineMenuVisibilitySetting;
|
protected inlineMenuVisibility: InlineMenuVisibilitySetting =
|
||||||
protected autoFillOverlayVisibilityOptions: any[];
|
AutofillOverlayVisibility.OnFieldFocus;
|
||||||
protected disablePasswordManagerLink: string;
|
protected browserClientVendor: BrowserClientVendor = BrowserClientVendors.Unknown;
|
||||||
enableAutoFillOnPageLoad = false;
|
protected disablePasswordManagerURI: DisablePasswordManagerUri =
|
||||||
autoFillOnPageLoadDefault = false;
|
DisablePasswordManagerUris.Unknown;
|
||||||
autoFillOnPageLoadOptions: any[];
|
protected browserShortcutsURI: BrowserShortcutsUri = BrowserShortcutsUris.Unknown;
|
||||||
|
protected browserClientIsUnknown: boolean;
|
||||||
|
enableAutofillOnPageLoad = false;
|
||||||
|
enableInlineMenu = false;
|
||||||
|
enableInlineMenuOnIconSelect = false;
|
||||||
|
autofillOnPageLoadDefault = false;
|
||||||
|
autofillOnPageLoadOptions: { name: string; value: boolean }[];
|
||||||
enableContextMenuItem = false;
|
enableContextMenuItem = false;
|
||||||
enableAutoTotpCopy = false; // TODO: Does it matter if this is set to false or true?
|
enableAutoTotpCopy = false;
|
||||||
clearClipboard: ClearClipboardDelaySetting;
|
clearClipboard: ClearClipboardDelaySetting;
|
||||||
clearClipboardOptions: any[];
|
clearClipboardOptions: { name: string; value: ClearClipboardDelaySetting }[];
|
||||||
defaultUriMatch: UriMatchStrategySetting = UriMatchStrategy.Domain;
|
defaultUriMatch: UriMatchStrategySetting = UriMatchStrategy.Domain;
|
||||||
uriMatchOptions: any[];
|
uriMatchOptions: { name: string; value: UriMatchStrategySetting }[];
|
||||||
showCardsCurrentTab = false;
|
showCardsCurrentTab = true;
|
||||||
showIdentitiesCurrentTab = false;
|
showIdentitiesCurrentTab = true;
|
||||||
autofillKeyboardHelperText: string;
|
autofillKeyboardHelperText: string;
|
||||||
accountSwitcherEnabled = false;
|
accountSwitcherEnabled = false;
|
||||||
|
|
||||||
|
@ -50,38 +107,23 @@ export class AutofillComponent implements OnInit {
|
||||||
private i18nService: I18nService,
|
private i18nService: I18nService,
|
||||||
private platformUtilsService: PlatformUtilsService,
|
private platformUtilsService: PlatformUtilsService,
|
||||||
private domainSettingsService: DomainSettingsService,
|
private domainSettingsService: DomainSettingsService,
|
||||||
private autofillService: AutofillService,
|
|
||||||
private dialogService: DialogService,
|
private dialogService: DialogService,
|
||||||
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
private autofillSettingsService: AutofillSettingsServiceAbstraction,
|
||||||
private messagingService: MessagingService,
|
private messagingService: MessagingService,
|
||||||
private vaultSettingsService: VaultSettingsService,
|
private vaultSettingsService: VaultSettingsService,
|
||||||
) {
|
) {
|
||||||
this.autoFillOverlayVisibilityOptions = [
|
this.autofillOnPageLoadOptions = [
|
||||||
{
|
|
||||||
name: i18nService.t("autofillOverlayVisibilityOff"),
|
|
||||||
value: AutofillOverlayVisibility.Off,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: i18nService.t("autofillOverlayVisibilityOnFieldFocus"),
|
|
||||||
value: AutofillOverlayVisibility.OnFieldFocus,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: i18nService.t("autofillOverlayVisibilityOnButtonClick"),
|
|
||||||
value: AutofillOverlayVisibility.OnButtonClick,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
this.autoFillOnPageLoadOptions = [
|
|
||||||
{ name: i18nService.t("autoFillOnPageLoadYes"), value: true },
|
{ name: i18nService.t("autoFillOnPageLoadYes"), value: true },
|
||||||
{ name: i18nService.t("autoFillOnPageLoadNo"), value: false },
|
{ name: i18nService.t("autoFillOnPageLoadNo"), value: false },
|
||||||
];
|
];
|
||||||
this.clearClipboardOptions = [
|
this.clearClipboardOptions = [
|
||||||
{ name: i18nService.t("never"), value: null },
|
{ name: i18nService.t("never"), value: ClearClipboardDelay.Never },
|
||||||
{ name: i18nService.t("tenSeconds"), value: 10 },
|
{ name: i18nService.t("tenSeconds"), value: ClearClipboardDelay.TenSeconds },
|
||||||
{ name: i18nService.t("twentySeconds"), value: 20 },
|
{ name: i18nService.t("twentySeconds"), value: ClearClipboardDelay.TwentySeconds },
|
||||||
{ name: i18nService.t("thirtySeconds"), value: 30 },
|
{ name: i18nService.t("thirtySeconds"), value: ClearClipboardDelay.ThirtySeconds },
|
||||||
{ name: i18nService.t("oneMinute"), value: 60 },
|
{ name: i18nService.t("oneMinute"), value: ClearClipboardDelay.OneMinute },
|
||||||
{ name: i18nService.t("twoMinutes"), value: 120 },
|
{ name: i18nService.t("twoMinutes"), value: ClearClipboardDelay.TwoMinutes },
|
||||||
{ name: i18nService.t("fiveMinutes"), value: 300 },
|
{ name: i18nService.t("fiveMinutes"), value: ClearClipboardDelay.FiveMinutes },
|
||||||
];
|
];
|
||||||
this.uriMatchOptions = [
|
this.uriMatchOptions = [
|
||||||
{ name: i18nService.t("baseDomain"), value: UriMatchStrategy.Domain },
|
{ name: i18nService.t("baseDomain"), value: UriMatchStrategy.Domain },
|
||||||
|
@ -92,28 +134,32 @@ export class AutofillComponent implements OnInit {
|
||||||
{ name: i18nService.t("never"), value: UriMatchStrategy.Never },
|
{ name: i18nService.t("never"), value: UriMatchStrategy.Never },
|
||||||
];
|
];
|
||||||
|
|
||||||
this.accountSwitcherEnabled = enableAccountSwitching();
|
this.browserClientVendor = this.getBrowserClientVendor();
|
||||||
this.disablePasswordManagerLink = this.getDisablePasswordManagerLink();
|
this.disablePasswordManagerURI = DisablePasswordManagerUris[this.browserClientVendor];
|
||||||
|
this.browserShortcutsURI = BrowserShortcutsUris[this.browserClientVendor];
|
||||||
|
this.browserClientIsUnknown = this.browserClientVendor === BrowserClientVendors.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
async ngOnInit() {
|
async ngOnInit() {
|
||||||
this.canOverrideBrowserAutofillSetting =
|
this.canOverrideBrowserAutofillSetting = !this.browserClientIsUnknown;
|
||||||
this.platformUtilsService.isChrome() ||
|
|
||||||
this.platformUtilsService.isEdge() ||
|
|
||||||
this.platformUtilsService.isOpera() ||
|
|
||||||
this.platformUtilsService.isVivaldi();
|
|
||||||
|
|
||||||
this.defaultBrowserAutofillDisabled = await this.browserAutofillSettingCurrentlyOverridden();
|
this.defaultBrowserAutofillDisabled = await this.browserAutofillSettingCurrentlyOverridden();
|
||||||
|
|
||||||
this.autoFillOverlayVisibility = await firstValueFrom(
|
this.inlineMenuVisibility = await firstValueFrom(
|
||||||
this.autofillSettingsService.inlineMenuVisibility$,
|
this.autofillSettingsService.inlineMenuVisibility$,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.enableAutoFillOnPageLoad = await firstValueFrom(
|
this.enableInlineMenuOnIconSelect =
|
||||||
|
this.inlineMenuVisibility === AutofillOverlayVisibility.OnButtonClick;
|
||||||
|
|
||||||
|
this.enableInlineMenu =
|
||||||
|
this.inlineMenuVisibility === AutofillOverlayVisibility.OnFieldFocus ||
|
||||||
|
this.enableInlineMenuOnIconSelect;
|
||||||
|
|
||||||
|
this.enableAutofillOnPageLoad = await firstValueFrom(
|
||||||
this.autofillSettingsService.autofillOnPageLoad$,
|
this.autofillSettingsService.autofillOnPageLoad$,
|
||||||
);
|
);
|
||||||
|
|
||||||
this.autoFillOnPageLoadDefault = await firstValueFrom(
|
this.autofillOnPageLoadDefault = await firstValueFrom(
|
||||||
this.autofillSettingsService.autofillOnPageLoadDefault$,
|
this.autofillSettingsService.autofillOnPageLoadDefault$,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -140,17 +186,27 @@ export class AutofillComponent implements OnInit {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateAutoFillOverlayVisibility() {
|
async updateInlineMenuVisibility() {
|
||||||
await this.autofillSettingsService.setInlineMenuVisibility(this.autoFillOverlayVisibility);
|
if (!this.enableInlineMenu) {
|
||||||
|
this.enableInlineMenuOnIconSelect = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newInlineMenuVisibilityValue = this.enableInlineMenuOnIconSelect
|
||||||
|
? AutofillOverlayVisibility.OnButtonClick
|
||||||
|
: this.enableInlineMenu
|
||||||
|
? AutofillOverlayVisibility.OnFieldFocus
|
||||||
|
: AutofillOverlayVisibility.Off;
|
||||||
|
|
||||||
|
await this.autofillSettingsService.setInlineMenuVisibility(newInlineMenuVisibilityValue);
|
||||||
await this.requestPrivacyPermission();
|
await this.requestPrivacyPermission();
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateAutoFillOnPageLoad() {
|
async updateAutofillOnPageLoad() {
|
||||||
await this.autofillSettingsService.setAutofillOnPageLoad(this.enableAutoFillOnPageLoad);
|
await this.autofillSettingsService.setAutofillOnPageLoad(this.enableAutofillOnPageLoad);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateAutoFillOnPageLoadDefault() {
|
async updateAutofillOnPageLoadDefault() {
|
||||||
await this.autofillSettingsService.setAutofillOnPageLoadDefault(this.autoFillOnPageLoadDefault);
|
await this.autofillSettingsService.setAutofillOnPageLoadDefault(this.autofillOnPageLoadDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveDefaultUriMatch() {
|
async saveDefaultUriMatch() {
|
||||||
|
@ -165,57 +221,81 @@ export class AutofillComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async commandSettings() {
|
private getBrowserClientVendor(): BrowserClientVendor {
|
||||||
if (this.platformUtilsService.isChrome()) {
|
if (this.platformUtilsService.isChrome()) {
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
return BrowserClientVendors.Chrome;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
BrowserApi.createNewTab("chrome://extensions/shortcuts");
|
|
||||||
} else if (this.platformUtilsService.isOpera()) {
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
BrowserApi.createNewTab("opera://extensions/shortcuts");
|
|
||||||
} else if (this.platformUtilsService.isEdge()) {
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
BrowserApi.createNewTab("edge://extensions/shortcuts");
|
|
||||||
} else if (this.platformUtilsService.isVivaldi()) {
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
BrowserApi.createNewTab("vivaldi://extensions/shortcuts");
|
|
||||||
} else {
|
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
BrowserApi.createNewTab("https://bitwarden.com/help/keyboard-shortcuts");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private getDisablePasswordManagerLink(): string {
|
|
||||||
if (this.platformUtilsService.isChrome()) {
|
|
||||||
return "chrome://settings/autofill";
|
|
||||||
}
|
|
||||||
if (this.platformUtilsService.isOpera()) {
|
if (this.platformUtilsService.isOpera()) {
|
||||||
return "opera://settings/autofill";
|
return BrowserClientVendors.Opera;
|
||||||
}
|
|
||||||
if (this.platformUtilsService.isEdge()) {
|
|
||||||
return "edge://settings/passwords";
|
|
||||||
}
|
|
||||||
if (this.platformUtilsService.isVivaldi()) {
|
|
||||||
return "vivaldi://settings/autofill";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return "https://bitwarden.com/help/disable-browser-autofill/";
|
if (this.platformUtilsService.isEdge()) {
|
||||||
|
return BrowserClientVendors.Edge;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.platformUtilsService.isVivaldi()) {
|
||||||
|
return BrowserClientVendors.Vivaldi;
|
||||||
|
}
|
||||||
|
|
||||||
|
return BrowserClientVendors.Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected openDisablePasswordManagerLink(event: Event) {
|
protected async openURI(event: Event, uri: BrowserShortcutsUri | DisablePasswordManagerUri) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
// FIXME: Verify that this floating promise is intentional. If it is, add an explanatory comment and ensure there is proper error handling.
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
// If the destination is a password management settings page, ask the user to confirm before proceeding
|
||||||
BrowserApi.createNewTab(this.disablePasswordManagerLink);
|
if (uri === DisablePasswordManagerUris[this.browserClientVendor]) {
|
||||||
|
await this.dialogService.openSimpleDialog({
|
||||||
|
...(this.browserClientIsUnknown
|
||||||
|
? {
|
||||||
|
content: { key: "confirmContinueToHelpCenterPasswordManagementContent" },
|
||||||
|
title: { key: "confirmContinueToHelpCenter" },
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
content: { key: "confirmContinueToBrowserPasswordManagementSettingsContent" },
|
||||||
|
title: { key: "confirmContinueToBrowserSettingsTitle" },
|
||||||
|
}),
|
||||||
|
acceptButtonText: { key: "continue" },
|
||||||
|
acceptAction: async () => {
|
||||||
|
await BrowserApi.createNewTab(uri);
|
||||||
|
},
|
||||||
|
cancelButtonText: { key: "cancel" },
|
||||||
|
type: "info",
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the destination is a browser shortcut settings page, ask the user to confirm before proceeding
|
||||||
|
if (uri === BrowserShortcutsUris[this.browserClientVendor]) {
|
||||||
|
await this.dialogService.openSimpleDialog({
|
||||||
|
...(this.browserClientIsUnknown
|
||||||
|
? {
|
||||||
|
content: { key: "confirmContinueToHelpCenterKeyboardShortcutsContent" },
|
||||||
|
title: { key: "confirmContinueToHelpCenter" },
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
content: { key: "confirmContinueToBrowserKeyboardShortcutSettingsContent" },
|
||||||
|
title: { key: "confirmContinueToBrowserSettingsTitle" },
|
||||||
|
}),
|
||||||
|
acceptButtonText: { key: "continue" },
|
||||||
|
acceptAction: async () => {
|
||||||
|
await BrowserApi.createNewTab(uri);
|
||||||
|
},
|
||||||
|
cancelButtonText: { key: "cancel" },
|
||||||
|
type: "info",
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await BrowserApi.createNewTab(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
async requestPrivacyPermission() {
|
async requestPrivacyPermission() {
|
||||||
if (
|
if (
|
||||||
this.autoFillOverlayVisibility === AutofillOverlayVisibility.Off ||
|
this.inlineMenuVisibility === AutofillOverlayVisibility.Off ||
|
||||||
!this.canOverrideBrowserAutofillSetting ||
|
!this.canOverrideBrowserAutofillSetting ||
|
||||||
(await this.browserAutofillSettingCurrentlyOverridden())
|
(await this.browserAutofillSettingCurrentlyOverridden())
|
||||||
) {
|
) {
|
||||||
|
@ -225,9 +305,9 @@ export class AutofillComponent implements OnInit {
|
||||||
await this.dialogService.openSimpleDialog({
|
await this.dialogService.openSimpleDialog({
|
||||||
title: { key: "overrideDefaultBrowserAutofillTitle" },
|
title: { key: "overrideDefaultBrowserAutofillTitle" },
|
||||||
content: { key: "overrideDefaultBrowserAutofillDescription" },
|
content: { key: "overrideDefaultBrowserAutofillDescription" },
|
||||||
acceptButtonText: { key: "makeDefault" },
|
acceptButtonText: { key: "continue" },
|
||||||
acceptAction: async () => await this.handleOverrideDialogAccept(),
|
acceptAction: async () => await this.handleOverrideDialogAccept(),
|
||||||
cancelButtonText: { key: "ignore" },
|
cancelButtonText: { key: "cancel" },
|
||||||
type: "info",
|
type: "info",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import { TwoFactorAuthComponent } from "../auth/popup/two-factor-auth.component"
|
||||||
import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component";
|
import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component";
|
||||||
import { TwoFactorComponent } from "../auth/popup/two-factor.component";
|
import { TwoFactorComponent } from "../auth/popup/two-factor.component";
|
||||||
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
|
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
|
||||||
|
import { AutofillV1Component } from "../autofill/popup/settings/autofill-v1.component";
|
||||||
import { AutofillComponent } from "../autofill/popup/settings/autofill.component";
|
import { AutofillComponent } from "../autofill/popup/settings/autofill.component";
|
||||||
import { ExcludedDomainsV1Component } from "../autofill/popup/settings/excluded-domains-v1.component";
|
import { ExcludedDomainsV1Component } from "../autofill/popup/settings/excluded-domains-v1.component";
|
||||||
import { ExcludedDomainsComponent } from "../autofill/popup/settings/excluded-domains.component";
|
import { ExcludedDomainsComponent } from "../autofill/popup/settings/excluded-domains.component";
|
||||||
|
@ -278,12 +279,11 @@ const routes: Routes = [
|
||||||
canActivate: [AuthGuard],
|
canActivate: [AuthGuard],
|
||||||
data: { state: "export" },
|
data: { state: "export" },
|
||||||
}),
|
}),
|
||||||
{
|
...extensionRefreshSwap(AutofillV1Component, AutofillComponent, {
|
||||||
path: "autofill",
|
path: "autofill",
|
||||||
component: AutofillComponent,
|
|
||||||
canActivate: [AuthGuard],
|
canActivate: [AuthGuard],
|
||||||
data: { state: "autofill" },
|
data: { state: "autofill" },
|
||||||
},
|
}),
|
||||||
{
|
{
|
||||||
path: "account-security",
|
path: "account-security",
|
||||||
component: AccountSecurityComponent,
|
component: AccountSecurityComponent,
|
||||||
|
|
|
@ -36,6 +36,7 @@ import { SsoComponent } from "../auth/popup/sso.component";
|
||||||
import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component";
|
import { TwoFactorOptionsComponent } from "../auth/popup/two-factor-options.component";
|
||||||
import { TwoFactorComponent } from "../auth/popup/two-factor.component";
|
import { TwoFactorComponent } from "../auth/popup/two-factor.component";
|
||||||
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
|
import { UpdateTempPasswordComponent } from "../auth/popup/update-temp-password.component";
|
||||||
|
import { AutofillV1Component } from "../autofill/popup/settings/autofill-v1.component";
|
||||||
import { AutofillComponent } from "../autofill/popup/settings/autofill.component";
|
import { AutofillComponent } from "../autofill/popup/settings/autofill.component";
|
||||||
import { ExcludedDomainsV1Component } from "../autofill/popup/settings/excluded-domains-v1.component";
|
import { ExcludedDomainsV1Component } from "../autofill/popup/settings/excluded-domains-v1.component";
|
||||||
import { ExcludedDomainsComponent } from "../autofill/popup/settings/excluded-domains.component";
|
import { ExcludedDomainsComponent } from "../autofill/popup/settings/excluded-domains.component";
|
||||||
|
@ -93,6 +94,7 @@ import "../platform/popup/locales";
|
||||||
imports: [
|
imports: [
|
||||||
A11yModule,
|
A11yModule,
|
||||||
AppRoutingModule,
|
AppRoutingModule,
|
||||||
|
AutofillComponent,
|
||||||
ToastModule.forRoot({
|
ToastModule.forRoot({
|
||||||
maxOpened: 2,
|
maxOpened: 2,
|
||||||
autoDismiss: true,
|
autoDismiss: true,
|
||||||
|
@ -180,7 +182,7 @@ import "../platform/popup/locales";
|
||||||
RemovePasswordComponent,
|
RemovePasswordComponent,
|
||||||
VaultSelectComponent,
|
VaultSelectComponent,
|
||||||
Fido2Component,
|
Fido2Component,
|
||||||
AutofillComponent,
|
AutofillV1Component,
|
||||||
EnvironmentSelectorComponent,
|
EnvironmentSelectorComponent,
|
||||||
AccountSwitcherComponent,
|
AccountSwitcherComponent,
|
||||||
],
|
],
|
||||||
|
|
|
@ -61,3 +61,27 @@ export const AutofillOverlayVisibility = {
|
||||||
OnButtonClick: 1,
|
OnButtonClick: 1,
|
||||||
OnFieldFocus: 2,
|
OnFieldFocus: 2,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const BrowserClientVendors = {
|
||||||
|
Chrome: "Chrome",
|
||||||
|
Opera: "Opera",
|
||||||
|
Edge: "Edge",
|
||||||
|
Vivaldi: "Vivaldi",
|
||||||
|
Unknown: "Unknown",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const BrowserShortcutsUris = {
|
||||||
|
Chrome: "chrome://extensions/shortcuts",
|
||||||
|
Opera: "opera://extensions/shortcuts",
|
||||||
|
Edge: "edge://extensions/shortcuts",
|
||||||
|
Vivaldi: "vivaldi://extensions/shortcuts",
|
||||||
|
Unknown: "https://bitwarden.com/help/keyboard-shortcuts",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const DisablePasswordManagerUris = {
|
||||||
|
Chrome: "chrome://settings/autofill",
|
||||||
|
Opera: "opera://settings/autofill",
|
||||||
|
Edge: "edge://settings/passwords",
|
||||||
|
Vivaldi: "vivaldi://settings/autofill",
|
||||||
|
Unknown: "https://bitwarden.com/help/disable-browser-autofill/",
|
||||||
|
} as const;
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
import { ClearClipboardDelay, AutofillOverlayVisibility } from "../constants";
|
import {
|
||||||
|
AutofillOverlayVisibility,
|
||||||
|
BrowserClientVendors,
|
||||||
|
BrowserShortcutsUris,
|
||||||
|
ClearClipboardDelay,
|
||||||
|
DisablePasswordManagerUris,
|
||||||
|
} from "../constants";
|
||||||
|
|
||||||
export type ClearClipboardDelaySetting =
|
export type ClearClipboardDelaySetting =
|
||||||
(typeof ClearClipboardDelay)[keyof typeof ClearClipboardDelay];
|
(typeof ClearClipboardDelay)[keyof typeof ClearClipboardDelay];
|
||||||
|
|
||||||
export type InlineMenuVisibilitySetting =
|
export type InlineMenuVisibilitySetting =
|
||||||
(typeof AutofillOverlayVisibility)[keyof typeof AutofillOverlayVisibility];
|
(typeof AutofillOverlayVisibility)[keyof typeof AutofillOverlayVisibility];
|
||||||
|
|
||||||
|
export type BrowserClientVendor = (typeof BrowserClientVendors)[keyof typeof BrowserClientVendors];
|
||||||
|
export type BrowserShortcutsUri = (typeof BrowserShortcutsUris)[keyof typeof BrowserShortcutsUris];
|
||||||
|
export type DisablePasswordManagerUri =
|
||||||
|
(typeof DisablePasswordManagerUris)[keyof typeof DisablePasswordManagerUris];
|
||||||
|
|
Loading…
Reference in New Issue