import { delGroupSuccess, buddy2 } from './../store/messenger/sync/actions'; import { Injectable, Inject } from '@angular/core'; import { tap, withLatestFrom, take } from 'rxjs/operators'; import { Store, select } from '@ngrx/store'; import { SSVC_TYPE_LOGOUT_RES, SSVC_TYPE_LOGOUT_REMOTE_NOTI, AuthenticationProtocolService, LogoutResponse, LogoutRemoteNotification, LogoutNotification, LoginResponse } from '@ucap-webmessenger/protocol-authentication'; import { NGXLogger } from 'ngx-logger'; import { EventProtocolService, SSVC_TYPE_EVENT_SEND_NOTI, SendNotification, SSVC_TYPE_EVENT_READ_NOTI, SSVC_TYPE_EVENT_CANCEL_NOTI, SSVC_TYPE_EVENT_DEL_RES, SSVC_TYPE_EVENT_SEND_RES, SSVC_TYPE_EVENT_READ_RES, EventType } from '@ucap-webmessenger/protocol-event'; import { InfoProtocolService, SSVC_TYPE_INFO_USER_NOTI, SSVC_TYPE_INFO_USER_RES, UserNotification } from '@ucap-webmessenger/protocol-info'; import { RoomProtocolService, SSVC_TYPE_ROOM_INVITE_NOTI, SSVC_TYPE_ROOM_EXIT_NOTI, SSVC_TYPE_ROOM_EXIT_FORCING_NOTI, SSVC_TYPE_ROOM_FONT_UPD_NOTI, InviteNotification, UpdateNotification as RoomUpdateNotification, SSVC_TYPE_ROOM_UPD_RES, SSVC_TYPE_ROOM_EXIT_FORCING_RES, SSVC_TYPE_ROOM_EXIT_RES, SSVC_TYPE_ROOM_INVITE_RES, ExitForcingResponse, RoomInfo, UserInfo, UserInfoShort } from '@ucap-webmessenger/protocol-room'; import { StatusProtocolService, SSVC_TYPE_STATUS_NOTI, StatusNotification } from '@ucap-webmessenger/protocol-status'; import { ReadNotification, CancelNotification, DelNotification } from '@ucap-webmessenger/protocol-event'; import { ExitNotification, ExitForcingNotification, UpdateFontNotification } from '@ucap-webmessenger/protocol-room'; import { GroupProtocolService, SSVC_TYPE_GROUP_UPD_RES2, UpdateNotification as GroupUpdateNotification, SSVC_TYPE_GROUP_ADD_RES, AddNotification as GroupAddNotification, SSVC_TYPE_GROUP_DEL_RES, DelNotification as GroupDelNotification } from '@ucap-webmessenger/protocol-group'; import { BuddyProtocolService, SSVC_TYPE_BUDDY_UPD_RES, UpdateNotification as BuddyUpdateNotification, SSVC_TYPE_BUDDY_ADD_RES, AddNotification as BuddyAddNotification, SSVC_TYPE_BUDDY_DEL_RES, DelNotification as BuddyDelNotification } from '@ucap-webmessenger/protocol-buddy'; import { SyncProtocolService, PhoneBookSyncType, SSVC_TYPE_SYNC_PHONEBOOK_READY_NOTI, SSVC_TYPE_SYNC_PHONEBOOK_SND_NOTI, PhoneBookSndNotification, RoomUserData } from '@ucap-webmessenger/protocol-sync'; import * as AppStore from '@app/store'; import * as AuthenticationStore from '@app/store/account/authentication'; import * as InfoStore from '@app/store/account/info'; import * as EventStore from '@app/store/messenger/event'; import * as SyncStore from '@app/store/messenger/sync'; import * as RoomStore from '@app/store/messenger/room'; import * as StatusStore from '@app/store/messenger/status'; import { NotificationRequest, NativeService, UCAP_NATIVE_SERVICE, NotificationType, WindowState } from '@ucap-webmessenger/native'; import { StringUtil, DialogService } from '@ucap-webmessenger/ui'; import { LocalStorageService, SessionStorageService } from '@ucap-webmessenger/web-storage'; import { AppUserInfo, KEY_APP_USER_INFO } from '@app/types/app-user-info.type'; import { environment } from '../../environments/environment'; import { NotificationMethod } from '@ucap-webmessenger/core'; import { Dictionary } from '@ngrx/entity'; import { MessageType } from '@ucap-webmessenger/api-message'; import { LogoutInfo, KEY_LOGOUT_INFO } from '@app/types'; import { TranslateService } from '@ngx-translate/core'; import { deleteMessageSuccess } from '@app/store/messenger/message'; import { ServerErrorCode } from '@ucap-webmessenger/protocol'; import { OptionProtocolService, SSVC_TYPE_OPTION_REG_UPD_RES, RegUpdateResponse, RegUpdateNotification } from '@ucap-webmessenger/protocol-option'; import { GeneralSetting, Settings, NotificationSetting, ChatSetting } from '@ucap-webmessenger/ui-settings'; import clone from 'clone'; @Injectable() export class AppNotificationService { constructor( private authenticationProtocolService: AuthenticationProtocolService, private eventProtocolService: EventProtocolService, private infoProtocolService: InfoProtocolService, private roomProtocolService: RoomProtocolService, private groupProtocolService: GroupProtocolService, private buddyProtocolService: BuddyProtocolService, private statusProtocolService: StatusProtocolService, private translateService: TranslateService, private syncProtocolService: SyncProtocolService, private optionProtocolService: OptionProtocolService, // 쪽지 비활성화 2020-0226 // private umgProtocolService: UmgProtocolService, private localStorageService: LocalStorageService, private sessionStorageService: SessionStorageService, @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService, private dialogService: DialogService, private store: Store, private logger: NGXLogger ) {} public subscribe(): void { this.authenticationProtocolService.logoutNotification$ .pipe( tap(notiOrRes => { switch (notiOrRes.SSVC_TYPE) { case SSVC_TYPE_LOGOUT_RES: { const res = notiOrRes as LogoutNotification; this.logger.debug( 'Notification::authenticationProtocolService::LogoutResponse', res ); this.sessionStorageService.set(KEY_LOGOUT_INFO, { personLogout: true, reasonCode: res.reasonCode, ip: res.ip, mac: res.mac } as LogoutInfo); } break; case SSVC_TYPE_LOGOUT_REMOTE_NOTI: { const noti = notiOrRes as LogoutRemoteNotification; this.logger.debug( 'Notification::authenticationProtocolService::LogoutRemoteNotification', noti ); this.sessionStorageService.set(KEY_LOGOUT_INFO, { personLogout: true, reasonCode: ServerErrorCode.ERRCD_FORCE_INIT, forceType: noti.requestDeviceType } as LogoutInfo); } break; default: break; } this.dialogService.closeAll(); this.store.dispatch(AuthenticationStore.loginRedirect()); }) ) .subscribe(); this.eventProtocolService.notification$ .pipe( 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 ) ), this.store.pipe( select( (state: any) => state.messenger.sync.roomUserShort.entities as Dictionary< RoomUserData > ) ) ), tap(([notiOrRes, curRoomInfo, roomList, roomUserShorts]) => { switch (notiOrRes.SSVC_TYPE) { case SSVC_TYPE_EVENT_SEND_RES: case SSVC_TYPE_EVENT_SEND_NOTI: { const noti = notiOrRes as SendNotification; this.logger.debug( 'Notification::eventProtocolService::SendNotification', noti ); this.store.dispatch( EventStore.sendNotification({ noti }) ); // notification.. if (notiOrRes.SSVC_TYPE === SSVC_TYPE_EVENT_SEND_NOTI) { let doNoti = true; // 방별 알림이 꺼져 있으면 노티 안함. if ( !!roomList[noti.roomSeq] && !roomList[noti.roomSeq].receiveAlarm ) { doNoti = false; } const windowState = this.nativeService.getWindowState(); // 현재 열려 있는 방일경우 노티 안함. if ( !!curRoomInfo && !!curRoomInfo.roomSeq && curRoomInfo.roomSeq === noti.roomSeq && !!windowState && windowState !== WindowState.Minimized && windowState !== WindowState.Hidden ) { doNoti = false; } if (doNoti) { // const dd = roomUserShorts..filter(u => u.seq === noti.SENDER_SEQ ); const roomUsers = roomUserShorts[noti.roomSeq]; let senderUser: UserInfoShort; const senderUserTemp = roomUsers.userInfos.filter( userInfo => { if (!!userInfo && !!userInfo.seq) { return userInfo.seq === noti.SENDER_SEQ; } } ); senderUser = senderUserTemp[0]; const appUserInfo = this.localStorageService.encGet< AppUserInfo >(KEY_APP_USER_INFO, environment.customConfig.appKey); if (appUserInfo.settings.notification.use) { if ( appUserInfo.settings.notification.method === NotificationMethod.Sound ) { const audio = new Audio( 'assets/sounds/messageAlarm.mp3' ); audio.play(); } else { // const userTemp = userInfoList.filter(user => { user.seq === noti.SENDER_SEQ }); let contents = StringUtil.convertFinalEventMessage( noti.eventType, noti.info.sentMessageJson ); if (!appUserInfo.settings.notification.preView) { contents = ''; } if (!!contents || contents === '') { const notiReq: NotificationRequest = { type: NotificationType.Event, seq: noti.roomSeq, title: senderUser.name + '
' + this.translateService.instant( 'notification.titleChatEventArrived' ), contents, image: senderUser.profileImageFile, useSound: [ NotificationMethod.Sound, NotificationMethod.SoundAndAlert ].some( n => n === appUserInfo.settings.notification.method ) ? true : false, displayTime: appUserInfo.settings.notification .alertExposureTime * 1000 }; this.nativeService.notify(notiReq); } } } } } } break; case SSVC_TYPE_EVENT_READ_RES: case SSVC_TYPE_EVENT_READ_NOTI: { // 대화방 unread count 처리. const noti = notiOrRes as ReadNotification; this.logger.debug( 'Notification::eventProtocolService::ReadNotification', noti ); this.store.dispatch(EventStore.readNotification(noti)); } break; case SSVC_TYPE_EVENT_CANCEL_NOTI: { const noti = notiOrRes as CancelNotification; this.logger.debug( 'Notification::eventProtocolService::CancelNotification', noti ); this.store.dispatch( EventStore.cancelNotification({ noti }) ); } break; case SSVC_TYPE_EVENT_DEL_RES: { const noti = notiOrRes as DelNotification; this.logger.debug( 'Notification::eventProtocolService::DelNotification', noti ); this.store.dispatch( EventStore.delNotification({ noti }) ); } break; default: break; } }) ) .subscribe(); this.infoProtocolService.notification$ .pipe( tap(notiOrRes => { switch (notiOrRes.SSVC_TYPE) { case SSVC_TYPE_INFO_USER_NOTI: case SSVC_TYPE_INFO_USER_RES: { const noti = notiOrRes as UserNotification; this.logger.debug( 'Notification::infoProtocolService::UserNotification', noti ); this.store.dispatch( InfoStore.userNotification({ noti }) ); } break; default: break; } }) ) .subscribe(); this.groupProtocolService.notification$ .pipe( withLatestFrom( this.store.pipe( select( (state: any) => state.messenger.sync.group2.syncDate as string ) ) ), tap(([notiOrRes, syncDate]) => { switch (notiOrRes.SSVC_TYPE) { case SSVC_TYPE_GROUP_UPD_RES2: { const noti = notiOrRes as GroupUpdateNotification; this.logger.debug( 'Notification::groupProtocolService::GroupUpdateNotification', noti ); this.store.dispatch( SyncStore.group2({ syncDate }) ); } break; case SSVC_TYPE_GROUP_ADD_RES: { const noti = notiOrRes as GroupAddNotification; this.logger.debug( 'Notification::groupProtocolService::GroupAddNotification', noti ); this.store.dispatch(SyncStore.createGroupSuccess(noti)); } break; case SSVC_TYPE_GROUP_DEL_RES: { const noti = notiOrRes as GroupDelNotification; this.logger.debug( 'Notification::groupProtocolService::GroupDelNotification', noti ); this.store.dispatch(SyncStore.delGroupSuccess(noti)); } break; default: break; } }) ) .subscribe(); this.buddyProtocolService.notification$ .pipe( withLatestFrom( this.store.pipe( select( (state: any) => state.messenger.sync.buddy2.syncDate as string ) ) ), tap(([notiOrRes, syncDate]) => { switch (notiOrRes.SSVC_TYPE) { case SSVC_TYPE_BUDDY_UPD_RES: { const noti = notiOrRes as BuddyUpdateNotification; this.logger.debug( 'Notification::groupProtocolService::BuddyUpdateNotification', noti ); this.store.dispatch(SyncStore.updateBuddySuccess(noti)); } break; case SSVC_TYPE_BUDDY_ADD_RES: { const noti = notiOrRes as BuddyAddNotification; this.logger.debug( 'Notification::groupProtocolService::BuddyAddNotification', noti ); this.store.dispatch(SyncStore.buddy2({ syncDate })); } break; case SSVC_TYPE_BUDDY_DEL_RES: { const noti = notiOrRes as BuddyDelNotification; this.logger.debug( 'Notification::groupProtocolService::BuddyDelNotification', noti ); this.store.dispatch(SyncStore.delBuddySuccess(noti)); } break; default: break; } }) ) .subscribe(); this.roomProtocolService.notification$ .pipe( withLatestFrom( this.store.pipe( select( (state: any) => state.account.authentication.loginRes as LoginResponse ) ) ), tap(([notiOrRes, loginResInfo]) => { switch (notiOrRes.SSVC_TYPE) { case SSVC_TYPE_ROOM_INVITE_RES: case SSVC_TYPE_ROOM_INVITE_NOTI: { const noti = notiOrRes as InviteNotification; this.logger.debug( 'Notification::roomProtocolService::InviteNotification', noti ); this.store.dispatch( RoomStore.inviteNotification({ noti }) ); } break; case SSVC_TYPE_ROOM_UPD_RES: { const noti = notiOrRes as RoomUpdateNotification; this.logger.debug( 'Notification::roomProtocolService::RoomUpdateNotification', noti ); this.store.dispatch( RoomStore.updateSuccess({ res: { roomSeq: noti.roomSeq, roomName: noti.roomName.trim().length === 0 ? ' ' : noti.roomName.trim(), receiveAlarm: noti.receiveAlarm, syncAll: false } }) ); } break; case SSVC_TYPE_ROOM_EXIT_RES: case SSVC_TYPE_ROOM_EXIT_NOTI: { const noti = notiOrRes as ExitNotification; this.logger.debug( 'Notification::roomProtocolService::ExitNotification', noti ); if (noti.SENDER_SEQ === loginResInfo.userSeq) { this.store.dispatch( RoomStore.exitNotification({ noti }) ); } else { this.store.dispatch( RoomStore.exitNotificationOthers({ roomSeq: noti.roomSeq, trgtUser: [noti.SENDER_SEQ] }) ); if (!!noti && !!noti.SENDER_SEQ) { this.store.dispatch( SyncStore.clearRoomUsers({ roomSeq: noti.roomSeq, userSeqs: [noti.SENDER_SEQ] }) ); } } } break; case SSVC_TYPE_ROOM_EXIT_FORCING_RES: { // 내가 강퇴 진행. const res = notiOrRes as ExitForcingResponse; this.logger.debug( 'Notification::roomProtocolService::ExitForcingNotification RES', res ); this.store.dispatch( RoomStore.exitForcingSuccess({ res }) ); } break; case SSVC_TYPE_ROOM_EXIT_FORCING_NOTI: { const noti = notiOrRes as ExitForcingNotification; this.logger.debug( 'Notification::roomProtocolService::ExitForcingNotification NOTI', noti ); if (noti.userSeqs.indexOf(loginResInfo.userSeq) >= 0) { // 강퇴 대상이 본인이면 열려 있는 대화방을 닫고, 대화리스트에서 삭제. this.store.dispatch( RoomStore.exitForcingNotification({ noti }) ); } else { // ROOM::열려 있는 대화방에서 강퇴 인원의 isJoinRoom = false 로 변경. this.store.dispatch( RoomStore.exitNotificationOthers({ roomSeq: noti.roomSeq, trgtUser: noti.userSeqs }) ); // SYNC::대화리스트의 대화자정보에서 강퇴 인원의 isJoinRoom = false 로 변경. this.store.dispatch( SyncStore.clearRoomUsers({ roomSeq: noti.roomSeq, userSeqs: noti.userSeqs }) ); } } break; case SSVC_TYPE_ROOM_FONT_UPD_NOTI: { const noti = notiOrRes as UpdateFontNotification; this.logger.debug( 'Notification::roomProtocolService::UpdateFontNotification', noti ); this.store.dispatch( RoomStore.updateFontNotification({ noti }) ); } break; default: break; } }) ) .subscribe(); this.statusProtocolService.notification$ .pipe( tap(notiOrRes => { switch (notiOrRes.SSVC_TYPE) { case SSVC_TYPE_STATUS_NOTI: { const noti = notiOrRes as StatusNotification; this.logger.debug( 'Notification::statusProtocolService::StatusNotification', noti ); this.store.dispatch( StatusStore.statusNotification({ noti }) ); } break; default: break; } }) ) .subscribe(); this.optionProtocolService.notification$ .pipe( tap(notiOrRes => { switch (notiOrRes.SSVC_TYPE) { case SSVC_TYPE_OPTION_REG_UPD_RES: { const noti = notiOrRes as RegUpdateNotification; this.logger.debug( 'Notification::optionProtocolService::RegUpdateNotification', noti ); const appUserInfo: AppUserInfo = this.localStorageService.encGet< AppUserInfo >(KEY_APP_USER_INFO, environment.customConfig.appKey); const modifiedSettings: Settings = clone(appUserInfo.settings); // 모바일에서 해당 값만 수정함. modifiedSettings.notification.receiveForMobile = noti.mobileNotification; appUserInfo.settings = modifiedSettings; this.localStorageService.encSet( KEY_APP_USER_INFO, appUserInfo, environment.customConfig.appKey ); } break; default: break; } }) ) .subscribe(); this.syncProtocolService.notification$ .pipe( tap(notiOrRes => { switch (notiOrRes.SSVC_TYPE) { case SSVC_TYPE_SYNC_PHONEBOOK_READY_NOTI: { this.logger.debug( 'Notification::syncProtocolService::SSVC_TYPE_SYNC_PHONEBOOK_READY_NOTI', notiOrRes ); // destination ?: PhoneBookSyncType; // // (W: 전체(Whole)) (W: 부분(Part)) // syncType ?: // PhoneBook ready ok dispatch this.store.dispatch( SyncStore.phoneBookReadyOk({ req: { syncReadyOk: PhoneBookSyncType.OK_Y, syncType: PhoneBookSyncType.SYNC_TYPE_WHOLE } }) ); } break; case SSVC_TYPE_SYNC_PHONEBOOK_SND_NOTI: { this.logger.debug( 'Notification::syncProtocolService::SSVC_TYPE_SYNC_PHONEBOOK_SND_NOTI', notiOrRes ); // PhoneBook sed noti dispatch (data parse) const noti = notiOrRes as PhoneBookSndNotification; this.store.dispatch( SyncStore.phoneBookSndNotification({ noti }) ); } break; default: break; } }) ) .subscribe(); } } /* 쪽지 비활성화 2020-0226 this.umgProtocolService.notification$ .pipe( tap(notiOrRes => { switch (notiOrRes.SSVC_TYPE) { case SSVC_TYPE_UMG_NOTI: { const noti = notiOrRes as UmgNotiNotification; this.logger.debug( 'Notification::umgProtocolService::UmgNotiNotification', noti ); // unreadCount refresh.. this.store.dispatch(MessageStore.retrieveUnreadCount({})); // Receive Message List refresh.. this.store.dispatch( MessageStore.retrieveMessage({ messageType: MessageType.Receive }) ); // notification.. const appUserInfo = this.localStorageService.encGet( KEY_APP_USER_INFO, environment.customConfig.appKey ); if (appUserInfo.settings.notification.use) { if ( appUserInfo.settings.notification.method === NotificationMethod.Sound ) { const audio = new Audio('assets/sounds/messageAlarm.mp3'); audio.play(); } else { const notiReq: NotificationRequest = { type: NotificationType.Message, seq: noti.keyId, title: this.translateService.instant( 'notification.titleMessageArrived' ), contents: noti.text, image: noti.senderInfo.profileImageFile, useSound: [ NotificationMethod.Sound, NotificationMethod.SoundAndAlert ].some(n => n === appUserInfo.settings.notification.method) ? true : false, displayTime: appUserInfo.settings.notification.alertExposureTime * 1000 }; this.nativeService.notify(notiReq); } } // direct open detail if (appUserInfo.settings.notification.receiveForMessage) { this.store.dispatch( MessageStore.detailMessage({ messageType: MessageType.Receive, msgId: Number(noti.keyId) }) ); } } break; case SSVC_TYPE_UMG_DELETE_NOTI: { const noti = notiOrRes as UmgDeleteNotiNotification; this.logger.debug( 'Notification::umgProtocolService::UmgDeleteNotiNotification', noti ); // Remove one Receive Message if (!!noti && !!noti.keyId) { // clear badge in left navi this.store.dispatch(MessageStore.retrieveUnreadCount({})); // delete message in receive message list this.store.dispatch( deleteMessageSuccess({ messageType: MessageType.Receive, msgList: [ { msgId: Number(noti.keyId) } ] }) ); } } break; default: break; } }) ) .subscribe(); */