Merge branch 'master' of https://git.loafle.net/ucap-web/next-ucap-messenger
This commit is contained in:
commit
7438d1d691
|
@ -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%;
|
||||||
|
|
|
@ -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
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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({}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,5 +114,5 @@ textarea {
|
||||||
}
|
}
|
||||||
|
|
||||||
.mat-error {
|
.mat-error {
|
||||||
font-size: 0.8em;
|
font-size: 0.84em;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user