no message

This commit is contained in:
leejinho 2020-01-15 14:07:50 +09:00
commit d78506cb8e
8 changed files with 629 additions and 207 deletions

2
package-lock.json generated
View File

@ -1,6 +1,6 @@
{
"name": "ucap-webmessenger",
"version": "0.0.0",
"version": "0.0.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@ -0,0 +1,191 @@
<!-- MESSAGE -->
<div
#mbContainer
class="message-row hide"
[ngClass]="{
me: mine,
contact: !mine,
searched: searched
}"
>
<ucap-chat-message-box-read-here
id="message-box-readhere"
*ngIf="existReadToHere"
class="date-splitter"
>
</ucap-chat-message-box-read-here>
<ucap-chat-message-box-date-splitter
*ngIf="dateChanged"
class="date-splitter"
[message]="message"
>
</ucap-chat-message-box-date-splitter>
<div class="chat-row">
<div *ngIf="isInformation(message); then information; else contents"></div>
<ng-template #information>
<ng-container
class="bubble"
*ngIf="message.type !== EventType.NotificationForTimerRoom"
[ngSwitch]="message.type"
>
<ucap-chat-message-box-information
*ngSwitchCase="EventType.Join"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-information>
<ucap-chat-message-box-information
*ngSwitchCase="EventType.Exit"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-information>
<ucap-chat-message-box-information
*ngSwitchCase="EventType.ForcedExit"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-information>
<ucap-chat-message-box-information
*ngSwitchCase="EventType.RenameRoom"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-information>
<ucap-chat-message-box-information
*ngSwitchCase="EventType.GuideForRoomTimerChanged"
[message]="message"
[senderName]="senderName"
class="information-msg"
>
</ucap-chat-message-box-information>
</ng-container>
</ng-template>
<ng-template #contents>
<div *ngIf="profileImage != ''" class="profile-img thumbnail-mask">
<img
class="avatar"
ucapImage
[base]="profileImageRoot"
[path]="profileImage"
[default]="'assets/images/img_nophoto_50.png'"
(click)="onClickOpenProfile($event, message.senderSeq)"
/>
<!-- <ucap-ui-imaage
[style]="'width: 50px; height: 50px;'"
[imageClass]="'avatar'"
[base]="profileImageRoot"
[path]="profileImage"
[default]="'assets/images/img_nophoto_50.png'"
></ucap-ui-imaage> -->
</div>
<div class="message-main">
<div class="chat-name">
{{ senderName }}
</div>
<div class="bubble">
<ng-container
class="bubble"
*ngIf="message.type !== EventType.NotificationForTimerRoom"
[ngSwitch]="message.type"
>
<ucap-chat-message-box-mass
*ngSwitchCase="EventType.MassText"
[message]="message"
(massDetail)="onMassDetail($event)"
(contextmenu)="onContextMenu($event, message)"
>
</ucap-chat-message-box-mass>
<ucap-chat-message-box-file
*ngSwitchCase="EventType.File"
[eventInfoStatus]="eventInfoStatus"
[message]="message"
(save)="onSave($event)"
(fileViewer)="onFileViewer($event)"
(contextmenu)="onContextMenu($event, message)"
>
</ucap-chat-message-box-file>
<ucap-chat-message-box-sticker
*ngSwitchCase="EventType.Sticker"
[message]="message"
(contextmenu)="onContextMenu($event, message)"
>
</ucap-chat-message-box-sticker>
<ucap-chat-message-box-recall
*ngSwitchCase="EventType.RecalledMessage"
></ucap-chat-message-box-recall>
<ucap-chat-message-box-text
*ngSwitchCase="EventType.Character"
[message]="message"
(contextmenu)="onContextMenu($event, message)"
>
</ucap-chat-message-box-text>
<ucap-chat-message-box-schedule
*ngSwitchCase="EventType.Plan"
[message]="message"
(contextmenu)="onContextMenu($event, message)"
>
</ucap-chat-message-box-schedule>
<ucap-chat-message-box-translation
*ngSwitchCase="EventType.Translation"
[message]="message"
[translationSimpleview]="translationSimpleview"
[isMe]="mine"
(contextMenu)="onContextMenu($event, message)"
class="information-msg"
></ucap-chat-message-box-translation>
<ucap-chat-message-box-mass-translation
*ngSwitchCase="EventType.MassTranslation"
class="information-msg"
[message]="message"
[translationSimpleview]="translationSimpleview"
[isMe]="mine"
(contextMenu)="onContextMenu($event, message)"
(massTranslationDetail)="onMassTranslationDetail($event)"
>
</ucap-chat-message-box-mass-translation>
<ucap-chat-message-box-allim
*ngSwitchCase="EventType.AllimTms"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-allim>
<ucap-chat-message-box-allim
*ngSwitchCase="EventType.AllimElephant"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-allim>
<div *ngSwitchDefault>
<!--
notice
<ucap-chat-message-box-notice></ucap-chat-message-box-notice>
video-conference
<ucap-chat-message-box-video-conference></ucap-chat-message-box-video-conference>
<div class="message">
{{ message.sentMessage }}
</div> -->
{{ message.type }} / {{ message.sentMessage }}
</div>
</ng-container>
</div>
</div>
<div class="time secondary-text">
<ul>
<li *ngIf="unreadCount">{{ unreadCount }}</li>
<li>
{{ message.sendDate | ucapDate: 'a hh:mm' }}
</li>
</ul>
</div>
</ng-template>
</div>
</div>

