import { map, tap, take, catchError, debounce } from 'rxjs/operators'; import { Component, OnInit, Inject, OnDestroy, ViewChild, NgZone, ElementRef } from '@angular/core'; import { Store, select } from '@ngrx/store'; import * as AppStore from '@app/store'; import * as ChatStore from '@app/store/messenger/chat'; import * as MessageStore from '@app/store/messenger/message'; import * as StatusStore from '@app/store/messenger/status'; import { Observable, Subscription, of, timer, EMPTY } from 'rxjs'; import { UCAP_NATIVE_SERVICE, NativeService } from '@ucap-webmessenger/native'; import { StatusProtocolService } from '@ucap-webmessenger/protocol-status'; import { StatusType, StatusCode } from '@ucap-webmessenger/core'; import { DialogService, ConfirmDialogComponent, ConfirmDialogResult, AlertDialogComponent, AlertDialogResult, AlertDialogData, ConfirmDialogData, StatusBarService } from '@ucap-webmessenger/ui'; import { ProfileDialogComponent, ProfileDialogData, ProfileDialogResult } from '@app/layouts/messenger/dialogs/profile/profile.dialog.component'; import { MatDrawer } from '@angular/material'; import { NGXLogger } from 'ngx-logger'; import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; import { OpenProfileOptions } from '@ucap-webmessenger/protocol-buddy'; import { DaesangProtocolService, SmsUtils } from '@ucap-webmessenger/daesang'; import { CallService } from '@ucap-webmessenger/api-prompt'; import { EnvironmentsInfo, KEY_ENVIRONMENTS_INFO } from '@app/types'; import { SessionStorageService, LocalStorageService } from '@ucap-webmessenger/web-storage'; import { MessageType } from '@ucap-webmessenger/api-message'; import { AppUserInfo, KEY_APP_USER_INFO } from '@app/types/app-user-info.type'; import { environment } from '../../../../environments/environment'; import { TranslateService } from '@ngx-translate/core'; import { LeftSideComponent } from '@app/layouts/messenger/components/left-side.component'; @Component({ selector: 'app-page-messenger-main', templateUrl: './main.page.component.html', styleUrls: ['./main.page.component.scss'] }) export class MainPageComponent implements OnInit, OnDestroy { @ViewChild('rightDrawer', { static: true }) rightDrawer: MatDrawer; @ViewChild('leftSideDrawer', { static: true }) leftSideDrawer: MatDrawer; @ViewChild('leftSideContainer', { static: false }) leftSideContainer: LeftSideComponent; @ViewChild('statusbarContainer', { static: true }) statusbarContainer: ElementRef; selectedChat$: Observable; selectedRightDrawer$: Observable; idleStateChangedSubscription: Subscription; chatOpenRoomSubscription: Subscription; msgOpenMessageSubscription: Subscription; myIdleCheckTimeSubscription: Subscription; leftSideDrawerSubscription: Subscription; leftSideDrawerIndicatorSubscription: Subscription; defaultLeftSideComponentWidth = 380; leftSideComponentWidth = this.defaultLeftSideComponentWidth; loginRes: LoginResponse; loginResSubscription: Subscription; environmentsInfo: EnvironmentsInfo; showLeftDrawer = true; showLeftDrawerIndicator = false; onLeftDrawerIndicator = false; constructor( @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService, private store: Store, private ngZone: NgZone, private statusProtocolService: StatusProtocolService, private daesangProtocolService: DaesangProtocolService, private callService: CallService, private localStorageService: LocalStorageService, private sessionStorageService: SessionStorageService, private translateService: TranslateService, private dialogService: DialogService, private statusBarService: StatusBarService, private logger: NGXLogger ) { this.environmentsInfo = this.sessionStorageService.get( KEY_ENVIRONMENTS_INFO ); } ngOnInit(): void { this.statusBarService.container = this.statusbarContainer; this.selectedChat$ = this.store.pipe( select(AppStore.MessengerSelector.ChatSelector.selectedRoom), tap(selectedRoom => { if (!selectedRoom) { this.rightDrawer.close(); } return selectedRoom; }) ); this.selectedRightDrawer$ = this.store.pipe( select(AppStore.MessengerSelector.ChatSelector.selectedRightDrawer), tap(selectedRightDrawer => { if (!!selectedRightDrawer) { this.rightDrawer.open(); } else { this.rightDrawer.close(); } }) ); this.leftSideDrawerSubscription = this.store .pipe( select(AppStore.MessengerSelector.ChatSelector.selectLeftSideDrawer) ) .subscribe(leftSideDrawer => { if (leftSideDrawer) { this.leftSideDrawer.open().then(() => { this.showLeftDrawer = true; }); } else { this.showLeftDrawer = false; this.leftSideDrawer.close(); this.store.dispatch( ChatStore.toggleLeftSideDrawerIndicator({ show: false }) ); } }); this.leftSideDrawerIndicatorSubscription = this.store .pipe( select( AppStore.MessengerSelector.ChatSelector.selectLeftSideDrawerIndicator ), debounce(leftSideDrawerIndicator => leftSideDrawerIndicator ? EMPTY : timer(500) ) ) .subscribe(leftSideDrawerIndicator => { this.showLeftDrawerIndicator = leftSideDrawerIndicator; }); this.idleStateChangedSubscription = this.nativeService .idleStateChanged() .subscribe(action => { this.logger.debug(action); let statusType: StatusCode; if (action === 'IDLE') { // away statusType = StatusCode.Away; } else { // online statusType = StatusCode.OnLine; } this.store.dispatch( StatusStore.status({ req: { statusDivisionType: StatusType.Messenger, statusType, statusMessage: '' } }) ); }); this.myIdleCheckTimeSubscription = this.store .pipe( select(AppStore.MessengerSelector.StatusSelector.selectMyIdleCheckTime) ) .subscribe(checkTime => { this.nativeService.changeLimitOfIdleState(checkTime); const appUserInfo = this.localStorageService.encGet( KEY_APP_USER_INFO, environment.customConfig.appKey ); this.localStorageService.encSet( KEY_APP_USER_INFO, { ...appUserInfo, idleCheckTime: checkTime }, environment.customConfig.appKey ); }); this.chatOpenRoomSubscription = this.nativeService .chatOpenRoom() .subscribe(roomSeq => { this.store.dispatch(ChatStore.selectedRoom({ roomSeq })); }); this.msgOpenMessageSubscription = this.nativeService .msgOpenMessage() .subscribe(messageSeq => { const appUserInfo = this.localStorageService.encGet( KEY_APP_USER_INFO, environment.customConfig.appKey ); // direct open detail if (!appUserInfo.settings.notification.receiveForMessage) { // unreadCount refresh.. this.store.dispatch(MessageStore.retrieveUnreadCount({})); this.ngZone.run(() => { /** * 쪽지 상세보기. * state 를 구독하여 Message.component.ts 에서 팝업 띄움. */ this.store.dispatch( MessageStore.detailMessage({ messageType: MessageType.Receive, msgId: Number(messageSeq) }) ); }); } }); this.loginResSubscription = this.store .pipe( select(AppStore.AccountSelector.AuthenticationSelector.loginRes), tap(loginRes => { this.loginRes = loginRes; }) ) .subscribe(); } ngOnDestroy(): void { if (!!this.idleStateChangedSubscription) { this.idleStateChangedSubscription.unsubscribe(); } if (!!this.chatOpenRoomSubscription) { this.chatOpenRoomSubscription.unsubscribe(); } if (!!this.loginResSubscription) { this.loginResSubscription.unsubscribe(); } if (!!this.myIdleCheckTimeSubscription) { this.myIdleCheckTimeSubscription.unsubscribe(); } if (!!this.leftSideDrawerSubscription) { this.leftSideDrawerSubscription.unsubscribe(); } if (!!this.leftSideDrawerIndicatorSubscription) { this.leftSideDrawerIndicatorSubscription.unsubscribe(); } this.logger.debug('-----------------------MainPageComponent ngOnDestroy'); } onOpenedChange(event: boolean) { if (!event) { this.store.dispatch( ChatStore.selectedRightDrawer({ req: null }) ); } } onGutterDragEnd(e: { gutterNum: number; sizes: Array }) { this.leftSideComponentWidth = e.sizes[0]; } onGutterDblClick(e: { gutterNum: number; sizes: Array }) { this.leftSideComponentWidth = this.defaultLeftSideComponentWidth; } onClickOpenProfile(params: { userSeq: number; openProfileOptions?: OpenProfileOptions; }) { if (!params.userSeq || params.userSeq < 0) { return; } // [GROUP] // this.queryProtocolService // .dataUser({ // divCd: 'OPENPROF', // seq: params.userSeq, // senderCompanyCode: this.loginRes.userInfo.companyCode, // senderEmployeeType: this.loginRes.userInfo.employeeType // }) // .pipe( // take(1), // map(res => { // if (!!res && !!res.userInfo) { // this.dialogService.open< // ProfileDialogComponent, // ProfileDialogData, // ProfileDialogResult // >(ProfileDialogComponent, { // data: { // userInfo: res.userInfo // } // }); // } // }) // ) // .subscribe(); // [Daesang] this.daesangProtocolService .dataUserDaesang({ divCd: 'OPENPROF', seq: params.userSeq, senderCompanyCode: this.loginRes.userInfo.companyCode, senderEmployeeType: this.loginRes.userInfo.employeeType }) .pipe( take(1), map(res => { if (!!res && !!res.userInfo) { this.dialogService.open< ProfileDialogComponent, ProfileDialogData, ProfileDialogResult >(ProfileDialogComponent, { data: { userInfo: res.userInfo, openProfileOptions: params.openProfileOptions } }); } }) ) .subscribe(); } async sendClickToCall(calleeNumber: string) { const madn = this.loginRes.madn; if (!madn || madn.trim().length === 0) { this.dialogService.open< AlertDialogComponent, AlertDialogData, AlertDialogResult >(AlertDialogComponent, { data: { title: this.translateService.instant('call.errors.label'), html: this.translateService.instant('call.errors.cannotCallToUser') } }); return false; } calleeNumber = calleeNumber.replace(/\D/g, ''); if (!!calleeNumber && calleeNumber.length > 0) { const result = await this.dialogService.open< ConfirmDialogComponent, ConfirmDialogData, ConfirmDialogResult >(ConfirmDialogComponent, { width: '360px', data: { title: this.translateService.instant('call.callTo'), html: this.translateService.instant('call.callWithNumber', { phoneNumber: calleeNumber }) } }); if (!!result && !!result.choice && result.choice) { this.callService .sendCall({ userSeq: this.loginRes.userSeq, deviceType: this.environmentsInfo.deviceType, tokenKey: this.loginRes.tokenString, calleeNumber }) .pipe( take(1), map(res => { this.logger.debug(res); }), catchError(error => of(this.logger.debug(error))) ) .subscribe(); } } else { this.dialogService.open< AlertDialogComponent, AlertDialogData, AlertDialogResult >(AlertDialogComponent, { data: { title: this.translateService.instant('call.errors.label'), html: this.translateService.instant( 'call.errors.cannotCallToUserWithoutPhomeNumber' ) } }); } } openSms(calleeNumber: string) { const smsUtil = new SmsUtils( this.sessionStorageService, this.nativeService ); if (!smsUtil.getAuthSms()) { this.dialogService.open< AlertDialogComponent, AlertDialogData, AlertDialogResult >(AlertDialogComponent, { data: { title: this.translateService.instant('sms.errors.label'), html: this.translateService.instant('sms.errors.haveNoPermission') } }); return false; } calleeNumber = calleeNumber.replace(/\D/g, ''); smsUtil.openSendSms(this.loginRes.tokenString, [calleeNumber]); } onCloseRightDrawer() { this.rightDrawer.close(); } onClickLeftDrawerToggle() { this.store.dispatch(ChatStore.toggleLeftSideDrawer()); } onMouseOverLeftDrawerIndicator(event: MouseEvent) { if (!this.onLeftDrawerIndicator) { this.onLeftDrawerIndicator = true; } } onMouseLeaveLeftDrawerIndicator(event: MouseEvent) { if (this.onLeftDrawerIndicator) { this.onLeftDrawerIndicator = false; } } onMouseEnterLeftSideContainer(event: MouseEvent) { const rect = this.leftSideContainer.elementRef.nativeElement.getBoundingClientRect(); const minX = rect.left + rect.width - 10; const maxX = rect.left + rect.width; const minY = rect.top; const maxY = rect.top + rect.height; if ( event.pageX >= minX && event.pageX <= maxX && event.pageY >= minY && event.pageY <= maxY ) { this.store.dispatch( ChatStore.toggleLeftSideDrawerIndicator({ show: true }) ); } } onMouseLeaveLeftSideContainer(event: MouseEvent) { this.store.dispatch( ChatStore.toggleLeftSideDrawerIndicator({ show: false }) ); } }