대화방 > 스크롤 관련 로직 수정.

>> 스크롤 중 최근대화 유입시 스크롤 처리. 및 snackbar 로 유입대화 보기기능 추가.
This commit is contained in:
leejh 2019-11-07 13:14:44 +09:00
parent 43a4ee05dc
commit 0362bc427c
4 changed files with 122 additions and 42 deletions

View File

@ -95,11 +95,12 @@
<perfect-scrollbar <perfect-scrollbar
fxFlex="1 1 auto" fxFlex="1 1 auto"
#psChatContent #psChatContent
(psScrollUp)="scrollUpinit = true" (psScrollUp)="onScrollup($event)"
(psYReachStart)="onScrollup($event)" (psYReachStart)="onScrollReachStart($event)"
(psYReachEnd)="onScrollReachEnd($event)"
> >
<ucap-chat-messages <ucap-chat-messages
[messages]="eventList$ | async" [messages]="eventList"
[eventInfoStatus]="eventInfoStatus$ | async" [eventInfoStatus]="eventInfoStatus$ | async"
[eventRemain]="eventRemain$ | async" [eventRemain]="eventRemain$ | async"
[userInfos]="userInfoList" [userInfos]="userInfoList"

View File

@ -104,3 +104,11 @@
} }
} }
} }
::ng-deep .chat-snackbar-class {
.mat-simple-snackbar {
span {
@include ellipsis(1);
}
}
}

View File

