531 lines
15 KiB
TypeScript
531 lines
15 KiB
TypeScript
|
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 {
|
||
|
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, LoginSelector } from '@ucap/ng-store-authentication';
|
||
|
import * as ChattingAction from '../Chatting/actions';
|
||
|
import { RoomSelector, ChattingSelector } from '../state';
|
||
|
|
||
|
import {
|
||
|
rooms,
|
||
|
room,
|
||
|
roomFailure,
|
||
|
inviteNotification,
|
||
|
exitNotification,
|
||
|
excludeUser,
|
||
|
excludeUserSuccess,
|
||
|
close,
|
||
|
delSuccess,
|
||
|
create,
|
||
|
createSuccess,
|
||
|
createFailure,
|
||
|
createTimer,
|
||
|
createTimerSuccess,
|
||
|
createTimerFailure,
|
||
|
del,
|
||
|
delFailure,
|
||
|
update,
|
||
|
updateSuccess,
|
||
|
updateFailure,
|
||
|
open,
|
||
|
openSuccess,
|
||
|
closeSuccess,
|
||
|
invite,
|
||
|
inviteSuccess,
|
||
|
inviteFailure,
|
||
|
expel,
|
||
|
expelSuccess,
|
||
|
expelFailure,
|
||
|
updateTimeRoomInterval,
|
||
|
updateTimeRoomIntervalSuccess,
|
||
|
updateTimeRoomIntervalFailure,
|
||
|
rooms2Success,
|
||
|
rooms2Failure,
|
||
|
delMulti,
|
||
|
delMultiSuccess,
|
||
|
delMultiFailure,
|
||
|
selectedRoom,
|
||
|
room2Success,
|
||
|
selectedRoomSuccess,
|
||
|
clearSelectedRoom
|
||
|
} from './actions';
|
||
|
import { LocaleCode } from '@ucap/core';
|
||
|
import { PresenceActions } from '@ucap/ng-store-organization';
|
||
|
import { I18nService } from '@ucap/ng-i18n';
|
||
|
|
||
|
@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.roomProtocolService
|
||
|
.info2(req)
|
||
|
.pipe(
|
||
|
map((res) => {
|
||
|
let isJoinRoom = true;
|
||
|
if (!res.roomInfo || !res.roomInfo.isJoinRoom) {
|
||
|
isJoinRoom = false;
|
||
|
}
|
||
|
|
||
|
if (!!isJoinRoom) {
|
||
|
this.store.dispatch(
|
||
|
selectedRoomSuccess({
|
||
|
roomId: req.roomId,
|
||
|
roomInfo2Res: res
|
||
|
})
|
||
|
);
|
||
|
|
||
|
// Buddy Presence
|
||
|
const targetUserInfos = req.isDetail
|
||
|
? res.roomUserInfo.userInfoList.map(
|
||
|
(userInfo) => userInfo.seq + ''
|
||
|
)
|
||
|
: res.roomUserInfo.userInfoShortList.map(
|
||
|
(userInfo) => userInfo.seq + ''
|
||
|
);
|
||
|
if (!!targetUserInfos && targetUserInfos.length > 0) {
|
||
|
this.store.dispatch(
|
||
|
PresenceActions.bulkInfo({
|
||
|
divCd: 'roomBulk',
|
||
|
userSeqs: targetUserInfos
|
||
|
})
|
||
|
);
|
||
|
}
|
||
|
} else {
|
||
|
// is not join room. so, redirect chat main.
|
||
|
this.store.dispatch(
|
||
|
clearSelectedRoom({ roomId: req.roomId })
|
||
|
);
|
||
|
}
|
||
|
}),
|
||
|
catchError((error) => of(roomFailure({ error })))
|
||
|
)
|
||
|
.subscribe();
|
||
|
|
||
|
// retrieve event info >> chatting.effect.selectedRoom$
|
||
|
})
|
||
|
);
|
||
|
},
|
||
|
{ dispatch: false }
|
||
|
);
|
||
|
|
||
|
selectedRoomSuccess$ = createEffect(
|
||
|
() => {
|
||
|
return this.actions$.pipe(
|
||
|
ofType(selectedRoomSuccess),
|
||
|
tap((action) => {
|
||
|
// room info success reduce.
|
||
|
this.store.dispatch(
|
||
|
room2Success({
|
||
|
roomInfo: action.roomInfo2Res.roomInfo,
|
||
|
roomUserInfo: action.roomInfo2Res.roomUserInfo
|
||
|
})
|
||
|
);
|
||
|
})
|
||
|
);
|
||
|
},
|
||
|
{ 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) => {
|
||
|
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) => [
|
||
|
// clear activeRoomId
|
||
|
clearSelectedRoom({ roomId: res.roomId }),
|
||
|
// close room, clear chatting
|
||
|
close({ roomIds: [res.roomId] }),
|
||
|
// clear room in rooms.
|
||
|
delSuccess({ res })
|
||
|
]),
|
||
|
catchError((error) => of(delFailure({ error })))
|
||
|
);
|
||
|
})
|
||
|
)
|
||
|
);
|
||
|
|
||
|
delMulti$ = createEffect(() =>
|
||
|
this.actions$.pipe(
|
||
|
ofType(delMulti),
|
||
|
map((action) => action.req),
|
||
|
withLatestFrom(this.store.pipe(select(ChattingSelector.activeRoomId))),
|
||
|
exhaustMap(([req, activeRoomId]) => {
|
||
|
const existActiveRoomId = req.roomIds.find(
|
||
|
(roomId) => roomId === activeRoomId
|
||
|
);
|
||
|
|
||
|
return this.roomProtocolService.exitAll(req).pipe(
|
||
|
switchMap((res: DeleteMultiResponse) => {
|
||
|
if (!!existActiveRoomId) {
|
||
|
return [
|
||
|
// clear selected room
|
||
|
clearSelectedRoom({ roomId: existActiveRoomId }),
|
||
|
// close room, clear chatting
|
||
|
close({ roomIds: res.roomIds }),
|
||
|
// clear room in rooms.
|
||
|
delMultiSuccess({ res })
|
||
|
];
|
||
|
} else {
|
||
|
return [
|
||
|
// close room, clear chatting
|
||
|
close({ roomIds: res.roomIds }),
|
||
|
// clear room in rooms.
|
||
|
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] }))
|
||
|
);
|
||
|
});
|
||
|
|
||
|
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 })))
|
||
|
);
|
||
|
})
|
||
|
)
|
||
|
);
|
||
|
|
||
|
/**
|
||
|
* @discription Call by notifications case in SSVC_TYPE_ROOM_INVITE_RES, SSVC_TYPE_ROOM_INVITE_NOTI
|
||
|
* 1. roomlist 를 체크하여 없을경우 내가 초대된 경우라 간주하고 방 조회하여 갱신하지 않도록 한다.(첫 대화가 들어오면 그때 조회.)
|
||
|
* 2. roomlist 를 체크하여 있을 경우 기존방에 다른 인원이 추가되었을 경우이므로 방 조회하여 갱신한다.
|
||
|
*/
|
||
|
inviteNotification$ = createEffect(
|
||
|
() => {
|
||
|
return this.actions$.pipe(
|
||
|
ofType(inviteNotification),
|
||
|
withLatestFrom(this.store.pipe(select(RoomSelector.rooms))),
|
||
|
map(([action, roomList]) => {
|
||
|
const roomId = action.noti.roomId;
|
||
|
if (!!roomList && roomList.length > 0) {
|
||
|
if (roomList.some((roomInfo) => roomId === roomInfo.roomId)) {
|
||
|
this.store.dispatch(
|
||
|
room({
|
||
|
req: {
|
||
|
roomId,
|
||
|
isDetail: true,
|
||
|
localeCode: action.localeCode
|
||
|
}
|
||
|
})
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
})
|
||
|
);
|
||
|
},
|
||
|
{
|
||
|
dispatch: false
|
||
|
}
|
||
|
);
|
||
|
|
||
|
exitNotification$ = createEffect(() => {
|
||
|
return this.actions$.pipe(
|
||
|
ofType(exitNotification),
|
||
|
withLatestFrom(this.store.pipe(select(LoginSelector.loginRes))),
|
||
|
switchMap(([action, loginRes]) => {
|
||
|
if (loginRes.userSeq + '' === action.senderSeq + '') {
|
||
|
return [
|
||
|
close({ roomIds: [action.roomId] }),
|
||
|
clearSelectedRoom({ roomId: 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(ChattingAction.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: this.i18nService.currentLng.toUpperCase() as LocaleCode
|
||
|
})
|
||
|
);
|
||
|
}
|
||
|
})
|
||
|
);
|
||
|
},
|
||
|
{ dispatch: false }
|
||
|
);
|
||
|
|
||
|
constructor(
|
||
|
private actions$: Actions,
|
||
|
private store: Store<any>,
|
||
|
private syncProtocolService: SyncProtocolService,
|
||
|
private roomProtocolService: RoomProtocolService,
|
||
|
private i18nService: I18nService
|
||
|
) {}
|
||
|
}
|