import { ChatConversationType, ChatCustomMessageBody, ChatMessage, ChatMessageType, ChatMultiDeviceEvent, ChatSearchDirection, } from '../rename.chat'; import { timeoutTask } from '../utils'; import { gNewRequestConversationId, gNewRequestConversationMsgEventType, gNewRequestConversationState, gNewRequestConversationTip, gNewRequestConversationUserAvatar, gNewRequestConversationUserId, gNewRequestConversationUserName, } from './const'; import type { RequestList, RequestListListener } from './requestList.types'; import type { ChatService, ChatServiceListener, ResultCallback } from './types'; import type { NewRequestModel, NewRequestStateType } from './types.ui'; import { getNewRequest } from './utils'; let gListener: ChatServiceListener | undefined; const gUserList: Map = new Map(); /** * Request List Implementation. */ export class RequestListImpl implements RequestList { _client: ChatService; _listener?: ChatServiceListener; _newRequestList: NewRequestModel[] = []; _userList: Map; constructor(client: ChatService) { this._client = client; this._userList = gUserList; } init() { this.unInit(); gListener = { onContactInvited: this.bindOnContactInvited.bind(this), onFriendRequestAccepted: this.bindOnFriendRequestAccepted.bind(this), onFriendRequestDeclined: this.bindOnFriendRequestDeclined.bind(this), onConversationEvent: this.bindOnConversationEvent.bind(this), onContactEvent: this.bindOnContactEvent.bind(this), }; this._client.addListener(gListener); } unInit() { this.reset(); if (gListener) { this._client.removeListener(gListener); gListener = undefined; } } reset() { this._newRequestList = []; this._userList.clear(); } addListener(key: string, listener: RequestListListener) { this._userList.set(key, listener); } removeListener(key: string) { this._userList.delete(key); } emitNewRequestListChanged(changed: number) { for (const listener of this._userList.values()) { timeoutTask(0, () => listener.onNewRequestListChanged([...this._newRequestList], changed) ); } } bindOnContactInvited(userId: string): void { const isExisted = this._newRequestList.findIndex((v) => { const t2 = v.msg?.body.type === ChatMessageType.CUSTOM; if (t2 === true) { const body = v.msg?.body as ChatCustomMessageBody; const t3 = body.event === gNewRequestConversationMsgEventType; const t1 = v.msg?.attributes[gNewRequestConversationUserId] === userId; return t1 === true && t3 === true; } return false; }); if (isExisted !== -1) { return; } const newMsg = ChatMessage.createCustomMessage( gNewRequestConversationId, gNewRequestConversationMsgEventType ); newMsg.attributes[gNewRequestConversationUserId] = userId; newMsg.attributes[gNewRequestConversationUserName] = userId; newMsg.attributes[gNewRequestConversationUserAvatar] = ''; newMsg.attributes[gNewRequestConversationState] = 'pending' as NewRequestStateType; newMsg.attributes[gNewRequestConversationTip] = '_uikit_new_quest_list_item_tip'; this._client.getUserInfo({ userId: userId, onResult: (res) => { if (res.isOk && res.value) { newMsg.attributes[gNewRequestConversationUserName] = res.value.userName; newMsg.attributes[gNewRequestConversationUserAvatar] = res.value.avatarURL; const item = getNewRequest(newMsg); if (item) { this._newRequestList.unshift(item); } this._client.insertMessage({ message: newMsg, onResult: () => { this.emitNewRequestListChanged(1); }, }); } else { const item = getNewRequest(newMsg); if (item) { this._newRequestList.unshift(item); } this._client.insertMessage({ message: newMsg, onResult: () => { this.emitNewRequestListChanged(1); }, }); } }, }); } bindOnFriendRequestAccepted(userId: string): void { for (const request of this._newRequestList) { if (request.requestId === userId) { request.state = 'accepted'; this.removeRequest(request); break; } } } bindOnFriendRequestDeclined(userId: string): void { for (const request of this._newRequestList) { if (request.requestId === userId) { request.state = 'declined'; this.removeRequest(request); break; } } } bindOnConversationEvent( event?: ChatMultiDeviceEvent, convId?: string, _convType?: ChatConversationType ): void { if (event === ChatMultiDeviceEvent.CONTACT_ACCEPT) { for (const request of this._newRequestList) { if (request.requestId === convId) { this.removeRequest(request); break; } } } else if (event === ChatMultiDeviceEvent.CONTACT_DECLINE) { for (const request of this._newRequestList) { if (request.requestId === convId) { this.removeRequest(request); break; } } } } bindOnContactEvent( event?: ChatMultiDeviceEvent, target?: string, _ext?: string ): void { if (event === ChatMultiDeviceEvent.CONTACT_ACCEPT) { for (const request of this._newRequestList) { if (request.requestId === target) { this.removeRequest(request); break; } } } } getRequestList(params: { onResult: ResultCallback; }): void { if (this._newRequestList.length > 0) { params.onResult({ isOk: true, value: this._newRequestList }); return; } // this._client.removeConversation({ convId: gNewRequestConversationId }); this._client.getNewRequestList({ convId: gNewRequestConversationId, convType: 0, pageSize: 200, direction: ChatSearchDirection.UP, onResult: (result) => { if (result.isOk) { if (result.value) { const list = result.value .map((v) => { return getNewRequest(v); }) .filter((v) => { return v !== undefined; }) as NewRequestModel[]; const uniqueList = list.filter( (item, index, self) => index === self.findIndex((t) => t.requestId === item.requestId) ); this._newRequestList = uniqueList; params.onResult({ isOk: true, value: this._newRequestList }); } else { params.onResult({ isOk: true, value: [], }); } } }, }); } updateRequest(request: NewRequestModel) { if (request.msg === undefined) { return; } // !!! why is isFrozen, see `Object.isFrozen()` request.msg = { ...request.msg } as ChatMessage; request.msg.attributes = { [gNewRequestConversationUserId]: request.requestId, [gNewRequestConversationUserName]: request.name, [gNewRequestConversationUserAvatar]: request.avatar, [gNewRequestConversationState]: request.state, [gNewRequestConversationTip]: request.tip, }; for (let index = 0; index < this._newRequestList.length; index++) { const localRequest = this._newRequestList[index]; if ( localRequest?.requestId === request.requestId && localRequest.state !== 'accepted' && localRequest?.state !== 'declined' ) { this._newRequestList[index] = request; } } this._client.updateMessage({ message: request.msg, onResult: () => { this.emitNewRequestListChanged(0); }, }); } removeRequest(request: NewRequestModel) { if (request.msg === undefined) { return; } let isExisted = false; for (let index = 0; index < this._newRequestList.length; index++) { const localRequest = this._newRequestList[index]; if (localRequest?.requestId === request.requestId) { this._newRequestList.splice(index, 1); isExisted = true; break; } } if (isExisted === true) { this._client.removeMessage({ message: request.msg, onResult: () => { this.emitNewRequestListChanged(-1); }, }); } } }