1
0
mirror of https://github.com/bitwarden/browser.git synced 2025-02-08 00:01:28 +01:00

Replace toaster library (#2210)

This commit is contained in:
Oscar Hinton 2021-12-07 19:42:18 +00:00 committed by GitHub
parent 86b4340bfb
commit e4aaf81816
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 91 additions and 112 deletions

2
jslib

@ -1 +1 @@
Subproject commit 5db94cc9d06ba478a29e9b625993108dfa0d7ec8 Subproject commit a6b95b15e36737ccf2e7664ed3c881bc19366b84

45
package-lock.json generated
View File

@ -11,11 +11,11 @@
"dependencies": { "dependencies": {
"@bitwarden/jslib-angular": "file:jslib/angular", "@bitwarden/jslib-angular": "file:jslib/angular",
"@bitwarden/jslib-common": "file:jslib/common", "@bitwarden/jslib-common": "file:jslib/common",
"angular2-toaster": "^11.0.1",
"core-js": "^3.11.0", "core-js": "^3.11.0",
"date-input-polyfill": "^2.14.0", "date-input-polyfill": "^2.14.0",
"font-awesome": "4.7.0", "font-awesome": "4.7.0",
"mousetrap": "^1.6.5", "mousetrap": "^1.6.5",
"ngx-toastr": "^13.2.1",
"nord": "^0.2.1", "nord": "^0.2.1",
"sweetalert2": "^10.16.6", "sweetalert2": "^10.16.6",
"web-animations-js": "^2.3.2" "web-animations-js": "^2.3.2"
@ -1293,20 +1293,6 @@
"ajv": "^6.9.1" "ajv": "^6.9.1"
} }
}, },
"node_modules/angular2-toaster": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/angular2-toaster/-/angular2-toaster-11.0.1.tgz",
"integrity": "sha512-IRXE5zujPMNOhckcp+Hk2n+UrKSrlAviz55wGvSd9ECrqsSRjgh148UEtgsqkcYQ8leKcybZ4d0lrueDuQofNA==",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/common": "^11.0.0",
"@angular/compiler": "^11.0.0",
"@angular/core": "^11.0.0",
"rxjs": "^6.5.3"
}
},
"node_modules/ansi-colors": { "node_modules/ansi-colors": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
@ -7777,6 +7763,19 @@
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true "dev": true
}, },
"node_modules/ngx-toastr": {
"version": "13.2.1",
"resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-13.2.1.tgz",
"integrity": "sha512-UAzp7/xWK9IXA2LsOmhpaaIGCqscvJokoQpBNpAMrjEkDeSlFf8PWQAuQY795KW0mJb3qF9UG/s23nsXfMYKmg==",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"@angular/common": ">=10.0.0-0",
"@angular/core": ">=10.0.0-0",
"@angular/platform-browser": ">=10.0.0-0"
}
},
"node_modules/no-case": { "node_modules/no-case": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
@ -13764,14 +13763,6 @@
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },
"angular2-toaster": {
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/angular2-toaster/-/angular2-toaster-11.0.1.tgz",
"integrity": "sha512-IRXE5zujPMNOhckcp+Hk2n+UrKSrlAviz55wGvSd9ECrqsSRjgh148UEtgsqkcYQ8leKcybZ4d0lrueDuQofNA==",
"requires": {
"tslib": "^2.0.0"
}
},
"ansi-colors": { "ansi-colors": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz",
@ -18925,6 +18916,14 @@
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
"dev": true "dev": true
}, },
"ngx-toastr": {
"version": "13.2.1",
"resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-13.2.1.tgz",
"integrity": "sha512-UAzp7/xWK9IXA2LsOmhpaaIGCqscvJokoQpBNpAMrjEkDeSlFf8PWQAuQY795KW0mJb3qF9UG/s23nsXfMYKmg==",
"requires": {
"tslib": "^2.0.0"
}
},
"no-case": { "no-case": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",

View File

@ -71,11 +71,11 @@
"dependencies": { "dependencies": {
"@bitwarden/jslib-angular": "file:jslib/angular", "@bitwarden/jslib-angular": "file:jslib/angular",
"@bitwarden/jslib-common": "file:jslib/common", "@bitwarden/jslib-common": "file:jslib/common",
"angular2-toaster": "^11.0.1",
"core-js": "^3.11.0", "core-js": "^3.11.0",
"date-input-polyfill": "^2.14.0", "date-input-polyfill": "^2.14.0",
"font-awesome": "4.7.0", "font-awesome": "4.7.0",
"mousetrap": "^1.6.5", "mousetrap": "^1.6.5",
"ngx-toastr": "^13.2.1",
"nord": "^0.2.1", "nord": "^0.2.1",
"sweetalert2": "^10.16.6", "sweetalert2": "^10.16.6",
"web-animations-js": "^2.3.2" "web-animations-js": "^2.3.2"

View File

@ -1,13 +1,3 @@
import { BrowserApi } from '../browser/browserApi';
import {
BodyOutputType,
Toast,
ToasterConfig,
ToasterService,
} from 'angular2-toaster';
import Swal, { SweetAlertIcon } from 'sweetalert2/src/sweetalert2.js';
import { import {
ChangeDetectorRef, ChangeDetectorRef,
Component, Component,
@ -21,6 +11,12 @@ import {
Router, Router,
RouterOutlet, RouterOutlet,
} from '@angular/router'; } from '@angular/router';
import {
IndividualConfig,
ToastrService,
} from 'ngx-toastr';
import Swal, { SweetAlertIcon } from 'sweetalert2/src/sweetalert2.js';
import { BrowserApi } from '../browser/browserApi';
import { AuthService } from 'jslib-common/abstractions/auth.service'; import { AuthService } from 'jslib-common/abstractions/auth.service';
import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service'; import { BroadcasterService } from 'jslib-common/abstractions/broadcaster.service';
@ -40,24 +36,15 @@ import { routerTransition } from './app-routing.animations';
styles: [], styles: [],
animations: [routerTransition], animations: [routerTransition],
template: ` template: `
<toaster-container [toasterconfig]="toasterConfig" aria-live="polite"></toaster-container>
<main [@routerTransition]="getState(o)"> <main [@routerTransition]="getState(o)">
<router-outlet #o="outlet"></router-outlet> <router-outlet #o="outlet"></router-outlet>
</main>`, </main>`,
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit {
toasterConfig: ToasterConfig = new ToasterConfig({
showCloseButton: false,
mouseoverTimerStop: true,
animation: 'slideUp',
limit: 2,
positionClass: 'toast-bottom-full-width',
newestOnTop: false,
});
private lastActivity: number = null; private lastActivity: number = null;
constructor(private toasterService: ToasterService, private storageService: StorageService, constructor(private toastrService: ToastrService, private storageService: StorageService,
private broadcasterService: BroadcasterService, private authService: AuthService, private broadcasterService: BroadcasterService, private authService: AuthService,
private i18nService: I18nService, private router: Router, private i18nService: I18nService, private router: Router,
private stateService: StateService, private messagingService: MessagingService, private stateService: StateService, private messagingService: MessagingService,
@ -183,30 +170,29 @@ export class AppComponent implements OnInit {
} }
private showToast(msg: any) { private showToast(msg: any) {
const toast: Toast = { let message = '';
type: msg.type,
title: msg.title, const options: Partial<IndividualConfig> = {};
};
if (typeof (msg.text) === 'string') { if (typeof (msg.text) === 'string') {
toast.body = msg.text; message = msg.text;
} else if (msg.text.length === 1) { } else if (msg.text.length === 1) {
toast.body = msg.text[0]; message = msg.text[0];
} else { } else {
let message = '';
msg.text.forEach((t: string) => msg.text.forEach((t: string) =>
message += ('<p>' + this.sanitizer.sanitize(SecurityContext.HTML, t) + '</p>')); message += ('<p>' + this.sanitizer.sanitize(SecurityContext.HTML, t) + '</p>'));
toast.body = message; options.enableHtml = true;
toast.bodyOutputType = BodyOutputType.TrustedHtml;
} }
if (msg.options != null) { if (msg.options != null) {
if (msg.options.trustedHtml === true) { if (msg.options.trustedHtml === true) {
toast.bodyOutputType = BodyOutputType.TrustedHtml; options.enableHtml = true;
} }
if (msg.options.timeout != null && msg.options.timeout > 0) { if (msg.options.timeout != null && msg.options.timeout > 0) {
toast.timeout = msg.options.timeout; options.timeOut = msg.options.timeout;
} }
} }
this.toasterService.popAsync(toast);
this.toastrService.show(message, msg.title, options, 'toast-' + msg.type);
} }
private async showDialog(msg: any) { private async showDialog(msg: any) {

View File

@ -1,7 +1,6 @@
import { A11yModule } from '@angular/cdk/a11y'; import { A11yModule } from '@angular/cdk/a11y';
import { DragDropModule } from '@angular/cdk/drag-drop'; import { DragDropModule } from '@angular/cdk/drag-drop';
import { ScrollingModule } from '@angular/cdk/scrolling'; import { ScrollingModule } from '@angular/cdk/scrolling';
import { ToasterModule } from 'angular2-toaster';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
import { ServicesModule } from './services/services.module'; import { ServicesModule } from './services/services.module';
@ -85,6 +84,7 @@ import { VerifyMasterPasswordComponent } from './components/verify-master-passwo
import { CalloutComponent } from 'jslib-angular/components/callout.component'; import { CalloutComponent } from 'jslib-angular/components/callout.component';
import { IconComponent } from 'jslib-angular/components/icon.component'; import { IconComponent } from 'jslib-angular/components/icon.component';
import { BitwardenToastModule } from 'jslib-angular/components/toastr.component';
import { import {
CurrencyPipe, CurrencyPipe,
@ -188,7 +188,12 @@ registerLocaleData(localeZhTw, 'zh-TW');
ReactiveFormsModule, ReactiveFormsModule,
ScrollingModule, ScrollingModule,
ServicesModule, ServicesModule,
ToasterModule.forRoot(), BitwardenToastModule.forRoot({
maxOpened: 2,
autoDismiss: true,
closeButton: true,
positionClass: 'toast-bottom-full-width',
}),
], ],
declarations: [ declarations: [
A11yTitleDirective, A11yTitleDirective,

View File

@ -5,8 +5,6 @@ import {
Output, Output,
} from '@angular/core'; } from '@angular/core';
import { ToasterService } from 'angular2-toaster';
import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType'; import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType';
import { CipherType } from 'jslib-common/enums/cipherType'; import { CipherType } from 'jslib-common/enums/cipherType';
import { EventType } from 'jslib-common/enums/eventType'; import { EventType } from 'jslib-common/enums/eventType';
@ -33,7 +31,7 @@ export class ActionButtonsComponent {
cipherType = CipherType; cipherType = CipherType;
userHasPremiumAccess = false; userHasPremiumAccess = false;
constructor(private toasterService: ToasterService, private i18nService: I18nService, constructor(private i18nService: I18nService,
private platformUtilsService: PlatformUtilsService, private eventService: EventService, private platformUtilsService: PlatformUtilsService, private eventService: EventService,
private totpService: TotpService, private userService: UserService, private totpService: TotpService, private userService: UserService,
private passwordRepromptService: PasswordRepromptService) { } private passwordRepromptService: PasswordRepromptService) { }
@ -63,7 +61,7 @@ export class ActionButtonsComponent {
} }
this.platformUtilsService.copyToClipboard(value, { window: window }); this.platformUtilsService.copyToClipboard(value, { window: window });
this.toasterService.popAsync('info', null, this.platformUtilsService.showToast('info', null,
this.i18nService.t('valueCopied', this.i18nService.t(typeI18nKey))); this.i18nService.t('valueCopied', this.i18nService.t(typeI18nKey)));
if (typeI18nKey === 'password' || typeI18nKey === 'verificationCodeTotp') { if (typeI18nKey === 'password' || typeI18nKey === 'verificationCodeTotp') {

View File

@ -1,6 +1,6 @@
$fa-font-path: "~font-awesome/fonts"; $fa-font-path: "~font-awesome/fonts";
@import "~font-awesome/scss/font-awesome.scss"; @import "~font-awesome/scss/font-awesome.scss";
@import "~angular2-toaster/toaster"; @import '~ngx-toastr/toastr';
@import "~sweetalert2/src/sweetalert2.scss"; @import "~sweetalert2/src/sweetalert2.scss";
@import "variables.scss"; @import "variables.scss";
@ -9,32 +9,36 @@ $fa-font-path: "~font-awesome/fonts";
// Toaster // Toaster
.toast-container { .toast-container {
&.toast-bottom-full-width div.toast { .toast-close-button {
margin: 0 10px 10px; font-size: 18px;
width: calc(100% - 20px); margin-right: 4px;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.35);
&:hover {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.6);
}
} }
.toast { .ngx-toastr {
&:before { align-items: center;
background-image: none !important;
border-radius: $border-radius;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.35);
display: flex;
padding: 15px;
.toast-close-button {
position: absolute;
right: 5px;
top: 0;
}
&:hover {
box-shadow: 0 0 10px rgba(0, 0, 0, 0.6);
}
.icon i::before {
float: left;
font-style: normal;
font-family: FontAwesome; font-family: FontAwesome;
font-size: 25px; font-size: 25px;
line-height: 20px; line-height: 20px;
float: left; padding-right: 15px;
color: #ffffff;
margin: auto 0 auto 15px;
}
.toast-content {
padding: 15px;
}
.toaster-icon {
display: none;
} }
.toast-message { .toast-message {
@ -48,49 +52,41 @@ $fa-font-path: "~font-awesome/fonts";
} }
&.toast-danger, &.toast-error { &.toast-danger, &.toast-error {
background-image: none !important;
@include themify($themes) { @include themify($themes) {
background-color: themed('dangerColor'); background-color: themed('dangerColor');
} }
&:before { .icon i::before {
content: "\f0e7"; content: "\f0e7";
} }
} }
&.toast-warning { &.toast-warning {
background-image: none !important;
@include themify($themes) { @include themify($themes) {
background-color: themed('warningColor'); background-color: themed('warningColor');
} }
&:before { .icon i::before {
content: "\f071"; content: "\f071";
} }
} }
&.toast-info { &.toast-info {
background-image: none !important;
@include themify($themes) { @include themify($themes) {
background-color: themed('infoColor'); background-color: themed('infoColor');
} }
&:before { .icon i:before {
content: "\f05a"; content: "\f05a";
} }
} }
&.toast-success { &.toast-success {
background-image: none !important;
@include themify($themes) { @include themify($themes) {
background-color: themed('successColor'); background-color: themed('successColor');
} }
&:before { .icon i:before {
content: "\f00C"; content: "\f00C";
} }
} }

View File

@ -6,7 +6,6 @@ import {
} from '@angular/core'; } from '@angular/core';
import { FormControl } from '@angular/forms'; import { FormControl } from '@angular/forms';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import Swal from 'sweetalert2/src/sweetalert2.js'; import Swal from 'sweetalert2/src/sweetalert2.js';
import { BrowserApi } from '../../browser/browserApi'; import { BrowserApi } from '../../browser/browserApi';
@ -68,7 +67,7 @@ export class SettingsComponent implements OnInit {
public messagingService: MessagingService, private router: Router, public messagingService: MessagingService, private router: Router,
private environmentService: EnvironmentService, private cryptoService: CryptoService, private environmentService: EnvironmentService, private cryptoService: CryptoService,
private userService: UserService, private popupUtilsService: PopupUtilsService, private userService: UserService, private popupUtilsService: PopupUtilsService,
private modalService: ModalService, private toasterService: ToasterService, private modalService: ModalService,
private keyConnectorService: KeyConnectorService) { private keyConnectorService: KeyConnectorService) {
} }
@ -136,7 +135,7 @@ export class SettingsComponent implements OnInit {
} }
if (!this.vaultTimeout.valid) { if (!this.vaultTimeout.valid) {
this.toasterService.popAsync('error', null, this.i18nService.t('vaultTimeoutToLarge')); this.platformUtilsService.showToast('error', null, this.i18nService.t('vaultTimeoutToLarge'));
return; return;
} }
@ -165,7 +164,7 @@ export class SettingsComponent implements OnInit {
} }
if (!this.vaultTimeout.valid) { if (!this.vaultTimeout.valid) {
this.toasterService.popAsync('error', null, this.i18nService.t('vaultTimeoutToLarge')); this.platformUtilsService.showToast('error', null, this.i18nService.t('vaultTimeoutToLarge'));
return; return;
} }

View File

@ -1,11 +1,10 @@
import { ToasterService } from 'angular2-toaster';
import { import {
Component, Component,
OnInit, OnInit,
} from '@angular/core'; } from '@angular/core';
import { I18nService } from 'jslib-common/abstractions/i18n.service'; import { I18nService } from 'jslib-common/abstractions/i18n.service';
import { PlatformUtilsService } from 'jslib-common/abstractions/platformUtils.service';
import { SyncService } from 'jslib-common/abstractions/sync.service'; import { SyncService } from 'jslib-common/abstractions/sync.service';
@Component({ @Component({
@ -16,7 +15,7 @@ export class SyncComponent implements OnInit {
lastSync = '--'; lastSync = '--';
syncPromise: Promise<any>; syncPromise: Promise<any>;
constructor(private syncService: SyncService, private toasterService: ToasterService, constructor(private syncService: SyncService, private platformUtilsService: PlatformUtilsService,
private i18nService: I18nService) { private i18nService: I18nService) {
} }
@ -29,9 +28,9 @@ export class SyncComponent implements OnInit {
const success = await this.syncPromise; const success = await this.syncPromise;
if (success) { if (success) {
await this.setLastSync(); await this.setLastSync();
this.toasterService.popAsync('success', null, this.i18nService.t('syncingComplete')); this.platformUtilsService.showToast('success', null, this.i18nService.t('syncingComplete'));
} else { } else {
this.toasterService.popAsync('error', null, this.i18nService.t('syncingFailed')); this.platformUtilsService.showToast('error', null, this.i18nService.t('syncingFailed'));
} }
} }

View File

@ -5,11 +5,8 @@ import {
OnDestroy, OnDestroy,
OnInit, OnInit,
} from '@angular/core'; } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { ToasterService } from 'angular2-toaster';
import { BrowserApi } from '../../browser/browserApi'; import { BrowserApi } from '../../browser/browserApi';
import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType'; import { CipherRepromptType } from 'jslib-common/enums/cipherRepromptType';
@ -59,7 +56,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
constructor(private platformUtilsService: PlatformUtilsService, private cipherService: CipherService, constructor(private platformUtilsService: PlatformUtilsService, private cipherService: CipherService,
private popupUtilsService: PopupUtilsService, private autofillService: AutofillService, private popupUtilsService: PopupUtilsService, private autofillService: AutofillService,
private toasterService: ToasterService, private i18nService: I18nService, private router: Router, private i18nService: I18nService, private router: Router,
private ngZone: NgZone, private broadcasterService: BroadcasterService, private ngZone: NgZone, private broadcasterService: BroadcasterService,
private changeDetectorRef: ChangeDetectorRef, private syncService: SyncService, private changeDetectorRef: ChangeDetectorRef, private syncService: SyncService,
private searchService: SearchService, private storageService: StorageService, private searchService: SearchService, private storageService: StorageService,
@ -140,7 +137,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
} }
if (this.pageDetails == null || this.pageDetails.length === 0) { if (this.pageDetails == null || this.pageDetails.length === 0) {
this.toasterService.popAsync('error', null, this.i18nService.t('autofillError')); this.platformUtilsService.showToast('error', null, this.i18nService.t('autofillError'));
return; return;
} }
@ -164,7 +161,7 @@ export class CurrentTabComponent implements OnInit, OnDestroy {
} }
} catch { } catch {
this.ngZone.run(() => { this.ngZone.run(() => {
this.toasterService.popAsync('error', null, this.i18nService.t('autofillError')); this.platformUtilsService.showToast('error', null, this.i18nService.t('autofillError'));
this.changeDetectorRef.detectChanges(); this.changeDetectorRef.detectChanges();
}); });
} }