import { of } from 'rxjs'; import { catchError, map, switchMap, exhaustMap, withLatestFrom, tap, debounceTime } from 'rxjs/operators'; import { Injectable } from '@angular/core'; import { Store, select } from '@ngrx/store'; import { Actions, ofType, createEffect } from '@ngrx/effects'; import { RoomType, OpenResponse as CreateResponse, Open3Response as CreateTimerResponse, ExitResponse as DeleteResponse, ExitAllResponse as DeleteMultiResponse, UpdateResponse, InviteResponse, ExitForcingResponse, UpdateTimerSetResponse, InfoRequest } from '@ucap/protocol-room'; import { RoomProtocolService } from '@ucap/ng-protocol-room'; import { SyncProtocolService } from '@ucap/ng-protocol-sync'; import { LoginActions } from '@ucap/ng-store-authentication'; import { addEventSuccess } from '../Chatting/actions'; import { RoomSelector } from '../state'; import { rooms, roomsFailure, roomsSuccess, room, roomSuccess, roomFailure, inviteNotification, exitNotification, excludeUser, excludeUserSuccess, close, delSuccess, create, createSuccess, createFailure, createTimer, createTimerSuccess, createTimerFailure, del, delFailure, update, updateSuccess, updateFailure, open, openSuccess, closeSuccess, inviteOrCreate, invite, inviteSuccess, inviteFailure, expel, expelSuccess, expelFailure, updateTimeRoomInterval, updateTimeRoomIntervalSuccess, updateTimeRoomIntervalFailure, rooms2Success, rooms2Failure, delMulti, delMultiSuccess, delMultiFailure, selectedRoom, room2Success } from './actions'; import { Router } from '@angular/router'; import { LocaleCode } from '@ucap/core'; @Injectable() export class Effects { sessionCreatedForRooms$ = createEffect(() => { return this.actions$.pipe( ofType(LoginActions.sessionCreated), map((action) => rooms({ localeCode: action.loginSession.localeCode })) ); }); selectedRoom$ = createEffect( () => { return this.actions$.pipe( ofType(selectedRoom), debounceTime(300), tap((action) => { const req: InfoRequest = { ...action, isDetail: false }; // retrieve room info this.store.dispatch(room({ req })); // retrieve event info >> chatting.effect.selectedRoom$ }) ); }, { dispatch: false } ); rooms$ = createEffect(() => { return this.actions$.pipe( ofType(rooms), withLatestFrom(this.store.pipe(select(RoomSelector.roomsSyncDate))), switchMap(([action, syncDate]) => { // // CASE :: RoomUser Data 중 Detail data 만 수집. // return this.syncProtocolService // .room({ syncDate, localeCode: action.localeCode }) // .pipe( // map((res) => { // return roomsSuccess({ // roomList: res.roomList, // roomUserInfoMap: res.roomUserInfoMap, // syncDate: res.res.syncDate // }); // }), // catchError((error) => of(roomsFailure({ error }))) // ); // CASE :: RoomUser Data 중 Detail data, Short data 수집. return this.syncProtocolService .room2({ syncDate, localeCode: action.localeCode }) .pipe( map((res) => { return rooms2Success({ roomList: res.roomList, roomUserInfoMap: res.roomUserInfoMap, syncDate: res.res.syncDate }); }), catchError((error) => of(rooms2Failure({ error }))) ); }) ); }); room$ = createEffect(() => { return this.actions$.pipe( ofType(room), switchMap((action) => { const req = action.req; // // CASE :: RoomUser Data 중 Detail data 만 수집. // return this.roomProtocolService.info(req).pipe( // map((res) => // roomSuccess({ // roomInfo: res.roomInfo, // userInfoList: res.userInfoList // }) // ), // catchError((error) => of(roomFailure({ error }))) // ); // CASE :: RoomUser Data 중 Detail data, Short data 수집. return this.roomProtocolService.info2(req).pipe( map((res) => room2Success({ roomInfo: res.roomInfo, roomUserInfo: res.roomUserInfo }) ), catchError((error) => of(roomFailure({ error }))) ); }) ); }); create$ = createEffect( () => { return this.actions$.pipe( ofType(create), map((action) => action.req), exhaustMap((req) => { return this.roomProtocolService.open(req).pipe( map((res: CreateResponse) => { console.log('CreateResponse', res); this.store.dispatch(createSuccess({ res })); this.router.navigate( [ 'chat', { outlets: { content: 'chatroom' } } ], { queryParams: { roomId: res.roomId } } ); // if (!res.newRoom) { // } else { // } }), catchError((error) => of(createFailure({ error }))) ); }) ); }, { dispatch: false } ); createTimer$ = createEffect(() => this.actions$.pipe( ofType(createTimer), map((action) => action.req), exhaustMap((req) => { return this.roomProtocolService.open3(req).pipe( map((res: CreateTimerResponse) => { return createTimerSuccess({ res }); }), catchError((error) => of(createTimerFailure({ error }))) ); }) ) ); del$ = createEffect(() => this.actions$.pipe( ofType(del), map((action) => action.req), exhaustMap((req) => { return this.roomProtocolService.exit(req).pipe( switchMap((res: DeleteResponse) => [ close({ roomIds: [res.roomId] }), delSuccess({ res }) ]), catchError((error) => of(delFailure({ error }))) ); }) ) ); delMulti$ = createEffect(() => this.actions$.pipe( ofType(delMulti), map((action) => action.req), exhaustMap((req) => { return this.roomProtocolService.exitAll(req).pipe( switchMap((res: DeleteMultiResponse) => [ close({ roomIds: res.roomIds }), delMultiSuccess({ res }) ]), catchError((error) => of(delMultiFailure({ error }))) ); }) ) ); update$ = createEffect(() => this.actions$.pipe( ofType(update), map((action) => action.req), exhaustMap((req) => { return this.roomProtocolService.update(req).pipe( map((res: UpdateResponse) => { return updateSuccess({ res }); }), catchError((error) => of(updateFailure({ error }))) ); }) ) ); excludeUser$ = createEffect(() => { return this.actions$.pipe( ofType(excludeUser), map((action) => excludeUserSuccess({ roomId: action.roomId, userSeqs: action.userSeqs }) ) ); }); open$ = createEffect(() => { return this.actions$.pipe( ofType(open), map((action) => openSuccess({ roomIds: [...action.roomIds] })) ); }); close$ = createEffect(() => { return this.actions$.pipe( ofType(close), map((action) => closeSuccess({ roomIds: [...action.roomIds] })) ); }); inviteOrCreate$ = createEffect(() => this.actions$.pipe( ofType(inviteOrCreate), map((action) => { const roomInfo = action.roomInfo; const localeCode = action.localeCode; switch (roomInfo.roomType) { case RoomType.Single: return create({ req: action.req }); case RoomType.Multi: return invite({ req: { roomId: roomInfo.roomId, inviteUserSeqs: [...action.req.userSeqs] }, localeCode }); default: return inviteFailure({ error: `type[${roomInfo.roomType}] of room is not valid` }); } }) ) ); invite$ = createEffect(() => this.actions$.pipe( ofType(invite), exhaustMap((action) => { const req = action.req; const localeCode = action.localeCode; return this.roomProtocolService.invite(req).pipe( switchMap((res: InviteResponse) => { return [ inviteSuccess({ res }), room({ req: { roomId: req.roomId, isDetail: true, localeCode } }) ]; }), catchError((error) => of(inviteFailure({ error }))) ); }) ) ); expel$ = createEffect(() => this.actions$.pipe( ofType(expel), map((action) => action.req), exhaustMap((req) => { return this.roomProtocolService.exitForcing(req).pipe( map((res: ExitForcingResponse) => { return expelSuccess({ res }); }), catchError((error) => of(expelFailure({ error }))) ); }) ) ); updateTimeRoomInterval$ = createEffect(() => this.actions$.pipe( ofType(updateTimeRoomInterval), map((action) => action.req), exhaustMap((req) => { return this.roomProtocolService.updateTimerSet(req).pipe( map((res: UpdateTimerSetResponse) => { return updateTimeRoomIntervalSuccess({ res }); }), catchError((error) => of(updateTimeRoomIntervalFailure({ error }))) ); }) ) ); inviteNotification$ = createEffect(() => { return this.actions$.pipe( ofType(inviteNotification), map((action) => room({ req: { roomId: action.noti.roomId, isDetail: true, localeCode: action.localeCode } }) ) ); }); exitNotification$ = createEffect(() => { return this.actions$.pipe( ofType(exitNotification), switchMap((action) => { if (action.userSeq === action.senderSeq) { return [ close({ roomIds: [action.roomId] }), delSuccess({ res: { roomId: action.roomId } }) ]; } else { return [ excludeUser({ roomId: action.roomId, userSeqs: [action.senderSeq] }) ]; } }) ); }); /******************************************************************* * [Chatting Action watching.] *******************************************************************/ addEventSuccess$ = createEffect( () => { return this.actions$.pipe( ofType(addEventSuccess), withLatestFrom(this.store.pipe(select(RoomSelector.rooms))), map(([action, roomList]) => { const roomId = action.roomId; if (!roomList.find((roomInfo) => roomInfo.roomId === roomId)) { this.store.dispatch(rooms({ localeCode: LocaleCode.Korean })); } }) ); }, { dispatch: false } ); constructor( private actions$: Actions, private store: Store, private router: Router, private syncProtocolService: SyncProtocolService, private roomProtocolService: RoomProtocolService ) {} }