show toasts on copying, resolves #28

This commit is contained in:
Kyle Spearrin 2018-02-23 16:31:52 -05:00
parent accb4436ba
commit e24a083936
6 changed files with 53 additions and 28 deletions

View File

@ -1,5 +1,6 @@
import * as template from './password-generator-history.component.html';
import { ToasterService } from 'angular2-toaster';
import { Angulartics2 } from 'angulartics2';
import {
@ -8,6 +9,7 @@ import {
} from '@angular/core';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { PasswordHistory } from 'jslib/models/domain/passwordHistory';
@ -17,10 +19,11 @@ import { PasswordHistory } from 'jslib/models/domain/passwordHistory';
template: template,
})
export class PasswordGeneratorHistoryComponent implements OnInit {
history: PasswordHistory[];
history: PasswordHistory[] = [];
constructor(private passwordGenerationService: PasswordGenerationService, private analytics: Angulartics2,
private platformUtilsService: PlatformUtilsService) { }
private platformUtilsService: PlatformUtilsService, private i18nService: I18nService,
private toasterService: ToasterService) { }
async ngOnInit() {
this.history = await this.passwordGenerationService.getHistory();
@ -34,5 +37,6 @@ export class PasswordGeneratorHistoryComponent implements OnInit {
copy(password: string) {
this.analytics.eventTrack.next({ action: 'Copied Historical Password' });
this.platformUtilsService.copyToClipboard(password);
this.toasterService.popAsync('info', null, this.i18nService.t('valueCopied', this.i18nService.t('password')));
}
}

View File

@ -12,6 +12,7 @@ import {
} from '@angular/core';
import { PasswordGenerationService } from 'jslib/abstractions/passwordGeneration.service';
import { I18nService } from 'jslib/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
@Component({
@ -28,7 +29,8 @@ export class PasswordGeneratorComponent implements OnInit {
avoidAmbiguous = false;
constructor(private passwordGenerationService: PasswordGenerationService, private analytics: Angulartics2,
private platformUtilsService: PlatformUtilsService) { }
private platformUtilsService: PlatformUtilsService, private i18nService: I18nService,
private toasterService: ToasterService) { }
async ngOnInit() {
this.options = await this.passwordGenerationService.getOptions();
@ -73,6 +75,7 @@ export class PasswordGeneratorComponent implements OnInit {
copy() {
this.analytics.eventTrack.next({ action: 'Copied Generated Password' });
this.platformUtilsService.copyToClipboard(this.password);
this.toasterService.popAsync('info', null, this.i18nService.t('valueCopied', this.i18nService.t('password')));
}
select() {

View File

@ -212,21 +212,15 @@ export class VaultComponent implements OnInit, OnDestroy {
const menu = new remote.Menu();
menu.append(new remote.MenuItem({
label: this.i18nService.t('view'),
click: () => {
this.ngZone.run(async () => {
this.viewCipher(cipher);
this.changeDetectorRef.detectChanges();
});
},
click: () => this.functionWithChangeDetection(() => {
this.viewCipher(cipher);
}),
}));
menu.append(new remote.MenuItem({
label: this.i18nService.t('edit'),
click: () => {
this.ngZone.run(async () => {
this.editCipher(cipher);
this.changeDetectorRef.detectChanges();
});
},
click: () => this.functionWithChangeDetection(() => {
this.editCipher(cipher);
}),
}));
switch (cipher.type) {
@ -243,13 +237,13 @@ export class VaultComponent implements OnInit, OnDestroy {
if (cipher.login.username != null) {
menu.append(new remote.MenuItem({
label: this.i18nService.t('copyUsername'),
click: () => this.platformUtilsService.copyToClipboard(cipher.login.username),
click: () => this.copyValue(cipher.login.username, 'username'),
}));
}
if (cipher.login.password != null) {
menu.append(new remote.MenuItem({
label: this.i18nService.t('copyPassword'),
click: () => this.platformUtilsService.copyToClipboard(cipher.login.password),
click: () => this.copyValue(cipher.login.password, 'password'),
}));
}
break;
@ -260,13 +254,13 @@ export class VaultComponent implements OnInit, OnDestroy {
if (cipher.card.number != null) {
menu.append(new remote.MenuItem({
label: this.i18nService.t('copyNumber'),
click: () => this.platformUtilsService.copyToClipboard(cipher.card.number),
click: () => this.copyValue(cipher.card.number, 'number'),
}));
}
if (cipher.card.code != null) {
menu.append(new remote.MenuItem({
label: this.i18nService.t('copySecurityCode'),
click: () => this.platformUtilsService.copyToClipboard(cipher.card.code),
click: () => this.copyValue(cipher.card.code, 'securityCode'),
}));
}
break;
@ -488,8 +482,20 @@ export class VaultComponent implements OnInit, OnDestroy {
}
private addCipherWithChangeDetection(type: CipherType = null) {
this.functionWithChangeDetection(() => this.addCipher(type));
}
private copyValue(value: string, labelI18nKey: string) {
this.functionWithChangeDetection(() => {
this.platformUtilsService.copyToClipboard(value);
this.toasterService.popAsync('info', null,
this.i18nService.t('valueCopied', this.i18nService.t(labelI18nKey)));
});
}
private functionWithChangeDetection(func: Function) {
this.ngZone.run(async () => {
this.addCipher(type);
func();
this.changeDetectorRef.detectChanges();
});
}

View File

@ -23,7 +23,7 @@
<i class="fa fa-lg fa-share-square-o"></i>
</a>
<a class="row-btn" href="#" appStopClick title="{{'copyValue' | i18n}}"
(click)="copy(cipher.login.uri, 'URI')">
(click)="copy(cipher.login.uri, 'uri', 'URI')">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
@ -35,7 +35,7 @@
</div>
<div class="action-buttons">
<a class="row-btn" href="#" appStopClick title="{{'copyUsername' | i18n}}"
(click)="copy(cipher.login.username, 'Username')">
(click)="copy(cipher.login.username, 'username', 'Username')">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
@ -53,7 +53,7 @@
[ngClass]="{'fa-eye': !showPassword, 'fa-eye-slash': showPassword}"></i>
</a>
<a class="row-btn" href="#" appStopClick title="{{'copyPassword' | i18n}}"
(click)="copy(cipher.login.password, 'Password')">
(click)="copy(cipher.login.password, 'password', 'Password')">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
@ -76,7 +76,7 @@
</span>
<div class="action-buttons">
<a class="row-btn" href="#" appStopClick title="{{'copyValue' | i18n}}"
(click)="copy(totpCode, 'TOTP')">
(click)="copy(totpCode, 'verificationCodeTotp', 'TOTP')">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
@ -95,7 +95,7 @@
</div>
<div class="action-buttons">
<a class="row-btn" href="#" appStopClick title="{{'copyNumber' | i18n}}"
(click)="copy(cipher.card.number, 'Number')">
(click)="copy(cipher.card.number, 'number', 'Number')">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
@ -115,7 +115,7 @@
</div>
<div class="action-buttons">
<a class="row-btn" href="#" appStopClick title="{{'copySecurityCode' | i18n}}"
(click)="copy(cipher.card.code, 'Security Code')">
(click)="copy(cipher.card.code, 'securityCode', 'Security Code')">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>
@ -207,7 +207,7 @@
</a>
<a class="row-btn" href="#" appStopClick title="{{'copyValue' | i18n}}"
*ngIf="field.value && field.type !== fieldType.Boolean"
(click)="copy(field.value, 'Field')">
(click)="copy(field.value, 'value', 'Field')">
<i class="fa fa-lg fa-clipboard"></i>
</a>
</div>

View File

@ -96,13 +96,15 @@ export class ViewComponent implements OnChanges, OnDestroy {
this.platformUtilsService.launchUri(this.cipher.login.uri);
}
copy(value: string, aType: string) {
copy(value: string, typeI18nKey: string, aType: string) {
if (value == null) {
return;
}
this.analytics.eventTrack.next({ action: 'Copied ' + aType });
this.platformUtilsService.copyToClipboard(value);
this.toasterService.popAsync('info', null,
this.i18nService.t('valueCopied', this.i18nService.t(typeI18nKey)));
}
async downloadAttachment(attachment: AttachmentView) {

View File

@ -941,5 +941,15 @@
},
"quitBitwarden": {
"message": "Quit Bitwarden"
},
"valueCopied": {
"message": "$VALUE$ copied",
"description": "Value has been copied to the clipboard.",
"placeholders": {
"value": {
"content": "$1",
"example": "Password"
}
}
}
}