View File

@ -0,0 +1,193 @@
.hide {
opacity: 0 !important;
}
$otherBox-line: #cccccc;
$otherBox-bg: #ffffff;
$meBox-line: #cccccc;
$meBox-bg: #ffffff;
.chat-messages {
padding: 30px 40px;
display: flex;
flex-direction: column;
}
.information-msg {
width: 100%;
}
.message-row {
width: 100%;
height: 100%;
margin-bottom: 20px;
.date-splitter {
display: block;
width: 100%;
margin-bottom: 10px;
}
.chat-row {
position: relative;
display: flex;
flex-direction: row;
margin-left: 0;
.profile-img {
flex: 0 0 auto;
&.thumbnail-mask {
border-radius: 50%;
width: 50px;
height: 50px;
overflow: hidden;
img {
width: 50px;
height: auto;
}
}
}
}
&.me {
.chat-row {
flex-direction: row-reverse;
margin-left: 0;
margin-right: 0;
.profile-info {
flex-direction: row-reverse;
display: flex;
justify-content: flex-end;
}
}
}
.message-main {
margin-left: 20px;
margin-right: 10px;
max-width: 80%;
.chat-name {
font-size: 12px;
color: #333333;
margin-bottom: 6px;
}
.bubble {
border-radius: 0 10px 10px 10px;
font-weight: 900;
position: relative;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.15);
word-break: break-all;
word-wrap: break-word;
}
}
.secondary-text {
align-self: flex-end;
font-size: 11px;
color: #666666;
word-wrap: break-word;
white-space: nowrap;
}
&.me {
.secondary-text {
text-align: end;
}
}
&.searched {
.bubble {
color: red;
}
}
}
/*.message-row.me > .bubble {
border: 1px solid $meBox-line;
background-color: $meBox-bg;
}*/
.message-row.me {
.profile-img {
display: none;
}
.chat-name {
display: none;
}
.message-main {
text-align: right;
margin-left: 10px;
margin-right: 20px;
.bubble {
border-radius: 10px 10px 0 10px;
}
/* & .bubble:before {
content: '';
width: 0px;
height: 0px;
position: absolute;
border-left: 6px solid $meBox-line;
border-right: 6px solid transparent;
border-top: 6px solid $meBox-line;
border-bottom: 6px solid transparent;
left: initial;
right: -12px;
top: 4px;
}
& .bubble:after {
content: '';
width: 0px;
height: 0px;
position: absolute;
border-left: 6px solid $meBox-bg;
border-right: 6px solid transparent;
border-top: 6px solid $meBox-bg;
border-bottom: 6px solid transparent;
left: initial;
right: -10px;
top: 5px;
}*/
}
}
.bubble-main {
word-wrap: break-word;
white-space: pre-wrap;
word-break: break-word;
}
::ng-deep .view-previous {
display: flex;
flex-flow: column;
//background-color: rgba(0, 0, 0, 0.4);
color: #ffffff;
justify-content: center;
justify-items: center;
margin: 10px 0 20px;
button {
height: 100%;
width: 100%;
line-height: 2em;
border-radius: 100px;
.mat-button-wrapper {
justify-items: center;
svg {
stroke: #ffffff;
align-self: center;
margin-right: 4px;
}
}
}
.unRead-count {
display: flex;
justify-items: self-end;
flex-flow: row;
align-items: flex-end;
height: 20px;
margin: 10px 0;
.line {
height: 1px;
background-color: #cccccc;
width: 40%;
flex: 1 1 auto;
margin-bottom: 10px;
display: inline-flex;
}
.count {
width: 260px;
font-size: 13px;
text-align: center;
font-weight: 600;
color: #333333;
}
}
}

