쪽지 노티팝업 기능 추가.

This commit is contained in:
leejinho 2019-12-17 16:39:02 +09:00
parent d5bdbd2cd7
commit 8cfb56efe1
15 changed files with 292 additions and 18 deletions

View File

@ -13,7 +13,8 @@ import {
IdleStateChannel, IdleStateChannel,
NotificationChannel, NotificationChannel,
ChatChannel, ChatChannel,
MessengerChannel MessengerChannel,
MessageChannel
} from '@ucap-webmessenger/native-electron'; } from '@ucap-webmessenger/native-electron';
import { ElectronNotificationService } from '@ucap-webmessenger/electron-notification'; import { ElectronNotificationService } from '@ucap-webmessenger/electron-notification';
import { ElectronUpdateWindowService } from '@ucap-webmessenger/electron-update-window'; import { ElectronUpdateWindowService } from '@ucap-webmessenger/electron-update-window';
@ -25,7 +26,8 @@ import { FileUtil } from './lib/file-util';
import { IdleChecker } from './lib/idle-checker'; import { IdleChecker } from './lib/idle-checker';
import { import {
NotificationRequest, NotificationRequest,
UpdateCheckConfig UpdateCheckConfig,
NotificationType
} from '@ucap-webmessenger/native'; } from '@ucap-webmessenger/native';
import { ElectronAppChannel } from '@ucap-webmessenger/electron-core'; import { ElectronAppChannel } from '@ucap-webmessenger/electron-core';
@ -478,10 +480,17 @@ ipcMain.on(
: '', : '',
onClick: e => { onClick: e => {
appWindow.browserWindow.flashFrame(false); appWindow.browserWindow.flashFrame(false);
appWindow.browserWindow.webContents.send( if (noti.type === NotificationType.Event) {
ChatChannel.OpenRoom, appWindow.browserWindow.webContents.send(
noti.roomSeq ChatChannel.OpenRoom,
); noti.seq
);
} else if (noti.type === NotificationType.Message) {
appWindow.browserWindow.webContents.send(
MessageChannel.OpenMessage,
noti.seq
);
}
appWindow.show(); appWindow.show();
e.close(); e.close();
} }

View File

@ -1,5 +1,12 @@
import { map, tap, take, catchError } from 'rxjs/operators'; 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'; import { Store, select } from '@ngrx/store';
@ -38,6 +45,17 @@ import { DaesangProtocolService } from '@ucap-webmessenger/daesang';
import { CallService } from '@ucap-webmessenger/api-prompt'; import { CallService } from '@ucap-webmessenger/api-prompt';
import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types'; import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types';
import { SessionStorageService } from '@ucap-webmessenger/web-storage'; 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({ @Component({
selector: 'app-page-messenger-main', selector: 'app-page-messenger-main',
@ -49,6 +67,7 @@ export class MainPageComponent implements OnInit, OnDestroy {
selectedRightDrawer$: Observable<string | null>; selectedRightDrawer$: Observable<string | null>;
idleStateChangedSubscription: Subscription; idleStateChangedSubscription: Subscription;
chatOpenRoomSubscription: Subscription; chatOpenRoomSubscription: Subscription;
msgOpenMessageSubscription: Subscription;
defaultLeftSideComponentWidth = 380; defaultLeftSideComponentWidth = 380;
leftSideComponentWidth = this.defaultLeftSideComponentWidth; leftSideComponentWidth = this.defaultLeftSideComponentWidth;
@ -63,11 +82,13 @@ export class MainPageComponent implements OnInit, OnDestroy {
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService, @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
private store: Store<any>, private store: Store<any>,
private statusProtocolService: StatusProtocolService, private statusProtocolService: StatusProtocolService,
private messageApiService: MessageApiService,
private daesangProtocolService: DaesangProtocolService, private daesangProtocolService: DaesangProtocolService,
private callService: CallService, private callService: CallService,
private sessionStorageService: SessionStorageService, private sessionStorageService: SessionStorageService,
private dialogService: DialogService, private dialogService: DialogService,
private logger: NGXLogger private logger: NGXLogger,
private changeDetectorRef: ChangeDetectorRef
) { ) {
this.environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>( this.environmentsInfo = this.sessionStorageService.get<EnvironmentsInfo>(
KEY_ENVIRONMENTS_INFO KEY_ENVIRONMENTS_INFO
@ -122,6 +143,46 @@ export class MainPageComponent implements OnInit, OnDestroy {
this.store.dispatch(ChatStore.selectedRoom({ roomSeq })); 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 this.loginResSubscription = this.store
.pipe( .pipe(
select(AppStore.AccountSelector.AuthenticationSelector.loginRes), select(AppStore.AccountSelector.AuthenticationSelector.loginRes),

View File

@ -86,9 +86,15 @@ import * as StatusStore from '@app/store/messenger/status';
import { import {
NotificationRequest, NotificationRequest,
NativeService, NativeService,
UCAP_NATIVE_SERVICE UCAP_NATIVE_SERVICE,
NotificationType
} from '@ucap-webmessenger/native'; } from '@ucap-webmessenger/native';
import { StringUtil } from '@ucap-webmessenger/ui'; import { StringUtil } from '@ucap-webmessenger/ui';
import {
UmgProtocolService,
SSVC_TYPE_UMG_NOTI,
UmgNotiNotification
} from '@ucap-webmessenger/protocol-umg';
@Injectable() @Injectable()
export class AppNotificationService { export class AppNotificationService {
@ -100,6 +106,7 @@ export class AppNotificationService {
private groupProtocolService: GroupProtocolService, private groupProtocolService: GroupProtocolService,
private buddyProtocolService: BuddyProtocolService, private buddyProtocolService: BuddyProtocolService,
private statusProtocolService: StatusProtocolService, private statusProtocolService: StatusProtocolService,
private umgProtocolService: UmgProtocolService,
@Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService, @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService,
private store: Store<any>, private store: Store<any>,
private logger: NGXLogger private logger: NGXLogger
@ -158,7 +165,8 @@ export class AppNotificationService {
// notification.. // notification..
if (notiOrRes.SSVC_TYPE === SSVC_TYPE_EVENT_SEND_NOTI) { if (notiOrRes.SSVC_TYPE === SSVC_TYPE_EVENT_SEND_NOTI) {
const notiReq: NotificationRequest = { const notiReq: NotificationRequest = {
roomSeq: noti.roomSeq, type: NotificationType.Event,
seq: noti.roomSeq,
title: '메세지가 도착했습니다.', title: '메세지가 도착했습니다.',
contents: StringUtil.convertFinalEventMessage( contents: StringUtil.convertFinalEventMessage(
noti.eventType, noti.eventType,
@ -485,5 +493,36 @@ export class AppNotificationService {
}) })
) )
.subscribe(); .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

@ -6,7 +6,8 @@ import {
NotificationRequest, NotificationRequest,
WindowIdle, WindowIdle,
UpdateInfo, UpdateInfo,
UpdateCheckConfig UpdateCheckConfig,
NotificationType
} from '@ucap-webmessenger/native'; } from '@ucap-webmessenger/native';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { map, share } from 'rxjs/operators'; import { map, share } from 'rxjs/operators';
@ -25,6 +26,9 @@ export class BrowserNativeService extends NativeService {
private chatOpenRoomSubject: Subject<string> | null = null; private chatOpenRoomSubject: Subject<string> | null = null;
private chatOpenRoom$: Observable<string> | null = null; private chatOpenRoom$: Observable<string> | null = null;
private msgOpenMessageSubject: Subject<string> | null = null;
private msgOpenMessage$: Observable<string> | null = null;
postAppInit(): void { postAppInit(): void {
this.notificationService.requestPermission(); this.notificationService.requestPermission();
} }
@ -65,7 +69,11 @@ export class BrowserNativeService extends NativeService {
notify(noti: NotificationRequest): void { notify(noti: NotificationRequest): void {
this.notificationService.notify(noti, () => { this.notificationService.notify(noti, () => {
window.focus(); 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 {} closeAllNotify(): void {}
@ -170,6 +178,17 @@ export class BrowserNativeService extends NativeService {
return this.chatOpenRoom$; 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 { getTranslateLoader(prefix?: string, suffix?: string): TranslateLoader {
return new TranslateLoaderService(this, prefix, suffix); return new TranslateLoaderService(this, prefix, suffix);
} }

View File

@ -18,7 +18,8 @@ import {
WindowStateChannel, WindowStateChannel,
IdleStateChannel, IdleStateChannel,
ChatChannel, ChatChannel,
MessengerChannel MessengerChannel,
MessageChannel
} from '../types/channel.type'; } from '../types/channel.type';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { TranslateLoaderService } from '../translate/electron-loader'; import { TranslateLoaderService } from '../translate/electron-loader';
@ -51,6 +52,9 @@ export class ElectronNativeService implements NativeService {
private chatOpenRoomSubject: Subject<string> | null = null; private chatOpenRoomSubject: Subject<string> | null = null;
private chatOpenRoom$: Observable<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 backgroundCheckForUpdatesSubject: Subject<UpdateInfo> | null = null;
private backgroundCheckForUpdates$: Observable<UpdateInfo> | null = null; private backgroundCheckForUpdates$: Observable<UpdateInfo> | null = null;
@ -296,6 +300,23 @@ export class ElectronNativeService implements NativeService {
return this.chatOpenRoom$; 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 { getTranslateLoader(prefix?: string, suffix?: string): TranslateLoader {
return new TranslateLoaderService(this, prefix, suffix); return new TranslateLoaderService(this, prefix, suffix);
} }

View File

@ -8,6 +8,10 @@ export enum ChatChannel {
OpenRoom = 'UCAP::chat::openRoom' OpenRoom = 'UCAP::chat::openRoom'
} }
export enum MessageChannel {
OpenMessage = 'UCAP::message::openMessage'
}
export enum NotificationChannel { export enum NotificationChannel {
Notify = 'UCAP::notification::notify', Notify = 'UCAP::notification::notify',
CloseAllNotify = 'UCAP::notification::closeAllNotify' CloseAllNotify = 'UCAP::notification::closeAllNotify'

View File

@ -1,5 +1,8 @@
import { NotificationType } from '../types/notification.type';
export interface NotificationRequest { export interface NotificationRequest {
roomSeq: string; type: NotificationType;
seq: string;
title: string; title: string;
contents: string; contents: string;
image: string; image: string;

View File

@ -47,6 +47,7 @@ export abstract class NativeService {
abstract idleStateChanged(): Observable<WindowIdle>; abstract idleStateChanged(): Observable<WindowIdle>;
abstract chatOpenRoom(): Observable<string>; abstract chatOpenRoom(): Observable<string>;
abstract msgOpenMessage(): Observable<string>;
abstract getTranslateLoader( abstract getTranslateLoader(
prefix?: string, 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 * Public API Surface of ucap-webmessenger-native
*/ */
export * from './lib/types/notification.type';
export * from './lib/types/token'; 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/notification';
export * from './lib/models/update-info'; export * from './lib/models/update-info';
export * from './lib/services/native.service'; 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'; 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 { 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({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class UmgProtocolService { 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 * 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/services/umg-protocol.service';
export * from './lib/types/service';
export * from './lib/ucap-umg-protocol.module'; export * from './lib/ucap-umg-protocol.module';