import { Injectable } from '@angular/core' ; import { Effect , Actions , ofType , createEffect } from '@ngrx/effects' ; import { ActionWithPayload , UserActions } from '../actions' ; import { User , RouterStateUrl , Game , Friends , Friend , Invitation , Account } from '../../../shared/model' ; import { UserService , GameService , Utils } from '../../services' ; import { switchMap , map , distinct , mergeMap , filter , take , debounceTime , distinctUntilChanged , catchError } from 'rxjs/operators' ; import { empty , of , asyncScheduler } from 'rxjs' ; import { Store , select } from '@ngrx/store' ; import { coreState , CoreState } from '../reducers' ; import { ROUTER_NAVIGATION } from '@ngrx/router-store' ; @ Injectable ( ) export class UserEffects { @ Effect ( ) loadUserProfile$ = this . actions$ . pipe ( ofType ( UserActions . LOGIN_SUCCESS ) ) . pipe ( map ( ( action ) => action . payload ) , switchMap ( ( user ) => { if ( user ) { return this . svc . loadUserProfile ( user ) . pipe ( catchError ( ( error ) => { return of ( ) ; } ) ) ; } else { return of ( ) ; } } ) , mergeMap ( ( user ) => this . utils . setLoginFirebaseAnalyticsParameter ( user ) . pipe ( catchError ( ( error ) => { return of ( ) ; } ) ) ) , map ( ( user ) => this . userActions . addUserWithRoles ( user ) ) , catchError ( ( error ) => { this . userActions . logoff ( ) ; return of ( ) ; } ) ) ; @ Effect ( ) loadUserAccounts$ = this . actions$ . pipe ( ofType ( UserActions . LOGIN_SUCCESS ) ) . pipe ( map ( ( action ) => action . payload ) , switchMap ( ( account ) => this . svc . loadAccounts ( account ) . pipe ( catchError ( ( error ) => { return empty ( ) ; } ) ) ) , map ( ( account ) => this . userActions . loadAccountsSuccess ( account ) ) ) ; @ Effect ( ) loadOtherUserProfile$ = this . actions$ . pipe ( ofType ( UserActions . LOAD_OTHER_USER_PROFILE ) ) . pipe ( map ( ( action ) => action . payload ) , distinct ( null , this . store . select ( coreState ) . pipe ( select ( s => s . user ) ) ) , mergeMap ( ( userId ) => this . svc . loadOtherUserProfile ( userId ) ) , mergeMap ( ( user ) => this . svc . getUserStatus ( user ) ) , map ( ( user ) => this . userActions . loadOtherUserProfileSuccess ( user ) ) , catchError ( ( error ) => { this . userActions . logoff ( ) ; return empty ( ) ; } ) ) ; @ Effect ( ) loadOtherUserExtendedInfo$ = this . actions$ . pipe ( ofType ( UserActions . LOAD_OTHER_USER_EXTEDED_INFO ) ) . pipe ( map ( ( action ) => action . payload ) , distinct ( null , this . store . select ( coreState ) . pipe ( select ( s => s . user ) ) ) , mergeMap ( ( userId ) => this . svc . loadOtherUserProfileWithExtendedInfo ( userId ) ) , mergeMap ( ( user ) => this . svc . getUserStatus ( user ) ) , map ( ( user ) => this . userActions . loadOtherUserProfileWithExtendedInfoSuccess ( user ) ) ) ; @ Effect ( ) loadUserInvitationsInfo$ = this . actions$ . pipe ( ofType ( UserActions . LOAD_USER_INVITATIONS_INFO ) ) . pipe ( map ( ( action ) => action . payload ) , distinct ( ) , mergeMap ( ( data ) => this . svc . loadUserInvitationsInfo ( data . userId , data . invitedUserEmail , data . invitedUserId ) ) , map ( ( invitation ) => this . userActions . loadUserInvitationsInfoSuccess ( invitation ) ) ) ; @ Effect ( ) UpdateUser$ = this . actions$ . pipe ( ofType ( UserActions . UPDATE_USER ) ) . pipe ( switchMap ( ( action ) => this . svc . updateUser ( action . payload . user ) . pipe ( map ( ( status ) => this . userActions . updateUserSuccess ( action . payload . status ) ) ) ) ) ; @ Effect ( ) loadGameInvites$ = this . actions$ . pipe ( ofType ( UserActions . LOAD_GAME_INVITES ) ) . pipe ( switchMap ( ( action ) => this . svc . getGameInvites ( action . payload ) . pipe ( map ( ( games ) => this . userActions . loadGameInvitesSuccess ( games ) ) ) ) ) ; @ Effect ( ) rejectGameInvitation$ = this . actions$ . pipe ( ofType ( UserActions . REJECT_GAME_INVITATION ) ) . pipe ( switchMap ( ( action ) => this . svc . rejectGameInvitation ( action . payload ) . pipe ( map ( ( msg ) => this . userActions . updateGameSuccess ( ) ) ) ) ) ; @ Effect ( ) LoadUserFriends$ = this . actions$ . pipe ( ofType ( UserActions . LOAD_USER_FRIENDS ) ) . pipe ( switchMap ( ( action ) => this . svc . loadUserFriends ( action . payload ) . pipe ( map ( ( friends ) => { const friendList = [ ] ; if ( friends && friends . myFriends ) { friends . myFriends . map ( ( friend , index ) => { friendList . push ( Object . keys ( friend ) [ 0 ] ) ; } ) ; } return friendList ; } ) , switchMap ( ( friendsList ) => this . svc . getOtherUserGamePlayedStat ( action . payload , friendsList ) . pipe ( map ( ( friends ) => this . userActions . loadUserFriendsSuccess ( friends ) ) ) ) ) ) ) ; @ Effect ( ) loadFriendInvitations$ = this . actions$ . pipe ( ofType ( ROUTER_NAVIGATION ) ) . pipe ( map ( ( action ) : RouterStateUrl => action . payload . routerState ) , filter ( ( routerState ) => routerState . url . toLowerCase ( ) . startsWith ( '/dashboard' ) ) , mergeMap ( ( routerState ) => this . store . select ( coreState ) . pipe ( map ( s => s . user ) , filter ( u => ! ! u ) , take ( 1 ) , map ( user => user . email || user . authState . phoneNumber ) ) ) ) . pipe ( switchMap ( ( email ) => { return this . svc . loadFriendInvitations ( email ) . pipe ( map ( ( invitations ) => this . userActions . loadUserInvitationsSuccess ( invitations ) ) ) ; } ) ) ; @ Effect ( ) UpdateInvitation$ = this . actions$ . pipe ( ofType ( UserActions . UPDATE_INVITATION ) ) . pipe ( switchMap ( ( action ) => { return this . svc . setInvitation ( action . payload ) . pipe ( map ( ( ) => this . userActions . updateInvitationSuccess ( ) ) ) ; } ) ) ; @ Effect ( ) makeFriend$ = this . actions$ . pipe ( ofType ( UserActions . MAKE_FRIEND ) ) . pipe ( switchMap ( ( action ) => this . svc . checkInvitationToken ( action . payload ) . pipe ( map ( ( friend ) => this . userActions . storeInvitationToken ( 'NONE' ) ) ) . pipe ( map ( ( ) => this . userActions . makeFriendSuccess ( ) ) ) ) ) ; @ Effect ( ) saveInvitation$ = this . actions$ . pipe ( ofType ( UserActions . ADD_USER_INVITATION ) ) . pipe ( switchMap ( ( action ) => this . svc . saveUserInvitations ( action . payload ) . pipe ( map ( ( statusMessages ) => this . userActions . addUserInvitationSuccess ( statusMessages [ 'messages' ] ) ) ) ) ) ; @ Effect ( ) addUser$ = this . actions$ . pipe ( ofType ( UserActions . ADD_USER_PROFILE ) ) . pipe ( switchMap ( ( action ) => { return this . svc . saveUserProfile ( action . payload . user ) . pipe ( mergeMap ( ( status ) => this . utils . setUserLocationFirebaseAnalyticsParameter ( action . payload . user , action . payload . isLocationChanged ) ) , map ( ( ) => this . userActions . addUserProfileSuccess ( ) ) ) ; } ) ) ; @ Effect ( ) addFeedback$ = this . actions$ . pipe ( ofType ( UserActions . ADD_FEEDBACK ) ) . pipe ( map ( ( action ) => action . payload ) , switchMap ( ( feedback ) => this . svc . addFeedback ( feedback ) ) , map ( ( res ) => this . userActions . addFeedbackSuccess ( ) ) ) ; @ Effect ( ) getCountries$ = this . actions$ . pipe ( ofType ( UserActions . GET_COUNTRIES ) ) . pipe ( switchMap ( ( ) => { return this . svc . getCountries ( ) . pipe ( map ( ( countries ) => { return this . userActions . loadCountriesSuccess ( countries ) ; } ) ) ; } ) ) ; @ Effect ( ) AddUserLives$ = this . actions$ . pipe ( ofType ( UserActions . ADD_USER_LIVES ) ) . pipe ( switchMap ( ( action ) => { return this . svc . addUserLives ( action . payload ) . pipe ( map ( ( ) => this . userActions . addUserLivesSuccess ( ) ) ) ; } ) ) ; @ Effect ( ) GetGameResult$ = this . actions$ . pipe ( ofType ( UserActions . GET_GAME_RESULT ) ) . pipe ( switchMap ( ( action ) => this . gameService . getGameResult ( action . payload ) . pipe ( map ( ( games ) => this . userActions . getGameResultSuccess ( games ) ) ) ) ) ; @ Effect ( ) loadAddressUsingLatLong = this . actions$ . pipe ( ofType ( UserActions . LOAD_ADDRESS_USING_LAT_LONG ) ) . pipe ( switchMap ( ( action ) => this . svc . getAddressByLatLang ( action . payload ) . pipe ( map ( ( result ) => this . userActions . loadAddressUsingLatLongSuccess ( result ) ) ) ) ) ; @ Effect ( ) loadAddressSuggestions = createEffect ( ( ) => ( { debounce = 2000 , scheduler = asyncScheduler } = { } ) => this . actions$ . pipe ( ofType ( UserActions . LOAD_ADDRESS_SUGGESTIONS ) ) . pipe ( debounceTime ( debounce , scheduler ) , distinctUntilChanged ( ) , switchMap ( ( action ) => this . svc . getAddressSuggestions ( action . payload ) . pipe ( map ( ( result ) => this . userActions . loadAddressSuggestionsSuccess ( result ) ) ) ) ) ) ; @ Effect ( ) checkDisplayName$ = this . actions$ . pipe ( ofType ( UserActions . CHECK_DISPLAY_NAME ) ) . pipe ( switchMap ( ( action ) => this . svc . checkDisplayName ( action . payload ) . pipe ( map ( ( result ) => this . userActions . checkDisplayNameSuccess ( result ) ) ) ) ) ; @ Effect ( ) setFirstQuestionBits = this . actions$ . pipe ( ofType ( UserActions . SET_FIRST_QUESTION_BITS ) ) . pipe ( switchMap ( ( action ) => this . svc . firstQuestionSetBits ( action . payload ) . pipe ( map ( ( result ) => this . userActions . setFirstQuestionBitsSuccess ( result ) ) ) ) ) ; constructor ( private actions$ , private userActions , private gameService , private svc , private store , private utils ) { } }