View File

@ -0,0 +1,24 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MessageBoxComponent } from './message-box.component';
describe('Chat::MessageBoxComponent', () => {
let component: MessageBoxComponent;
let fixture: ComponentFixture<MessageBoxComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MessageBoxComponent]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MessageBoxComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,186 @@
import {
Component,
OnInit,
Input,
EventEmitter,
Output,
AfterViewInit,
ElementRef,
ViewChild
} from '@angular/core';
import {
Info,
EventType,
InfoResponse,
EventJson,
FileEventJson,
MassTranslationEventJson
} from '@ucap-webmessenger/protocol-event';
import { NGXLogger } from 'ngx-logger';
import { DatePipe } from '@angular/common';
import moment from 'moment';
import { FileDownloadItem } from '@ucap-webmessenger/api';
@Component({
selector: 'ucap-chat-message-box',
templateUrl: './message-box.component.html',
styleUrls: ['./message-box.component.scss']
})
export class MessageBoxComponent implements OnInit, AfterViewInit {
@Input()
message: Info<EventJson>;
@Input()
mine = false;
@Input()
searched = false;
@Input()
existReadToHere = false;
@Input()
dateChanged = false;
@Input()
senderName: string;
@Input()
profileImageRoot: string;
@Input()
profileImage: string;
@Input()
eventInfoStatus?: InfoResponse;
@Input()
translationSimpleview = false;
@Input()
unreadCount: number;
@Output()
openProfile = new EventEmitter<number>();
@Output()
massDetail = new EventEmitter<number>();
@Output()
massTranslationDetail = new EventEmitter<{
message: Info<MassTranslationEventJson>;
contentsType: string;
}>();
@Output()
fileViewer = new EventEmitter<FileEventJson>();
@Output()
save = new EventEmitter<{
fileInfo: FileEventJson;
fileDownloadItem: FileDownloadItem;
type: string;
}>();
@Output()
contextMenu = new EventEmitter<{
event: MouseEvent;
message: Info<EventJson>;
type?: string;
}>();
@ViewChild('mbContainer', { static: true })
mbContainer: ElementRef<HTMLElement>;
EventType = EventType;
moment = moment;
firstEventSeq = 0;
existReadHere = false;
constructor(
private elementRef: ElementRef<HTMLElement>,
private logger: NGXLogger,
private datePipe: DatePipe
) {}
ngOnInit() {
// this.elementRef.nativeElement.classList.add('hide');
}
ngAfterViewInit(): void {
this.logger.debug(
'offsetHeight' + this.message.seq,
this.elementRef.nativeElement.offsetHeight
);
this.elementRef.nativeElement.style.height = `${this.elementRef.nativeElement.offsetHeight}px`;
this.elementRef.nativeElement.style.maxHeight = `${this.elementRef.nativeElement.offsetHeight}px`;
this.mbContainer.nativeElement.classList.remove('hide');
}
/**
* Event .
* @description event , .
* Edit with reducers.ts / sync / updateRoomForNewEventMessage
*/
isInformation(info: Info<EventJson>) {
if (
info.type === EventType.Join ||
info.type === EventType.Exit ||
info.type === EventType.ForcedExit ||
info.type === EventType.RenameRoom ||
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<MassTranslationEventJson>;
contentsType: string;
}) {
this.massTranslationDetail.emit(params);
}
/** [Event] Image Viewer */
onFileViewer(fileInfo: FileEventJson) {
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<EventJson>) {
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 });
}
}
}

View File

