import { ChangeDetectorRef , Component , NgZone , OnInit , SecurityContext } from "@angular/core" ; import { DomSanitizer } from "@angular/platform-browser" ; import { NavigationEnd , Router , RouterOutlet } 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 { BroadcasterService } from "jslib-common/abstractions/broadcaster.service" ; import { I18nService } from "jslib-common/abstractions/i18n.service" ; import { KeyConnectorService } from "jslib-common/abstractions/keyConnector.service" ; import { MessagingService } from "jslib-common/abstractions/messaging.service" ; import { PlatformUtilsService } from "jslib-common/abstractions/platformUtils.service" ; import { StateService } from "jslib-common/abstractions/state.service" ; import { StorageService } from "jslib-common/abstractions/storage.service" ; import { ConstantsService } from "jslib-common/services/constants.service" ; import { routerTransition } from "./app-routing.animations" ; @ Component ( { selector : "app-root" , styles : [ ] , animations : [ routerTransition ] , template : ` <main [@routerTransition]="getState(o)">
    <router-outlet #o="outlet"></router-outlet>
  </main>` , } ) export class AppComponent implements OnInit { private lastActivity : number = null ; constructor ( private toastrService , private storageService , private broadcasterService , private authService , private i18nService , private router , private stateService , private messagingService , private changeDetectorRef , private ngZone , private sanitizer , private platformUtilsService , private keyConnectoService ) { } ngOnInit ( ) { if ( BrowserApi . getBackgroundPage ( ) == null ) { return ; } this . ngZone . runOutsideAngular ( ( ) => { window . onmousemove = ( ) => this . recordActivity ( ) ; window . onmousedown = ( ) => this . recordActivity ( ) ; window . ontouchstart = ( ) => this . recordActivity ( ) ; window . onclick = ( ) => this . recordActivity ( ) ; window . onscroll = ( ) => this . recordActivity ( ) ; window . onkeypress = ( ) => this . recordActivity ( ) ; } ) ; ( window as any ) . bitwardenPopupMainMessageListener = async ( msg , sender , sendResponse ) => { if ( msg . command === "doneLoggingOut" ) { this . ngZone . run ( async ( ) => { this . authService . logOut ( ( ) => { if ( msg . expired ) { this . showToast ( { type : "warning" , title : this . i18nService . t ( "loggedOut" ) , text : this . i18nService . t ( "loginExpired" ) , } ) ; } this . router . navigate ( [ "home" ] ) ; this . stateService . purge ( ) ; } ) ; this . changeDetectorRef . detectChanges ( ) ; } ) ; } else if ( msg . command === "authBlocked" ) { this . ngZone . run ( ( ) => { this . router . navigate ( [ "home" ] ) ; } ) ; } else if ( msg . command === "locked" ) { this . stateService . purge ( ) ; this . ngZone . run ( ( ) => { this . router . navigate ( [ "lock" ] ) ; } ) ; } else if ( msg . command === "showDialog" ) { await this . showDialog ( msg ) ; } else if ( msg . command === "showToast" ) { this . ngZone . run ( ( ) => { this . showToast ( msg ) ; } ) ; } else if ( msg . command === "reloadProcess" ) { const windowReload = this . platformUtilsService . isSafari ( ) || this . platformUtilsService . isFirefox ( ) || this . platformUtilsService . isOpera ( ) ; if ( windowReload ) { window . setTimeout ( ( ) => BrowserApi . reloadExtension ( window ) , 2000 ) ; } } else if ( msg . command === "reloadPopup" ) { this . ngZone . run ( ( ) => { this . router . navigate ( [ "/" ] ) ; } ) ; } else if ( msg . command === "convertAccountToKeyConnector" ) { this . ngZone . run ( async ( ) => { await this . keyConnectoService . setConvertAccountRequired ( true ) ; this . router . navigate ( [ "/remove-password" ] ) ; } ) ; } else { msg . webExtSender = sender ; this . broadcasterService . send ( msg ) ; } } ; BrowserApi . messageListener ( "app.component" , ( window as any ) . bitwardenPopupMainMessageListener ) ; this . router . events . subscribe ( ( event ) => { if ( event instanceof NavigationEnd ) { const url = event . urlAfterRedirects || event . url || "" ; if ( url . startsWith ( "/tabs/" ) && ( window as any ) . previousPopupUrl != null && ( window as any ) . previousPopupUrl . startsWith ( "/tabs/" ) ) { this . stateService . remove ( "GroupingsComponent" ) ; this . stateService . remove ( "GroupingsComponentScope" ) ; this . stateService . remove ( "CiphersComponent" ) ; this . stateService . remove ( "SendGroupingsComponent" ) ; this . stateService . remove ( "SendGroupingsComponentScope" ) ; this . stateService . remove ( "SendTypeComponent" ) ; } if ( url . startsWith ( "/tabs/" ) ) { this . stateService . remove ( "addEditCipherInfo" ) ; } ( window as any ) . previousPopupUrl = url ; if ( ( window as any ) . routeDirection != null ) { window . setTimeout ( ( ) => { ( window as any ) . routeDirection = null ; } , 400 ) ; } } } ) ; } getState ( outlet ) { if ( outlet . activatedRouteData . state === "ciphers" ) { const routeDirection = ( window as any ) . routeDirection != null ? ( window as any ) . routeDirection : "" ; return ( "ciphers_direction=" + routeDirection + "_" + ( outlet . activatedRoute . queryParams as any ) . value . folderId + "_" + ( outlet . activatedRoute . queryParams as any ) . value . collectionId ) ; } else { return outlet . activatedRouteData . state ; } } private async recordActivity ( ) { const now = new Date ( ) . getTime ( ) ; if ( this . lastActivity != null && now - this . lastActivity < 250 ) { return ; } this . lastActivity = now ; this . storageService . save ( ConstantsService . lastActiveKey , now ) ; } private showToast ( msg ) { let message = "" ; const options = { } ; if ( typeof msg . text === "string" ) { message = msg . text ; } else if ( msg . text . length === 1 ) { message = msg . text [ 0 ] ; } else { msg . text . forEach ( ( t ) => ( message += "<p>" + this . sanitizer . sanitize ( SecurityContext . HTML , t ) + "</p>" ) ) ; options . enableHtml = true ; } if ( msg . options != null ) { if ( msg . options . trustedHtml === true ) { options . enableHtml = true ; } if ( msg . options . timeout != null && msg . options . timeout > 0 ) { options . timeOut = msg . options . timeout ; } } this . toastrService . show ( message , msg . title , options , "toast-" + msg . type ) ; } private async showDialog ( msg ) { let iconClasses = null ; const type = msg . type ; if ( type != null ) { switch ( type ) { case "success" : iconClasses = "fa-check text-success" ; break ; case "warning" : iconClasses = "fa-warning text-warning" ; break ; case "error" : iconClasses = "fa-bolt text-danger" ; break ; case "info" : iconClasses = "fa-info-circle text-info" ; break ; default : break ; } } const cancelText = msg . cancelText ; const confirmText = msg . confirmText ; const confirmed = await Swal . fire ( { heightAuto : false , buttonsStyling : false , icon : type as SweetAlertIcon , iconHtml : iconClasses != null ? `<i class="swal-custom-icon fa ${ iconClasses }"></i>` : undefined , text : msg . text , html : msg . html , titleText : msg . title , showCancelButton : cancelText != null , cancelButtonText : cancelText , showConfirmButton : true , confirmButtonText : confirmText == null ? this . i18nService . t ( "ok" ) : confirmText , timer : 300000 , } ) ; this . messagingService . send ( "showDialogResolve" , { dialogId : msg . dialogId , confirmed : confirmed . value , } ) ; } }