스티커 기능 구현..

## issue : 스티커 해제를 위한 로직 추가 필요.
This commit is contained in:
leejinho 2019-11-25 14:12:49 +09:00
parent 92e2ec75e4
commit d7cec3f93f
9 changed files with 234 additions and 30 deletions

View File

@ -79,8 +79,10 @@
<button <button
mat-icon-button mat-icon-button
#chatMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="contactMenu" [matMenuTriggerFor]="contactMenu"
aria-label="more" aria-label="more"
(ucapClickOutside)="chatMenuTrigger.closeMenu()"
> >
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
@ -190,13 +192,15 @@
></ucap-file-upload-queue> ></ucap-file-upload-queue>
</div> </div>
<!-- <div class="sticker-selector-container"> <div class="sticker-selector-container">
<ucap-sticker-selector <ucap-sticker-selector
*ngIf="isShowStickerSelector" *ngIf="isShowStickerSelector"
#stickerSelector
(selectedSticker)="onSelectedSticker($event)"
class="sticker-selector-zone" class="sticker-selector-zone"
></ucap-sticker-selector> ></ucap-sticker-selector>
<div></div> <div></div>
</div> --> </div>
</div> </div>
<!-- / CHAT CONTENT --> <!-- / CHAT CONTENT -->
@ -208,6 +212,7 @@
[fileUploadQueue]="fileUploadQueue" [fileUploadQueue]="fileUploadQueue"
(send)="onSendMessage($event)" (send)="onSendMessage($event)"
(sendFiles)="onFileSelected($event)" (sendFiles)="onFileSelected($event)"
(clearView)="clearView()"
(toggleStickerSelector)="onShowToggleStickerSelector($event)" (toggleStickerSelector)="onShowToggleStickerSelector($event)"
></ucap-chat-form> ></ucap-chat-form>
<!-- / REPLY FORM --> <!-- / REPLY FORM -->

View File