@ -52,7 +52,11 @@ import {
} from '@ucap-webmessenger/ui-chat'; } 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'; import {
MatMenuTrigger,
MatSnackBarRef,
SimpleSnackBar
} from '@angular/material';
import { import {
CommonApiService, CommonApiService,
FileUploadItem, FileUploadItem,
@ -69,7 +73,7 @@ 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 } from '@ucap-webmessenger/core'; import { CONST, StringUtil } 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 {
@ -105,7 +109,9 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
loginRes: LoginResponse; loginRes: LoginResponse;
loginResSubscription: Subscription; loginResSubscription: Subscription;
eventList$: Observable<Info<EventJson>[]>; eventList: Info<EventJson>[];
eventListNew: Info<EventJson>[];
eventListSubscription: Subscription;
baseEventSeq = 0; baseEventSeq = 0;
roomInfo: RoomInfo; roomInfo: RoomInfo;
roomInfoSubscription: Subscription; roomInfoSubscription: Subscription;
@ -127,6 +133,8 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
/** Timer 대화방의 대화 삭제를 위한 interval */ /** Timer 대화방의 대화 삭제를 위한 interval */
interval: any; interval: any;
snackBarPreviewEvent: MatSnackBarRef<SimpleSnackBar>;
constructor( constructor(
private store: Store<any>, private store: Store<any>,
private sessionStorageService: SessionStorageService, private sessionStorageService: SessionStorageService,
@ -145,6 +153,13 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
); );
} }
setEventMoreInit() {
console.log('setEventMoreInit');
// 방정보가 바뀌면 이전대화 보기 관련 값들을 초기화 한다.
this.scrollUpinit = false;
this.eventMorePosition = 0;
}
ngOnInit() { ngOnInit() {
this.loginResSubscription = this.store this.loginResSubscription = this.store
.pipe( .pipe(
@ -161,9 +176,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
tap(roomInfo => { tap(roomInfo => {
this.roomInfo = roomInfo; this.roomInfo = roomInfo;
// 방정보가 바뀌면 이전대화 보기 관련 값들을 초기화 한다. this.setEventMoreInit();
this.scrollUpinit = false;
this.eventMorePosition = 0;
}) })
) )
.subscribe(); .subscribe();
@ -188,15 +201,27 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
}) })
); );
this.eventList$ = this.store.pipe( this.eventListSubscription = this.store
select(AppStore.MessengerSelector.EventSelector.selectAllInfoList), .pipe(
tap(infoList => { select(AppStore.MessengerSelector.EventSelector.selectAllInfoList),
if (!!infoList && infoList.length > 0) { tap(infoList => {
this.baseEventSeq = infoList[0].seq; if (!!this.eventList && this.eventList.length > 0) {
this.readyToReply(); this.eventListNew = infoList.filter(info => {
} if (info.seq <= this.eventList[this.eventList.length - 1].seq) {
}) return false;
); }
return true;
});
}
this.eventList = infoList;
if (!!infoList && infoList.length > 0) {
this.baseEventSeq = infoList[0].seq;
this.readyToReply();
}
})
)
.subscribe();
this.eventInfoStatus$ = this.store.pipe( this.eventInfoStatus$ = this.store.pipe(
select(AppStore.MessengerSelector.EventSelector.infoStatus) select(AppStore.MessengerSelector.EventSelector.infoStatus)
@ -219,6 +244,9 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
if (!!this.userInfoListSubscription) { if (!!this.userInfoListSubscription) {
this.userInfoListSubscription.unsubscribe(); this.userInfoListSubscription.unsubscribe();
} }
if (!!this.eventListSubscription) {
this.eventListSubscription.unsubscribe();
}
clearInterval(this.interval); clearInterval(this.interval);
} }
@ -259,6 +287,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
} }
} }
/** 대화전송 가능한 방인지 판단 */
getEnableSend() { getEnableSend() {
if (!this.roomInfo) { if (!this.roomInfo) {
return false; return false;
@ -287,8 +316,6 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
} }
} }
selectContact() {}
readyToReply(): void { readyToReply(): void {
setTimeout(() => { setTimeout(() => {
this.focusReplyInput(); this.focusReplyInput();
@ -304,6 +331,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
}); });
} }
/** Scroll Handler */
scrollToBottom(speed?: number): void { scrollToBottom(speed?: number): void {
if (this.eventMorePosition > 0) { if (this.eventMorePosition > 0) {
if (this.psChatContent.directiveRef) { if (this.psChatContent.directiveRef) {
@ -316,7 +344,34 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
speed speed
); );
this.scrollUpinit = false; this.eventMorePosition = 0;
});
}
} else if (this.scrollUpinit) {
if (!!this.eventListNew && this.eventListNew.length > 0) {
let message = '';
const info = this.eventListNew[this.eventListNew.length - 1];
const senderUser = this.userInfoList.filter(
user => user.seq === info.senderSeq
);
if (!!senderUser && senderUser.length > 0) {
message += `${senderUser[0].name} : `;
}
message += StringUtil.convertFinalEventMessage(
info.type,
info.sentMessageJson || info.sentMessage
);
this.snackBarPreviewEvent = this.snackBarService.open(message, 'GO', {
// duration: 3000,
verticalPosition: 'bottom',
horizontalPosition: 'center',
panelClass: ['chat-snackbar-class']
});
this.snackBarPreviewEvent.onAction().subscribe(() => {
this.setEventMoreInit();
this.scrollToBottom();
this.snackBarPreviewEvent.dismiss();
}); });
} }
} else { } else {
@ -330,8 +385,37 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
} }
} }
} }
onScrollup(event: any) {
this.scrollUpinit = true;
}
onScrollReachStart(event: any) {
this.onMoreEvent(this.baseEventSeq);
}
onScrollReachEnd(event: any) {
this.setEventMoreInit();
if (!!this.snackBarPreviewEvent) {
this.snackBarPreviewEvent.dismiss();
}
}
/** More Event */
onMoreEvent(seq: number) {
if (this.scrollUpinit && this.eventRemain) {
this.eventMorePosition = this.psChatContent.directiveRef.elementRef.nativeElement.scrollHeight;
this.store.dispatch(
EventStore.info({
roomSeq: this.roomInfo.roomSeq,
baseSeq: seq,
requestCount: CONST.EVENT_INFO_READ_COUNT
})
);
}
}
async onSendMessage(message: string) { async onSendMessage(message: string) {
this.setEventMoreInit();
if (!message || message.trim().length === 0) { if (!message || message.trim().length === 0) {
const result = await this.dialogService.open< const result = await this.dialogService.open<
AlertDialogComponent, AlertDialogComponent,
@ -378,24 +462,6 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewInit {
this.store.dispatch(RoomStore.updateOnlyAlarm({ roomInfo: this.roomInfo })); this.store.dispatch(RoomStore.updateOnlyAlarm({ roomInfo: this.roomInfo }));
} }
onScrollup(event: any) {
this.onMoreEvent(this.baseEventSeq);
}
/** More Event */
onMoreEvent(seq: number) {
if (this.scrollUpinit && this.eventRemain) {
this.store.dispatch(
EventStore.info({
roomSeq: this.roomInfo.roomSeq,
baseSeq: seq,
requestCount: CONST.EVENT_INFO_READ_COUNT
})
);
this.scrollUpinit = false;
this.eventMorePosition = this.psChatContent.directiveRef.elementRef.nativeElement.scrollHeight;
}
}
/** MassText Detail View */ /** MassText Detail View */
onMassDetail(value: number) { onMassDetail(value: number) {
this.store.dispatch( this.store.dispatch(

View File

@ -1,6 +1,11 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { MatSnackBar, MatSnackBarConfig } from '@angular/material'; import {
MatSnackBar,
MatSnackBarConfig,
MatSnackBarRef,
SimpleSnackBar
} from '@angular/material';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
@ -12,7 +17,7 @@ export class SnackBarService {
message: string, message: string,
action?: string, action?: string,
config?: MatSnackBarConfig config?: MatSnackBarConfig
): void { ): MatSnackBarRef<SimpleSnackBar> {
this.matSnackBar.open(message, action, config); return this.matSnackBar.open(message, action, config);
} }
} }