mirror of
https://github.com/bitwarden/browser.git
synced 2024-09-27 04:03:00 +02:00
[SG-900] Autofill callout updates (#4738)
* Updated messages * Implement method in platformUtils to get autofill command * Updates to callout in current tab component * Add autofill keyboard shortcut to autofill settings * style updates * Add routing animation for autofill settings * Remove extra function * Remove unnecessary safari logic * Remove autofill settings transition added in another PR * Fix callout still present after clicking 'Got it' (#4797) --------- Co-authored-by: Jared Snider <116684653+JaredSnider-Bitwarden@users.noreply.github.com>
This commit is contained in:
parent
4780a9ce18
commit
999a40e755
@ -2111,25 +2111,49 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"tryAutofillPageLoad": {
|
||||
"message": "Try auto-fill on page load?"
|
||||
},
|
||||
"tryAutofill": {
|
||||
"howToAutofill": {
|
||||
"message": "How to auto-fill"
|
||||
},
|
||||
"autofillPageLoadInfo": {
|
||||
"message": "Login forms will automatically fill in matching credentials if you turn on auto-fill on page load."
|
||||
},
|
||||
"autofillSelectInfo": {
|
||||
"message": "Select an item from this page to auto-fill the active tab's form."
|
||||
"message": "Select an item from this page or use the shortcut: $COMMAND$. You can also try auto-fill on page load.",
|
||||
"placeholders": {
|
||||
"command": {
|
||||
"content": "$1",
|
||||
"example": "CTRL+Shift+L"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autofillTurnedOn": {
|
||||
"message": "Auto-fill on page load turned on"
|
||||
"autofillSelectInfoNoCommand": {
|
||||
"message": "Select an item from this page or set a shortcut in settings. You can also try auto-fill on page load."
|
||||
},
|
||||
"turnOn": {
|
||||
"message": "Turn on"
|
||||
"gotIt": {
|
||||
"message": "Got it"
|
||||
},
|
||||
"notNow": {
|
||||
"message": "Not now"
|
||||
"autofillSettings": {
|
||||
"message": "Auto-fill settings"
|
||||
},
|
||||
"autofillShortcut": {
|
||||
"message": "Auto-fill keyboard shortcut"
|
||||
},
|
||||
"autofillShortcutNotSet": {
|
||||
"message": "The auto-fill shortcut is not set. Change this in the browser's settings."
|
||||
},
|
||||
"autofillShortcutText": {
|
||||
"message": "The auto-fill shortcut is: $COMMAND$. Change this in the browser's settings.",
|
||||
"placeholders": {
|
||||
"command": {
|
||||
"content": "$1",
|
||||
"example": "CTRL+Shift+L"
|
||||
}
|
||||
}
|
||||
},
|
||||
"autofillShortcutTextSafari": {
|
||||
"message": "Default auto-fill shortcut: $COMMAND$.",
|
||||
"placeholders": {
|
||||
"command": {
|
||||
"content": "$1",
|
||||
"example": "CTRL+Shift+L"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -354,6 +354,7 @@
|
||||
&.box-content-row-flex,
|
||||
.box-content-row-flex,
|
||||
&.box-content-row-checkbox,
|
||||
&.box-content-row-link,
|
||||
&.box-content-row-input,
|
||||
&.box-content-row-slider,
|
||||
&.box-content-row-multi {
|
||||
@ -398,6 +399,7 @@
|
||||
}
|
||||
|
||||
&.box-content-row-checkbox,
|
||||
&.box-content-row-link,
|
||||
&.box-content-row-input,
|
||||
&.box-content-row-slider {
|
||||
padding-top: 10px;
|
||||
|
@ -28,7 +28,7 @@
|
||||
|
||||
&.callout-half {
|
||||
font-weight: bold;
|
||||
max-width: 45%;
|
||||
max-width: 50%;
|
||||
}
|
||||
|
||||
&:hover:not([disabled]) {
|
||||
|
@ -72,4 +72,19 @@
|
||||
{{ "defaultUriMatchDetectionDesc" | i18n }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="box">
|
||||
<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>
|
||||
</main>
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { Component, OnInit } from "@angular/core";
|
||||
|
||||
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
|
||||
import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service";
|
||||
import { StateService } from "@bitwarden/common/abstractions/state.service";
|
||||
import { UriMatchType } from "@bitwarden/common/enums/uriMatchType";
|
||||
|
||||
@ -16,8 +17,13 @@ export class AutofillComponent implements OnInit {
|
||||
autoFillOnPageLoadOptions: any[];
|
||||
defaultUriMatch = UriMatchType.Domain;
|
||||
uriMatchOptions: any[];
|
||||
autofillKeyboardHelperText: string;
|
||||
|
||||
constructor(private stateService: StateService, i18nService: I18nService) {
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
private i18nService: I18nService,
|
||||
private platformUtilsService: PlatformUtilsService
|
||||
) {
|
||||
this.autoFillOnPageLoadOptions = [
|
||||
{ name: i18nService.t("autoFillOnPageLoadYes"), value: true },
|
||||
{ name: i18nService.t("autoFillOnPageLoadNo"), value: false },
|
||||
@ -40,6 +46,9 @@ export class AutofillComponent implements OnInit {
|
||||
|
||||
const defaultUriMatch = await this.stateService.getDefaultUriMatch();
|
||||
this.defaultUriMatch = defaultUriMatch == null ? UriMatchType.Domain : defaultUriMatch;
|
||||
|
||||
const command = await this.platformUtilsService.getAutofillKeyboardShortcut();
|
||||
await this.setAutofillKeyboardHelperText(command);
|
||||
}
|
||||
|
||||
async updateAutoFillOnPageLoad() {
|
||||
@ -57,4 +66,26 @@ export class AutofillComponent implements OnInit {
|
||||
AboutAutofill() {
|
||||
BrowserApi.createNewTab("https://bitwarden.com/help/auto-fill-browser/");
|
||||
}
|
||||
|
||||
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()) {
|
||||
BrowserApi.createNewTab("chrome://extensions/shortcuts");
|
||||
} else if (this.platformUtilsService.isOpera()) {
|
||||
BrowserApi.createNewTab("opera://extensions/shortcuts");
|
||||
} else if (this.platformUtilsService.isEdge()) {
|
||||
BrowserApi.createNewTab("edge://extensions/shortcuts");
|
||||
} else if (this.platformUtilsService.isVivaldi()) {
|
||||
BrowserApi.createNewTab("vivaldi://extensions/shortcuts");
|
||||
} else {
|
||||
BrowserApi.createNewTab("https://bitwarden.com/help/keyboard-shortcuts");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -377,4 +377,31 @@ export default class BrowserPlatformUtilsService implements PlatformUtilsService
|
||||
supportsSecureStorage(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
async getAutofillKeyboardShortcut(): Promise<string> {
|
||||
let autofillCommand: string;
|
||||
// You can not change the command in Safari or obtain it programmatically
|
||||
if (this.isSafari()) {
|
||||
autofillCommand = "Cmd+Shift+L";
|
||||
} else if (this.isFirefox()) {
|
||||
autofillCommand = (await browser.commands.getAll()).find(
|
||||
(c) => c.name === "autofill_login"
|
||||
).shortcut;
|
||||
// Firefox is returing Ctrl instead of Cmd for the modifier key on macOS if
|
||||
// the command is the default one set on installation.
|
||||
if (
|
||||
(await browser.runtime.getPlatformInfo()).os === "mac" &&
|
||||
autofillCommand === "Ctrl+Shift+L"
|
||||
) {
|
||||
autofillCommand = "Cmd+Shift+L";
|
||||
}
|
||||
} else {
|
||||
await new Promise((resolve) =>
|
||||
chrome.commands.getAll((c) =>
|
||||
resolve((autofillCommand = c.find((c) => c.name === "autofill_login").shortcut))
|
||||
)
|
||||
);
|
||||
}
|
||||
return autofillCommand;
|
||||
}
|
||||
}
|
||||
|
@ -36,27 +36,20 @@
|
||||
</div>
|
||||
<ng-container *ngIf="loaded">
|
||||
<app-vault-select (onVaultSelectionChanged)="load()"></app-vault-select>
|
||||
<app-callout
|
||||
*ngIf="showTryAutofillOnPageLoad"
|
||||
type="info"
|
||||
title="{{ 'tryAutofillPageLoad' | i18n }}"
|
||||
>
|
||||
<p>{{ "autofillPageLoadInfo" | i18n }}</p>
|
||||
<app-callout *ngIf="showHowToAutofill" type="info" title="{{ 'howToAutofill' | i18n }}">
|
||||
<p>{{ autofillCalloutText }}</p>
|
||||
<button
|
||||
type="button"
|
||||
class="btn primary callout-half"
|
||||
appStopClick
|
||||
(click)="setAutofillOnPageLoad()"
|
||||
(click)="dismissCallout()"
|
||||
>
|
||||
{{ "turnOn" | i18n }}
|
||||
{{ "gotIt" | i18n }}
|
||||
</button>
|
||||
<button type="button" class="btn callout-half" appStopClick (click)="notNow()">
|
||||
{{ "notNow" | i18n }}
|
||||
<button type="button" class="btn callout-half" appStopClick (click)="goToSettings()">
|
||||
{{ "autofillSettings" | i18n }}
|
||||
</button>
|
||||
</app-callout>
|
||||
<app-callout *ngIf="showSelectAutofillCallout" type="info" title="{{ 'tryAutofill' | i18n }}">
|
||||
<p>{{ "autofillSelectInfo" | i18n }}</p>
|
||||
</app-callout>
|
||||
<div class="box list" *ngIf="loginCiphers">
|
||||
<h2 class="box-header">
|
||||
{{ "typeLogins" | i18n }}
|
||||
|
@ -42,8 +42,8 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
||||
loaded = false;
|
||||
isLoading = false;
|
||||
showOrganizations = false;
|
||||
showTryAutofillOnPageLoad = false;
|
||||
showSelectAutofillCallout = false;
|
||||
showHowToAutofill = false;
|
||||
autofillCalloutText: string;
|
||||
protected search$ = new Subject<void>();
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
@ -103,10 +103,12 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
||||
|
||||
if (!this.syncService.syncInProgress) {
|
||||
await this.load();
|
||||
await this.setCallout();
|
||||
} else {
|
||||
this.loadedTimeout = window.setTimeout(async () => {
|
||||
if (!this.isLoading) {
|
||||
await this.load();
|
||||
await this.setCallout();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
@ -114,11 +116,6 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
||||
this.search$
|
||||
.pipe(debounceTime(500), takeUntil(this.destroy$))
|
||||
.subscribe(() => this.searchVault());
|
||||
|
||||
this.showTryAutofillOnPageLoad =
|
||||
this.loginCiphers.length > 0 &&
|
||||
!(await this.stateService.getEnableAutoFillOnPageLoad()) &&
|
||||
!(await this.stateService.getDismissedAutofillCallout());
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
@ -274,17 +271,32 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
|
||||
this.isLoading = this.loaded = true;
|
||||
}
|
||||
|
||||
async setAutofillOnPageLoad() {
|
||||
await this.stateService.setEnableAutoFillOnPageLoad(true);
|
||||
this.platformUtilsService.showToast("success", null, this.i18nService.t("autofillTurnedOn"));
|
||||
await this.fillCipher(this.loginCiphers[0], 3000);
|
||||
await this.stateService.setDismissedAutofillCallout(true);
|
||||
this.showTryAutofillOnPageLoad = false;
|
||||
async goToSettings() {
|
||||
this.router.navigate(["autofill"]);
|
||||
}
|
||||
|
||||
async notNow() {
|
||||
async dismissCallout() {
|
||||
await this.stateService.setDismissedAutofillCallout(true);
|
||||
this.showTryAutofillOnPageLoad = false;
|
||||
this.showSelectAutofillCallout = true;
|
||||
this.showHowToAutofill = false;
|
||||
}
|
||||
|
||||
private async setCallout() {
|
||||
this.showHowToAutofill =
|
||||
this.loginCiphers.length > 0 &&
|
||||
!(await this.stateService.getEnableAutoFillOnPageLoad()) &&
|
||||
!(await this.stateService.getDismissedAutofillCallout());
|
||||
|
||||
if (this.showHowToAutofill) {
|
||||
const autofillCommand = await this.platformUtilsService.getAutofillKeyboardShortcut();
|
||||
await this.setAutofillCalloutText(autofillCommand);
|
||||
}
|
||||
}
|
||||
|
||||
private setAutofillCalloutText(command: string) {
|
||||
if (command) {
|
||||
this.autofillCalloutText = this.i18nService.t("autofillSelectInfo", command);
|
||||
} else {
|
||||
this.autofillCalloutText = this.i18nService.t("autofillSelectInfoNoCommand");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -150,4 +150,8 @@ export class CliPlatformUtilsService implements PlatformUtilsService {
|
||||
supportsSecureStorage(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
getAutofillKeyboardShortcut(): Promise<string> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -184,4 +184,8 @@ export class ElectronPlatformUtilsService implements PlatformUtilsService {
|
||||
supportsSecureStorage(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
getAutofillKeyboardShortcut(): Promise<string> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -262,4 +262,8 @@ export class WebPlatformUtilsService implements PlatformUtilsService {
|
||||
supportsSecureStorage() {
|
||||
return false;
|
||||
}
|
||||
|
||||
getAutofillKeyboardShortcut(): Promise<string> {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -44,4 +44,5 @@ export abstract class PlatformUtilsService {
|
||||
supportsBiometric: () => Promise<boolean>;
|
||||
authenticateBiometric: () => Promise<boolean>;
|
||||
supportsSecureStorage: () => boolean;
|
||||
getAutofillKeyboardShortcut: () => Promise<string>;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user