diff --git a/apps/browser/src/popup/app.component.ts b/apps/browser/src/popup/app.component.ts
index 815109c549..179abf5a8c 100644
--- a/apps/browser/src/popup/app.component.ts
+++ b/apps/browser/src/popup/app.component.ts
@@ -9,8 +9,7 @@ import {
import { DomSanitizer } from "@angular/platform-browser";
import { NavigationEnd, Router, RouterOutlet } from "@angular/router";
import { IndividualConfig, ToastrService } from "ngx-toastr";
-import { filter, concatMap, Subject, takeUntil } from "rxjs";
-import Swal from "sweetalert2";
+import { filter, concatMap, Subject, takeUntil, firstValueFrom } from "rxjs";
import { AuthService } from "@bitwarden/common/auth/abstractions/auth.service";
import { BroadcasterService } from "@bitwarden/common/platform/abstractions/broadcaster.service";
@@ -23,6 +22,7 @@ import { BrowserApi } from "../platform/browser/browser-api";
import { BrowserStateService } from "../platform/services/abstractions/browser-state.service";
import { routerTransition } from "./app-routing.animations";
+import { DesktopSyncVerificationDialogComponent } from "./components/desktop-sync-verification-dialog.component";
@Component({
selector: "app-root",
@@ -242,19 +242,11 @@ export class AppComponent implements OnInit, OnDestroy {
}
private async showNativeMessagingFingerprintDialog(msg: any) {
- await Swal.fire({
- heightAuto: false,
- buttonsStyling: false,
- icon: "warning",
- iconHtml: '',
- html: `${this.i18nService.t("desktopIntegrationVerificationText")}
${
- msg.fingerprint
- }`,
- titleText: this.i18nService.t("desktopSyncVerificationTitle"),
- showConfirmButton: true,
- confirmButtonText: this.i18nService.t("ok"),
- timer: 300000,
+ const dialogRef = DesktopSyncVerificationDialogComponent.open(this.dialogService, {
+ fingerprint: msg.fingerprint,
});
+
+ return firstValueFrom(dialogRef.closed);
}
private async clearComponentStates() {
diff --git a/apps/browser/src/popup/components/desktop-sync-verification-dialog.component.html b/apps/browser/src/popup/components/desktop-sync-verification-dialog.component.html
new file mode 100644
index 0000000000..d9bb0e33b2
--- /dev/null
+++ b/apps/browser/src/popup/components/desktop-sync-verification-dialog.component.html
@@ -0,0 +1,15 @@
+
+
+ {{ "desktopSyncVerificationTitle" | i18n }}
+
+
+ {{ "desktopIntegrationVerificationText" | i18n }}
+
+ {{ params.fingerprint }}
+
+
+
+
+
diff --git a/apps/browser/src/popup/components/desktop-sync-verification-dialog.component.ts b/apps/browser/src/popup/components/desktop-sync-verification-dialog.component.ts
new file mode 100644
index 0000000000..4e5bbe18f7
--- /dev/null
+++ b/apps/browser/src/popup/components/desktop-sync-verification-dialog.component.ts
@@ -0,0 +1,29 @@
+import { DIALOG_DATA } from "@angular/cdk/dialog";
+import { Component, Inject } from "@angular/core";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import {
+ AsyncActionsModule,
+ ButtonModule,
+ DialogModule,
+ DialogService,
+} from "@bitwarden/components";
+
+export type DesktopSyncVerificationDialogParams = {
+ fingerprint: string;
+};
+
+@Component({
+ templateUrl: "desktop-sync-verification-dialog.component.html",
+ standalone: true,
+ imports: [JslibModule, ButtonModule, DialogModule, AsyncActionsModule],
+})
+export class DesktopSyncVerificationDialogComponent {
+ constructor(@Inject(DIALOG_DATA) protected params: DesktopSyncVerificationDialogParams) {}
+
+ static open(dialogService: DialogService, data: DesktopSyncVerificationDialogParams) {
+ return dialogService.open(DesktopSyncVerificationDialogComponent, {
+ data,
+ });
+ }
+}
diff --git a/apps/browser/src/popup/settings/await-desktop-dialog.component.html b/apps/browser/src/popup/settings/await-desktop-dialog.component.html
new file mode 100644
index 0000000000..765bc3d140
--- /dev/null
+++ b/apps/browser/src/popup/settings/await-desktop-dialog.component.html
@@ -0,0 +1,11 @@
+
+ {{ "awaitDesktop" | i18n }}:
+
+ {{ "awaitDesktopDesc" | i18n }}
+
+
+
+
+
diff --git a/apps/browser/src/popup/settings/await-desktop-dialog.component.ts b/apps/browser/src/popup/settings/await-desktop-dialog.component.ts
new file mode 100644
index 0000000000..6bccc927e6
--- /dev/null
+++ b/apps/browser/src/popup/settings/await-desktop-dialog.component.ts
@@ -0,0 +1,22 @@
+import { Component } from "@angular/core";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import {
+ AsyncActionsModule,
+ ButtonModule,
+ DialogModule,
+ DialogService,
+} from "@bitwarden/components";
+
+@Component({
+ templateUrl: "await-desktop-dialog.component.html",
+ standalone: true,
+ imports: [JslibModule, ButtonModule, DialogModule, AsyncActionsModule],
+})
+export class AwaitDesktopDialogComponent {
+ static open(dialogService: DialogService) {
+ return dialogService.open(AwaitDesktopDialogComponent, {
+ disableClose: true,
+ });
+ }
+}
diff --git a/apps/browser/src/popup/settings/fingerprint-dialog.component.html b/apps/browser/src/popup/settings/fingerprint-dialog.component.html
new file mode 100644
index 0000000000..c6b806ee03
--- /dev/null
+++ b/apps/browser/src/popup/settings/fingerprint-dialog.component.html
@@ -0,0 +1,22 @@
+
+ {{ "yourAccountsFingerprint" | i18n }}:
+
+ {{ data.fingerprint }}
+
+
+
+
+ {{ "learnMore" | i18n }}
+
+
+
diff --git a/apps/browser/src/popup/settings/fingerprint-dialog.component.ts b/apps/browser/src/popup/settings/fingerprint-dialog.component.ts
new file mode 100644
index 0000000000..8156219083
--- /dev/null
+++ b/apps/browser/src/popup/settings/fingerprint-dialog.component.ts
@@ -0,0 +1,33 @@
+import { DIALOG_DATA } from "@angular/cdk/dialog";
+import { Component, Inject } from "@angular/core";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import { CryptoService } from "@bitwarden/common/platform/abstractions/crypto.service";
+import { StateService } from "@bitwarden/common/platform/abstractions/state.service";
+import {
+ AsyncActionsModule,
+ ButtonModule,
+ DialogModule,
+ DialogService,
+} from "@bitwarden/components";
+
+export type FingerprintDialogData = {
+ fingerprint: string;
+};
+
+@Component({
+ templateUrl: "fingerprint-dialog.component.html",
+ standalone: true,
+ imports: [JslibModule, ButtonModule, DialogModule, AsyncActionsModule],
+})
+export class FingerprintDialogComponent {
+ constructor(
+ @Inject(DIALOG_DATA) protected data: FingerprintDialogData,
+ private cryptoService: CryptoService,
+ private stateService: StateService
+ ) {}
+
+ static open(dialogService: DialogService, data: FingerprintDialogData) {
+ return dialogService.open(FingerprintDialogComponent, { data });
+ }
+}
diff --git a/apps/browser/src/popup/settings/settings.component.ts b/apps/browser/src/popup/settings/settings.component.ts
index 30a1f03eac..965a74c3f7 100644
--- a/apps/browser/src/popup/settings/settings.component.ts
+++ b/apps/browser/src/popup/settings/settings.component.ts
@@ -15,7 +15,6 @@ import {
switchMap,
takeUntil,
} from "rxjs";
-import Swal from "sweetalert2";
import { ModalService } from "@bitwarden/angular/services/modal.service";
import { VaultTimeoutSettingsService } from "@bitwarden/common/abstractions/vault-timeout/vault-timeout-settings.service";
@@ -39,6 +38,8 @@ import { SetPinComponent } from "../components/set-pin.component";
import { PopupUtilsService } from "../services/popup-utils.service";
import { AboutComponent } from "./about.component";
+import { AwaitDesktopDialogComponent } from "./await-desktop-dialog.component";
+import { FingerprintDialogComponent } from "./fingerprint-dialog.component";
const RateUrls = {
[DeviceType.ChromeExtension]:
@@ -361,25 +362,15 @@ export class SettingsComponent implements OnInit {
return;
}
- const submitted = Swal.fire({
- heightAuto: false,
- buttonsStyling: false,
- titleText: this.i18nService.t("awaitDesktop"),
- text: this.i18nService.t("awaitDesktopDesc"),
- icon: "info",
- iconHtml: '',
- showCancelButton: true,
- cancelButtonText: this.i18nService.t("cancel"),
- showConfirmButton: false,
- allowOutsideClick: false,
- });
+ const awaitDesktopDialogRef = AwaitDesktopDialogComponent.open(this.dialogService);
+ const awaitDesktopDialogClosed = firstValueFrom(awaitDesktopDialogRef.closed);
await this.stateService.setBiometricAwaitingAcceptance(true);
await this.cryptoService.refreshAdditionalKeys();
await Promise.race([
- submitted.then(async (result) => {
- if (result.dismiss === Swal.DismissReason.cancel) {
+ awaitDesktopDialogClosed.then(async (result) => {
+ if (result) {
this.form.controls.biometric.setValue(false);
await this.stateService.setBiometricAwaitingAcceptance(null);
}
@@ -389,7 +380,7 @@ export class SettingsComponent implements OnInit {
.then((result) => {
this.form.controls.biometric.setValue(result);
- Swal.close();
+ awaitDesktopDialogRef.close(false);
if (!result) {
this.platformUtilsService.showToast(
"error",
@@ -494,30 +485,15 @@ export class SettingsComponent implements OnInit {
}
async fingerprint() {
- const fingerprint = await this.cryptoService.getFingerprint(
- await this.stateService.getUserId()
- );
- const p = document.createElement("p");
- p.innerText = this.i18nService.t("yourAccountsFingerprint") + ":";
- const p2 = document.createElement("p");
- p2.innerText = fingerprint.join("-");
- const div = document.createElement("div");
- div.appendChild(p);
- div.appendChild(p2);
+ const fingerprint = await this.cryptoService
+ .getFingerprint(await this.stateService.getUserId())
+ .then((rawFingerprint) => rawFingerprint.join("-"));
- const result = await Swal.fire({
- heightAuto: false,
- buttonsStyling: false,
- html: div,
- showCancelButton: true,
- cancelButtonText: this.i18nService.t("close"),
- showConfirmButton: true,
- confirmButtonText: this.i18nService.t("learnMore"),
+ const dialogRef = FingerprintDialogComponent.open(this.dialogService, {
+ fingerprint,
});
- if (result.value) {
- this.platformUtilsService.launchUri("https://bitwarden.com/help/fingerprint-phrase/");
- }
+ return firstValueFrom(dialogRef.closed);
}
rate() {
diff --git a/apps/desktop/src/app/components/browser-sync-verification-dialog.component.html b/apps/desktop/src/app/components/browser-sync-verification-dialog.component.html
new file mode 100644
index 0000000000..558e317bea
--- /dev/null
+++ b/apps/desktop/src/app/components/browser-sync-verification-dialog.component.html
@@ -0,0 +1,18 @@
+
+
+ {{ "verifyBrowserTitle" | i18n }}
+
+
+ {{ "verifyBrowserDesc" | i18n }}
+
+ {{ params.fingerprint }}
+
+
+
+
+
+
diff --git a/apps/desktop/src/app/components/browser-sync-verification-dialog.component.ts b/apps/desktop/src/app/components/browser-sync-verification-dialog.component.ts
new file mode 100644
index 0000000000..f627380860
--- /dev/null
+++ b/apps/desktop/src/app/components/browser-sync-verification-dialog.component.ts
@@ -0,0 +1,25 @@
+import { DIALOG_DATA } from "@angular/cdk/dialog";
+import { Component, Inject } from "@angular/core";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import { ButtonModule, DialogModule, DialogService } from "@bitwarden/components";
+
+export type BrowserSyncVerificationDialogParams = {
+ fingerprint: string;
+};
+
+@Component({
+ templateUrl: "browser-sync-verification-dialog.component.html",
+ standalone: true,
+ imports: [JslibModule, ButtonModule, DialogModule],
+})
+export class BrowserSyncVerificationDialogComponent {
+ constructor(@Inject(DIALOG_DATA) protected params: BrowserSyncVerificationDialogParams) {}
+
+ static open(dialogService: DialogService, data: BrowserSyncVerificationDialogParams) {
+ return dialogService.open(BrowserSyncVerificationDialogComponent, {
+ data,
+ disableClose: true,
+ });
+ }
+}
diff --git a/apps/desktop/src/app/components/verify-native-messaging-dialog.component.html b/apps/desktop/src/app/components/verify-native-messaging-dialog.component.html
new file mode 100644
index 0000000000..5c35870f77
--- /dev/null
+++ b/apps/desktop/src/app/components/verify-native-messaging-dialog.component.html
@@ -0,0 +1,18 @@
+
+
+ {{ "verifyNativeMessagingConnectionTitle" | i18n : data.applicationName }}:
+
+
+ {{ "verifyNativeMessagingConnectionDesc" | i18n }}
+
+ {{ "verifyNativeMessagingConnectionWarning" | i18n }}
+
+
+
+
+
+
diff --git a/apps/desktop/src/app/components/verify-native-messaging-dialog.component.ts b/apps/desktop/src/app/components/verify-native-messaging-dialog.component.ts
new file mode 100644
index 0000000000..507d566336
--- /dev/null
+++ b/apps/desktop/src/app/components/verify-native-messaging-dialog.component.ts
@@ -0,0 +1,24 @@
+import { DIALOG_DATA } from "@angular/cdk/dialog";
+import { Component, Inject } from "@angular/core";
+
+import { JslibModule } from "@bitwarden/angular/jslib.module";
+import { ButtonModule, DialogModule, DialogService } from "@bitwarden/components";
+
+export type VerifyNativeMessagingDialogData = {
+ applicationName: string;
+};
+
+@Component({
+ templateUrl: "verify-native-messaging-dialog.component.html",
+ standalone: true,
+ imports: [JslibModule, ButtonModule, DialogModule],
+})
+export class VerifyNativeMessagingDialogComponent {
+ constructor(@Inject(DIALOG_DATA) protected data: VerifyNativeMessagingDialogData) {}
+
+ static open(dialogService: DialogService, data: VerifyNativeMessagingDialogData) {
+ return dialogService.open(VerifyNativeMessagingDialogComponent, {
+ data,
+ });
+ }
+}
diff --git a/apps/desktop/src/services/native-message-handler.service.ts b/apps/desktop/src/services/native-message-handler.service.ts
index 9f5f1d460d..b9107c0ecd 100644
--- a/apps/desktop/src/services/native-message-handler.service.ts
+++ b/apps/desktop/src/services/native-message-handler.service.ts
@@ -1,6 +1,6 @@
import { Injectable } from "@angular/core";
import { ipcRenderer } from "electron";
-import Swal from "sweetalert2";
+import { firstValueFrom } from "rxjs";
import { NativeMessagingVersion } from "@bitwarden/common/enums";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
@@ -11,7 +11,9 @@ import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncryptedString, EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
import { StateService } from "@bitwarden/common/platform/services/state.service";
+import { DialogService } from "@bitwarden/components";
+import { VerifyNativeMessagingDialogComponent } from "../app/components/verify-native-messaging-dialog.component";
import { DecryptedCommandData } from "../models/native-messaging/decrypted-command-data";
import { EncryptedMessage } from "../models/native-messaging/encrypted-message";
import { EncryptedMessageResponse } from "../models/native-messaging/encrypted-message-response";
@@ -33,7 +35,8 @@ export class NativeMessageHandlerService {
private cryptoFunctionService: CryptoFunctionService,
private messagingService: MessagingService,
private i18nService: I18nService,
- private encryptedMessageHandlerService: EncryptedMessageHandlerService
+ private encryptedMessageHandlerService: EncryptedMessageHandlerService,
+ private dialogService: DialogService
) {}
async handleMessage(message: Message) {
@@ -87,21 +90,12 @@ export class NativeMessageHandlerService {
// Ask for confirmation from user
this.messagingService.send("setFocus");
- const submitted = await Swal.fire({
- heightAuto: false,
- titleText: this.i18nService.t("verifyNativeMessagingConnectionTitle", applicationName),
- html: `${this.i18nService.t("verifyNativeMessagingConnectionDesc")}
${this.i18nService.t(
- "verifyNativeMessagingConnectionWarning"
- )}`,
- showCancelButton: true,
- cancelButtonText: this.i18nService.t("no"),
- showConfirmButton: true,
- confirmButtonText: this.i18nService.t("yes"),
- allowOutsideClick: false,
- focusCancel: true,
- });
- if (submitted.value !== true) {
+ const submitted = await firstValueFrom(
+ VerifyNativeMessagingDialogComponent.open(this.dialogService, { applicationName }).closed
+ );
+
+ if (submitted !== true) {
this.sendResponse({
messageId: messageId,
version: NativeMessagingVersion.Latest,
diff --git a/apps/desktop/src/services/native-messaging.service.ts b/apps/desktop/src/services/native-messaging.service.ts
index 3928778f31..646e7bcc50 100644
--- a/apps/desktop/src/services/native-messaging.service.ts
+++ b/apps/desktop/src/services/native-messaging.service.ts
@@ -1,7 +1,6 @@
import { Injectable } from "@angular/core";
import { ipcRenderer } from "electron";
import { firstValueFrom } from "rxjs";
-import Swal from "sweetalert2";
import { KeySuffixOptions } from "@bitwarden/common/enums";
import { CryptoFunctionService } from "@bitwarden/common/platform/abstractions/crypto-function.service";
@@ -14,7 +13,9 @@ import { StateService } from "@bitwarden/common/platform/abstractions/state.serv
import { Utils } from "@bitwarden/common/platform/misc/utils";
import { EncString } from "@bitwarden/common/platform/models/domain/enc-string";
import { SymmetricCryptoKey } from "@bitwarden/common/platform/models/domain/symmetric-crypto-key";
+import { DialogService } from "@bitwarden/components";
+import { BrowserSyncVerificationDialogComponent } from "../app/components/browser-sync-verification-dialog.component";
import { LegacyMessage } from "../models/native-messaging/legacy-message";
import { LegacyMessageWrapper } from "../models/native-messaging/legacy-message-wrapper";
import { Message } from "../models/native-messaging/message";
@@ -36,7 +37,8 @@ export class NativeMessagingService {
private i18nService: I18nService,
private messagingService: MessagingService,
private stateService: StateService,
- private nativeMessageHandler: NativeMessageHandlerService
+ private nativeMessageHandler: NativeMessageHandlerService,
+ private dialogService: DialogService
) {}
init() {
@@ -74,22 +76,15 @@ export class NativeMessagingService {
await this.stateService.getUserId(),
remotePublicKey
)
- ).join(" ");
+ ).join("-");
this.messagingService.send("setFocus");
- // Await confirmation that fingerprint is correct
- const submitted = await Swal.fire({
- titleText: this.i18nService.t("verifyBrowserTitle"),
- html: `${this.i18nService.t("verifyBrowserDesc")}
${fingerprint}`,
- showCancelButton: true,
- cancelButtonText: this.i18nService.t("cancel"),
- showConfirmButton: true,
- confirmButtonText: this.i18nService.t("approve"),
- allowOutsideClick: false,
- });
+ const submitted = await firstValueFrom(
+ BrowserSyncVerificationDialogComponent.open(this.dialogService, { fingerprint }).closed
+ );
- if (submitted.value !== true) {
+ if (submitted !== true) {
return;
}
}
@@ -127,12 +122,12 @@ export class NativeMessagingService {
if (!(await this.stateService.getBiometricUnlock({ userId: message.userId }))) {
this.send({ command: "biometricUnlock", response: "not enabled" }, appId);
- return await Swal.fire({
- title: this.i18nService.t("biometricsNotEnabledTitle"),
- text: this.i18nService.t("biometricsNotEnabledDesc"),
- showCancelButton: true,
- cancelButtonText: this.i18nService.t("cancel"),
- showConfirmButton: false,
+ return this.dialogService.openSimpleDialog({
+ type: "warning",
+ title: { key: "biometricsNotEnabledTitle" },
+ content: { key: "biometricsNotEnabledDesc" },
+ cancelButtonText: null,
+ acceptButtonText: { key: "cancel" },
});
}