@ -45,200 +45,26 @@
</div>
<!-- MESSAGE -->
<div
<ucap-chat-message-box
*ngFor="let message of messages; let i = index"
class="message-row"
[id]="message.seq"
[ngClass]="{
me: message.senderSeq === loginRes.userSeq,
contact: message.senderSeq !== loginRes.userSeq,
searched: getEventSearched(message.seq)
}"
[message]="message"
[mine]="message.senderSeq === loginRes.userSeq"
[searched]="getEventSearched(message.seq)"
[existReadToHere]="getReadHere(i) && existReadHere && !clearReadHere"
[dateChanged]="getDateSplitter(i)"
[senderName]="getUserName(message.senderSeq)"
[profileImageRoot]="profileImageRoot"
[profileImage]="getUserProfile(message.senderSeq)"
[eventInfoStatus]="eventInfoStatus"
[translationSimpleview]="translationSimpleview"
[unreadCount]="isShowUnreadCount ? getUnreadCount(message) : undefined"
(openProfile)="onClickOpenProfile($event)"
(massDetail)="onMassDetail($event)"
(massTranslationDetail)="onMassTranslationDetail($event)"
(fileViewer)="onFileViewer($event)"
(save)="onSave($event)"
(contextMenu)="onContextMenu($event)"
>
<ucap-chat-message-box-read-here
id="message-box-readhere"
*ngIf="getReadHere(i) && existReadHere && !clearReadHere"
class="date-splitter"
>
</ucap-chat-message-box-read-here>
<ucap-chat-message-box-date-splitter
*ngIf="getDateSplitter(i)"
class="date-splitter"
[message]="message"
>
</ucap-chat-message-box-date-splitter>
<div class="chat-row">
<div
*ngIf="getIsInformation(message); then information; else contents"
></div>
<ng-template #information>
<ng-container
class="bubble"
*ngIf="message.type !== EventType.NotificationForTimerRoom"
[ngSwitch]="message.type"
>
<ucap-chat-message-box-information
*ngSwitchCase="EventType.Join"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-information>
<ucap-chat-message-box-information
*ngSwitchCase="EventType.Exit"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-information>
<ucap-chat-message-box-information
*ngSwitchCase="EventType.ForcedExit"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-information>
<ucap-chat-message-box-information
*ngSwitchCase="EventType.RenameRoom"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-information>
<ucap-chat-message-box-information
*ngSwitchCase="EventType.GuideForRoomTimerChanged"
[message]="message"
[senderName]="getUserName(message.senderSeq)"
class="information-msg"
>
</ucap-chat-message-box-information>
</ng-container>
</ng-template>
<ng-template #contents>
<div
*ngIf="getUserProfile(message.senderSeq) != ''"
class="profile-img thumbnail-mask"
>
<img
class="avatar"
ucapImage
[base]="profileImageRoot"
[path]="getUserProfile(message.senderSeq)"
[default]="'assets/images/img_nophoto_50.png'"
(click)="onClickOpenProfile($event, message.senderSeq)"
/>
<!-- <ucap-ui-imaage
[style]="'width: 50px; height: 50px;'"
[imageClass]="'avatar'"
[base]="profileImageRoot"
[path]="getUserProfile(message.senderSeq)"
[default]="'assets/images/img_nophoto_50.png'"
></ucap-ui-imaage> -->
</div>
<div class="message-main">
<div class="chat-name">
{{ getUserName(message.senderSeq) }}
</div>
<div class="bubble">
<ng-container
class="bubble"
*ngIf="message.type !== EventType.NotificationForTimerRoom"
[ngSwitch]="message.type"
>
<ucap-chat-message-box-mass
*ngSwitchCase="EventType.MassText"
[message]="message"
(massDetail)="onMassDetail($event)"
(contextmenu)="onContextMenuMessage($event, message)"
>
</ucap-chat-message-box-mass>
<ucap-chat-message-box-file
*ngSwitchCase="EventType.File"
[eventInfoStatus]="eventInfoStatus"
[message]="message"
(save)="onSave($event)"
(fileViewer)="onFileViewer($event)"
(contextmenu)="onContextMenuMessage($event, message)"
>
</ucap-chat-message-box-file>
<ucap-chat-message-box-sticker
*ngSwitchCase="EventType.Sticker"
[message]="message"
(contextmenu)="onContextMenuMessage($event, message)"
>
</ucap-chat-message-box-sticker>
<ucap-chat-message-box-recall
*ngSwitchCase="EventType.RecalledMessage"
></ucap-chat-message-box-recall>
<ucap-chat-message-box-text
*ngSwitchCase="EventType.Character"
[message]="message"
(contextmenu)="onContextMenuMessage($event, message)"
>
</ucap-chat-message-box-text>
<ucap-chat-message-box-schedule
*ngSwitchCase="EventType.Plan"
[message]="message"
(contextmenu)="onContextMenuMessage($event, message)"
>
</ucap-chat-message-box-schedule>
<ucap-chat-message-box-translation
*ngSwitchCase="EventType.Translation"
[message]="message"
[translationSimpleview]="translationSimpleview"
[isMe]="message.senderSeq === loginRes.userSeq"
(contextMenu)="onContextMenuMessage($event, message)"
class="information-msg"
></ucap-chat-message-box-translation>
<ucap-chat-message-box-mass-translation
*ngSwitchCase="EventType.MassTranslation"
class="information-msg"
[message]="message"
[translationSimpleview]="translationSimpleview"
[isMe]="message.senderSeq === loginRes.userSeq"
(contextMenu)="onContextMenuMessage($event, message)"
(massTranslationDetail)="onMassTranslationDetail($event)"
>
</ucap-chat-message-box-mass-translation>
<ucap-chat-message-box-allim
*ngSwitchCase="EventType.AllimTms"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-allim>
<ucap-chat-message-box-allim
*ngSwitchCase="EventType.AllimElephant"
[message]="message"
class="information-msg"
>
</ucap-chat-message-box-allim>
<div *ngSwitchDefault>
<!--
notice
<ucap-chat-message-box-notice></ucap-chat-message-box-notice>
video-conference
<ucap-chat-message-box-video-conference></ucap-chat-message-box-video-conference>
<div class="message">
{{ message.sentMessage }}
</div> -->
{{ message.type }} / {{ message.sentMessage }}
</div>
</ng-container>
</div>
</div>
<div class="time secondary-text">
<ul>
<li *ngIf="isShowUnreadCount">{{ getUnreadCount(message) }}</li>
<li>
{{ message.sendDate | ucapDate: 'a hh:mm' }}
</li>
</ul>
</div>
</ng-template>
</div>
</div>
</ucap-chat-message-box>
</div>

