messengerControllers.ts 3.9 Ko
Télécharger le fichier
import { MarkMessengerReadComposer, RequestMessengerHistoryComposer, SendMessengerMessageComposer } from '@octane/renderer';
import { MessengerMessage, MessengerState, selectMessageByClientId, selectMessages } from '../../../api';
import { MessengerAction } from '../../../api/friends/messenger/messengerReducer';
type Dispatch = (action: MessengerAction) => void;
type Send = (composer: object) => void;
export const createMessengerHistoryController = (
getState: () => MessengerState,
dispatch: Dispatch,
send: Send,
makeRequest: (conversationId: number, beforeMessageId: number, limit: number) => object = (conversationId, beforeMessageId, limit) => new RequestMessengerHistoryComposer(conversationId, beforeMessageId, limit)
) => ({
loadInitial(conversationId: number)
{
if(conversationId <= 0) return;
const history = getState().historyByConversation[conversationId];
if(history?.loading || history?.loaded) return;
dispatch({ type: 'historyLoading', conversationId });
send(makeRequest(conversationId, 0, 50));
},
loadOlder(conversationId: number)
{
const state = getState();
const history = state.historyByConversation[conversationId];
if(history?.loading || history?.hasMore === false) return;
const beforeMessageId = selectMessages(state, conversationId).find(message => message.id > 0)?.id || 0;
dispatch({ type: 'historyLoading', conversationId });
send(makeRequest(conversationId, beforeMessageId, 30));
}
});
export const createMessengerActionsController = (
getState: () => MessengerState,
dispatch: Dispatch,
send: Send,
getOwnUserId: () => number,
initialConfirmationId: number = 1,
makeSend: (conversationId: number, recipientId: number, confirmationId: number, type: number, text: string, metadata: string) => object = (conversationId, recipientId, confirmationId, type, text, metadata) => new SendMessengerMessageComposer(conversationId, recipientId, confirmationId, type, text, metadata),
makeRead: (conversationId: number, messageId: number) => object = (conversationId, messageId) => new MarkMessengerReadComposer(conversationId, messageId),
scheduleTimeout: (callback: () => void, delay: number) => unknown = (callback, delay) => globalThis.setTimeout(callback, delay)
) =>
{
let nextConfirmationId = initialConfirmationId;
const sendMessage = (conversationId: number, recipientId: number, text: string, type: number = 0, metadata: string = '') =>
{
const confirmationId = nextConfirmationId++;
const clientId = `c-${ confirmationId }`;
const message: MessengerMessage = { id: 0, clientId, conversationId, senderId: getOwnUserId(), type, message: text, metadata, createdAt: Math.floor(Date.now() / 1000), status: 'sending' };
dispatch({ type: 'messageOptimistic', message });
send(makeSend(conversationId, recipientId, confirmationId, type, text, metadata));
scheduleTimeout(() =>
{
if(selectMessageByClientId(getState(), clientId)?.status === 'sending') dispatch({ type: 'messageFailed', clientId, errorCode: 7 });
}, 10_000);
return { clientId, confirmationId };
};
return {
openDirectConversation(participantId: number, name: string)
{
dispatch({ type: 'directConversationOpened', participantId, name });
},
sendMessage,
retryMessage(clientId: string)
{
const failed = selectMessageByClientId(getState(), clientId);
if(!failed || failed.status !== 'failed') return null;
const recipientId = getState().conversationsById[failed.conversationId]?.participantId || 0;
return sendMessage(failed.conversationId, recipientId, failed.message, failed.type, failed.metadata);
},
markRead(conversationId: number, messageId: number)
{
send(makeRead(conversationId, messageId));
}
};
};
