This commit is contained in:
병준 박 2019-12-17 17:27:28 +09:00
commit db0c720f17
16 changed files with 346 additions and 43 deletions

View File

@ -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);
if (noti.type === NotificationType.Event) {
appWindow.browserWindow.webContents.send(
ChatChannel.OpenRoom,
noti.roomSeq
noti.seq
);
} else if (noti.type === NotificationType.Message) {
appWindow.browserWindow.webContents.send(
MessageChannel.OpenMessage,
noti.seq
);
}
appWindow.show();
e.close();
}

View File

@ -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<string | null>;
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<any>,
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<EnvironmentsInfo>(
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),

View File

@ -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<any>,
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();
}
}

View File

@ -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: `비밀번호가 만료되었습니다.<br/>비밀번호 변경 후 다시 로그인 하세요.`
}
});
if (!!result && result.choice) {
this.store.dispatch(
userPasswordSet({
req: {
companyCode: loginInfo.companyCode,
loginId: loginInfo.loginId,
oldLoginPw: result.currentLoginPw,
newLoginPw: result.newLoginPw
}
})
const passwordChangeUrl = urlInfo.webLink.filter(
weblink => weblink.key === 'WebLinkChgPassword'
);
} else {
return;
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;
// }
}
})
),

View File

@ -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<string> | null = null;
private chatOpenRoom$: Observable<string> | null = null;
private msgOpenMessageSubject: Subject<string> | null = null;
private msgOpenMessage$: Observable<string> | 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<string> {
if (!this.msgOpenMessageSubject) {
this.msgOpenMessageSubject = new Subject<WindowIdle>();
this.msgOpenMessage$ = this.msgOpenMessageSubject
.asObservable()
.pipe(share());
}
return this.msgOpenMessage$;
}
getTranslateLoader(prefix?: string, suffix?: string): TranslateLoader {
return new TranslateLoaderService(this, prefix, suffix);
}

View File

@ -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<string> | null = null;
private chatOpenRoom$: Observable<string> | null = null;
private msgOpenMessageSubject: Subject<string> | null = null;
private msgOpenMessage$: Observable<string> | null = null;
private backgroundCheckForUpdatesSubject: Subject<UpdateInfo> | null = null;
private backgroundCheckForUpdates$: Observable<UpdateInfo> | null = null;
@ -311,6 +315,23 @@ export class ElectronNativeService implements NativeService {
return this.chatOpenRoom$;
}
msgOpenMessage(): Observable<string> {
if (!this.msgOpenMessageSubject) {
this.msgOpenMessageSubject = new Subject<WindowIdle>();
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);
}

View File

@ -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'

View File

@ -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;

View File

@ -49,6 +49,7 @@ export abstract class NativeService {
abstract idleStateChanged(): Observable<WindowIdle>;
abstract chatOpenRoom(): Observable<string>;
abstract msgOpenMessage(): Observable<string>;
abstract getTranslateLoader(
prefix?: string,

View File

@ -0,0 +1,6 @@
export enum NotificationType {
/** 대화 */
Event = 'E',
/** 쪽지 */
Message = 'M'
}

View File

@ -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';

View File

@ -0,0 +1,9 @@
export interface SenderInfo {
seq: number;
/** 사용자명 */
name: string;
/** 프로필이미지 */
profileImageFile: string;
/** 직급 */
grade: string;
}

View File

@ -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<UmgNotiNotification> = (
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);
};

View File

@ -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<Notifications>;
public notification$: Observable<Notifications>;
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();
}
}

View File

@ -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 삭제 알림

View File

@ -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';