191 lines
4.6 KiB
TypeScript
191 lines
4.6 KiB
TypeScript
|
import {
|
||
|
Component,
|
||
|
OnInit,
|
||
|
Input,
|
||
|
Output,
|
||
|
EventEmitter,
|
||
|
ViewChild,
|
||
|
ContentChild,
|
||
|
TemplateRef,
|
||
|
AfterViewInit,
|
||
|
ChangeDetectorRef,
|
||
|
OnDestroy,
|
||
|
ElementRef
|
||
|
} from '@angular/core';
|
||
|
|
||
|
import { ucapAnimations } from '@ucap-webmessenger/ui';
|
||
|
|
||
|
import { NGXLogger } from 'ngx-logger';
|
||
|
import { FileUtil } from '@ucap-webmessenger/core';
|
||
|
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
|
||
|
|
||
|
interface Content {
|
||
|
contentType: 'text' | 'image' | 'attachment';
|
||
|
content: string;
|
||
|
}
|
||
|
|
||
|
@Component({
|
||
|
selector: 'ucap-message-write',
|
||
|
templateUrl: './write.component.html',
|
||
|
styleUrls: ['./write.component.scss'],
|
||
|
animations: ucapAnimations
|
||
|
})
|
||
|
export class WriteComponent implements OnInit, OnDestroy, AfterViewInit {
|
||
|
@ViewChild('editor', { static: true })
|
||
|
editor: ElementRef<HTMLDivElement>;
|
||
|
|
||
|
@ViewChild('fileInput', { static: true })
|
||
|
fileInput: ElementRef<HTMLInputElement>;
|
||
|
|
||
|
messageWriteForm: FormGroup;
|
||
|
receiverList: string[] = ['이진호', '강희경', '이유진'];
|
||
|
attachmentList: File[];
|
||
|
|
||
|
constructor(
|
||
|
private formBuilder: FormBuilder,
|
||
|
private changeDetectorRef: ChangeDetectorRef,
|
||
|
private logger: NGXLogger
|
||
|
) {}
|
||
|
|
||
|
ngOnInit() {
|
||
|
this.messageWriteForm = this.formBuilder.group({
|
||
|
receiverList: ['', [Validators.required]],
|
||
|
title: ['', [Validators.required]]
|
||
|
});
|
||
|
}
|
||
|
|
||
|
ngOnDestroy(): void {}
|
||
|
|
||
|
ngAfterViewInit(): void {}
|
||
|
|
||
|
onClickImage() {
|
||
|
this.fileInput.nativeElement.click();
|
||
|
const self = this;
|
||
|
this.fileInput.nativeElement.onchange = () => {
|
||
|
const fileList: FileList = self.fileInput.nativeElement.files;
|
||
|
|
||
|
FileUtil.fromBlobToDataUrl(fileList.item(0)).then(dataUrl => {
|
||
|
const img = document.createElement('img');
|
||
|
img.src = dataUrl as string;
|
||
|
self.insertNode(img);
|
||
|
});
|
||
|
|
||
|
self.fileInput.nativeElement.value = '';
|
||
|
};
|
||
|
}
|
||
|
|
||
|
onClickAttachment() {
|
||
|
this.fileInput.nativeElement.click();
|
||
|
const self = this;
|
||
|
this.fileInput.nativeElement.onchange = () => {
|
||
|
const fileList: FileList = this.fileInput.nativeElement.files;
|
||
|
|
||
|
if (!self.attachmentList) {
|
||
|
self.attachmentList = [];
|
||
|
}
|
||
|
|
||
|
for (let i = 0; i < fileList.length; i++) {
|
||
|
const file = fileList.item(i);
|
||
|
self.attachmentList.push(file);
|
||
|
}
|
||
|
|
||
|
self.changeDetectorRef.detectChanges();
|
||
|
|
||
|
self.fileInput.nativeElement.value = '';
|
||
|
};
|
||
|
}
|
||
|
|
||
|
onPasteEditor(event: ClipboardEvent) {
|
||
|
const text = document.createTextNode(
|
||
|
event.clipboardData.getData('text/plain')
|
||
|
);
|
||
|
this.insertNode(text, true);
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
onClickSend() {}
|
||
|
onClickCancel() {}
|
||
|
|
||
|
printEditor(): void {
|
||
|
const contentList: Content[] = [];
|
||
|
|
||
|
this.editor.nativeElement.childNodes.forEach((v, k) => {
|
||
|
this.parseNode(contentList, v);
|
||
|
});
|
||
|
|
||
|
this.logger.debug('printEditor', contentList);
|
||
|
}
|
||
|
|
||
|
private parseNode(contentList: Content[], node: ChildNode) {
|
||
|
switch (node.nodeType) {
|
||
|
case Node.ELEMENT_NODE:
|
||
|
{
|
||
|
if (0 < node.childNodes.length) {
|
||
|
let prevNode: ChildNode;
|
||
|
node.childNodes.forEach(v => {
|
||
|
if (
|
||
|
!!prevNode &&
|
||
|
'IMG' === prevNode.nodeName &&
|
||
|
'BR' === v.nodeName
|
||
|
) {
|
||
|
prevNode = v;
|
||
|
return;
|
||
|
}
|
||
|
prevNode = v;
|
||
|
this.parseNode(contentList, v);
|
||
|
});
|
||
|
} else {
|
||
|
if ('IMG' === node.nodeName) {
|
||
|
this.appendNode(contentList, 'image', node.textContent);
|
||
|
} else if ('BR' === node.nodeName) {
|
||
|
this.appendNode(contentList, 'text', `\n`);
|
||
|
} else {
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
case Node.TEXT_NODE:
|
||
|
this.appendNode(contentList, 'text', node.textContent);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private appendNode(
|
||
|
contentList: Content[],
|
||
|
contentType: 'text' | 'image' | 'attachment',
|
||
|
content: string
|
||
|
) {
|
||
|
const prevContent = contentList[contentList.length - 1];
|
||
|
switch (contentType) {
|
||
|
case 'text':
|
||
|
if (!!prevContent && 'text' === prevContent.contentType) {
|
||
|
prevContent.content = `${prevContent.content}${content}`;
|
||
|
} else {
|
||
|
contentList.push({
|
||
|
contentType: 'text',
|
||
|
content
|
||
|
});
|
||
|
}
|
||
|
break;
|
||
|
default:
|
||
|
contentList.push({ contentType, content });
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private insertNode(node: Node, removeSelected: boolean = false) {
|
||
|
const selection: Selection = document.getSelection();
|
||
|
const range: Range = selection.getRangeAt(0);
|
||
|
|
||
|
if (removeSelected) {
|
||
|
selection.empty();
|
||
|
}
|
||
|
|
||
|
range.insertNode(node);
|
||
|
}
|
||
|
}
|