diff --git a/apps/browser/src/_locales/en/messages.json b/apps/browser/src/_locales/en/messages.json index a3ac0cda882..99c5960ab2d 100644 --- a/apps/browser/src/_locales/en/messages.json +++ b/apps/browser/src/_locales/en/messages.json @@ -4175,6 +4175,20 @@ } } }, + "copyFieldValue": { + "message": "Copy $FIELD$, $VALUE$", + "description": "Title for a button that copies a field value to the clipboard.", + "placeholders": { + "field": { + "content": "$1", + "example": "Username" + }, + "value": { + "content": "$2", + "example": "Foo" + } + } + }, "noValuesToCopy": { "message": "No values to copy" }, diff --git a/apps/browser/src/vault/popup/components/vault-v2/item-copy-action/item-copy-actions.component.html b/apps/browser/src/vault/popup/components/vault-v2/item-copy-action/item-copy-actions.component.html index fbfebe8efff..fbdc0b4b4b7 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/item-copy-action/item-copy-actions.component.html +++ b/apps/browser/src/vault/popup/components/vault-v2/item-copy-action/item-copy-actions.component.html @@ -40,28 +40,41 @@ bitIconButton="bwi-clone" size="small" [appA11yTitle]=" - hasLoginValues ? ('copyInfoTitle' | i18n: cipher.name) : ('noValuesToCopy' | i18n) + 'copyFieldValue' | i18n: singleCopiableLogin.field : singleCopiableLogin.value " - [disabled]="!hasLoginValues" - [bitMenuTriggerFor]="loginOptions" + [appCopyClick]="singleCopiableLogin.value" + [valueLabel]="singleCopiableLogin.field" + *ngIf="singleCopiableLogin" > - - + - - + bitIconButton="bwi-clone" + size="small" + [appA11yTitle]=" + hasLoginValues ? ('copyInfoTitle' | i18n: cipher.name) : ('noValuesToCopy' | i18n) + " + [disabled]="!hasLoginValues" + [bitMenuTriggerFor]="loginOptions" + > + + + + + + diff --git a/apps/browser/src/vault/popup/components/vault-v2/item-copy-action/item-copy-actions.component.ts b/apps/browser/src/vault/popup/components/vault-v2/item-copy-action/item-copy-actions.component.ts index 53439dc4abd..d14675cc11c 100644 --- a/apps/browser/src/vault/popup/components/vault-v2/item-copy-action/item-copy-actions.component.ts +++ b/apps/browser/src/vault/popup/components/vault-v2/item-copy-action/item-copy-actions.component.ts @@ -37,6 +37,64 @@ export class ItemCopyActionsComponent { ); } + get singleCopiableLogin() { + const { username, password, hasTotp, totp } = this.cipher.login; + // If there is both a username and password but the password is not viewable, then the username is the only copiable value + if (username && password && !this.cipher.viewPassword) { + return { + value: username, + field: "username", + }; + } + if (username && !password && !hasTotp) { + return { + value: username, + field: "username", + }; + } + if (!username && password && !hasTotp) { + return { + value: password, + field: "password", + }; + } + if (!username && !password && hasTotp) { + return { + value: totp, + field: "totp", + }; + } + return null; + } + + get singleCopiableCardValue() { + const { code, number } = this.cipher.card; + if (code && !number) { + return code; + } + if (!code && number) { + return number; + } + return null; + } + + get singleCopiableIdentityValue() { + const { fullAddressForCopy, email, username, phone } = this.cipher.identity; + if (fullAddressForCopy && !email && !username && !phone) { + return fullAddressForCopy; + } + if (!fullAddressForCopy && email && !username && !phone) { + return email; + } + if (!fullAddressForCopy && !email && username && !phone) { + return username; + } + if (!fullAddressForCopy && !email && !username && phone) { + return phone; + } + return null; + } + get hasCardValues() { return !!this.cipher.card.code || !!this.cipher.card.number; }