import { Component, OnInit, Input, EventEmitter, Output, AfterViewInit, ElementRef, ViewChild, ChangeDetectorRef } from '@angular/core'; import { shakeAnimation } from 'angular-animations'; import { Info, EventType, InfoResponse, EventJson, FileEventJson, MassTranslationEventJson } from '@ucap-webmessenger/protocol-event'; import { NGXLogger } from 'ngx-logger'; import moment from 'moment'; import { FileDownloadItem } from '@ucap-webmessenger/api'; import { RoomInfo } from '@ucap-webmessenger/protocol-room'; import { SelectFileInfo } from '@ucap-webmessenger/ui'; @Component({ selector: 'ucap-chat-message-box', templateUrl: './message-box.component.html', styleUrls: ['./message-box.component.scss'], animations: [shakeAnimation()] }) export class MessageBoxComponent implements OnInit, AfterViewInit { @Input() message: Info; @Input() mine = false; @Input() highlight = false; @Input() existReadToHere = false; @Input() dateChanged = false; @Input() senderName: string; @Input() profileImageRoot: string; @Input() profileImage: string; @Input() roomInfo: RoomInfo; @Input() translationSimpleview = false; @Input() unreadCount: number; @Output() openProfile = new EventEmitter(); @Output() massDetail = new EventEmitter(); @Output() massTranslationDetail = new EventEmitter<{ message: Info; contentsType: string; }>(); @Output() fileViewer = new EventEmitter(); @Output() save = new EventEmitter<{ fileInfo: FileEventJson; fileDownloadItem: FileDownloadItem; type: string; }>(); @Output() contextMenu = new EventEmitter<{ event: MouseEvent; message: Info; type?: string; }>(); @ViewChild('mbContainer', { static: true }) mbContainer: ElementRef; @ViewChild('mbChatRow', { static: true }) mbChatRow: ElementRef; EventType = EventType; moment = moment; firstEventSeq = 0; existReadHere = false; shakeIt = false; get offsetTop() { return this.mbChatRow.nativeElement.offsetTop; } constructor( private elementRef: ElementRef, private changeDetectorRef: ChangeDetectorRef, private logger: NGXLogger ) {} ngOnInit() { this.mbContainer.nativeElement.classList.add('hide'); } ngAfterViewInit(): void { this.elementRef.nativeElement.style.height = `${this.mbContainer.nativeElement.offsetHeight}px`; this.elementRef.nativeElement.style.maxHeight = `${this.mbContainer.nativeElement.offsetHeight}px`; this.mbContainer.nativeElement.classList.remove('hide'); } /** * 정보성 Event 인지 판단. * @description 정보성 event 일 경우 프로필, 일시 를 표현하지 않는다. * Edit with reducers.ts / sync / updateRoomForNewEventMessage */ isInformation(info: Info) { if ( info.type === EventType.Join || info.type === EventType.Exit || info.type === EventType.ForcedExit || info.type === EventType.RenameRoom || info.type === EventType.NotificationForiOSCapture || info.type === EventType.NotificationForTimerRoom || info.type === EventType.GuideForRoomTimerChanged ) { return true; } return false; } onClickOpenProfile(event: MouseEvent, userSeq: number) { event.preventDefault(); event.stopPropagation(); this.openProfile.emit(userSeq); } /** [Event] MassTalk Detail View */ onMassDetail(value: number) { this.massDetail.emit(value); } // onMassTranslationDetail(params: { // message: Info; // contentsType: string; // }) { // this.massTranslationDetail.emit(params); // } /** [Event] Image Viewer */ onFileViewer(fileInfo: SelectFileInfo) { this.fileViewer.emit(fileInfo); } /** [Event] Attach File Save & Save As */ onSave(value: { fileInfo: FileEventJson; fileDownloadItem: FileDownloadItem; type: string; }) { this.save.emit(value); } /** [Event] Context Menu */ onContextMenu(event: any, message: Info) { if ( message.type === EventType.Translation || message.type === EventType.MassTranslation ) { this.contextMenu.emit({ event: event.event, message, type: event.type }); } else { this.contextMenu.emit({ event, message }); } } shake() { this.shakeIt = false; this.changeDetectorRef.detectChanges(); setTimeout(() => { this.shakeIt = true; this.changeDetectorRef.detectChanges(); }, 1); } }