contextMenu of messages is modified

This commit is contained in:
병준 박 2019-10-16 16:33:19 +09:00
parent 0dd36a92db
commit 0c1ae7ec64
6 changed files with 166 additions and 67 deletions

View File

@ -60,11 +60,10 @@ export class GroupComponent implements OnInit, OnDestroy {
@ViewChild('profileContextMenuTrigger', { static: true }) @ViewChild('profileContextMenuTrigger', { static: true })
profileContextMenuTrigger: MatMenuTrigger; profileContextMenuTrigger: MatMenuTrigger;
profileContextMenuPosition = { x: '0px', y: '0px' };
@ViewChild('groupContextMenuTrigger', { static: true }) @ViewChild('groupContextMenuTrigger', { static: true })
groupContextMenuTrigger: MatMenuTrigger; groupContextMenuTrigger: MatMenuTrigger;
profileContextMenuPosition = { x: '0px', y: '0px' };
groupContextMenuPosition = { x: '0px', y: '0px' }; groupContextMenuPosition = { x: '0px', y: '0px' };
groupBuddyList$: Observable< groupBuddyList$: Observable<

View File

@ -5,20 +5,37 @@
<div fxFlex fxLayout="row" fxLayoutAlign="space-between center"> <div fxFlex fxLayout="row" fxLayoutAlign="space-between center">
<div fxLayout="row" fxLayoutAlign="start center"> <div fxLayout="row" fxLayoutAlign="start center">
<!-- RESPONSIVE CHATS BUTTON--> <!-- RESPONSIVE CHATS BUTTON-->
<button mat-icon-button aria-label="chats button" fxHide.gt-md class="responsive-chats-button"> <button
mat-icon-button
aria-label="chats button"
fxHide.gt-md
class="responsive-chats-button"
>
<mat-icon>chat</mat-icon> <mat-icon>chat</mat-icon>
</button> </button>
<!-- / RESPONSIVE CHATS BUTTON--> <!-- / RESPONSIVE CHATS BUTTON-->
</div> </div>
<div> <div>
<button *ngIf="!!roomInfo" mat-icon-button (click)="onClickReceiveAlarm($event)" <button
aria-label="Toggle Receive Alarm"> *ngIf="!!roomInfo"
<mat-icon class="amber-fg" *ngIf="roomInfo.receiveAlarm">notifications_active</mat-icon> mat-icon-button
<mat-icon class="secondary-text" *ngIf="!roomInfo.receiveAlarm">notifications_off</mat-icon> (click)="onClickReceiveAlarm($event)"
aria-label="Toggle Receive Alarm"
>
<mat-icon class="amber-fg" *ngIf="roomInfo.receiveAlarm"
>notifications_active</mat-icon
>
<mat-icon class="secondary-text" *ngIf="!roomInfo.receiveAlarm"
>notifications_off</mat-icon
>
</button> </button>
<button mat-icon-button [matMenuTriggerFor]="contactMenu" aria-label="more"> <button
mat-icon-button
[matMenuTriggerFor]="contactMenu"
aria-label="more"
>
<mat-icon>more_vert</mat-icon> <mat-icon>more_vert</mat-icon>
</button> </button>
@ -31,7 +48,10 @@
</div> </div>
</mat-toolbar> </mat-toolbar>
<!-- / CHAT TOOLBAR --> <!-- / CHAT TOOLBAR -->
<mat-progress-bar *ngIf="eventListProcessing$ | async" mode="indeterminate"></mat-progress-bar> <mat-progress-bar
*ngIf="eventListProcessing$ | async"
mode="indeterminate"
></mat-progress-bar>
<!-- CHAT CONTENT --> <!-- CHAT CONTENT -->
<div fxFlex="1 1 auto" class="chat-content" #messageBoxContainer> <div fxFlex="1 1 auto" class="chat-content" #messageBoxContainer>
<!-- Timer Room Info --> <!-- Timer Room Info -->
@ -39,9 +59,16 @@
<!-- Timer Room Info --> <!-- Timer Room Info -->
<!-- CHAT MESSAGES --> <!-- CHAT MESSAGES -->
<ucap-chat-messages [messages]="eventList$ | async" [userInfos]="userInfoList$ | async" [loginRes]="loginRes" <ucap-chat-messages
[sessionVerInfo]="sessionVerInfo" (massDetail)="onMassDetail($event)" (save)="onSave($event)" [messages]="eventList$ | async"
(imageViewer)="onImageViewer($event)"> [userInfos]="userInfoList$ | async"
[loginRes]="loginRes"
[sessionVerInfo]="sessionVerInfo"
(massDetail)="onMassDetail($event)"
(save)="onSave($event)"
(imageViewer)="onImageViewer($event)"
(contextMenu)="onContextMenuMessage($event)"
>
</ucap-chat-messages> </ucap-chat-messages>
<!-- CHAT MESSAGES --> <!-- CHAT MESSAGES -->
</div> </div>
@ -56,3 +83,49 @@
<!-- / CHAT FOOTER--> <!-- / CHAT FOOTER-->
</div> </div>
<!-- / CHAT --> <!-- / CHAT -->
<div
style="visibility: hidden; position: fixed"
[style.left]="messageContextMenuPosition.x"
[style.top]="messageContextMenuPosition.y"
#messageContextMenuTrigger="matMenuTrigger"
[matMenuTriggerFor]="messageContextMenu"
></div>
<mat-menu #messageContextMenu="matMenu" [overlapTrigger]="false">
<ng-template matMenuContent let-message="message" let-loginRes="loginRes">
<ng-container *ngIf="!isRecalledMessage(message.type)">
<button
mat-menu-item
*ngIf="isCopyableMessage(message.type)"
(click)="onClickMessageContextMenu('COPY', message)"
>
대화 복사
</button>
<button
mat-menu-item
(click)="onClickMessageContextMenu('REPLAY', message)"
>
대화 전달
</button>
<button
mat-menu-item
(click)="onClickMessageContextMenu('REPLAY_TO_ME', message)"
>
대화 나에게 전달
</button>
<button
mat-menu-item
(click)="onClickMessageContextMenu('DELETE', message)"
>
대화 삭제
</button>
<button
mat-menu-item
*ngIf="isRecallableMessage(message, loginRes.userSeq)"
(click)="onClickMessageContextMenu('RECALL', message)"
>
대화 회수
</button>
</ng-container>
</ng-template>
</mat-menu>

View File

@ -10,7 +10,13 @@ import { ucapAnimations } from '@ucap-webmessenger/ui';
import { Store, select } from '@ngrx/store'; import { Store, select } from '@ngrx/store';
import { NGXLogger } from 'ngx-logger'; import { NGXLogger } from 'ngx-logger';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { Info, EventType } from '@ucap-webmessenger/protocol-event'; import {
Info,
EventType,
isRecalled,
isCopyable,
isRecallable
} from '@ucap-webmessenger/protocol-event';
import * as AppStore from '@app/store'; import * as AppStore from '@app/store';
import * as EventStore from '@app/store/messenger/event'; import * as EventStore from '@app/store/messenger/event';
@ -24,6 +30,7 @@ import { tap } from 'rxjs/operators';
import { FileInfo } from '@ucap-webmessenger/ui-chat'; import { FileInfo } from '@ucap-webmessenger/ui-chat';
import { KEY_VER_INFO } from '@app/types/ver-info.type'; import { KEY_VER_INFO } from '@app/types/ver-info.type';
import { VersionInfo2Response } from '@ucap-webmessenger/api-public'; import { VersionInfo2Response } from '@ucap-webmessenger/api-public';
import { MatMenuTrigger } from '@angular/material';
@Component({ @Component({
selector: 'app-layout-messenger-messages', selector: 'app-layout-messenger-messages',
@ -35,6 +42,10 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
@ViewChild('messageBoxContainer', { static: true }) @ViewChild('messageBoxContainer', { static: true })
private messageBoxContainer: ElementRef; private messageBoxContainer: ElementRef;
@ViewChild('messageContextMenuTrigger', { static: true })
messageContextMenuTrigger: MatMenuTrigger;
messageContextMenuPosition = { x: '0px', y: '0px' };
loginRes: LoginResponse; loginRes: LoginResponse;
loginResSubscription: Subscription; loginResSubscription: Subscription;
eventList$: Observable<Info[]>; eventList$: Observable<Info[]>;
@ -46,6 +57,10 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
KEY_VER_INFO KEY_VER_INFO
); );
isRecalledMessage = isRecalled;
isCopyableMessage = isCopyable;
isRecallableMessage = isRecallable;
constructor( constructor(
private store: Store<any>, private store: Store<any>,
private sessionStorageService: SessionStorageService, private sessionStorageService: SessionStorageService,
@ -143,4 +158,46 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
onSave(value: { fileInfo: FileInfo; type: string }) { onSave(value: { fileInfo: FileInfo; type: string }) {
this.logger.debug('fileSave', value); this.logger.debug('fileSave', value);
} }
onContextMenuMessage(params: { event: MouseEvent; message: Info }) {
params.event.preventDefault();
params.event.stopPropagation();
this.messageContextMenuPosition.x = params.event.clientX + 'px';
this.messageContextMenuPosition.y = params.event.clientY + 'px';
this.messageContextMenuTrigger.menu.focusFirstItem('mouse');
this.messageContextMenuTrigger.menuData = {
message: params.message,
loginRes: this.loginRes
};
this.messageContextMenuTrigger.openMenu();
}
onClickMessageContextMenu(menuType: string, message: Info) {
switch (menuType) {
case 'COPY':
{
this.logger.debug('onClickMessageContextMenu', menuType, message);
}
break;
case 'REPLAY':
{
}
break;
case 'REPLAY_TO_ME':
{
}
break;
case 'DELETE':
{
}
break;
case 'RECALL':
{
}
break;
default:
break;
}
}
} }

View File

@ -14,3 +14,19 @@ export interface Info {
// 수신자수 // 수신자수
receiverCount: number; receiverCount: number;
} }
export function isCopyable(eventType: EventType): boolean {
return (
EventType.Character === eventType || EventType.Translation === eventType
);
}
export function isRecalled(eventType: EventType): boolean {
return EventType.RecalledMessage === eventType;
}
export function isRecallable(event: Info, userSeq: number): boolean {
return (
event.senderSeq === userSeq && event.type !== EventType.RecalledMessage
);
}

View File

@ -92,9 +92,7 @@
<ucap-chat-message-box-text <ucap-chat-message-box-text
*ngSwitchCase="EventType.Character" *ngSwitchCase="EventType.Character"
[message]="message" [message]="message"
(contextmenu)=" (contextmenu)="onContextMenuMessage($event, message)"
onContextMenuMessage($event, EventType.Character, message)
"
> >
</ucap-chat-message-box-text> </ucap-chat-message-box-text>
<div *ngSwitchDefault> <div *ngSwitchDefault>
@ -120,23 +118,3 @@
</ng-template> </ng-template>
</div> </div>
</div> </div>
<div
style="visibility: hidden; position: fixed"
[style.left]="messageContextMenuPosition.x"
[style.top]="messageContextMenuPosition.y"
[matMenuTriggerFor]="messageContextMenu"
></div>
<mat-menu #messageContextMenu="matMenu" [overlapTrigger]="false">
<ng-template matMenuContent let-eventType="eventType" let-message="message">
<ng-container *ngIf="!isRecalledMessage(eventType)">
<button mat-menu-item *ngIf="isCopyableMessage(eventType)">
대화 복사
</button>
<button mat-menu-item>대화 전달</button>
<button mat-menu-item>대화 나에게 전달</button>
<button mat-menu-item>대화 삭제</button>
<button mat-menu-item *ngIf="isRecallable(message)">대화 회수</button>
</ng-container>
</ng-template>
</mat-menu>

View File

@ -43,10 +43,11 @@ export class MessagesComponent implements OnInit {
@Output() @Output()
save = new EventEmitter<{ fileInfo: FileInfo; type: string }>(); save = new EventEmitter<{ fileInfo: FileInfo; type: string }>();
@ViewChildren(MatMenuTrigger) menuTriggerList: QueryList<MatMenuTrigger>; @Output()
@ViewChild('messageContextMenu', { static: true }) contextMenu = new EventEmitter<{
messageContextMenu: MatMenu; event: MouseEvent;
messageContextMenuPosition = { x: '0px', y: '0px' }; message: Info;
}>();
EventType = EventType; EventType = EventType;
profileImageRoot: string; profileImageRoot: string;
@ -126,23 +127,6 @@ export class MessagesComponent implements OnInit {
return false; return false;
} }
isCopyableMessage(eventType: EventType): boolean {
return (
EventType.Character === eventType || EventType.Translation === eventType
);
}
isRecalledMessage(eventType: EventType): boolean {
return EventType.RecalledMessage === eventType;
}
isRecallable(message: Info): boolean {
return (
message.senderSeq === this.loginRes.userSeq &&
message.type !== EventType.RecalledMessage
);
}
/** [Event] MassTalk Detail View */ /** [Event] MassTalk Detail View */
onMassDetail(value: number) { onMassDetail(value: number) {
this.massDetail.emit(value); this.massDetail.emit(value);
@ -158,15 +142,7 @@ export class MessagesComponent implements OnInit {
this.save.emit(value); this.save.emit(value);
} }
onContextMenuMessage(event: MouseEvent, eventType: EventType, message: Info) { onContextMenuMessage(event: MouseEvent, message: Info) {
event.preventDefault(); this.contextMenu.emit({ event, message });
this.messageContextMenu.focusFirstItem('mouse');
this.messageContextMenuPosition.x = event.clientX + 'px';
this.messageContextMenuPosition.y = event.clientY + 'px';
const messageContextMenuTrigger = this.menuTriggerList.toArray()[0];
messageContextMenuTrigger.menuData = { eventType, message };
messageContextMenuTrigger.openMenu();
} }
} }