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:
@@ -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;
|
||||
|
||||
@@ -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/"
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user