From b3f29e89fd5d7b860d05a29fd4f0020ac6f72d1a Mon Sep 17 00:00:00 2001 From: leejinho Date: Mon, 2 Dec 2019 15:31:32 +0900 Subject: [PATCH] =?UTF-8?q?=EC=83=88=EC=AA=BD=EC=A7=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EC=A4=91=EA=B0=84=20=EC=BB=A4=EB=B0=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/left-side.component.ts | 71 ++++++- .../edit-message.dialog.component.html | 32 +++ .../edit-message.dialog.component.scss | 27 +++ .../edit-message.dialog.component.spec.ts | 24 +++ .../message/edit-message.dialog.component.ts | 99 +++++++++ .../messenger/dialogs/message/index.ts | 6 +- .../message-detail.dialog.component.ts | 10 +- .../components/message-editor.component.html | 25 +++ .../components/message-editor.component.scss | 9 + .../message-editor.component.spec.ts | 25 +++ .../components/message-editor.component.ts | 197 ++++++++++++++++++ .../src/lib/ucap-ui.module.ts | 2 + 12 files changed, 507 insertions(+), 20 deletions(-) create mode 100644 projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.html create mode 100644 projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.scss create mode 100644 projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.spec.ts create mode 100644 projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.ts create mode 100644 projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.html create mode 100644 projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.scss create mode 100644 projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.spec.ts create mode 100644 projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.ts diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.ts index 3736dde9..cb05a429 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/components/left-side.component.ts @@ -40,6 +40,11 @@ import { DeviceType } from '@ucap-webmessenger/core'; import { UnreadCountRequest } from 'projects/ucap-webmessenger-api-message/src/lib/apis/unread-count'; import { map, catchError } from 'rxjs/operators'; import { MessageStatusCode } from '@ucap-webmessenger/api'; +import { + EditMessageDialogComponent, + EditMessageDialogResult, + EditMessageDialogData +} from '../dialogs/message/edit-message.dialog.component'; export enum MainMenu { Group = 'GROUP', @@ -193,6 +198,34 @@ export class LeftSideComponent implements OnInit, OnDestroy { } } + async onClickNewMessage() { + const result = await this.dialogService.open< + EditMessageDialogComponent, + EditMessageDialogData, + EditMessageDialogResult + >(EditMessageDialogComponent, { + width: '600px', + data: { + loginRes: this.loginRes + } + }); + + // if (!!result && !!result.choice && result.choice) { + // if (!!result.selectedUserList && result.selectedUserList.length > 0) { + // const userSeqs: number[] = []; + // result.selectedUserList.map(user => userSeqs.push(user.seq)); + + // if (type === 'NORMAL') { + // this.store.dispatch(ChatStore.openRoom({ userSeqList: userSeqs })); + // } else if (type === 'TIMER') { + // this.store.dispatch( + // ChatStore.openRoom({ userSeqList: userSeqs, isTimeRoom: true }) + // ); + // } + // } + // } + } + onClickOpenProfile(userInfo: UserInfo | UserInfoSS | UserInfoF | UserInfoDN) { this.openProfile.emit(userInfo); } @@ -240,16 +273,28 @@ export class LeftSideComponent implements OnInit, OnDestroy { ]; } break; - // case MainMenu.Organization: - // { - - // } - // break; - // case MainMenu.Call: - // { - - // } - // break; + case MainMenu.Organization: + { + this.fabButtonShow = false; + } + break; + case MainMenu.Message: + { + this.fabButtonShow = true; + this.fabButtons = [ + { + icon: 'add', + tooltip: 'New Message', + divisionType: 'MESSAGE_NEW' + } + ]; + } + break; + case MainMenu.Call: + { + this.fabButtonShow = false; + } + break; default: { this.fabButtonShow = false; @@ -334,6 +379,12 @@ export class LeftSideComponent implements OnInit, OnDestroy { this.onClickNewChat('TIMER'); } break; + + case 'MESSAGE_NEW': + { + this.onClickNewMessage(); + } + break; } } diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.html b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.html new file mode 100644 index 00000000..a73c34ec --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.html @@ -0,0 +1,32 @@ + + + + 쪽지 보내기 + + + + 새쪽지를 보내요. + + + + + + + + + diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.scss b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.scss new file mode 100644 index 00000000..b2381d03 --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.scss @@ -0,0 +1,27 @@ +::ng-deep .mat-card-header-tex { + margin: 0; +} +.confirm-card { + min-width: 500px; + .mat-card-content { + } + .button-farm { + text-align: right; + .mat-primary { + margin-left: 4px; + } + } +} + +::ng-deep .mat-mini-fab .mat-button-wrapper { + padding: 0; +} + +.contents { + height: 380px; + + .thumbnail { + max-width: 250px; + max-height: 250px; + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.spec.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.spec.ts new file mode 100644 index 00000000..68f9559e --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.spec.ts @@ -0,0 +1,24 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EditMessageDialogComponent } from './edit-message.dialog.component'; + +describe('app::layouts::messenger::EditMessageDialogComponent', () => { + let component: EditMessageDialogComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [EditMessageDialogComponent] + }).compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(EditMessageDialogComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.ts new file mode 100644 index 00000000..8693473b --- /dev/null +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/edit-message.dialog.component.ts @@ -0,0 +1,99 @@ +import { + Component, + OnInit, + Inject, + ViewChild, + ElementRef +} from '@angular/core'; +import { + MatDialogRef, + MAT_DIALOG_DATA, + MatSelectionList, + MatSelectionListChange, + MatDrawer +} from '@angular/material'; +import { Observable, combineLatest, of } from 'rxjs'; +import { Store, select } from '@ngrx/store'; +import { map, catchError, take } from 'rxjs/operators'; + +import * as AppStore from '@app/store'; +import * as SyncStore from '@app/store/messenger/sync'; + +import { + DialogService, + ConfirmDialogComponent, + ConfirmDialogData, + ConfirmDialogResult, + SnackBarService, + AlertDialogComponent, + AlertDialogResult, + AlertDialogData +} from '@ucap-webmessenger/ui'; +import { GroupDetailData, UserInfo } from '@ucap-webmessenger/protocol-sync'; +import { + DetailResponse, + MessageType, + DetailContent, + DetailReceiver, + ContentType, + MessageDetailInfo, + MessageApiService, + RetrieveResourceFileRequest, + CancelRequest +} from '@ucap-webmessenger/api-message'; +import { DeviceType, MimeUtil, FileUtil } from '@ucap-webmessenger/core'; +import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; +import { NGXLogger } from 'ngx-logger'; +import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native'; +import { MessageStatusCode } from '@ucap-webmessenger/api'; +import { MessageEditorComponent } from 'projects/ucap-webmessenger-ui/src/lib/components/message-editor.component'; + +export interface EditMessageDialogData { + loginRes: LoginResponse; + detail?: DetailResponse; +} + +// tslint:disable-next-line: no-empty-interface +export interface EditMessageDialogResult {} + +export interface DownloadQueueForMessage extends DetailContent { + downloadType: string; +} + +@Component({ + selector: 'app-layout-messenger-edit-message', + templateUrl: './edit-message.dialog.component.html', + styleUrls: ['./edit-message.dialog.component.scss'] +}) +export class EditMessageDialogComponent implements OnInit { + @ViewChild(MessageEditorComponent, { static: false }) + editor?: MessageEditorComponent; + + constructor( + public dialogRef: MatDialogRef< + EditMessageDialogData, + EditMessageDialogResult + >, + @Inject(MAT_DIALOG_DATA) public data: EditMessageDialogData, + @Inject(UCAP_NATIVE_SERVICE) private nativeService: NativeService, + private messageApiService: MessageApiService, + private snackBarService: SnackBarService, + private logger: NGXLogger, + private store: Store, + private dialogService: DialogService + ) {} + + ngOnInit(): void {} + + getBtnValid() { + return true; + } + + onClickChoice(choice: boolean): void { + this.dialogRef.close(); + } + + onClickTest() { + console.log(this.editor.getContents()); + } +} diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/index.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/index.ts index 54a371f0..14898bde 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/index.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/index.ts @@ -1,3 +1,7 @@ import { MessageDetailDialogComponent } from './message-detail.dialog.component'; +import { EditMessageDialogComponent } from './edit-message.dialog.component'; -export const DIALOGS = [MessageDetailDialogComponent]; +export const DIALOGS = [ + MessageDetailDialogComponent, + EditMessageDialogComponent +]; diff --git a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/message-detail.dialog.component.ts b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/message-detail.dialog.component.ts index 8b1e1fb3..062e74aa 100644 --- a/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/message-detail.dialog.component.ts +++ b/projects/ucap-webmessenger-app/src/app/layouts/messenger/dialogs/message/message-detail.dialog.component.ts @@ -3,16 +3,10 @@ import { MatDialogRef, MAT_DIALOG_DATA, MatSelectionList, - MatSelectionListChange, MatDrawer } from '@angular/material'; -import { Observable, combineLatest, of } from 'rxjs'; -import { Store, select } from '@ngrx/store'; import { map, catchError, take } from 'rxjs/operators'; -import * as AppStore from '@app/store'; -import * as SyncStore from '@app/store/messenger/sync'; - import { DialogService, ConfirmDialogComponent, @@ -23,7 +17,6 @@ import { AlertDialogResult, AlertDialogData } from '@ucap-webmessenger/ui'; -import { GroupDetailData, UserInfo } from '@ucap-webmessenger/protocol-sync'; import { DetailResponse, MessageType, @@ -40,13 +33,13 @@ import { LoginResponse } from '@ucap-webmessenger/protocol-authentication'; import { NGXLogger } from 'ngx-logger'; import { NativeService, UCAP_NATIVE_SERVICE } from '@ucap-webmessenger/native'; import { MessageStatusCode } from '@ucap-webmessenger/api'; +import { of } from 'rxjs'; export interface MessageDetailDialogData { detail: DetailResponse; loginRes: LoginResponse; } -// tslint:disable-next-line: no-empty-interface export interface MessageDetailDialogResult { returnType: string; messageInfo?: MessageDetailInfo; @@ -91,7 +84,6 @@ export class MessageDetailDialogComponent implements OnInit { private messageApiService: MessageApiService, private snackBarService: SnackBarService, private logger: NGXLogger, - private store: Store, private dialogService: DialogService ) {} diff --git a/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.html b/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.html new file mode 100644 index 00000000..6c3813ff --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.html @@ -0,0 +1,25 @@ +
+ + + + +
+
+
+
diff --git a/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.scss b/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.scss new file mode 100644 index 00000000..cb4a5c84 --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.scss @@ -0,0 +1,9 @@ +.container { + height: 500px; + overflow: auto; + + .editor { + height: 100%; + width: 100%; + } +} diff --git a/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.spec.ts b/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.spec.ts new file mode 100644 index 00000000..cafed007 --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { MessageEditorComponent } from './message-editor.component'; + +describe('MessageEditorComponent', () => { + let component: MessageEditorComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ MessageEditorComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(MessageEditorComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.ts b/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.ts new file mode 100644 index 00000000..8b3e1c8f --- /dev/null +++ b/projects/ucap-webmessenger-ui/src/lib/components/message-editor.component.ts @@ -0,0 +1,197 @@ +import { + Component, + OnInit, + ElementRef, + ViewChild, + AfterViewInit, + HostListener +} from '@angular/core'; + +@Component({ + selector: 'ucap-message-editor', + templateUrl: './message-editor.component.html', + styleUrls: ['./message-editor.component.scss'] +}) +export class MessageEditorComponent implements OnInit, AfterViewInit { + @ViewChild('fileInput', { static: false }) + fileInput: ElementRef; + + @ViewChild('contentArea', { static: true }) contentArea: ElementRef; + + attachFileType: string; + + fileIndex = 0; + attachFiles: { file: File; idx: number }[] = []; + imageFiles: { file: File; idx: number }[] = []; + + constructor() {} + + ngOnInit() {} + + ngAfterViewInit(): void { + setTimeout(() => { + this.contentArea.nativeElement.focus(); + + document + .querySelector('#contentArea') + .addEventListener('paste', (event: ClipboardEvent) => { + event.stopPropagation(); + event.preventDefault(); + + const clipboardData = event.clipboardData; + let pastedData = clipboardData.getData('Text'); + pastedData = this.convertHtmltoEntity(pastedData); + clipboardData.setData('Text', pastedData); + const div = document.createElement('div'); + div.innerHTML = pastedData; + + this.attachElementNextFocused(div); + }); + + document + .querySelector('#contentArea') + .addEventListener('keyup', event => { + if ( + document.querySelector('#contentArea').innerHTML === '' || + document.querySelector('#contentArea').innerHTML === '
' + ) { + const div = document.createElement('div'); + div.innerHTML = ' 
'; + document.querySelector('#contentArea').innerHTML = ''; + this.attachElementNextFocused(div); + } + }); + + // init.. + if (document.querySelector('#contentArea').innerHTML === '') { + const div = document.createElement('div'); + div.innerHTML = ' 
'; + this.attachElementNextFocused(div); + } + }, 700); + } + + onClickFileInput(type: string) { + this.attachFileType = type; + if (type === 'attach') { + this.fileInput.nativeElement.setAttribute('multiple', 'true'); + this.fileInput.nativeElement.setAttribute('accept', '*.*'); + } else { + this.fileInput.nativeElement.removeAttribute('multiple'); + this.fileInput.nativeElement.setAttribute('accept', 'image/*'); + } + this.fileInput.nativeElement.click(); + } + + onChangeFileInput() { + const files: FileList = this.fileInput.nativeElement.files; + + // tslint:disable-next-line: prefer-for-of + for (let i = 0; i < files.length; i++) { + if (this.attachFileType === 'attach') { + this.attachFiles.push({ file: files[i], idx: this.fileIndex }); + } else { + this.imageFiles.push({ file: files[i], idx: this.fileIndex }); + this.addImageInInputField(files[i], this.fileIndex); + } + this.fileIndex++; + } + this.fileInput.nativeElement.value = ''; + } + + getContents(): string { + return 'this is contents'; + } + + addImageInInputField(image: File, index: number) { + const reader = new FileReader(); + reader.readAsDataURL(image); + reader.onloadend = () => { + const img = document.createElement('img'); + img.setAttribute('src', reader.result.toString()); + img.setAttribute('data-seq', index.toString()); + + this.attachElementNextFocused(img); + }; + } + + attachElementNextFocused(el: HTMLElement) { + if (window.getSelection) { + const sel = window.getSelection(); + const selAnchorNode: Node = sel.anchorNode; + const focusedEl = selAnchorNode.parentElement; + + if (this.isParentIdCheck(focusedEl, 'contentArea')) { + if (sel.rangeCount) { + const range = sel.getRangeAt(0); + + if (selAnchorNode.nodeType === Node.TEXT_NODE) { + const content: string = focusedEl.textContent; + + focusedEl.innerText = + content.substr(0, range.startOffset) + + el.textContent + + content.substr(range.endOffset); + } else if ( + selAnchorNode.nodeType === Node.ELEMENT_NODE && + focusedEl.id === 'contentArea' + ) { + const selEl = selAnchorNode as HTMLElement; + const content: string = selEl.textContent; + + selEl.innerText = + content.substr(0, range.startOffset) + + el.textContent + + content.substr(range.endOffset); + } else { + focusedEl.append(el); + } + } else { + focusedEl.append(el); + } + } else { + this.contentArea.nativeElement.appendChild(el); + } + } else { + this.contentArea.nativeElement.appendChild(el); + } + } + + isParentIdCheck(el: HTMLElement, id: string): boolean { + if (el.id === id) { + return true; + } else { + if (el.tagName === 'BODY' || el.tagName === 'body') { + return false; + } else { + return this.isParentIdCheck(el.parentElement, id); + } + } + } + + test(): void { + if (!!this.contentArea) { + const els: HTMLCollection = this.contentArea.nativeElement.children; + + // tslint:disable-next-line: prefer-for-of + for (let i = 0; i < els.length; i++) { + console.log(this.convertEntitytoHtml(els[i].textContent)); + } + } + } + + convertHtmltoEntity(str: string): string { + return str + .replace(/ /g, '  ') + .replace(//g, '>') + .replace(/\n/g, '
'); + } + convertEntitytoHtml(str: string): string { + return str + .replace(/ /g, ' ') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/
/g, ' \n'); + } +} diff --git a/projects/ucap-webmessenger-ui/src/lib/ucap-ui.module.ts b/projects/ucap-webmessenger-ui/src/lib/ucap-ui.module.ts index d6c159ab..ba88d404 100644 --- a/projects/ucap-webmessenger-ui/src/lib/ucap-ui.module.ts +++ b/projects/ucap-webmessenger-ui/src/lib/ucap-ui.module.ts @@ -49,6 +49,7 @@ import { import { SecondsToMinutesPipe } from './pipes/seconds-to-minutes.pipe'; import { LinkyPipe } from './pipes/linky.pipe'; import { StickerSelectorComponent } from './components/sticker-selector.component'; +import { MessageEditorComponent } from './components/message-editor.component'; import { MatTabsModule } from '@angular/material'; const COMPONENTS = [ @@ -57,6 +58,7 @@ const COMPONENTS = [ FileViewerComponent, ExpansionPanelComponent, StickerSelectorComponent, + MessageEditorComponent, BinaryViewerComponent, DocumentViewerComponent,