diff --git a/electron-projects/ucap-webmessenger-electron/src/index.ts b/electron-projects/ucap-webmessenger-electron/src/index.ts index 334a3c3d..28aad24a 100644 --- a/electron-projects/ucap-webmessenger-electron/src/index.ts +++ b/electron-projects/ucap-webmessenger-electron/src/index.ts @@ -15,7 +15,8 @@ import { IdleStateChannel, NotificationChannel, ChatChannel, - MessengerChannel + MessengerChannel, + MessageChannel } from '@ucap-webmessenger/native-electron'; import { ElectronNotificationService } from '@ucap-webmessenger/electron-notification'; import { ElectronUpdateWindowService } from '@ucap-webmessenger/electron-update-window'; @@ -27,7 +28,8 @@ import { FileUtil } from './lib/file-util'; import { IdleChecker } from './lib/idle-checker'; import { NotificationRequest, - UpdateCheckConfig + UpdateCheckConfig, + NotificationType } from '@ucap-webmessenger/native'; import { ElectronAppChannel } from '@ucap-webmessenger/electron-core'; @@ -513,10 +515,17 @@ ipcMain.on( : '', onClick: e => { appWindow.browserWindow.flashFrame(false); - appWindow.browserWindow.webContents.send( - ChatChannel.OpenRoom, - noti.roomSeq - ); + if (noti.type === NotificationType.Event) { + appWindow.browserWindow.webContents.send( + ChatChannel.OpenRoom, + noti.seq + ); + } else if (noti.type === NotificationType.Message) { + appWindow.browserWindow.webContents.send( + MessageChannel.OpenMessage, + noti.seq + ); + } appWindow.show(); e.close(); } diff --git a/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts b/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts index bcf03160..edccad61 100644 --- a/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts +++ b/projects/ucap-webmessenger-app/src/app/pages/messenger/components/main.page.component.ts @@ -1,5 +1,12 @@ import { map, tap, take, catchError } from 'rxjs/operators'; -import { Component, OnInit, Inject, OnDestroy, ViewChild } from '@angular/core'; +import { + Component, + OnInit, + Inject, + OnDestroy, + ViewChild, + ChangeDetectorRef +} from '@angular/core'; import { Store, select } from '@ngrx/store'; @@ -38,6 +45,17 @@ import { DaesangProtocolService } from '@ucap-webmessenger/daesang'; import { CallService } from '@ucap-webmessenger/api-prompt'; import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types'; import { SessionStorageService } from '@ucap-webmessenger/web-storage'; +import { + MessageApiService, + MessageType, + DetailRequest +} from '@ucap-webmessenger/api-message'; +import { MessageStatusCode } from '@ucap-webmessenger/api'; +import { + MessageDetailDialogComponent, + MessageDetailDialogResult, + MessageDetailDialogData +} from '@app/layouts/messenger/dialogs/message/message-detail.dialog.component'; @Component({ selector: 'app-page-messenger-main', @@ -49,6 +67,7 @@ export class MainPageComponent implements OnInit, OnDestroy { selectedRightDrawer$: Observable; idleStateChangedSubscription: Subscription; chatOpenRoomSubscription: Subscription; + msgOpenMessageSubscription: Subscription; defaultLeftSideComponentWidth = 380; leftSideComponentWidth = this.defaultLeftSideComponentWidth; @@ -63,11 +82,13 @@ export class MainPageComponent implements OnInit, OnDestroy { @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService, private store: Store, private statusProtocolService: StatusProtocolService, + private messageApiService: MessageApiService, private daesangProtocolService: DaesangProtocolService, private callService: CallService, private sessionStorageService: SessionStorageService, private dialogService: DialogService, - private logger: NGXLogger + private logger: NGXLogger, + private changeDetectorRef: ChangeDetectorRef ) { this.environmentsInfo = this.sessionStorageService.get( KEY_ENVIRONMENTS_INFO @@ -122,6 +143,46 @@ export class MainPageComponent implements OnInit, OnDestroy { this.store.dispatch(ChatStore.selectedRoom({ roomSeq })); }); + this.msgOpenMessageSubscription = this.nativeService + .msgOpenMessage() + .subscribe(messageSeq => { + console.log(messageSeq); + + // this.messageApiService + // .detailMessage({ + // userSeq: this.loginRes.userSeq, + // deviceType: this.environmentsInfo.deviceType, + // tokenKey: this.loginRes.tokenString, + // type: MessageType.Receive, + // msgId: Number(messageSeq) + // } as DetailRequest) + // .pipe( + // take(1), + // map(res => { + // if (res.responseCode === MessageStatusCode.Success) { + // // detail view.. + // this.dialogService.open< + // MessageDetailDialogComponent, + // MessageDetailDialogData, + // MessageDetailDialogResult + // >(MessageDetailDialogComponent, { + // width: '600px', + // data: { + // detail: res, + // loginRes: this.loginRes, + // environmentsInfo: this.environmentsInfo + // } + // }); + + // // this.changeDetectorRef.detectChanges(); + // } else { + // } + // }), + // catchError(error => of(this.logger.error(error))) + // ) + // .subscribe(); + }); + this.loginResSubscription = this.store .pipe( select(AppStore.AccountSelector.AuthenticationSelector.loginRes), diff --git a/projects/ucap-webmessenger-app/src/app/services/notification.service.ts b/projects/ucap-webmessenger-app/src/app/services/notification.service.ts index e1af66c9..adc1185b 100644 --- a/projects/ucap-webmessenger-app/src/app/services/notification.service.ts +++ b/projects/ucap-webmessenger-app/src/app/services/notification.service.ts @@ -86,9 +86,15 @@ import * as StatusStore from '@app/store/messenger/status'; import { NotificationRequest, NativeService, - UCAP_NATIVE_SERVICE + UCAP_NATIVE_SERVICE, + NotificationType } from '@ucap-webmessenger/native'; import { StringUtil } from '@ucap-webmessenger/ui'; +import { + UmgProtocolService, + SSVC_TYPE_UMG_NOTI, + UmgNotiNotification +} from '@ucap-webmessenger/protocol-umg'; @Injectable() export class AppNotificationService { @@ -100,6 +106,7 @@ export class AppNotificationService { private groupProtocolService: GroupProtocolService, private buddyProtocolService: BuddyProtocolService, private statusProtocolService: StatusProtocolService, + private umgProtocolService: UmgProtocolService, @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService, private store: Store, private logger: NGXLogger @@ -158,7 +165,8 @@ export class AppNotificationService { // notification.. if (notiOrRes.SSVC_TYPE === SSVC_TYPE_EVENT_SEND_NOTI) { const notiReq: NotificationRequest = { - roomSeq: noti.roomSeq, + type: NotificationType.Event, + seq: noti.roomSeq, title: '메세지가 도착했습니다.', contents: StringUtil.convertFinalEventMessage( noti.eventType, @@ -485,5 +493,36 @@ export class AppNotificationService { }) ) .subscribe(); + 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 + ); + console.log(noti); + // notification.. + const notiReq: NotificationRequest = { + type: NotificationType.Message, + seq: noti.keyId, + title: '쪽지가 도착했습니다.', + contents: noti.text, + image: noti.senderInfo.profileImageFile, + useSound: true, + interval: 0 + }; + this.nativeService.notify(notiReq); + } + break; + default: + break; + } + }) + ) + .subscribe(); } } diff --git a/projects/ucap-webmessenger-app/src/app/store/account/authentication/effects.ts b/projects/ucap-webmessenger-app/src/app/store/account/authentication/effects.ts index 4ec1c3f2..867b1918 100644 --- a/projects/ucap-webmessenger-app/src/app/store/account/authentication/effects.ts +++ b/projects/ucap-webmessenger-app/src/app/store/account/authentication/effects.ts @@ -47,7 +47,8 @@ import { LoginInfo, KEY_LOGIN_INFO, EnvironmentsInfo, - KEY_ENVIRONMENTS_INFO + KEY_ENVIRONMENTS_INFO, + KEY_URL_INFO } from '@app/types'; import { AppAuthenticationService } from '@app/services/authentication.service'; import { NGXLogger } from 'ngx-logger'; @@ -71,6 +72,7 @@ import { ServiceProtocolService, UserPasswordSetResponse } from '@ucap-webmessenger/protocol-service'; +import { DaesangUrlInfoResponse } from '@ucap-webmessenger/api-external'; @Injectable() export class Effects { @@ -287,35 +289,62 @@ export class Effects { } if (!loginRes.passwordValid) { - const result = await this.dialogService.open< - ChangePasswordDialogComponent, - ChangePasswordDialogData, - ChangePasswordDialogResult - >(ChangePasswordDialogComponent, { - width: '500px', - height: '500px', - disableClose: false, + // [Daesang] + const urlInfo: DaesangUrlInfoResponse = this.sessionStorageService.get< + DaesangUrlInfoResponse + >(KEY_URL_INFO); + + await this.dialogService.open< + AlertDialogComponent, + AlertDialogData, + AlertDialogResult + >(AlertDialogComponent, { data: { - loginId: loginInfo.loginId, - encryptedLoginPw: loginInfo.loginPw, - phoneNumber: loginRes.userInfo.hpNumber + title: '비밀번호 만기', + html: `비밀번호가 만료되었습니다.
비밀번호 변경 후 다시 로그인 하세요.` } }); - if (!!result && result.choice) { - this.store.dispatch( - userPasswordSet({ - req: { - companyCode: loginInfo.companyCode, - loginId: loginInfo.loginId, - oldLoginPw: result.currentLoginPw, - newLoginPw: result.newLoginPw - } - }) - ); - } else { - return; + const passwordChangeUrl = urlInfo.webLink.filter( + weblink => weblink.key === 'WebLinkChgPassword' + ); + if (passwordChangeUrl.length > 0) { + this.nativeService.openDefaultBrowser(passwordChangeUrl[0].url); } + + this.store.dispatch(logout()); + + // // [GROUP] + // const result = await this.dialogService.open< + // ChangePasswordDialogComponent, + // ChangePasswordDialogData, + // ChangePasswordDialogResult + // >(ChangePasswordDialogComponent, { + // width: '500px', + // height: '500px', + // disableClose: false, + // data: { + // loginId: loginInfo.loginId, + // encryptedLoginPw: loginInfo.loginPw, + // phoneNumber: loginRes.userInfo.hpNumber + // } + // }); + + // if (!!result && result.choice) { + // this.store.dispatch( + // userPasswordSet({ + // req: { + // companyCode: loginInfo.companyCode, + // loginId: loginInfo.loginId, + // oldLoginPw: result.currentLoginPw, + // newLoginPw: result.newLoginPw + // } + // }) + // ); + // } else { + // this.store.dispatch(logout()); + // return; + // } } }) ), diff --git a/projects/ucap-webmessenger-native-browser/src/lib/services/browser-native.service.ts b/projects/ucap-webmessenger-native-browser/src/lib/services/browser-native.service.ts index 078b142a..b1aa4fba 100644 --- a/projects/ucap-webmessenger-native-browser/src/lib/services/browser-native.service.ts +++ b/projects/ucap-webmessenger-native-browser/src/lib/services/browser-native.service.ts @@ -6,7 +6,8 @@ import { NotificationRequest, WindowIdle, UpdateInfo, - UpdateCheckConfig + UpdateCheckConfig, + NotificationType } from '@ucap-webmessenger/native'; import { HttpClient } from '@angular/common/http'; import { map, share } from 'rxjs/operators'; @@ -25,6 +26,9 @@ export class BrowserNativeService extends NativeService { private chatOpenRoomSubject: Subject | null = null; private chatOpenRoom$: Observable | null = null; + private msgOpenMessageSubject: Subject | null = null; + private msgOpenMessage$: Observable | null = null; + postAppInit(): void { this.notificationService.requestPermission(); } @@ -71,7 +75,11 @@ export class BrowserNativeService extends NativeService { notify(noti: NotificationRequest): void { this.notificationService.notify(noti, () => { window.focus(); - this.chatOpenRoomSubject.next(noti.roomSeq); + if (noti.type === NotificationType.Event) { + this.chatOpenRoomSubject.next(noti.seq); + } else if (noti.type === NotificationType.Message) { + this.msgOpenMessageSubject.next(noti.seq); + } }); } closeAllNotify(): void {} @@ -176,6 +184,17 @@ export class BrowserNativeService extends NativeService { return this.chatOpenRoom$; } + msgOpenMessage(): Observable { + if (!this.msgOpenMessageSubject) { + this.msgOpenMessageSubject = new Subject(); + this.msgOpenMessage$ = this.msgOpenMessageSubject + .asObservable() + .pipe(share()); + } + + return this.msgOpenMessage$; + } + getTranslateLoader(prefix?: string, suffix?: string): TranslateLoader { return new TranslateLoaderService(this, prefix, suffix); } diff --git a/projects/ucap-webmessenger-native-electron/src/lib/services/electron-native.service.ts b/projects/ucap-webmessenger-native-electron/src/lib/services/electron-native.service.ts index 05dd13c0..d8bcf14d 100644 --- a/projects/ucap-webmessenger-native-electron/src/lib/services/electron-native.service.ts +++ b/projects/ucap-webmessenger-native-electron/src/lib/services/electron-native.service.ts @@ -18,7 +18,8 @@ import { WindowStateChannel, IdleStateChannel, ChatChannel, - MessengerChannel + MessengerChannel, + MessageChannel } from '../types/channel.type'; import { Injectable } from '@angular/core'; import { TranslateLoaderService } from '../translate/electron-loader'; @@ -51,6 +52,9 @@ export class ElectronNativeService implements NativeService { private chatOpenRoomSubject: Subject | null = null; private chatOpenRoom$: Observable | null = null; + private msgOpenMessageSubject: Subject | null = null; + private msgOpenMessage$: Observable | null = null; + private backgroundCheckForUpdatesSubject: Subject | null = null; private backgroundCheckForUpdates$: Observable | null = null; @@ -311,6 +315,23 @@ export class ElectronNativeService implements NativeService { return this.chatOpenRoom$; } + msgOpenMessage(): Observable { + if (!this.msgOpenMessageSubject) { + this.msgOpenMessageSubject = new Subject(); + this.msgOpenMessage$ = this.msgOpenMessageSubject + .asObservable() + .pipe(share()); + } + + this.ipcRenderer.on( + MessageChannel.OpenMessage, + (event: any, messageSeq: string) => { + this.msgOpenMessageSubject.next(messageSeq); + } + ); + return this.msgOpenMessage$; + } + getTranslateLoader(prefix?: string, suffix?: string): TranslateLoader { return new TranslateLoaderService(this, prefix, suffix); } diff --git a/projects/ucap-webmessenger-native-electron/src/lib/types/channel.type.ts b/projects/ucap-webmessenger-native-electron/src/lib/types/channel.type.ts index 6bc3be7d..4f6ac160 100644 --- a/projects/ucap-webmessenger-native-electron/src/lib/types/channel.type.ts +++ b/projects/ucap-webmessenger-native-electron/src/lib/types/channel.type.ts @@ -9,6 +9,10 @@ export enum ChatChannel { OpenRoom = 'UCAP::chat::openRoom' } +export enum MessageChannel { + OpenMessage = 'UCAP::message::openMessage' +} + export enum NotificationChannel { Notify = 'UCAP::notification::notify', CloseAllNotify = 'UCAP::notification::closeAllNotify' diff --git a/projects/ucap-webmessenger-native/src/lib/models/notification.ts b/projects/ucap-webmessenger-native/src/lib/models/notification.ts index 3eb08394..d1de44ed 100644 --- a/projects/ucap-webmessenger-native/src/lib/models/notification.ts +++ b/projects/ucap-webmessenger-native/src/lib/models/notification.ts @@ -1,5 +1,8 @@ +import { NotificationType } from '../types/notification.type'; + export interface NotificationRequest { - roomSeq: string; + type: NotificationType; + seq: string; title: string; contents: string; image: string; diff --git a/projects/ucap-webmessenger-native/src/lib/services/native.service.ts b/projects/ucap-webmessenger-native/src/lib/services/native.service.ts index 7c36af6e..7cdd675e 100644 --- a/projects/ucap-webmessenger-native/src/lib/services/native.service.ts +++ b/projects/ucap-webmessenger-native/src/lib/services/native.service.ts @@ -49,6 +49,7 @@ export abstract class NativeService { abstract idleStateChanged(): Observable; abstract chatOpenRoom(): Observable; + abstract msgOpenMessage(): Observable; abstract getTranslateLoader( prefix?: string, diff --git a/projects/ucap-webmessenger-native/src/lib/types/notification.type.ts b/projects/ucap-webmessenger-native/src/lib/types/notification.type.ts new file mode 100644 index 00000000..dd0bcce6 --- /dev/null +++ b/projects/ucap-webmessenger-native/src/lib/types/notification.type.ts @@ -0,0 +1,6 @@ +export enum NotificationType { + /** 대화 */ + Event = 'E', + /** 쪽지 */ + Message = 'M' +} diff --git a/projects/ucap-webmessenger-native/src/public-api.ts b/projects/ucap-webmessenger-native/src/public-api.ts index 82c6bd83..b114fd0d 100644 --- a/projects/ucap-webmessenger-native/src/public-api.ts +++ b/projects/ucap-webmessenger-native/src/public-api.ts @@ -2,14 +2,14 @@ * Public API Surface of ucap-webmessenger-native */ +export * from './lib/types/notification.type'; export * from './lib/types/token'; +export * from './lib/types/window-state.type'; +export * from './lib/types/window-idle.type'; export * from './lib/models/notification'; export * from './lib/models/update-info'; export * from './lib/services/native.service'; -export * from './lib/types/window-state.type'; -export * from './lib/types/window-idle.type'; - export * from './lib/config/module-config'; diff --git a/projects/ucap-webmessenger-protocol-umg/src/lib/models/sender-info.ts b/projects/ucap-webmessenger-protocol-umg/src/lib/models/sender-info.ts new file mode 100644 index 00000000..c0d06a48 --- /dev/null +++ b/projects/ucap-webmessenger-protocol-umg/src/lib/models/sender-info.ts @@ -0,0 +1,9 @@ +export interface SenderInfo { + seq: number; + /** 사용자명 */ + name: string; + /** 프로필이미지 */ + profileImageFile: string; + /** 직급 */ + grade: string; +} diff --git a/projects/ucap-webmessenger-protocol-umg/src/lib/protocols/noti.ts b/projects/ucap-webmessenger-protocol-umg/src/lib/protocols/noti.ts new file mode 100644 index 00000000..0a09a0c8 --- /dev/null +++ b/projects/ucap-webmessenger-protocol-umg/src/lib/protocols/noti.ts @@ -0,0 +1,52 @@ +import { + ProtocolDecoder, + ProtocolMessage, + BodyStringDivider, + ProtocolNotification, + decodeProtocolMessage +} from '@ucap-webmessenger/protocol'; +import { SenderInfo } from '../models/sender-info'; + +export interface UmgNotiNotification extends ProtocolNotification { + /** 송신자SEQ(n) */ + senderSeq: number; + /** { 송신자정보 } */ + senderInfo: SenderInfo; + /** 푸시타입(s) */ + pushType: string; + /** keyID(s) */ + keyId: string; + /** Tiltle(s) */ + title: string; + /** 전달Text(s) */ + text: string; +} + +export const decodeUmgNotiNotification: ProtocolDecoder = ( + message: ProtocolMessage +) => { + let senderInfo: SenderInfo; + if (message.bodyList.length > 1) { + const info = message.bodyList[1].split(BodyStringDivider); + senderInfo = { + seq: Number(info[0]), + name: info[1], + profileImageFile: info[2], + grade: info[3] + }; + } + return decodeProtocolMessage(message, { + /** 송신자SEQ(n) */ + senderSeq: Number(message.bodyList[0]), + /** { 송신자정보 } */ + senderInfo, + /** 푸시타입(s) */ + pushType: message.bodyList[2], + /** keyID(s) */ + keyId: message.bodyList[3], + /** Tiltle(s) */ + title: message.bodyList[4], + /** 전달Text(s) */ + text: message.bodyList[5] + } as UmgNotiNotification); +}; diff --git a/projects/ucap-webmessenger-protocol-umg/src/lib/services/umg-protocol.service.ts b/projects/ucap-webmessenger-protocol-umg/src/lib/services/umg-protocol.service.ts index 9f1e800c..5e08eacc 100644 --- a/projects/ucap-webmessenger-protocol-umg/src/lib/services/umg-protocol.service.ts +++ b/projects/ucap-webmessenger-protocol-umg/src/lib/services/umg-protocol.service.ts @@ -1,8 +1,44 @@ import { Injectable } from '@angular/core'; +import { Subject, Observable } from 'rxjs'; +import { + UmgNotiNotification, + decodeUmgNotiNotification +} from '../protocols/noti'; +import { ProtocolService } from '@ucap-webmessenger/protocol'; +import { share, filter, tap } from 'rxjs/operators'; +import { SVC_TYPE_UMG, SSVC_TYPE_UMG_NOTI } from '../types/service'; + +type Notifications = UmgNotiNotification; @Injectable({ providedIn: 'root' }) export class UmgProtocolService { - constructor() {} + private notificationSubject: Subject; + public notification$: Observable; + + constructor(private protocolService: ProtocolService) { + this.notificationSubject = new Subject(); + this.notification$ = this.notificationSubject.asObservable().pipe(share()); + + this.protocolService.serverMessage + .pipe( + filter(message => message.serviceType === SVC_TYPE_UMG), + tap(message => { + switch (message.subServiceType) { + case SSVC_TYPE_UMG_NOTI: + { + this.notificationSubject.next( + decodeUmgNotiNotification(message) + ); + } + break; + + default: + break; + } + }) + ) + .subscribe(); + } } diff --git a/projects/ucap-webmessenger-protocol-umg/src/lib/types/service.ts b/projects/ucap-webmessenger-protocol-umg/src/lib/types/service.ts new file mode 100644 index 00000000..837e0a96 --- /dev/null +++ b/projects/ucap-webmessenger-protocol-umg/src/lib/types/service.ts @@ -0,0 +1,8 @@ +export const SVC_TYPE_UMG = 52; // Message +export const SSVC_TYPE_UMG_SEND_REQ = 1; // Message 전송 요청 +export const SSVC_TYPE_UMG_SEND_RES = 2; // Message 전송 응답 +export const SSVC_TYPE_UMG_NOTI = 3; // Message 도착 알림 +export const SSVC_TYPE_UMG_NOTI_FWD = 4; // Message 전송 요청 +export const SSVC_TYPE_UMG_DELETE_REQ = 11; // Message 삭제 요청 +export const SSVC_TYPE_UMG_DELETE_RES = 12; // Message 삭제 응답 +export const SSVC_TYPE_UMG_DELETE_NOTI = 13; // Message 삭제 알림 diff --git a/projects/ucap-webmessenger-protocol-umg/src/public-api.ts b/projects/ucap-webmessenger-protocol-umg/src/public-api.ts index 05418359..4e2e7302 100644 --- a/projects/ucap-webmessenger-protocol-umg/src/public-api.ts +++ b/projects/ucap-webmessenger-protocol-umg/src/public-api.ts @@ -2,6 +2,12 @@ * Public API Surface of ucap-webmessenger-protocol-umg */ +export * from './lib/models/sender-info'; + +export * from './lib/protocols/noti'; + export * from './lib/services/umg-protocol.service'; +export * from './lib/types/service'; + export * from './lib/ucap-umg-protocol.module';