import { RcModuleV2 } from '@ringcentral-integration/core' ; import { Module } from '@ringcentral-integration/commons/lib/di' ; import { Deps } from './Beforeunload.interface' ; const UNLOAD_EVENT_NAME = 'beforeunload' ; type BeforeunloadFn = ( ) => boolean ; @ Module ( { name : 'Beforeunload' , deps : [ { dep : 'BeforeunloadOptions' , optional : true } ] , } ) export class Beforeunload extends RcModuleV2 < Deps > { _window : Window ; private get list ( ) { return this . _list ; } private set list ( value ) { this . _list = value ; if ( this . _bindState && this . _list . length === 0 ) { this . _window . removeEventListener ( UNLOAD_EVENT_NAME , this . _beforeunloadHandler ) ; this . _bindState = false ; } else if ( ! this . _bindState && this . _list . length > 0 ) { this . _window . addEventListener ( UNLOAD_EVENT_NAME , this . _beforeunloadHandler ) ; this . _bindState = true ; } } private _list : BeforeunloadFn [ ] = [ ] ; private _bindState = false ; constructor ( ) { super ( { deps : { } , } ) ; this . _window = this . _deps . beforeunloadOptions ?. originWindow ?? window ; } param cb add ( cb ) { const index = this . list . indexOf ( cb ) ; if ( index === - 1 ) { this . list = [ ... this . list , cb ] ; return this . list . length ; } return index ; } param cb remove ( cb ) { const index = this . list . indexOf ( cb ) ; if ( index > - 1 ) { this . _removeItem ( index ) ; } return index ; } /**
     * clear all check methods
     */ clear ( ) { this . list = [ ] ; } /**
     * check all should block callback, and return should we need block
     */ checkShouldBlock ( ) { for ( const fn of this . _list ) { if ( fn ( ) ) { return true ; } } return false ; } /**
     * that method will trigger after check not leave success
     */ onAfterUnload ( cb , notNeedCheck = false ) { this . _window . addEventListener ( 'unload' , ( ) => { if ( notNeedCheck || this . checkShouldBlock ( ) ) { cb ( ) ; } } ) ; } removeAfterUnloadListener ( cb ) { console . log ( 'removeAfterUnloadListener~~' ) ; this . _window . removeEventListener ( 'unload' , cb ) ; } private _removeItem ( i ) { const list = [ ... this . list ] ; list . splice ( i , 1 ) ; this . list = list ; } private _beforeunloadHandler = ( event ) => { if ( this . checkShouldBlock ( ) ) { event . preventDefault ( ) ; event . returnValue = '' ; return ; } delete event . returnValue ; } ; }