대화방 > 이전 대화 보기 기능 구현. infinity scroll
This commit is contained in:
parent
4b4f8a0067
commit
749237b1bc
|
@ -19,7 +19,8 @@
|
|||
{{ getRoomName() }}
|
||||
</div>
|
||||
<div *ngIf="!!roomInfo && roomInfo.isTimeRoom">
|
||||
<mat-icon>timer</mat-icon> {{ getConvertTimer(roomInfo.timeRoomInterval) }}
|
||||
<mat-icon>timer</mat-icon>
|
||||
{{ getConvertTimer(roomInfo.timeRoomInterval) }}
|
||||
</div>
|
||||
<div class="room-option">
|
||||
<button
|
||||
|
@ -73,13 +74,19 @@
|
|||
<!-- Timer Room Info -->
|
||||
|
||||
<!-- CHAT MESSAGES -->
|
||||
<perfect-scrollbar fxFlex="1 1 auto" #psChatContent>
|
||||
<perfect-scrollbar
|
||||
fxFlex="1 1 auto"
|
||||
#psChatContent
|
||||
(psYReachStart)="onScrollup($event)"
|
||||
>
|
||||
<ucap-chat-messages
|
||||
[messages]="eventList$ | async"
|
||||
[eventInfoStatus]="eventInfoStatus$ | async"
|
||||
[eventRemain]="eventRemain$ | async"
|
||||
[userInfos]="userInfoList"
|
||||
[loginRes]="loginRes"
|
||||
[sessionVerInfo]="sessionVerInfo"
|
||||
(moreEvent)="onMoreEvent($event)"
|
||||
(massDetail)="onMassDetail($event)"
|
||||
(save)="onSave($event)"
|
||||
(imageViewer)="onImageViewer($event)"
|
||||
|
|
|
@ -58,7 +58,7 @@ import {
|
|||
ImageViewerDialogData,
|
||||
ImageViewerDialogResult
|
||||
} from '@app/layouts/common/dialogs/image-viewer.dialog.component';
|
||||
import { Maximum_Range } from '@ucap-webmessenger/core';
|
||||
import { CONST } from '@ucap-webmessenger/core';
|
||||
import { PerfectScrollbarComponent } from 'ngx-perfect-scrollbar';
|
||||
|
||||
@Component({
|
||||
|
@ -83,12 +83,15 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
|||
loginRes: LoginResponse;
|
||||
loginResSubscription: Subscription;
|
||||
eventList$: Observable<Info[]>;
|
||||
baseEventSeq = 0;
|
||||
roomInfo: RoomInfo;
|
||||
roomInfoSubscription: Subscription;
|
||||
userInfoList: UserInfo[];
|
||||
userInfoListSubscription: Subscription;
|
||||
eventListProcessing$: Observable<boolean>;
|
||||
eventInfoStatus$: Observable<InfoResponse>;
|
||||
eventRemain$: Observable<boolean>;
|
||||
eventRemain = false;
|
||||
sessionVerInfo: VersionInfo2Response;
|
||||
|
||||
isRecalledMessage = isRecalled;
|
||||
|
@ -148,8 +151,20 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
|||
select(AppStore.MessengerSelector.EventSelector.infoListProcessing)
|
||||
);
|
||||
|
||||
this.eventRemain$ = this.store.pipe(
|
||||
select(AppStore.MessengerSelector.EventSelector.remainInfo),
|
||||
tap(remainInfo => {
|
||||
this.eventRemain = remainInfo;
|
||||
})
|
||||
);
|
||||
|
||||
this.eventList$ = this.store.pipe(
|
||||
select(AppStore.MessengerSelector.EventSelector.selectAllInfoList)
|
||||
select(AppStore.MessengerSelector.EventSelector.selectAllInfoList),
|
||||
tap(infoList => {
|
||||
if (!!infoList && infoList.length > 0) {
|
||||
this.baseEventSeq = infoList[0].seq;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
this.eventInfoStatus$ = this.store.pipe(
|
||||
|
@ -229,7 +244,7 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
|||
return;
|
||||
}
|
||||
|
||||
if (message.trim().length > Maximum_Range.MassText) {
|
||||
if (message.trim().length > CONST.MASSTEXT_LEN) {
|
||||
// MASS TEXT
|
||||
this.store.dispatch(
|
||||
EventStore.sendMass({
|
||||
|
@ -260,6 +275,22 @@ export class MessagesComponent implements OnInit, OnDestroy, AfterViewChecked {
|
|||
this.store.dispatch(RoomStore.updateOnlyAlarm({ roomInfo: this.roomInfo }));
|
||||
}
|
||||
|
||||
onScrollup(event: any) {
|
||||
this.onMoreEvent(this.baseEventSeq);
|
||||
}
|
||||
/** More Event */
|
||||
onMoreEvent(seq: number) {
|
||||
if (this.eventRemain) {
|
||||
this.store.dispatch(
|
||||
EventStore.info({
|
||||
roomSeq: this.roomInfo.roomSeq,
|
||||
baseSeq: seq,
|
||||
requestCount: CONST.EVENT_INFO_READ_COUNT
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/** MassText Detail View */
|
||||
onMassDetail(value: number) {
|
||||
this.store.dispatch(
|
||||
|
|
|
@ -29,6 +29,14 @@ export const infoSuccess = createAction(
|
|||
}>()
|
||||
);
|
||||
|
||||
export const infoMoreSuccess = createAction(
|
||||
'[Messenger::Event] Info More Success',
|
||||
props<{
|
||||
infoList: Info[];
|
||||
res: InfoResponse;
|
||||
}>()
|
||||
);
|
||||
|
||||
export const infoFailure = createAction(
|
||||
'[Messenger::Event] Info Failure',
|
||||
props<{ error: any }>()
|
||||
|
|
|
@ -67,7 +67,8 @@ import {
|
|||
forwardFailure,
|
||||
forwardAfterRoomOpen,
|
||||
sendMass,
|
||||
sendMassFailure
|
||||
sendMassFailure,
|
||||
infoMoreSuccess
|
||||
} from './actions';
|
||||
import { SessionStorageService } from '@ucap-webmessenger/web-storage';
|
||||
import {
|
||||
|
@ -81,6 +82,7 @@ import { openSuccess, openFailure } from '../room';
|
|||
import { LoginResponse } from '@ucap-webmessenger/protocol-authentication';
|
||||
import { KEY_LOGIN_RES_INFO } from '@app/types/login-res-info.type';
|
||||
import { StatusCode } from '@ucap-webmessenger/api';
|
||||
import { CONST } from '@ucap-webmessenger/core';
|
||||
|
||||
@Injectable()
|
||||
export class Effects {
|
||||
|
@ -91,7 +93,7 @@ export class Effects {
|
|||
return info({
|
||||
roomSeq: action.roomSeq,
|
||||
baseSeq: 0,
|
||||
requestCount: 50
|
||||
requestCount: CONST.EVENT_INFO_READ_COUNT
|
||||
});
|
||||
})
|
||||
)
|
||||
|
@ -115,12 +117,21 @@ export class Effects {
|
|||
break;
|
||||
case SSVC_TYPE_EVENT_INFO_RES:
|
||||
{
|
||||
if (req.baseSeq === 0) {
|
||||
this.store.dispatch(
|
||||
infoSuccess({
|
||||
infoList,
|
||||
res: res as InfoResponse
|
||||
})
|
||||
);
|
||||
} else {
|
||||
this.store.dispatch(
|
||||
infoMoreSuccess({
|
||||
infoList,
|
||||
res: res as InfoResponse
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
if (req.baseSeq === 0) {
|
||||
// 최초 이벤트 목록 조회시 SSVC_TYPE_EVENT_READ_REQ 수행.
|
||||
|
|
|
@ -6,10 +6,12 @@ import {
|
|||
info,
|
||||
infoFailure,
|
||||
recallInfoList,
|
||||
delInfoList
|
||||
delInfoList,
|
||||
infoMoreSuccess
|
||||
} from './actions';
|
||||
import * as AuthenticationStore from '@app/store/account/authentication';
|
||||
import { Info, EventType } from '@ucap-webmessenger/protocol-event';
|
||||
import { CONST } from '@ucap-webmessenger/core';
|
||||
|
||||
export const reducer = createReducer(
|
||||
initialState,
|
||||
|
@ -27,7 +29,27 @@ export const reducer = createReducer(
|
|||
...state.infoList
|
||||
}),
|
||||
infoStatus: action.res,
|
||||
infoListProcessing: false
|
||||
infoListProcessing: false,
|
||||
remainInfo:
|
||||
!!action.infoList &&
|
||||
action.infoList.length === CONST.EVENT_INFO_READ_COUNT
|
||||
? true
|
||||
: false
|
||||
};
|
||||
}),
|
||||
on(infoMoreSuccess, (state, action) => {
|
||||
return {
|
||||
...state,
|
||||
infoList: adapterInfoList.upsertMany(action.infoList, {
|
||||
...state.infoList
|
||||
}),
|
||||
infoStatus: action.res,
|
||||
infoListProcessing: false,
|
||||
remainInfo:
|
||||
!!action.infoList &&
|
||||
action.infoList.length === CONST.EVENT_INFO_READ_COUNT
|
||||
? true
|
||||
: false
|
||||
};
|
||||
}),
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ export interface State {
|
|||
infoListProcessing: boolean;
|
||||
infoList: InfoListState;
|
||||
infoStatus: InfoResponse | null;
|
||||
remainInfo: boolean;
|
||||
}
|
||||
|
||||
export const adapterInfoList = createEntityAdapter<Info>({
|
||||
|
@ -22,7 +23,8 @@ const infoListInitialState: InfoListState = adapterInfoList.getInitialState({});
|
|||
export const initialState: State = {
|
||||
infoListProcessing: false,
|
||||
infoList: infoListInitialState,
|
||||
infoStatus: null
|
||||
infoStatus: null,
|
||||
remainInfo: false
|
||||
};
|
||||
|
||||
const {
|
||||
|
@ -43,6 +45,10 @@ export function selectors<S>(selector: Selector<any, State>) {
|
|||
selector,
|
||||
(state: State) => state.infoListProcessing
|
||||
),
|
||||
remainInfo: createSelector(
|
||||
selector,
|
||||
(state: State) => state.remainInfo
|
||||
),
|
||||
infoList: createSelector(
|
||||
selector,
|
||||
(state: State) => state.infoList
|
||||
|
|
|
@ -101,6 +101,7 @@ import {
|
|||
|
||||
import * as ChatStore from '@app/store/messenger/chat';
|
||||
import * as RoomStore from '@app/store/messenger/room';
|
||||
import { CONST } from '@ucap-webmessenger/core';
|
||||
|
||||
@Injectable()
|
||||
export class Effects {
|
||||
|
@ -405,7 +406,7 @@ export class Effects {
|
|||
divCd: 'DivCodeT',
|
||||
roomName: '',
|
||||
isTimerRoom: true,
|
||||
timerRoomInterval: 24 * 60 * 60, // 24h default
|
||||
timerRoomInterval: CONST.DEFAULT_TIMER_ROOM_INTERVAL, // 24h default
|
||||
userSeqs: userSeqList
|
||||
}
|
||||
})
|
||||
|
|
10
projects/ucap-webmessenger-core/src/lib/type/const.type.ts
Normal file
10
projects/ucap-webmessenger-core/src/lib/type/const.type.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
export enum CONST {
|
||||
/** 대용량 텍스트로 보내는 문자열의 길이 기준 */
|
||||
MASSTEXT_LEN = 800,
|
||||
/** 대화방의 이벤트를 조회하는 개수 */
|
||||
EVENT_INFO_READ_COUNT = 50,
|
||||
/** Timer Room 최초 오픈시 timer interval */
|
||||
DEFAULT_TIMER_ROOM_INTERVAL = 24 * 60 * 60,
|
||||
/** 한번에 채팅을 할 수 있는 인원수 제한 */
|
||||
CHATROOM_USER = 300
|
||||
}
|
|
@ -1,4 +0,0 @@
|
|||
export enum Maximum_Range {
|
||||
MassText = 800,
|
||||
ChatRoom = 300
|
||||
}
|
|
@ -7,12 +7,12 @@ export * from './lib/type/call-alarm.type';
|
|||
export * from './lib/type/call-forward.type';
|
||||
export * from './lib/type/call-mode.type';
|
||||
export * from './lib/type/caller-type.type';
|
||||
export * from './lib/type/const.type';
|
||||
export * from './lib/type/default-screen.type';
|
||||
export * from './lib/type/device-devision.type';
|
||||
export * from './lib/type/device-type.type';
|
||||
export * from './lib/type/file-transfer-permissions.type';
|
||||
export * from './lib/type/locale-code.type';
|
||||
export * from './lib/type/maximum-range.type';
|
||||
export * from './lib/type/notification-method.type';
|
||||
export * from './lib/type/organization-chart-permissions.type';
|
||||
export * from './lib/type/push-type.type';
|
||||
|
|
|
@ -35,8 +35,6 @@ export interface InfoResponse extends ProtocolResponse {
|
|||
baseSeq: number;
|
||||
// 유효한파일기준이벤트SEQ(n)
|
||||
validFileBaseSeq: number;
|
||||
// 이벤트정보 개수(n)
|
||||
count: number;
|
||||
}
|
||||
|
||||
export const encodeInfo: ProtocolEncoder<InfoRequest> = (req: InfoRequest) => {
|
||||
|
@ -82,7 +80,6 @@ export const decodeInfo: ProtocolDecoder<InfoResponse> = (
|
|||
return decodeProtocolMessage(message, {
|
||||
roomSeq: message.bodyList[0],
|
||||
baseSeq: message.bodyList[1],
|
||||
validFileBaseSeq: message.bodyList[2],
|
||||
count: message.bodyList[3]
|
||||
validFileBaseSeq: message.bodyList[2]
|
||||
} as InfoResponse);
|
||||
};
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
<div class="chat-messages">
|
||||
<!-- <div class="message-row" *ngIf="eventRemain">
|
||||
<button mat-button (click)="onClickMore($event)">이전 대화 보기</button>
|
||||
</div> -->
|
||||
<!-- MESSAGE -->
|
||||
<div
|
||||
*ngFor="let message of messages; let i = index"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { CONST } from '@ucap-webmessenger/core';
|
||||
import {
|
||||
Component,
|
||||
OnInit,
|
||||
|
@ -32,17 +33,20 @@ export class MessagesComponent implements OnInit {
|
|||
@Input()
|
||||
eventInfoStatus?: InfoResponse;
|
||||
@Input()
|
||||
eventRemain: boolean;
|
||||
@Input()
|
||||
userInfos?: UserInfo[];
|
||||
@Input()
|
||||
sessionVerInfo: VersionInfo2Response;
|
||||
|
||||
@Output()
|
||||
moreEvent = new EventEmitter<number>();
|
||||
@Output()
|
||||
massDetail = new EventEmitter<number>();
|
||||
@Output()
|
||||
imageViewer = new EventEmitter<FileInfo>();
|
||||
@Output()
|
||||
save = new EventEmitter<{ fileInfo: FileInfo; type: string }>();
|
||||
|
||||
@Output()
|
||||
contextMenu = new EventEmitter<{
|
||||
event: MouseEvent;
|
||||
|
@ -50,6 +54,7 @@ export class MessagesComponent implements OnInit {
|
|||
}>();
|
||||
|
||||
EventType = EventType;
|
||||
CONST = CONST;
|
||||
profileImageRoot: string;
|
||||
|
||||
constructor(private logger: NGXLogger, private datePipe: DatePipe) {}
|
||||
|
@ -138,6 +143,13 @@ export class MessagesComponent implements OnInit {
|
|||
return false;
|
||||
}
|
||||
|
||||
onClickMore(event: any) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
this.moreEvent.emit(this.messages[0].seq);
|
||||
}
|
||||
|
||||
/** [Event] MassTalk Detail View */
|
||||
onMassDetail(value: number) {
|
||||
this.massDetail.emit(value);
|
||||
|
|
Loading…
Reference in New Issue
Block a user