Skip to content

Commit

Permalink
[PM-1504] Migrate Dialogs to DialogService (#5013)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Hinton committed May 2, 2023
1 parent 7c4b2c0 commit 4e18676
Show file tree
Hide file tree
Showing 144 changed files with 1,517 additions and 1,215 deletions.
7 changes: 5 additions & 2 deletions apps/browser/src/auth/popup/lock.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component, NgZone } from "@angular/core";
import { Router } from "@angular/router";

import { LockComponent as BaseLockComponent } from "@bitwarden/angular/auth/components/lock.component";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { EnvironmentService } from "@bitwarden/common/abstractions/environment.service";
Expand Down Expand Up @@ -48,7 +49,8 @@ export class LockComponent extends BaseLockComponent {
policyApiService: PolicyApiServiceAbstraction,
policyService: InternalPolicyService,
passwordGenerationService: PasswordGenerationServiceAbstraction,
private authService: AuthService
private authService: AuthService,
dialogService: DialogServiceAbstraction
) {
super(
router,
Expand All @@ -66,7 +68,8 @@ export class LockComponent extends BaseLockComponent {
ngZone,
policyApiService,
policyService,
passwordGenerationService
passwordGenerationService,
dialogService
);
this.successRoute = "/tabs/current";
this.isInitialLockScreen = (window as any).previousPopupUrl == null;
Expand Down
7 changes: 5 additions & 2 deletions apps/browser/src/auth/popup/register.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { UntypedFormBuilder } from "@angular/forms";
import { Router } from "@angular/router";

import { RegisterComponent as BaseRegisterComponent } from "@bitwarden/angular/components/register.component";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AuditService } from "@bitwarden/common/abstractions/audit.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
Expand Down Expand Up @@ -36,7 +37,8 @@ export class RegisterComponent extends BaseRegisterComponent {
passwordGenerationService: PasswordGenerationServiceAbstraction,
environmentService: EnvironmentService,
logService: LogService,
auditService: AuditService
auditService: AuditService,
dialogService: DialogServiceAbstraction
) {
super(
formValidationErrorService,
Expand All @@ -51,7 +53,8 @@ export class RegisterComponent extends BaseRegisterComponent {
passwordGenerationService,
environmentService,
logService,
auditService
auditService,
dialogService
);
}
}
7 changes: 5 additions & 2 deletions apps/browser/src/auth/popup/set-password.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Component } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router";

import { SetPasswordComponent as BaseSetPasswordComponent } from "@bitwarden/angular/components/set-password.component";
import { DialogServiceAbstraction } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { CryptoService } from "@bitwarden/common/abstractions/crypto.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
Expand Down Expand Up @@ -34,7 +35,8 @@ export class SetPasswordComponent extends BaseSetPasswordComponent {
syncService: SyncService,
route: ActivatedRoute,
organizationApiService: OrganizationApiServiceAbstraction,
organizationUserService: OrganizationUserService
organizationUserService: OrganizationUserService,
dialogService: DialogServiceAbstraction
) {
super(
i18nService,
Expand All @@ -50,7 +52,8 @@ export class SetPasswordComponent extends BaseSetPasswordComponent {
route,
stateService,
organizationApiService,
organizationUserService
organizationUserService,
dialogService
);
}
}
15 changes: 8 additions & 7 deletions apps/browser/src/auth/popup/two-factor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { ActivatedRoute, Router } from "@angular/router";
import { first } from "rxjs/operators";

