From ac87fcf9c7d06b0302d8fe2ea6d99209c3805d25 Mon Sep 17 00:00:00 2001 From: leejh Date: Wed, 16 Oct 2019 14:52:31 +0900 Subject: [PATCH] =?UTF-8?q?=EC=B6=94=EA=B0=80=20::=20=EB=8C=80=ED=99=94?= =?UTF-8?q?=EB=B0=A9=20=EC=98=A4=ED=94=88=EC=8B=9C=20EVENT=5FREAD=5FREQ=20?= =?UTF-8?q?=EC=88=98=ED=96=89.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/app/store/messenger/event/actions.ts | 21 ++++- .../src/app/store/messenger/event/effects.ts | 79 ++++++++++++++++--- .../src/app/store/messenger/sync/actions.ts | 8 ++ .../src/app/store/messenger/sync/reducers.ts | 18 ++++- 4 files changed, 115 insertions(+), 11 deletions(-) diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/event/actions.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/event/actions.ts index 9edd9bc8..eab3cb8c 100644 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/event/actions.ts +++ b/projects/ucap-webmessenger-app/src/app/store/messenger/event/actions.ts @@ -8,7 +8,8 @@ import { SendNotification, ReadNotification, CancelNotification, - DelNotification + DelNotification, + ReadRequest } from '@ucap-webmessenger/protocol-event'; export const info = createAction( @@ -69,6 +70,24 @@ export const sendFailure = createAction( props<{ error: any }>() ); +export const read = createAction( + '[Messenger::Event] read', + props() +); + +export const readSuccess = createAction( + '[Messenger::Event] read Success', + props<{ + infoList: Info[]; + res: InfoResponse; + }>() +); + +export const readFailure = createAction( + '[Messenger::Event] read Failure', + props<{ error: any }>() +); + export const sendNotification = createAction( '[Messenger::Event] Send Notification', props<{ noti: SendNotification }>() diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/event/effects.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/event/effects.ts index e2151f30..a367fdfc 100644 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/event/effects.ts +++ b/projects/ucap-webmessenger-app/src/app/store/messenger/event/effects.ts @@ -22,7 +22,8 @@ import { EventProtocolService, SSVC_TYPE_EVENT_INFO_DATA, SSVC_TYPE_EVENT_INFO_RES, - SendResponse + SendResponse, + ReadResponse } from '@ucap-webmessenger/protocol-event'; import * as ChatStore from '@app/store/messenger/chat'; @@ -41,12 +42,15 @@ import { readNotification, cancelNotification, delNotification, - recallInfoList + recallInfoList, + read, + readFailure } from './actions'; import { SessionStorageService } from '@ucap-webmessenger/web-storage'; import { RoomInfo } from '@ucap-webmessenger/protocol-room'; import { refreshRoom } from '../sync'; import { LoginInfo, KEY_LOGIN_INFO } from '@app/types'; +import { Dictionary } from '@ngrx/entity'; @Injectable() export class Effects { @@ -80,12 +84,28 @@ export class Effects { infoList.push(...(res as InfoData).infoList); break; case SSVC_TYPE_EVENT_INFO_RES: - this.store.dispatch( - infoSuccess({ - infoList, - res: res as InfoResponse - }) - ); + { + this.store.dispatch( + infoSuccess({ + infoList, + res: res as InfoResponse + }) + ); + + if (req.baseSeq === 0) { + // 최초 이벤트 목록 조회시 SSVC_TYPE_EVENT_READ_REQ 수행. + const maxSeq = Math.max.apply( + Math, + infoList.map(v => v.seq) + ); + this.store.dispatch( + read({ + roomSeq: req.roomSeq, + lastReadSeq: Number(maxSeq) + }) + ); + } + } break; } }), @@ -97,6 +117,28 @@ export class Effects { { dispatch: false } ); + read$ = createEffect( + () => { + return this.actions$.pipe( + ofType(read), + switchMap(req => { + return this.eventProtocolService.read(req).pipe( + map((res: ReadResponse) => { + this.store.dispatch( + SyncStore.updateUnreadCount({ + roomSeq: res.roomSeq, + noReadCnt: 0 + }) + ); + }), + catchError(error => of(readFailure({ error }))) + ); + }) + ); + }, + { dispatch: false } + ); + send$ = createEffect(() => this.actions$.pipe( ofType(send), @@ -169,13 +211,32 @@ export class Effects { withLatestFrom( this.store.pipe( select((state: any) => state.messenger.room.roomInfo as RoomInfo) + ), + this.store.pipe( + select( + (state: any) => + state.messenger.sync.room.entities as Dictionary + ) ) ), - tap(([action, roomInfo]) => { + tap(([action, roomInfo, trgtRoomInfos]) => { + // opened room :: event add if (!!roomInfo && roomInfo.roomSeq === action.roomSeq) { this.store.dispatch(appendInfoList({ info: action.info })); } + // not opened room :: unread count increased + if (!roomInfo || roomInfo.roomSeq !== action.roomSeq) { + const noReadCnt = trgtRoomInfos[action.roomSeq].noReadCnt; + this.store.dispatch( + SyncStore.updateUnreadCount({ + roomSeq: action.roomSeq, + noReadCnt: noReadCnt + 1 + }) + ); + } + + // 대화 > 리스트 :: finalEventMessage refresh this.store.dispatch(ChatStore.newEventMessage(action)); }) ); diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/sync/actions.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/sync/actions.ts index e4de6b2f..62a94ced 100644 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/sync/actions.ts +++ b/projects/ucap-webmessenger-app/src/app/store/messenger/sync/actions.ts @@ -93,3 +93,11 @@ export const refreshRoomFailure = createAction( '[Messenger::Sync] refresh room in sync Failure', props<{ error: any }>() ); + +export const updateUnreadCount = createAction( + '[Messenger::Sync] Update unread count', + props<{ + roomSeq: string; + noReadCnt?: number; + }>() +); diff --git a/projects/ucap-webmessenger-app/src/app/store/messenger/sync/reducers.ts b/projects/ucap-webmessenger-app/src/app/store/messenger/sync/reducers.ts index af111f2e..85f00ebf 100644 --- a/projects/ucap-webmessenger-app/src/app/store/messenger/sync/reducers.ts +++ b/projects/ucap-webmessenger-app/src/app/store/messenger/sync/reducers.ts @@ -12,7 +12,8 @@ import { group2Success, roomSuccess, updateRoomForNewEventMessage, - refreshRoomSuccess + refreshRoomSuccess, + updateUnreadCount } from './actions'; import { RoomUserDetailData, @@ -145,6 +146,21 @@ export const reducer = createReducer( }; }), + on(updateUnreadCount, (state, action) => { + const roomInfo: RoomInfo = { + ...state.room.entities[action.roomSeq], + noReadCnt: action.noReadCnt + }; + + return { + ...state, + room: adapterRoom.updateOne( + { id: action.roomSeq, changes: roomInfo }, + { ...state.room } + ) + }; + }), + on(AuthenticationStore.logout, (state, action) => { return { ...initialState