1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-29 22:53:44 +00:00

[PM-1504] Migrate Dialogs to DialogService (#5013)

This PR introduces a generic `DialogService` which can be used by all the clients. This allows us to decouple dialogs from the `PlatformUtilsHelper`.

The `DialogService` provides a new method, `openSimpleDialog` which is the new interface for that type of dialogs.

This gives us 3 different implementations: 
- Web: DialogService modern dialogs
- Browser: SweetAlert
- Desktop: Native electron based
This commit is contained in:
Oscar Hinton
2023-05-02 18:46:03 +02:00
committed by GitHub
parent 7c4b2c04b9
commit 4e1867682f
144 changed files with 1514 additions and 1212 deletions

View File

@@ -3,6 +3,7 @@ import { FormBuilder } from "@angular/forms";
import { Observable, Subject } from "rxjs";
import { concatMap, debounceTime, filter, map, takeUntil, tap } from "rxjs/operators";
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import { AbstractThemingService } from "@bitwarden/angular/services/theming/theming.service.abstraction";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
@@ -109,7 +110,8 @@ export class SettingsComponent implements OnInit {
private cryptoService: CryptoService,
private modalService: ModalService,
private themingService: AbstractThemingService,
private settingsService: SettingsService
private settingsService: SettingsService,
private dialogService: DialogServiceAbstraction
) {
const isMac = this.platformUtilsService.getDevice() === DeviceType.MacOsDesktop;
@@ -295,13 +297,12 @@ export class SettingsComponent implements OnInit {
async saveVaultTimeout(newValue: number) {
if (newValue == null) {
const confirmed = await this.platformUtilsService.showDialog(
this.i18nService.t("neverLockWarning"),
"",
this.i18nService.t("yes"),
this.i18nService.t("cancel"),
"warning"
);
const confirmed = await this.dialogService.openSimpleDialog({
title: { key: "warning" },
content: { key: "neverLockWarning" },
type: SimpleDialogType.WARNING,
});
if (!confirmed) {
this.form.controls.vaultTimeout.setValue(this.previousVaultTimeout);
return;
@@ -332,13 +333,12 @@ export class SettingsComponent implements OnInit {
async saveVaultTimeoutAction(newValue: VaultTimeoutAction) {
if (newValue === "logOut") {
const confirmed = await this.platformUtilsService.showDialog(
this.i18nService.t("vaultTimeoutLogOutConfirmation"),
this.i18nService.t("vaultTimeoutLogOutConfirmationTitle"),
this.i18nService.t("yes"),
this.i18nService.t("cancel"),
"warning"
);
const confirmed = await this.dialogService.openSimpleDialog({
title: { key: "vaultTimeoutLogOutConfirmationTitle" },
content: { key: "vaultTimeoutLogOutConfirmation" },
type: SimpleDialogType.WARNING,
});
if (!confirmed) {
this.form.controls.vaultTimeoutAction.patchValue(VaultTimeoutAction.Lock, {
emitEvent: false,
@@ -462,13 +462,11 @@ export class SettingsComponent implements OnInit {
!this.form.value.enableTray &&
(this.form.value.startToTray || this.form.value.enableCloseToTray)
) {
const confirm = await this.platformUtilsService.showDialog(
this.i18nService.t("confirmTrayDesc"),
this.i18nService.t("confirmTrayTitle"),
this.i18nService.t("yes"),
this.i18nService.t("no"),
"warning"
);
const confirm = await this.dialogService.openSimpleDialog({
title: { key: "confirmTrayTitle" },
content: { key: "confirmTrayDesc" },
type: SimpleDialogType.WARNING,
});
if (confirm) {
this.form.controls.startToTray.setValue(false, { emitEvent: false });
@@ -524,35 +522,35 @@ export class SettingsComponent implements OnInit {
async saveBrowserIntegration() {
if (process.platform === "darwin" && !this.platformUtilsService.isMacAppStore()) {
await this.platformUtilsService.showDialog(
this.i18nService.t("browserIntegrationMasOnlyDesc"),
this.i18nService.t("browserIntegrationUnsupportedTitle"),
this.i18nService.t("ok"),
null,
"warning"
);
await this.dialogService.openSimpleDialog({
title: { key: "browserIntegrationUnsupportedTitle" },
content: { key: "browserIntegrationMasOnlyDesc" },
acceptButtonText: { key: "ok" },
cancelButtonText: null,
type: SimpleDialogType.WARNING,
});
this.form.controls.enableBrowserIntegration.setValue(false);
return;
} else if (isWindowsStore()) {
await this.platformUtilsService.showDialog(
this.i18nService.t("browserIntegrationWindowsStoreDesc"),
this.i18nService.t("browserIntegrationUnsupportedTitle"),
this.i18nService.t("ok"),
null,
"warning"
);
await this.dialogService.openSimpleDialog({
title: { key: "browserIntegrationUnsupportedTitle" },
content: { key: "browserIntegrationWindowsStoreDesc" },
acceptButtonText: { key: "ok" },
cancelButtonText: null,
type: SimpleDialogType.WARNING,
});
this.form.controls.enableBrowserIntegration.setValue(false);
return;
} else if (process.platform == "linux") {
await this.platformUtilsService.showDialog(
this.i18nService.t("browserIntegrationLinuxDesc"),
this.i18nService.t("browserIntegrationUnsupportedTitle"),
this.i18nService.t("ok"),
null,
"warning"
);
await this.dialogService.openSimpleDialog({
title: { key: "browserIntegrationUnsupportedTitle" },
content: { key: "browserIntegrationLinuxDesc" },
acceptButtonText: { key: "ok" },
cancelButtonText: null,
type: SimpleDialogType.WARNING,
});
this.form.controls.enableBrowserIntegration.setValue(false);
return;

View File

@@ -14,6 +14,7 @@ import { IndividualConfig, ToastrService } from "ngx-toastr";
import { firstValueFrom, Subject, takeUntil } from "rxjs";
import { ModalRef } from "@bitwarden/angular/components/modal/modal.ref";
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
import { ConfigServiceAbstraction } from "@bitwarden/common/abstractions/config/config.service.abstraction";
@@ -135,7 +136,8 @@ export class AppComponent implements OnInit, OnDestroy {
private policyService: InternalPolicyService,
private modalService: ModalService,
private keyConnectorService: KeyConnectorService,
private configService: ConfigServiceAbstraction
private configService: ConfigServiceAbstraction,
private dialogService: DialogServiceAbstraction
) {}
ngOnInit() {
@@ -231,12 +233,15 @@ export class AppComponent implements OnInit, OnDestroy {
const fingerprint = await this.cryptoService.getFingerprint(
await this.stateService.getUserId()
);
const result = await this.platformUtilsService.showDialog(
this.i18nService.t("yourAccountsFingerprint") + ":\n" + fingerprint.join("-"),
this.i18nService.t("fingerprintPhrase"),
this.i18nService.t("learnMore"),
this.i18nService.t("close")
);
const result = await this.dialogService.openSimpleDialog({
title: { key: "fingerprintPhrase" },
content:
this.i18nService.t("yourAccountsFingerprint") + ":\n" + fingerprint.join("-"),
acceptButtonText: { key: "learnMore" },
cancelButtonText: { key: "close" },
type: SimpleDialogType.INFO,
});
if (result) {
this.platformUtilsService.launchUri("https://bitwarden.com/help/fingerprint-phrase/");
}
@@ -265,24 +270,24 @@ export class AppComponent implements OnInit, OnDestroy {
});
break;
case "premiumRequired": {
const premiumConfirmed = await this.platformUtilsService.showDialog(
this.i18nService.t("premiumRequiredDesc"),
this.i18nService.t("premiumRequired"),
this.i18nService.t("learnMore"),
this.i18nService.t("cancel")
);
const premiumConfirmed = await this.dialogService.openSimpleDialog({
title: { key: "premiumRequired" },
content: { key: "premiumRequiredDesc" },
acceptButtonText: { key: "learnMore" },
type: SimpleDialogType.SUCCESS,
});
if (premiumConfirmed) {
await this.openModal<PremiumComponent>(PremiumComponent, this.premiumRef);
}
break;
}
case "emailVerificationRequired": {
const emailVerificationConfirmed = await this.platformUtilsService.showDialog(
this.i18nService.t("emailVerificationRequiredDesc"),
this.i18nService.t("emailVerificationRequired"),
this.i18nService.t("learnMore"),
this.i18nService.t("cancel")
);
const emailVerificationConfirmed = await this.dialogService.openSimpleDialog({
title: { key: "emailVerificationRequired" },
content: { key: "emailVerificationRequiredDesc" },
acceptButtonText: { key: "learnMore" },
type: SimpleDialogType.INFO,
});
if (emailVerificationConfirmed) {
this.platformUtilsService.launchUri(
"https://bitwarden.com/help/create-bitwarden-account/"

View File

@@ -3,6 +3,7 @@ import "zone.js";
// Register the locales for the application
import "./locales";
import { DialogModule } from "@angular/cdk/dialog";
import { NgModule } from "@angular/core";
import { ColorPasswordCountPipe } from "@bitwarden/angular/pipes/color-password-count.pipe";
@@ -56,7 +57,7 @@ import { EffluxDatesComponent as SendEffluxDatesComponent } from "./tools/send/e
import { SendComponent } from "./tools/send/send.component";
@NgModule({
imports: [SharedModule, AppRoutingModule, VaultFilterModule, LoginModule],
imports: [SharedModule, DialogModule, AppRoutingModule, VaultFilterModule, LoginModule],
declarations: [
AccessibilityCookieComponent,
AccountSwitcherComponent,

View File

@@ -1,5 +1,6 @@
import { APP_INITIALIZER, InjectionToken, NgModule } from "@angular/core";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import {
SECURE_STORAGE,
STATE_FACTORY,
@@ -43,6 +44,7 @@ import { PasswordRepromptService as PasswordRepromptServiceAbstraction } from "@
import { LoginGuard } from "../../auth/guards/login.guard";
import { Account } from "../../models/account";
import { ElectronCryptoService } from "../../services/electron-crypto.service";
import { ElectronDialogService } from "../../services/electron-dialog.service";
import { ElectronLogService } from "../../services/electron-log.service";
import { ElectronPlatformUtilsService } from "../../services/electron-platform-utils.service";
import { ElectronRendererMessagingService } from "../../services/electron-renderer-messaging.service";
@@ -176,6 +178,10 @@ const RELOAD_CALLBACK = new InjectionToken<() => any>("RELOAD_CALLBACK");
useClass: LoginService,
deps: [StateServiceAbstraction],
},
{
provide: DialogServiceAbstraction,
useClass: ElectronDialogService,
},
{
provide: CryptoServiceAbstraction,
useClass: ElectronCryptoService,

View File

@@ -3,6 +3,7 @@ import * as os from "os";
import { Component, OnInit } from "@angular/core";
import { UntypedFormBuilder } from "@angular/forms";
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
import { ExportComponent as BaseExportComponent } from "@bitwarden/angular/tools/export/components/export.component";
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
@@ -33,7 +34,8 @@ export class ExportComponent extends BaseExportComponent implements OnInit {
formBuilder: UntypedFormBuilder,
private broadcasterService: BroadcasterService,
logService: LogService,
fileDownloadService: FileDownloadService
fileDownloadService: FileDownloadService,
dialogService: DialogServiceAbstraction
) {
super(
cryptoService,
@@ -46,7 +48,8 @@ export class ExportComponent extends BaseExportComponent implements OnInit {
logService,
userVerificationService,
formBuilder,
fileDownloadService
fileDownloadService,
dialogService
);
}
@@ -56,25 +59,23 @@ export class ExportComponent extends BaseExportComponent implements OnInit {
async warningDialog() {
if (this.encryptedFormat) {
return await this.platformUtilsService.showDialog(
this.i18nService.t("encExportKeyWarningDesc") +
return await this.dialogService.openSimpleDialog({
title: { key: "confirmVaultExport" },
content:
this.i18nService.t("encExportKeyWarningDesc") +
os.EOL +
os.EOL +
this.i18nService.t("encExportAccountWarningDesc"),
this.i18nService.t("confirmVaultExport"),
this.i18nService.t("exportVault"),
this.i18nService.t("cancel"),
"warning",
true
);
acceptButtonText: { key: "exportVault" },
type: SimpleDialogType.WARNING,
});
} else {
return await this.platformUtilsService.showDialog(
this.i18nService.t("exportWarningDesc"),
this.i18nService.t("confirmVaultExport"),
this.i18nService.t("exportVault"),
this.i18nService.t("cancel"),
"warning"
);
return await this.dialogService.openSimpleDialog({
title: { key: "confirmVaultExport" },
content: { key: "exportWarningDesc" },
acceptButtonText: { key: "exportVault" },
type: SimpleDialogType.WARNING,
});
}
}
}

View File

@@ -1,6 +1,7 @@
import { DatePipe } from "@angular/common";
import { Component } from "@angular/core";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { AddEditComponent as BaseAddEditComponent } from "@bitwarden/angular/tools/send/add-edit.component";
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
@@ -27,7 +28,8 @@ export class AddEditComponent extends BaseAddEditComponent {
messagingService: MessagingService,
policyService: PolicyService,
logService: LogService,
sendApiService: SendApiService
sendApiService: SendApiService,
dialogService: DialogServiceAbstraction
) {
super(
i18nService,
@@ -39,7 +41,8 @@ export class AddEditComponent extends BaseAddEditComponent {
policyService,
logService,
stateService,
sendApiService
sendApiService,
dialogService
);
}

View File

@@ -1,5 +1,6 @@
import { Component, NgZone, OnDestroy, OnInit, ViewChild } from "@angular/core";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { SendComponent as BaseSendComponent } from "@bitwarden/angular/tools/send/send.component";
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
@@ -46,7 +47,8 @@ export class SendComponent extends BaseSendComponent implements OnInit, OnDestro
policyService: PolicyService,
private searchBarService: SearchBarService,
logService: LogService,
sendApiService: SendApiService
sendApiService: SendApiService,
dialogService: DialogServiceAbstraction
) {
super(
sendService,
@@ -57,7 +59,8 @@ export class SendComponent extends BaseSendComponent implements OnInit, OnDestro
searchService,
policyService,
logService,
sendApiService
sendApiService,
dialogService
);
// eslint-disable-next-line rxjs-angular/prefer-takeuntil
this.searchBarService.searchText$.subscribe((searchText) => {