This commit is contained in:
leejinho 2020-01-31 14:32:41 +09:00
commit 7438d1d691
14 changed files with 160 additions and 80 deletions

View File

@ -126,7 +126,7 @@
.file-drop-zone { .file-drop-zone {
position: absolute; position: absolute;
padding: 10px 10px 0 10px; padding: 10px;
background-color: rgb(54, 54, 54, 0.8); background-color: rgb(54, 54, 54, 0.8);
bottom: 0; bottom: 0;
width: 100%; width: 100%;

View File

@ -1772,10 +1772,13 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
// CASE :: searching text after retrieve All event Infos. // CASE :: searching text after retrieve All event Infos.
this.store.dispatch( this.store.dispatch(
EventStore.infoAll({ EventStore.infoAll({
req: {
roomSeq: this.roomInfoSubject.value.roomSeq, roomSeq: this.roomInfoSubject.value.roomSeq,
baseSeq: this.eventListSubject.value[0].seq, baseSeq: this.eventListSubject.value[0].seq,
requestCount: requestCount:
environment.productConfig.CommonSetting.eventRequestDefaultCount * 2 environment.productConfig.CommonSetting.eventRequestDefaultCount * 2
},
infoList: undefined
}) })
); );

View File

@ -50,7 +50,7 @@ export const infoForSearchEnd = createAction(
export const infoAll = createAction( export const infoAll = createAction(
'[Messenger::Event] Info All', '[Messenger::Event] Info All',
props<InfoRequest>() props<{ req: InfoRequest; infoList: Info<EventJson>[] }>()
); );
export const fileInfo = createAction( export const fileInfo = createAction(

View File

@ -412,7 +412,10 @@ export class Effects {
) )
) )
), ),
switchMap(([req, processing]) => { switchMap(([params, processing]) => {
const req = params.req;
const mergedInfoList = params.infoList;
return this.eventProtocolService.info(req).pipe( return this.eventProtocolService.info(req).pipe(
map(async res => { map(async res => {
switch (res.SSVC_TYPE) { switch (res.SSVC_TYPE) {
@ -421,31 +424,39 @@ export class Effects {
break; break;
case SSVC_TYPE_EVENT_INFO_RES: case SSVC_TYPE_EVENT_INFO_RES:
{ {
if (!!infoList && 0 < infoList.length) {
infoList = infoList.sort((a, b) => a.seq - b.seq);
}
if (
infoList.length > 0 &&
infoList.length >= req.requestCount &&
processing
) {
// 재귀
this.store.dispatch(
infoAll({
req: {
roomSeq: req.roomSeq,
baseSeq: infoList[0].seq,
requestCount: req.requestCount
},
infoList: !!mergedInfoList
? [...infoList, ...mergedInfoList]
: infoList
})
);
} else {
this.store.dispatch( this.store.dispatch(
infoMoreSuccess({ infoMoreSuccess({
infoList, infoList: !!mergedInfoList
? [...infoList, ...mergedInfoList]
: infoList,
res: res as InfoResponse, res: res as InfoResponse,
remainInfo: remainInfo:
infoList.length === req.requestCount ? true : false infoList.length === req.requestCount ? true : false
}) })
); );
if (infoList.length > 0) {
if (infoList.length === req.requestCount && processing) {
// 재귀
this.store.dispatch(
infoAll({
roomSeq: req.roomSeq,
baseSeq: infoList[0].seq,
requestCount: req.requestCount
})
);
} else {
if (infoList.length < req.requestCount) {
this.store.dispatch(infoForSearchEnd({}));
}
}
} else {
this.store.dispatch(infoForSearchEnd({})); this.store.dispatch(infoForSearchEnd({}));
} }
} }

View File

@ -23,6 +23,7 @@
</ucap-chat-message-box-date-splitter> </ucap-chat-message-box-date-splitter>
<div <div
#mbChatRow
class="chat-row" class="chat-row"
[@shake]="{ [@shake]="{
value: shakeIt, value: shakeIt,

View File

@ -96,6 +96,9 @@ export class MessageBoxComponent implements OnInit, AfterViewInit {
@ViewChild('mbContainer', { static: true }) @ViewChild('mbContainer', { static: true })
mbContainer: ElementRef<HTMLElement>; mbContainer: ElementRef<HTMLElement>;
@ViewChild('mbChatRow', { static: true })
mbChatRow: ElementRef<HTMLElement>;
EventType = EventType; EventType = EventType;
moment = moment; moment = moment;
@ -104,7 +107,12 @@ export class MessageBoxComponent implements OnInit, AfterViewInit {
existReadHere = false; existReadHere = false;
shakeIt = false; shakeIt = false;
get offsetTop() {
return this.mbChatRow.nativeElement.offsetTop;
}
constructor( constructor(
private elementRef: ElementRef<HTMLElement>,
private changeDetectorRef: ChangeDetectorRef, private changeDetectorRef: ChangeDetectorRef,
private logger: NGXLogger private logger: NGXLogger
) {} ) {}
@ -114,14 +122,12 @@ export class MessageBoxComponent implements OnInit, AfterViewInit {
} }
ngAfterViewInit(): void { ngAfterViewInit(): void {
// this.logger.debug( this.logger.debug(
// 'offsetHeight' + this.message.seq, 'offsetHeight' + this.message.seq,
// this.mbContainer.nativeElement.offsetHeight this.mbContainer.nativeElement.offsetHeight
// ); );
// this.elementRef.nativeElement.style.height = `${this.mbContainer this.elementRef.nativeElement.style.height = `${this.mbContainer.nativeElement.offsetHeight}px`;
// .nativeElement.offsetHeight + 20}px`; this.elementRef.nativeElement.style.maxHeight = `${this.mbContainer.nativeElement.offsetHeight}px`;
// this.elementRef.nativeElement.style.maxHeight = `${this.mbContainer
// .nativeElement.offsetHeight + 20}px`;
this.mbContainer.nativeElement.classList.remove('hide'); this.mbContainer.nativeElement.classList.remove('hide');
} }

View File

@ -1,4 +1,5 @@
$tablet-s-width: 768px; $tablet-s-width: 768px;
.bubble-main { .bubble-main {
display: flex; display: flex;
flex-direction: row; flex-direction: row;

View File

@ -6,10 +6,10 @@
background-color: rgba(0, 0, 0, 0.4); background-color: rgba(0, 0, 0, 0.4);
padding: 6px 20px; padding: 6px 20px;
color: #ffffff; color: #ffffff;
border-radius: 100px; border-radius: 20px;
justify-content: center; justify-content: center;
justify-items: center; justify-items: center;
margin: 10px 0 20px; margin: 10px 0 20px;
font-size: 0.9em; font-size: 0.9em;
line-height:1.2em line-height: 1.2em;
} }

View File

@ -1,11 +1,13 @@
$tablet-s-width: 768px;
.bubble-main { .bubble-main {
display:flex; display: flex;
flex-direction: row; flex-direction: row;
padding: 14px; padding: 14px;
.file-thumbimg{ .file-thumbimg {
display:inline-flex; display: inline-flex;
img { img {
height:140px; height: 140px;
padding-right: 20px; padding-right: 20px;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
@ -15,8 +17,8 @@
flex-direction: column; flex-direction: column;
text-align: left; text-align: left;
line-height: 1.6em; line-height: 1.6em;
min-width:100px; min-width: 100px;
margin-top:10px; margin-top: 10px;
.file-name { .file-name {
font-size: 14px; font-size: 14px;
font-weight: bold; font-weight: bold;
@ -41,28 +43,34 @@
width: 100%; width: 100%;
li { li {
width: 50%; width: 50%;
height:100%; height: 100%;
display: inline-block; display: inline-block;
text-align: center; text-align: center;
align-items: center; align-items: center;
font-size: 13px; font-size: 13px;
border-right: 1px solid #dddddd; border-right: 1px solid #dddddd;
@media screen and (max-width: #{$tablet-s-width}) {
width: 30%;
}
&:last-child { &:last-child {
border-right: none; border-right: none;
@media screen and (max-width: #{$tablet-s-width}) {
width: 70%;
}
} }
.mat-button { .mat-button {
width: 100%; width: 100%;
height:100%; height: 100%;
display: block; display: block;
} }
} }
&.expired{ &.expired {
li{ li {
width:100%; width: 100%;
white-space: nowrap; white-space: nowrap;
color:#999999; color: #999999;
align-items: center; align-items: center;
line-height:40px; line-height: 40px;
} }
} }
} }

View File

@ -31,6 +31,7 @@ import { TranslateService } from '@ngx-translate/core';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { VirtualScrollerComponent, IPageInfo } from 'ngx-virtual-scroller'; import { VirtualScrollerComponent, IPageInfo } from 'ngx-virtual-scroller';
import { MessageBoxComponent } from './message-box.component'; import { MessageBoxComponent } from './message-box.component';
import { PerfectScrollbarDirective } from 'ngx-perfect-scrollbar';
@Component({ @Component({
selector: 'ucap-chat-messages', selector: 'ucap-chat-messages',
@ -122,6 +123,7 @@ export class MessagesComponent implements OnInit, OnDestroy {
chatMessageBoxList: QueryList<MessageBoxComponent>; chatMessageBoxList: QueryList<MessageBoxComponent>;
storedScrollItem: Info<EventJson>; // 이전대화를 불러올 경우 현재 스크롤 포지션 유지를 위한 값. 0 이면 초기로딩. storedScrollItem: Info<EventJson>; // 이전대화를 불러올 경우 현재 스크롤 포지션 유지를 위한 값. 0 이면 초기로딩.
storedScrollItemOffsetTop: number | undefined;
scrollUpInitalized = false; // ps 에서 초기 로딩시 scroll reach start 이벤트 발생 버그를 우회하기 위한 init 값으로 scrollUp 에 의해 true 로 된다. scrollUpInitalized = false; // ps 에서 초기 로딩시 scroll reach start 이벤트 발생 버그를 우회하기 위한 init 값으로 scrollUp 에 의해 true 로 된다.
firstCheckReadHere = true; firstCheckReadHere = true;
initRoomLastEventSeq: number; initRoomLastEventSeq: number;
@ -395,6 +397,19 @@ export class MessagesComponent implements OnInit, OnDestroy {
this.storedScrollItem = this.eventList[ this.storedScrollItem = this.eventList[
this.virtualScroller.viewPortInfo.startIndex this.virtualScroller.viewPortInfo.startIndex
]; ];
const chatMessageBox = this.chatMessageBoxList.find(
el =>
el.message.seq ===
this.eventList[this.virtualScroller.viewPortInfo.startIndex].seq
);
if (!!chatMessageBox) {
this.storedScrollItemOffsetTop =
chatMessageBox.offsetTop -
this.virtualScroller.viewPortInfo.scrollStartPosition;
} else {
this.storedScrollItemOffsetTop = 0;
}
} }
swapScrollTo( swapScrollTo(
@ -402,20 +417,32 @@ export class MessagesComponent implements OnInit, OnDestroy {
preCallback: () => void, preCallback: () => void,
postCallback: () => void, postCallback: () => void,
useHide: boolean, useHide: boolean,
useSwap: boolean useSwap: boolean,
addtionalOffset?: number
) { ) {
this.preSwapScroll(useHide, useSwap); this.preSwapScroll(useHide, useSwap);
if (!!preCallback) { if (!!preCallback) {
preCallback(); preCallback();
} }
this.virtualScroller.scrollInto(to, true, 0, 0, () => {
this.virtualScroller.scrollInto(
to,
true,
undefined !== this.storedScrollItemOffsetTop
? -this.storedScrollItemOffsetTop
: undefined !== addtionalOffset
? -addtionalOffset
: 0,
0,
() => {
setTimeout(() => { setTimeout(() => {
if (!!postCallback) { if (!!postCallback) {
postCallback(); postCallback();
} }
this.postSwapScroll(useHide, useSwap); this.postSwapScroll(useHide, useSwap);
}); });
}); }
);
} }
preSwapScroll(useHide: boolean, useSwap: boolean) { preSwapScroll(useHide: boolean, useSwap: boolean) {
@ -465,15 +492,12 @@ export class MessagesComponent implements OnInit, OnDestroy {
true true
); );
} else { } else {
const index = this.eventList.findIndex(
i => i.seq === this.storedScrollItem.seq
);
this.swapScrollTo( this.swapScrollTo(
1 <= index ? this.eventList[index - 1] : this.eventList[0], this.storedScrollItem,
() => {}, () => {},
() => { () => {
this.storedScrollItem = undefined; this.storedScrollItem = undefined;
this.storedScrollItemOffsetTop = undefined;
}, },
true, true,
true true
@ -525,18 +549,21 @@ export class MessagesComponent implements OnInit, OnDestroy {
// 방정보가 바뀌면 이전대화 보기 관련 값들을 초기화 한다. // 방정보가 바뀌면 이전대화 보기 관련 값들을 초기화 한다.
this.scrollUpInitalized = false; this.scrollUpInitalized = false;
this.storedScrollItem = undefined; this.storedScrollItem = undefined;
this.storedScrollItemOffsetTop = undefined;
} }
clear() {} clear() {}
gotoPosition(eventSeq: number) { gotoPosition(eventSeq: number) {
const viewPortItemIndex = this.virtualScroller.viewPortItems.findIndex(
v => v.seq === eventSeq
);
if (!!this.virtualScroller) { if (!!this.virtualScroller) {
const index = this.eventList.findIndex(v => v.seq === eventSeq); const e = this.eventList.find(v => v.seq === eventSeq);
this.virtualScroller.scrollInto( this.swapScrollTo(
1 <= index ? this.eventList[index - 1] : this.eventList[0], e,
true, () => {},
0,
100,
() => { () => {
const chatMessageBox = this.chatMessageBoxList.find( const chatMessageBox = this.chatMessageBoxList.find(
el => el.message.seq === eventSeq el => el.message.seq === eventSeq
@ -544,7 +571,10 @@ export class MessagesComponent implements OnInit, OnDestroy {
if (!!chatMessageBox) { if (!!chatMessageBox) {
chatMessageBox.shake(); chatMessageBox.shake();
} }
} },
-1 === viewPortItemIndex,
-1 === viewPortItemIndex,
50
); );
} }
} }
@ -558,13 +588,14 @@ export class MessagesComponent implements OnInit, OnDestroy {
event.stopPropagation(); event.stopPropagation();
if (this.scrollUpInitalized && this.eventRemained) { if (this.scrollUpInitalized && this.eventRemained) {
this.virtualScroller.scrollToPosition(0);
this.virtualScroller.invalidateCachedMeasurementAtIndex(0);
this.storeScrollPosition(); this.storeScrollPosition();
this.preSwapScroll(true, true); this.preSwapScroll(true, true);
this.moreEvent.emit(this.eventList[0].seq); this.moreEvent.emit(this.eventList[0].seq);
this.virtualScroller.invalidateCachedMeasurementAtIndex(0);
} }
} }

View File

@ -114,5 +114,5 @@ textarea {
} }
.mat-error { .mat-error {
font-size: 0.8em; font-size: 0.84em;
} }

View File

@ -34,6 +34,8 @@ mat-icon {
border: none; border: none;
width: 20px; width: 20px;
height: 20px; height: 20px;
justify-items: center;
justify-content: center;
i { i {
font-family: 'material-outline-icons'; font-family: 'material-outline-icons';
font-size: 20px; font-size: 20px;

View File

@ -34,8 +34,11 @@
</div> </div>
</div> </div>
<div *ngIf="uploadItems" fxLayout="column"> <div *ngIf="uploadItems" fxLayout="column" class="uploadItems">
<div>{{ 'common.file.dropZoneForUpload' | translate }}</div> <div class="msg-guide">
<span class="icon-img"><i class="mid mdi-arrow-expand-all"></i></span
>{{ 'common.file.dropZoneForUpload' | translate }}
</div>
<div></div> <div></div>
</div> </div>
</div> </div>

View File

@ -38,4 +38,18 @@
padding: 6px 10px; padding: 6px 10px;
} }
} }
.uploadItems {
width: 100%;
font-size: 0.9em;
.msg-guide {
display: flex;
flex: row;
color: #ffffff;
justify-content: center;
align-items: center;
.icon-img {
margin-right: 6px;
}
}
}
} }