From e11e4db356aed90d6c7d54b2c94e756d3fc19813 Mon Sep 17 00:00:00 2001 From: Will Martin Date: Fri, 10 Mar 2023 10:13:07 -0500 Subject: [PATCH] [SM-632] fix copy secret value in Safari (#4974) * add async copy method * be more DRY --- .../overview/overview.component.ts | 21 +++---- .../project/project-secrets.component.ts | 21 +++---- .../secrets/secrets.component.ts | 21 +++---- .../shared/secrets-list.component.ts | 56 +++++++++++++++++++ 4 files changed, 80 insertions(+), 39 deletions(-) diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts index 0ce7d70651..fd7932560f 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/overview/overview.component.ts @@ -45,6 +45,7 @@ import { ServiceAccountOperation, } from "../service-accounts/dialog/service-account-dialog.component"; import { ServiceAccountService } from "../service-accounts/service-account.service"; +import { SecretsListComponent } from "../shared/secrets-list.component"; type Tasks = { [organizationId: string]: OrganizationTasks; @@ -277,21 +278,15 @@ export class OverviewComponent implements OnInit, OnDestroy { } copySecretName(name: string) { - this.platformUtilsService.copyToClipboard(name); - this.platformUtilsService.showToast( - "success", - null, - this.i18nService.t("valueCopied", this.i18nService.t("name")) - ); + SecretsListComponent.copySecretName(name, this.platformUtilsService, this.i18nService); } - async copySecretValue(id: string) { - const secret = await this.secretService.getBySecretId(id); - this.platformUtilsService.copyToClipboard(secret.value); - this.platformUtilsService.showToast( - "success", - null, - this.i18nService.t("valueCopied", this.i18nService.t("value")) + copySecretValue(id: string) { + SecretsListComponent.copySecretValue( + id, + this.platformUtilsService, + this.i18nService, + this.secretService ); } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts index 01d7e158d5..407b3588b1 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/projects/project/project-secrets.component.ts @@ -17,6 +17,7 @@ import { SecretOperation, } from "../../secrets/dialog/secret-dialog.component"; import { SecretService } from "../../secrets/secret.service"; +import { SecretsListComponent } from "../../shared/secrets-list.component"; @Component({ selector: "sm-project-secrets", @@ -81,21 +82,15 @@ export class ProjectSecretsComponent { } copySecretName(name: string) { - this.platformUtilsService.copyToClipboard(name); - this.platformUtilsService.showToast( - "success", - null, - this.i18nService.t("valueCopied", this.i18nService.t("name")) - ); + SecretsListComponent.copySecretName(name, this.platformUtilsService, this.i18nService); } - async copySecretValue(id: string) { - const secret = await this.secretService.getBySecretId(id); - this.platformUtilsService.copyToClipboard(secret.value); - this.platformUtilsService.showToast( - "success", - null, - this.i18nService.t("valueCopied", this.i18nService.t("value")) + copySecretValue(id: string) { + SecretsListComponent.copySecretValue( + id, + this.platformUtilsService, + this.i18nService, + this.secretService ); } } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts index 938e168188..5db22ad87b 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/secrets/secrets.component.ts @@ -7,6 +7,7 @@ import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUti import { DialogService } from "@bitwarden/components"; import { SecretListView } from "../models/view/secret-list.view"; +import { SecretsListComponent } from "../shared/secrets-list.component"; import { SecretDeleteDialogComponent, @@ -84,21 +85,15 @@ export class SecretsComponent implements OnInit { } copySecretName(name: string) { - this.platformUtilsService.copyToClipboard(name); - this.platformUtilsService.showToast( - "success", - null, - this.i18nService.t("valueCopied", this.i18nService.t("name")) - ); + SecretsListComponent.copySecretName(name, this.platformUtilsService, this.i18nService); } - async copySecretValue(id: string) { - const secret = await this.secretService.getBySecretId(id); - this.platformUtilsService.copyToClipboard(secret.value); - this.platformUtilsService.showToast( - "success", - null, - this.i18nService.t("valueCopied", this.i18nService.t("value")) + copySecretValue(id: string) { + SecretsListComponent.copySecretValue( + id, + this.platformUtilsService, + this.i18nService, + this.secretService ); } } diff --git a/bitwarden_license/bit-web/src/app/secrets-manager/shared/secrets-list.component.ts b/bitwarden_license/bit-web/src/app/secrets-manager/shared/secrets-list.component.ts index 7cc2aa5e1e..0f20e1e216 100644 --- a/bitwarden_license/bit-web/src/app/secrets-manager/shared/secrets-list.component.ts +++ b/bitwarden_license/bit-web/src/app/secrets-manager/shared/secrets-list.component.ts @@ -2,9 +2,12 @@ import { SelectionModel } from "@angular/cdk/collections"; import { Component, EventEmitter, Input, OnDestroy, Output } from "@angular/core"; import { Subject, takeUntil } from "rxjs"; +import { I18nService } from "@bitwarden/common/abstractions/i18n.service"; +import { PlatformUtilsService } from "@bitwarden/common/abstractions/platformUtils.service"; import { TableDataSource } from "@bitwarden/components"; import { SecretListView } from "../models/view/secret-list.view"; +import { SecretService } from "../secrets/secret.service"; @Component({ selector: "sm-secrets-list", @@ -89,4 +92,57 @@ export class SecretsListComponent implements OnDestroy { return aProjects[0]?.name.localeCompare(bProjects[0].name); }; + + /** + * TODO: Refactor to smart component and remove + */ + static copySecretName( + name: string, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService + ) { + platformUtilsService.copyToClipboard(name); + platformUtilsService.showToast( + "success", + null, + i18nService.t("valueCopied", i18nService.t("name")) + ); + } + + /** + * TODO: Refactor to smart component and remove + */ + static copySecretValue( + id: string, + platformUtilsService: PlatformUtilsService, + i18nService: I18nService, + secretService: SecretService + ) { + const value = secretService.getBySecretId(id).then((secret) => secret.value); + SecretsListComponent.copyToClipboardAsync(value, platformUtilsService).then(() => { + platformUtilsService.showToast( + "success", + null, + i18nService.t("valueCopied", i18nService.t("value")) + ); + }); + } + + /** + * TODO: Remove in favor of updating `PlatformUtilsService.copyToClipboard` + */ + private static copyToClipboardAsync( + text: Promise, + platformUtilsService: PlatformUtilsService + ) { + if (platformUtilsService.isSafari()) { + return navigator.clipboard.write([ + new ClipboardItem({ + ["text/plain"]: text, + }), + ]); + } + + return text.then((t) => platformUtilsService.copyToClipboard(t)); + } }