341 lines
9.5 KiB
TypeScript
341 lines
9.5 KiB
TypeScript
import { Subject, of, Observable, forkJoin } from 'rxjs';
|
|
import { takeUntil, map, catchError, take } from 'rxjs/operators';
|
|
|
|
import {
|
|
Component,
|
|
OnInit,
|
|
OnDestroy,
|
|
ChangeDetectionStrategy,
|
|
ChangeDetectorRef,
|
|
Input,
|
|
ViewChild,
|
|
ElementRef
|
|
} from '@angular/core';
|
|
import { Store, select } from '@ngrx/store';
|
|
import { Dictionary } from '@ngrx/entity';
|
|
|
|
import { RoomInfo } from '@ucap/protocol-room';
|
|
import {
|
|
SendRequest as SendEventRequest,
|
|
EventType
|
|
} from '@ucap/protocol-event';
|
|
import { LoginResponse } from '@ucap/protocol-authentication';
|
|
|
|
import { ChattingActions } from '@ucap/ng-store-chat';
|
|
import {
|
|
LoginSelector,
|
|
ConfigurationSelector
|
|
} from '@ucap/ng-store-authentication';
|
|
import { StickerFilesInfo, KEY_STICKER_HISTORY } from '@ucap/ng-core';
|
|
import {
|
|
AlertDialogComponent,
|
|
AlertDialogData,
|
|
AlertDialogResult
|
|
} from '@ucap/ng-ui';
|
|
import { I18nService } from '@ucap/ng-i18n';
|
|
import { LogService } from '@ucap/ng-logger';
|
|
|
|
import { MatDialog } from '@angular/material/dialog';
|
|
import {
|
|
TranslationSaveResponse,
|
|
MassTalkSaveRequest,
|
|
FileTalkSaveResponse,
|
|
FileTalkSaveRequest
|
|
} from '@ucap/api-common';
|
|
import { environment } from '@environments';
|
|
import { LocalStorageService } from '@ucap/ng-web-storage';
|
|
import { CommonApiService } from '@ucap/ng-api-common';
|
|
import { LoginSession } from '@app/models/login-session';
|
|
import { AppAuthenticationService } from '@app/services/app-authentication.service';
|
|
import { StatusCode, FileUploadItem } from '@ucap/api';
|
|
import { AppFileService } from '@app/services/app-file.service';
|
|
import { VersionInfo2Response } from '@ucap/api-public';
|
|
import { FileUploadSelectorComponent } from '@app/ucap/chat/components/file-upload.selector.component';
|
|
import { FileUtil } from '@ucap/core';
|
|
import { AppChatService } from '@app/services/app-chat.service';
|
|
|
|
export enum SelectorType {
|
|
EMPTY = '',
|
|
STICKER = 'STICKER',
|
|
TRANSLATION = 'TRANSLATION',
|
|
FILEUPLOAD = 'FILEUPLOAD',
|
|
EMAILSENDER = 'EMAILSENDER'
|
|
}
|
|
|
|
@Component({
|
|
selector: 'app-sections-chat-form',
|
|
templateUrl: './form.section.component.html',
|
|
styleUrls: ['./form.section.component.scss'],
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
})
|
|
export class FormSectionComponent implements OnInit, OnDestroy {
|
|
@Input()
|
|
set roomId(roomId: string) {
|
|
this._roomId = roomId;
|
|
}
|
|
get roomId(): string {
|
|
return this._roomId;
|
|
}
|
|
// tslint:disable-next-line: variable-name
|
|
_roomId: string;
|
|
|
|
versionInfo2Res: VersionInfo2Response;
|
|
loginSession: LoginSession;
|
|
loginRes: LoginResponse;
|
|
|
|
currentRoomInfo: RoomInfo;
|
|
|
|
selectorType: SelectorType = SelectorType.EMPTY;
|
|
|
|
/** About Sticker */
|
|
selectedSticker: StickerFilesInfo;
|
|
|
|
/** About Translation */
|
|
translationSimpleview = false;
|
|
translationPreview = false;
|
|
destLocale = 'en'; // default English :: en
|
|
translationPreviewInfo: {
|
|
previewInfo: TranslationSaveResponse | null;
|
|
translationType: EventType.Translation | EventType.MassTranslation;
|
|
};
|
|
|
|
@ViewChild('messageInput', { static: false })
|
|
messageInput: ElementRef<HTMLTextAreaElement>;
|
|
@ViewChild('fileInput', { static: false })
|
|
fileInput: ElementRef<HTMLInputElement>;
|
|
@ViewChild('fileUploadSelector', { static: false })
|
|
fileUploadSelector: FileUploadSelectorComponent;
|
|
|
|
SelectorType = SelectorType;
|
|
|
|
private ngOnDestroySubject: Subject<boolean>;
|
|
constructor(
|
|
private appFileService: AppFileService,
|
|
private appChatService: AppChatService,
|
|
private store: Store<any>,
|
|
private i18nService: I18nService,
|
|
private dialog: MatDialog,
|
|
private localStorageService: LocalStorageService,
|
|
private logService: LogService,
|
|
private appAuthenticationService: AppAuthenticationService,
|
|
private commonApiService: CommonApiService,
|
|
private changeDetectorRef: ChangeDetectorRef
|
|
) {}
|
|
|
|
ngOnInit(): void {
|
|
this.ngOnDestroySubject = new Subject<boolean>();
|
|
|
|
this.store
|
|
.pipe(
|
|
takeUntil(this.ngOnDestroySubject),
|
|
select(ConfigurationSelector.versionInfo2Response)
|
|
)
|
|
.subscribe((versionInfo2Res) => {
|
|
this.versionInfo2Res = versionInfo2Res;
|
|
});
|
|
this.store
|
|
.pipe(takeUntil(this.ngOnDestroySubject), select(LoginSelector.loginRes))
|
|
.subscribe((loginRes) => {
|
|
this.loginRes = loginRes;
|
|
});
|
|
this.appAuthenticationService
|
|
.getLoginSession$()
|
|
.pipe(takeUntil(this.ngOnDestroySubject))
|
|
.subscribe((loginSession) => (this.loginSession = loginSession));
|
|
|
|
this.store
|
|
.pipe(
|
|
takeUntil(this.ngOnDestroySubject),
|
|
select(
|
|
(state: any) => state.chat.room.rooms.entities as Dictionary<RoomInfo>
|
|
)
|
|
)
|
|
.subscribe((rooms) => {
|
|
if (!!this.roomId) {
|
|
this.currentRoomInfo = rooms[this.roomId];
|
|
|
|
this.changeDetectorRef.detectChanges();
|
|
}
|
|
});
|
|
}
|
|
|
|
ngOnDestroy(): void {
|
|
if (!!this.ngOnDestroySubject) {
|
|
this.ngOnDestroySubject.complete();
|
|
}
|
|
}
|
|
|
|
/** About Selector */
|
|
onOpenSelector(type: SelectorType): void {
|
|
this.selectorType = type;
|
|
this.changeDetectorRef.detectChanges();
|
|
}
|
|
clearSelector(): void {
|
|
this.selectorType = SelectorType.EMPTY;
|
|
this.selectedSticker = null;
|
|
this.changeDetectorRef.detectChanges();
|
|
}
|
|
|
|
/** Element Handling */
|
|
focus(clearField: boolean = true): void {
|
|
if (!!this.messageInput) {
|
|
if (!!clearField) {
|
|
this.messageInput.nativeElement.value = '';
|
|
|
|
this.clearSelector();
|
|
}
|
|
this.messageInput.nativeElement.focus();
|
|
}
|
|
}
|
|
|
|
onChangeFileInput(): void {
|
|
const self = this;
|
|
const fileList = this.fileInput.nativeElement.files;
|
|
|
|
this.appFileService
|
|
.validUploadFile(fileList, this.versionInfo2Res?.fileAllowSize)
|
|
.then((result) => {
|
|
if (!result) {
|
|
self.fileInput.nativeElement.value = '';
|
|
return;
|
|
} else {
|
|
// selector open
|
|
self.onOpenSelector(SelectorType.FILEUPLOAD);
|
|
|
|
// FileuploadItem Init. & FileSelector Init.
|
|
const fileUploadItems = FileUploadItem.fromFiles(fileList);
|
|
if (!!self.fileUploadSelector) {
|
|
self.fileUploadSelector.onFileSelected(fileUploadItems);
|
|
}
|
|
self.fileInput.nativeElement.value = '';
|
|
|
|
// File Upload..
|
|
self.appChatService
|
|
.sendMessageOfAttachFile(
|
|
self.loginRes,
|
|
self.loginSession.deviceType,
|
|
self.currentRoomInfo.roomId,
|
|
fileUploadItems
|
|
)
|
|
.then((success) => {
|
|
if (!!success) {
|
|
self.clearSelector();
|
|
if (!!self.fileUploadSelector) {
|
|
self.fileUploadSelector.onUploadComplete();
|
|
}
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
alert(err);
|
|
if (!!self.fileUploadSelector) {
|
|
self.fileUploadSelector.onUploadComplete();
|
|
}
|
|
});
|
|
}
|
|
})
|
|
.catch((err) => {
|
|
self.fileInput.nativeElement.value = '';
|
|
self.logService.error(`validUploadFile ${err}`);
|
|
});
|
|
}
|
|
|
|
onKeydown(event: KeyboardEvent) {
|
|
if (event.key === 'PageUp' || event.key === 'PageDown') {
|
|
event.preventDefault();
|
|
return false;
|
|
} else if (event.key === 'Enter' && !event.shiftKey) {
|
|
event.preventDefault();
|
|
this.send();
|
|
}
|
|
}
|
|
|
|
onSelectedSticker(stickerInfo: StickerFilesInfo) {
|
|
this.selectedSticker = stickerInfo;
|
|
this.focus(false);
|
|
}
|
|
|
|
async send() {
|
|
const roomId = this.currentRoomInfo.roomId;
|
|
const userSeq = this.loginRes.userSeq;
|
|
let message = this.messageInput.nativeElement.value;
|
|
|
|
if (!!message || message.trim().length > 0) {
|
|
message = message.replace(/\t/g, ' ');
|
|
}
|
|
|
|
// Empty Check.
|
|
if (!this.selectedSticker) {
|
|
try {
|
|
if (!message || message.trim().length === 0) {
|
|
const result = await this.dialog.open<
|
|
AlertDialogComponent,
|
|
AlertDialogData,
|
|
AlertDialogResult
|
|
>(AlertDialogComponent, {
|
|
data: {
|
|
title: this.i18nService.t('errors.label'),
|
|
message: this.i18nService.t('errors.inputChatMessage')
|
|
},
|
|
panelClass: ''
|
|
});
|
|
return;
|
|
}
|
|
} catch (e) {
|
|
this.logService.debug(e);
|
|
}
|
|
}
|
|
|
|
if (
|
|
this.selectorType === SelectorType.TRANSLATION &&
|
|
this.destLocale.trim().length > 0
|
|
) {
|
|
/** CASE : Translation */
|
|
// 번역할 대화 없이 스티커만 전송할 경우.
|
|
if (!message || message.trim().length === 0) {
|
|
this.appChatService.sendMessageOfSticker(
|
|
userSeq,
|
|
roomId,
|
|
this.selectedSticker,
|
|
message
|
|
);
|
|
|
|
this.clearSelector();
|
|
} else {
|
|
this.appChatService.sendMessageOfTranslate(
|
|
this.loginRes,
|
|
this.loginSession.deviceType,
|
|
this.destLocale,
|
|
roomId,
|
|
message,
|
|
this.selectedSticker
|
|
);
|
|
}
|
|
} else if (!!this.selectedSticker) {
|
|
/** CASE : Sticker */
|
|
this.appChatService.sendMessageOfSticker(
|
|
userSeq,
|
|
roomId,
|
|
this.selectedSticker,
|
|
message
|
|
);
|
|
|
|
this.clearSelector();
|
|
} else if (
|
|
message.trim().length > environment.productConfig.chat.masstextLength
|
|
) {
|
|
/** CASE : MASS TEXT */
|
|
this.appChatService.sendMessageOfMassText(
|
|
this.loginRes,
|
|
this.loginSession.deviceType,
|
|
roomId,
|
|
message
|
|
);
|
|
} else {
|
|
/** CASE : Normal Text */
|
|
this.appChatService.sendMessageOfNormal(userSeq, roomId, message);
|
|
}
|
|
|
|
this.focus();
|
|
}
|
|
}
|