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