@ -103,16 +103,15 @@
.sticker-selector-container { .sticker-selector-container {
position: absolute; position: absolute;
top: 0; bottom: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%;
background-color: transparent; background-color: transparent;
.sticker-selector-zone { .sticker-selector-zone {
position: absolute; position: absolute;
padding: 10px 10px 0 10px; padding: 10px 10px 0 10px;
background-color: rgb(54, 54, 54, 0.8); background-color: rgba(250, 255, 255, 0.8);
bottom: 0; bottom: 0;
width: 100%; width: 100%;
} }

View File

@ -33,7 +33,8 @@ import {
isRecallable, isRecallable,
InfoResponse, InfoResponse,
EventJson, EventJson,
FileEventJson FileEventJson,
StickerEventJson
} from '@ucap-webmessenger/protocol-event'; } from '@ucap-webmessenger/protocol-event';
import * as AppStore from '@app/store'; import * as AppStore from '@app/store';
@ -78,7 +79,12 @@ import {
FileViewerDialogData, FileViewerDialogData,
FileViewerDialogResult FileViewerDialogResult
} from '@app/layouts/common/dialogs/file-viewer.dialog.component'; } from '@app/layouts/common/dialogs/file-viewer.dialog.component';
import { CONST, FileUtil } from '@ucap-webmessenger/core'; import {
CONST,
FileUtil,
StickerFilesInfo,
StickerUtil
} from '@ucap-webmessenger/core';
import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar'; import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar';
import { StatusCode } from '@ucap-webmessenger/api'; import { StatusCode } from '@ucap-webmessenger/api';
import { import {
@ -147,7 +153,9 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
/** Timer 대화방의 대화 삭제를 위한 interval */ /** Timer 대화방의 대화 삭제를 위한 interval */
interval: any; interval: any;
/** About Sticker */
isShowStickerSelector = false; isShowStickerSelector = false;
selectedSticker: StickerFilesInfo;
snackBarPreviewEvent: MatSnackBarRef<SimpleSnackBar>; snackBarPreviewEvent: MatSnackBarRef<SimpleSnackBar>;
@ -270,6 +278,15 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
// this.readyToReply(); // this.readyToReply();
} }
/**
* .
*/
clearView() {
// Sticker Selector Clear..
this.isShowStickerSelector = false;
this.selectedSticker = undefined;
}
getRoomName() { getRoomName() {
if (!this.roomInfo || !this.userInfoList) { if (!this.roomInfo || !this.userInfoList) {
return '대화방명을 가져오고 있습니다..'; return '대화방명을 가져오고 있습니다..';
@ -468,22 +485,58 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
async onSendMessage(message: string) { async onSendMessage(message: string) {
this.setEventMoreInit(); this.setEventMoreInit();
if (!message || message.trim().length === 0) { if (!this.selectedSticker) {
const result = await this.dialogService.open< if (!message || message.trim().length === 0) {
AlertDialogComponent, const result = await this.dialogService.open<
AlertDialogData, AlertDialogComponent,
AlertDialogResult AlertDialogData,
>(AlertDialogComponent, { AlertDialogResult
width: '360px', >(AlertDialogComponent, {
data: { width: '360px',
title: 'Alert', data: {
message: `대화내용을 입력해주세요.` title: 'Alert',
} message: `대화내용을 입력해주세요.`
}); }
return; });
return;
}
} }
if (message.trim().length > CONST.MASSTEXT_LEN) { if (!!this.selectedSticker) {
// Send Sticker
if (message.trim().length > CONST.MASSTEXT_LEN) {
const result = await this.dialogService.open<
AlertDialogComponent,
AlertDialogData,
AlertDialogResult
>(AlertDialogComponent, {
width: '360px',
data: {
title: 'Alert',
message: `스티커를 포함할 경우 ${CONST.MASSTEXT_LEN}자 이상 보낼 수 없습니다.`
}
});
return;
}
const stickerJson: StickerEventJson = {
name: '스티커',
file: this.selectedSticker.index,
chat: message.trim()
};
this.store.dispatch(
EventStore.send({
senderSeq: this.loginRes.userSeq,
req: {
roomSeq: this.roomInfo.roomSeq,
eventType: EventType.Sticker,
sentMessage: JSON.stringify(stickerJson)
}
})
);
this.isShowStickerSelector = false;
StickerUtil.setStickerHistory(this.selectedSticker);
} else if (message.trim().length > CONST.MASSTEXT_LEN) {
// MASS TEXT // MASS TEXT
this.store.dispatch( this.store.dispatch(
EventStore.sendMass({ EventStore.sendMass({
@ -523,10 +576,6 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
); );
} }
onShowToggleStickerSelector() {
this.isShowStickerSelector = !this.isShowStickerSelector;
}
async onFileViewer(fileInfo: FileEventJson) { async onFileViewer(fileInfo: FileEventJson) {
const result = await this.dialogService.open< const result = await this.dialogService.open<
FileViewerDialogComponent, FileViewerDialogComponent,
@ -558,6 +607,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
} }
onFileDragEnter(items: DataTransferItemList) { onFileDragEnter(items: DataTransferItemList) {
this.clearView();
this.logger.debug('onFileDragEnter', items); this.logger.debug('onFileDragEnter', items);
} }
@ -571,6 +621,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
async onFileSelected(fileUploadItems: FileUploadItem[]) { async onFileSelected(fileUploadItems: FileUploadItem[]) {
this.logger.debug('onFileSelected', fileUploadItems); this.logger.debug('onFileSelected', fileUploadItems);
this.clearView();
const info = { const info = {
senderSeq: this.loginRes.userSeq, senderSeq: this.loginRes.userSeq,
@ -1031,4 +1082,13 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
this.openProfile.emit(userInfo); this.openProfile.emit(userInfo);
} }
} }
/** About Sticker */
onShowToggleStickerSelector() {
this.isShowStickerSelector = !this.isShowStickerSelector;
}
onSelectedSticker(stickerInfo: StickerFilesInfo) {
this.selectedSticker = stickerInfo;
}
} }

View File

@ -1,3 +1,5 @@
import { LocalStorageService } from '@ucap-webmessenger/web-storage';
export interface StickerInfo { export interface StickerInfo {
index: string; index: string;
title: string; title: string;
@ -148,7 +150,13 @@ export class StickerUtil {
const stickerInfos: StickerInfo[] = StickerMap.filter( const stickerInfos: StickerInfo[] = StickerMap.filter(
sticker => sticker.index === idx && sticker.useYn sticker => sticker.index === idx && sticker.useYn
); );
if (!!stickerInfos && stickerInfos.length > 0) { if (!!stickerInfos && stickerInfos.length > 0) {
if (idx === '00') {
// history.
stickerInfos[0].fileInfos = this.getStickerHistory();
}
rtnStickerList.push(stickerInfos[0]); rtnStickerList.push(stickerInfos[0]);
} }
}); });
@ -168,4 +176,50 @@ export class StickerUtil {
return stickerFilesList; return stickerFilesList;
} }
static setStickerHistory(sticker: StickerFilesInfo) {
const localStorageService = new LocalStorageService();
const history = localStorageService.get<string[]>('ucap::Sticker_History');
if (!!history && history.length > 0) {
const stickers: string[] = [];
[sticker.index, ...history.filter(hist => hist !== sticker.index)].map(
(s, i) => {
if (i < 10) {
stickers.push(s);
}
}
);
localStorageService.set<string[]>('ucap::Sticker_History', stickers);
} else {
localStorageService.set<string[]>('ucap::Sticker_History', [
sticker.index
]);
}
}
static getStickerHistory(): StickerFilesInfo[] {
const rtnArray: StickerFilesInfo[] = [];
const localStorageService = new LocalStorageService();
const history = localStorageService.get<string[]>('ucap::Sticker_History');
if (!!history && history.length > 0) {
history.forEach(sticker => {
const arr: string[] = sticker.split('_');
if (arr.length === 2) {
const sInfo: StickerInfo[] = StickerMap.filter(
stickerInfo => stickerInfo.index === arr[0]
);
if (!!sInfo && sInfo.length > 0) {
rtnArray.push(
...sInfo[0].fileInfos.filter(
fileInfo => fileInfo.index === sticker
)
);
}
}
});
}
return rtnArray;
}
} }

View File

@ -29,6 +29,9 @@ export class FormComponent implements OnInit {
@Output() @Output()
toggleStickerSelector = new EventEmitter<void>(); toggleStickerSelector = new EventEmitter<void>();
@Output()
clearView = new EventEmitter();
@ViewChild('replyForm', { static: false }) @ViewChild('replyForm', { static: false })
replyForm: NgForm; replyForm: NgForm;
@ -54,6 +57,7 @@ export class FormComponent implements OnInit {
} }
onClickFileInput() { onClickFileInput() {
this.clearView.emit();
this.fileInput.nativeElement.click(); this.fileInput.nativeElement.click();
} }

View File

@ -1,4 +1,39 @@
<p>sticker-selector works!</p> <div *ngIf="currentSticker" class="selected-sticker">
<p *ngFor="let stickerInfo of stickerInfoList"> <img [src]="getStickerContentsImage(currentSticker)" />
{{ stickerInfo.title }} </div>
</p> <div class="sticker-selector">
<mat-tab-group
mat-stretch-tabs
animationDuration="0ms"
(selectedIndexChange)="onSelectedIndexChange($event)"
>
<mat-tab
*ngFor="let stickerInfo of stickerInfoList; let idx = index"
[aria-label]="stickerInfo.title"
>
<ng-template mat-tab-label>
<img
#stickerTitle
[matTooltip]="stickerInfo.title"
matTooltipPosition="after"
[src]="getStickerTitleImage(stickerInfo, false, idx)"
(mouseover)="
stickerTitle.src = getStickerTitleImage(stickerInfo, true, idx)
"
(mouseout)="
stickerTitle.src = getStickerTitleImage(stickerInfo, false, idx)
"
/>
</ng-template>
<div fxFlex fxLayout="row" fxLayoutGap="10px">
<div
*ngFor="let sticker of stickerInfo.fileInfos"
(click)="onClickSelectSticker(sticker)"
class="sticker-item"
>
<img [src]="getStickerContentsImage(sticker)" />
</div>
</div>
</mat-tab>
</mat-tab-group>
</div>

View File

@ -0,0 +1,8 @@
.sticker-selector {
height: 200px;
overflow: auto;
}
.sticker-item {
cursor: pointer;
}

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { import {
StickerInfo, StickerInfo,
StickerFilesInfo, StickerFilesInfo,
@ -11,12 +11,49 @@ import {
styleUrls: ['./sticker-selector.component.scss'] styleUrls: ['./sticker-selector.component.scss']
}) })
export class StickerSelectorComponent implements OnInit { export class StickerSelectorComponent implements OnInit {
@Output()
selectedSticker = new EventEmitter<StickerFilesInfo>();
stickerBasePath = 'assets/sticker/';
stickerInfoList: StickerInfo[] = []; stickerInfoList: StickerInfo[] = [];
stickerFileInfoList: StickerFilesInfo[] = []; stickerFileInfoList: StickerFilesInfo[] = [];
currentSticker: StickerFilesInfo;
currentTabIndex: number;
constructor() {} constructor() {}
ngOnInit() { ngOnInit() {
this.stickerInfoList = StickerUtil.getStickerInfoList(); this.stickerInfoList = StickerUtil.getStickerInfoList();
this.currentTabIndex = 0;
}
onSelectedIndexChange(value: number) {
this.currentTabIndex = value;
}
getStickerTitleImage(
stickerInfo: StickerInfo,
hover: boolean,
tabIndex: number
) {
if (this.currentTabIndex === tabIndex) {
return this.stickerBasePath + stickerInfo.iconPathOn;
}
if (!hover) {
return this.stickerBasePath + stickerInfo.iconPath;
} else {
return this.stickerBasePath + stickerInfo.iconPathOn;
}
}
getStickerContentsImage(sticker: StickerFilesInfo) {
return this.stickerBasePath + sticker.path;
}
onClickSelectSticker(sticker: StickerFilesInfo) {
this.currentSticker = sticker;
this.selectedSticker.emit(sticker);
} }
} }

View File

@ -48,6 +48,7 @@ import {
import { SecondsToMinutesPipe } from './pipes/seconds-to-minutes.pipe'; import { SecondsToMinutesPipe } from './pipes/seconds-to-minutes.pipe';
import { LinkyPipe } from './pipes/linky.pipe'; import { LinkyPipe } from './pipes/linky.pipe';
import { StickerSelectorComponent } from './components/sticker-selector.component'; import { StickerSelectorComponent } from './components/sticker-selector.component';
import { MatTabsModule } from '@angular/material';
const COMPONENTS = [ const COMPONENTS = [
FileUploadQueueComponent, FileUploadQueueComponent,
@ -98,6 +99,7 @@ const SERVICES = [
MatSnackBarModule, MatSnackBarModule,
MatToolbarModule, MatToolbarModule,
MatTooltipModule, MatTooltipModule,
MatTabsModule,
DragDropModule DragDropModule
], ],
exports: [...COMPONENTS, ...DIRECTIVES, ...PIPES], exports: [...COMPONENTS, ...DIRECTIVES, ...PIPES],