View File

@ -209,10 +209,7 @@ export class MessagesComponent implements OnInit {
return false;
}
onClickOpenProfile(event: MouseEvent, userSeq: number) {
event.preventDefault();
event.stopPropagation();
onClickOpenProfile(userSeq: number) {
this.openProfile.emit(userSeq);
}
@ -250,14 +247,11 @@ export class MessagesComponent implements OnInit {
}
/** [Event] Context Menu */
onContextMenuMessage(event: any, message: Info<EventJson>) {
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 });
}
onContextMenu(event: {
event: MouseEvent;
message: Info<EventJson>;
type?: string;
}) {
this.contextMenu.emit(event);
}
}

View File

@ -10,10 +10,14 @@ import { MatInputModule } from '@angular/material/input';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { TranslateModule } from '@ngx-translate/core';
import { UCapUiModule } from '@ucap-webmessenger/ui';
import { FormComponent } from './components/form.component';
import { MessageBoxComponent } from './components/message-box.component';
import { MessagesComponent } from './components/messages.component';
import { SearchComponent } from './components/search.component';
import { DateSplitterComponent as MBDateSplitterComponent } from './components/message-box/date-splitter.component';
import { FileComponent as MBFileComponent } from './components/message-box/file.component';
@ -32,13 +36,17 @@ import { TranslationComponent as MBTranslationComponent } from './components/mes
import { VideoComponent as MBVideoComponent } from './components/message-box/video.component';
import { VideoConferenceComponent as MBVideoConferenceComponent } from './components/message-box/video-conference.component';
import { AllimComponent as MBAllimComponent } from './components/message-box/allim.component';
<<<<<<< HEAD
import { SearchComponent } from './components/search.component';
import { TranslateModule } from '@ngx-translate/core';
import { MatTooltipModule } from '@angular/material';
=======
>>>>>>> 704b2a09834f43610fe3eaaf982c94be25927985
const COMPONENTS = [
FormComponent,
MessagesComponent,
MessageBoxComponent,
SearchComponent,
MBDateSplitterComponent,