import { noop } from "remeda" ; import { produce } from "immer" ; import * as fromRoot from "src/web/browser-window/app/store/reducers/root" ; import { ACCOUNTS_ACTIONS , NAVIGATION_ACTIONS } from "src/web/browser-window/app/store/actions" ; import { LoginFieldContainer } from "src/shared/model/container" ; import { UnionOf } from "src/shared/ngrx-util" ; import { WebAccount } from "src/web/browser-window/app/model" ; import { accountPickingPredicate } from "src/shared/util" ; import { getWebLogger } from "src/web/browser-window/util" ; const logger = getWebLogger ( __filename ) ; export const featureName = "accounts" ; export interface State extends fromRoot . State { selectedLogin ? : string ; initialized ? : boolean ; globalProgress : { indexing ? : boolean ; } ; accounts : WebAccount [ ] ; } const initialState = { accounts : [ ] , globalProgress : { } , } ; const resolveAccountByLogin = < T extends boolean > ( accounts , filterCriteria , strict ) : typeof strict extends true ? WebAccount : WebAccount | undefined => { const filterPredicate = accountPickingPredicate ( filterCriteria ) ; const webAccount = accounts . find ( ( { accountConfig } ) => filterPredicate ( accountConfig ) ) ; if ( ! webAccount && strict ) { throw new Error ( "Failed to resolve account" ) ; } return webAccount as any ; } ; export function reducer ( state = initialState , action ) { if ( NAVIGATION_ACTIONS . is ( action ) ) { return action . type === NAVIGATION_ACTIONS . Logout . type ? initialState : state ; } return produce ( state , ( draftState ) => { ACCOUNTS_ACTIONS . match ( action , { WireUpConfigs ( { accountConfigs } ) { const webAccounts = accountConfigs . filter ( ( accountConfig ) => ! accountConfig . disabled ) . reduce ( ( accounts , accountConfig ) => { const account = resolveAccountByLogin ( draftState . accounts , accountConfig , false ) ; if ( account ) { account . accountConfig = accountConfig ; if ( ! account . accountConfig . database ) { delete account . databaseView ; } accounts . push ( account ) ; } else { const webAccount = { accountIndex : - 1 , accountConfig , progress : { } , notifications : { unread : 0 , loggedIn : false , loggedInCalendar : false , pageType : { url : "" , type : "unknown" } , } , dbExportProgress : [ ] , webviewSrcValues : { calendar : "" , primary : "" } , } ; accounts . push ( webAccount ) ; } return accounts ; } , [ ] ) ; if ( typeof draftState . selectedLogin === "undefined" || ! webAccounts . map ( ( { accountConfig : { login } } ) => login ) . includes ( draftState . selectedLogin ) ) { const webAccountToSelect = webAccounts . find ( ( webAccount ) => { return ( ! webAccount . loginDelayedUntilSelected && ! webAccount . loginDelayedSeconds ) ; } ) ; draftState . selectedLogin = webAccountToSelect && webAccountToSelect . accountConfig . login ; } webAccounts . forEach ( ( webAccount , index ) => webAccount . accountIndex = index ) ; draftState . accounts = webAccounts ; draftState . initialized = true ; } , Select ( { login } ) { draftState . selectedLogin = login ; } , DeSelect ( { login } ) { if ( draftState . selectedLogin === login ) { delete draftState . selectedLogin ; } } , PatchProgress ( { login , patch , optionalAccount } ) { logger . verbose ( "(PatchProgress)" , JSON . stringify ( { patch , optionalAccount } ) ) ; const account = resolveAccountByLogin ( draftState . accounts , { login } , ! optionalAccount ) ; if ( ! account ) { logger . verbose ( "(PatchProgress) reducing skipped" ) ; return ; } account . progress = { ... account . progress , ... patch } ; } , Patch ( { login , patch , optionalAccount } ) { logger . verbose ( "(Patch)" , JSON . stringify ( { patch , optionalAccount } ) ) ; const account = resolveAccountByLogin ( draftState . accounts , { login } , ! optionalAccount ) ; if ( ! account ) { logger . verbose ( "(Patch) reducing skipped" ) ; return ; } if ( "webviewSrcValues" in patch ) { account . webviewSrcValues = { ... account . webviewSrcValues , ... patch . webviewSrcValues } ; } if ( "notifications" in patch ) { account . notifications = { ... account . notifications , ... patch . notifications } ; if ( ! account . loggedInOnce && account . notifications . loggedIn ) { account . loggedInOnce = true ; } } if ( "syncingActivated" in patch ) { account . syncingActivated = patch . syncingActivated ; } if ( "loginFilledOnce" in patch ) { account . loginFilledOnce = patch . loginFilledOnce ; } if ( "loginDelayedSeconds" in patch ) { account . loginDelayedSeconds = patch . loginDelayedSeconds ; } if ( "loginDelayedUntilSelected" in patch ) { account . loginDelayedUntilSelected = patch . loginDelayedUntilSelected ; } } , PatchDbExportProgress ( { pk : { login } , uuid , progress } ) { const account = resolveAccountByLogin ( draftState . accounts , { login } , true ) ; const item = account . dbExportProgress . find ( ( _ ) => _ . uuid === uuid ) ; if ( typeof progress === "number" ) { if ( item ) { item . progress = progress ; } else { account . dbExportProgress . push ( { uuid , progress } ) ; } } else if ( item ) { account . dbExportProgress . splice ( account . dbExportProgress . indexOf ( item ) , 1 ) ; } } , ToggleDatabaseView ( { login , forced } ) { const account = resolveAccountByLogin ( draftState . accounts , { login } , true ) ; account . databaseView = forced ? forced . databaseView : ! account . databaseView ; } , PatchGlobalProgress ( { patch } ) { draftState . globalProgress = { ... draftState . globalProgress , ... patch } ; } , default : noop , } ) ; } ) ; }