import { TwoFactorComponent as BaseTwoFactorComponent } from "@bitwarden/angular/auth/components/two-factor.component";
import { DialogServiceAbstraction, SimpleDialogType } from "@bitwarden/angular/services/dialog";
import { ApiService } from "@bitwarden/common/abstractions/api.service";
import { AppIdService } from "@bitwarden/common/abstractions/appId.service";
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
Expand Down Expand Up @@ -46,7 +47,8 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
logService: LogService,
twoFactorService: TwoFactorService,
appIdService: AppIdService,
loginService: LoginService
loginService: LoginService,
private dialogService: DialogServiceAbstraction
) {
super(
authService,
Expand Down Expand Up @@ -102,12 +104,11 @@ export class TwoFactorComponent extends BaseTwoFactorComponent {
this.selectedProviderType === TwoFactorProviderType.Email &&
this.popupUtilsService.inPopup(window)
) {
const confirmed = await this.platformUtilsService.showDialog(
this.i18nService.t("popup2faCloseMessage"),
null,
this.i18nService.t("yes"),
this.i18nService.t("no")
);
const confirmed = await this.dialogService.openSimpleDialog({
title: { key: "warning" },
content: { key: "popup2faCloseMessage" },
type: SimpleDialogType.WARNING,
});
if (confirmed) {
this.popupUtilsService.popOut(window);
}
Expand Down
54 changes: 27 additions & 27 deletions apps/browser/src/background/nativeMessaging.background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,10 +153,11 @@ export class NativeMessagingBackground {
this.connected = false;

this.messagingService.send("showDialog", {
text: this.i18nService.t("nativeMessagingInvalidEncryptionDesc"),
title: this.i18nService.t("nativeMessagingInvalidEncryptionTitle"),
confirmText: this.i18nService.t("ok"),
type: "error",
title: { key: "nativeMessagingInvalidEncryptionTitle" },
content: { key: "nativeMessagingInvalidEncryptionDesc" },
acceptButtonText: { key: "ok" },
cancelButtonText: null,
type: "danger",
});
break;
case "verifyFingerprint": {
Expand Down Expand Up @@ -199,10 +200,11 @@ export class NativeMessagingBackground {

showWrongUserDialog() {
this.messagingService.send("showDialog", {
text: this.i18nService.t("nativeMessagingWrongUserDesc"),
title: this.i18nService.t("nativeMessagingWrongUserTitle"),
confirmText: this.i18nService.t("ok"),
type: "error",
title: { key: "nativeMessagingWrongUserTitle" },
content: { key: "nativeMessagingWrongUserDesc" },
acceptButtonText: { key: "ok" },
cancelButtonText: null,
type: "danger",
});
}

Expand Down Expand Up @@ -258,10 +260,11 @@ export class NativeMessagingBackground {
this.connected = false;

this.messagingService.send("showDialog", {
text: this.i18nService.t("nativeMessagingInvalidEncryptionDesc"),
title: this.i18nService.t("nativeMessagingInvalidEncryptionTitle"),
confirmText: this.i18nService.t("ok"),
type: "error",
title: { key: "nativeMessagingInvalidEncryptionTitle" },
content: { key: "nativeMessagingInvalidEncryptionDesc" },
acceptButtonText: { key: "ok" },
cancelButtonText: null,
type: "danger",
});
}
}
Expand All @@ -285,18 +288,20 @@ export class NativeMessagingBackground {

if (message.response === "not enabled") {
this.messagingService.send("showDialog", {
text: this.i18nService.t("biometricsNotEnabledDesc"),
title: this.i18nService.t("biometricsNotEnabledTitle"),
confirmText: this.i18nService.t("ok"),
type: "error",
title: { key: "biometricsNotEnabledTitle" },
content: { key: "biometricsNotEnabledDesc" },
acceptButtonText: { key: "ok" },
cancelButtonText: null,
type: "danger",
});
break;
} else if (message.response === "not supported") {
this.messagingService.send("showDialog", {
text: this.i18nService.t("biometricsNotSupportedDesc"),
title: this.i18nService.t("biometricsNotSupportedTitle"),
confirmText: this.i18nService.t("ok"),
type: "error",
title: { key: "biometricsNotSupportedTitle" },
content: { key: "biometricsNotSupportedDesc" },
acceptButtonText: { key: "ok" },
cancelButtonText: null,
type: "danger",
});
break;
}
Expand Down Expand Up @@ -377,13 +382,8 @@ export class NativeMessagingBackground {
await this.cryptoService.getFingerprint(await this.stateService.getUserId(), this.publicKey)
).join(" ");

this.messagingService.send("showDialog", {
html: `${this.i18nService.t(
"desktopIntegrationVerificationText"
)}<br><br><strong>${fingerprint}</strong>`,
title: this.i18nService.t("desktopSyncVerificationTitle"),
confirmText: this.i18nService.t("ok"),
type: "warning",
this.messagingService.send("showNativeMessagingFinterprintDialog", {
fingerprint: fingerprint,
});
}
}
11 changes: 4 additions & 7 deletions apps/browser/src/background/runtime.background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,6 @@ export default class RuntimeBackground {
BrowserApi.closeBitwardenExtensionTab();
}, msg.delay ?? 0);
break;
case "showDialogResolve":
this.platformUtilsService.resolveDialogPromise(msg.dialogId, msg.confirmed);
break;
case "bgCollectPageDetails":
await this.main.collectPageDetailsForContentScript(sender.tab, msg.sender, sender.frameId);
break;
Expand Down Expand Up @@ -204,10 +201,10 @@ export default class RuntimeBackground {
break;
case "emailVerificationRequired":
this.messagingService.send("showDialog", {
dialogId: "emailVerificationRequired",
title: this.i18nService.t("emailVerificationRequired"),
text: this.i18nService.t("emailVerificationRequiredDesc"),
confirmText: this.i18nService.t("ok"),
title: { key: "emailVerificationRequired" },
content: { key: "emailVerificationRequiredDesc" },
acceptButtonText: { key: "ok" },
cancelButtonText: null,
type: "info",
});
break;
Expand Down
60 changes: 19 additions & 41 deletions apps/browser/src/popup/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ import { DomSanitizer } from "@angular/platform-browser";
import { NavigationEnd, Router, RouterOutlet } from "@angular/router";
import { IndividualConfig, ToastrService } from "ngx-toastr";
import { Subject, takeUntil } from "rxjs";
import Swal, { SweetAlertIcon } from "sweetalert2";
import Swal from "sweetalert2";

import { DialogServiceAbstraction, SimpleDialogOptions } from "@bitwarden/angular/services/dialog";
import { BroadcasterService } from "@bitwarden/common/abstractions/broadcaster.service";
import { I18nService } from "@bitwarden/common/abstractions/i18n.service";
import { MessagingService } from "@bitwarden/common/abstractions/messaging.service";
Expand Down Expand Up @@ -48,7 +49,8 @@ export class AppComponent implements OnInit, OnDestroy {
private changeDetectorRef: ChangeDetectorRef,
private ngZone: NgZone,
private sanitizer: DomSanitizer,
private platformUtilsService: PlatformUtilsService
private platformUtilsService: PlatformUtilsService,
private dialogService: DialogServiceAbstraction
) {}

async ngOnInit() {
Expand Down Expand Up @@ -102,6 +104,9 @@ export class AppComponent implements OnInit, OnDestroy {
}
} else if (msg.command === "showDialog") {
await this.showDialog(msg);
} else if (msg.command === "showNativeMessagingFinterprintDialog") {
// TODO: Should be refactored to live in another service.
await this.showNativeMessagingFingerprintDialog(msg);
} else if (msg.command === "showToast") {
this.ngZone.run(() => {
this.showToast(msg);
Expand Down Expand Up @@ -222,51 +227,24 @@ export class AppComponent implements OnInit, OnDestroy {
this.toastrService.show(message, msg.title, options, "toast-" + msg.type);
}

private async showDialog(msg: any) {
let iconClasses: string = null;
const type = msg.type;
if (type != null) {
// If you add custom types to this part, the type to SweetAlertIcon cast below needs to be changed.
switch (type) {
case "success":
iconClasses = "bwi-check text-success";
break;
case "warning":
iconClasses = "bwi-exclamation-triangle text-warning";
break;
case "error":
iconClasses = "bwi-error text-danger";
break;
case "info":
iconClasses = "bwi-info-circle text-info";
break;
default:
break;
}
}
private async showDialog(msg: SimpleDialogOptions) {
await this.dialogService.openSimpleDialog(msg);
}

const cancelText = msg.cancelText;
const confirmText = msg.confirmText;
const confirmed = await Swal.fire({
private async showNativeMessagingFingerprintDialog(msg: any) {
await Swal.fire({
heightAuto: false,
buttonsStyling: false,
icon: type as SweetAlertIcon, // required to be any of the SweetAlertIcons to output the iconHtml.
iconHtml:
iconClasses != null ? `<i class="swal-custom-icon bwi ${iconClasses}"></i>` : undefined,
text: msg.text,
html: msg.html,
titleText: msg.title,
showCancelButton: cancelText != null,
cancelButtonText: cancelText,
icon: "warning",
iconHtml: '<i class="swal-custom-icon bwi bwi-exclamation-triangle text-warning"></i>',
html: `${this.i18nService.t("desktopIntegrationVerificationText")}<br><br><strong>${
msg.fingerprint
}</strong>`,
titleText: this.i18nService.t("desktopSyncVerificationTitle"),
showConfirmButton: true,
confirmButtonText: confirmText == null ? this.i18nService.t("ok") : confirmText,
confirmButtonText: this.i18nService.t("ok"),
timer: 300000,
});

this.messagingService.send("showDialogResolve", {
dialogId: msg.dialogId,
confirmed: confirmed.value,
});
}

private async clearComponentStates() {
Expand Down
10 changes: 5 additions & 5 deletions apps/browser/src/popup/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { A11yModule } from "@angular/cdk/a11y";
import { DialogModule } from "@angular/cdk/dialog";
import { DragDropModule } from "@angular/cdk/drag-drop";
import { LayoutModule } from "@angular/cdk/layout";
import { OverlayModule } from "@angular/cdk/overlay";
import { ScrollingModule } from "@angular/cdk/scrolling";
// eslint-disable-next-line import/order
import { CurrencyPipe, DatePipe } from "@angular/common";

// Register the locales for the application
import "./locales";

import { NgModule } from "@angular/core";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { BrowserModule } from "@angular/platform-browser";
Expand Down Expand Up @@ -76,6 +72,9 @@ import { SyncComponent } from "./settings/sync.component";
import { VaultTimeoutInputComponent } from "./settings/vault-timeout-input.component";
import { TabsComponent } from "./tabs.component";

// Register the locales for the application
import "./locales";

@NgModule({
imports: [
A11yModule,
Expand All @@ -96,6 +95,7 @@ import { TabsComponent } from "./tabs.component";
ReactiveFormsModule,
ScrollingModule,
ServicesModule,
DialogModule,
],
declarations: [
ActionButtonsComponent,
Expand Down
Loading

0 comments on commit 4e18676

Please sign in to comment.