diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index ddf43edd3..f27f9d694 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -289,6 +289,9 @@ export type ConversationsStateType = { selectedConversation?: string; // NOTE the messages that are in view messages: Array; + // NOTE the quotes that are in view + // key is message [timestamp]-[author-pubkey] + quotes: Record; firstUnreadMessageId: string | undefined; messageDetailProps?: MessagePropsDetails; showRightPanel: boolean; @@ -340,26 +343,67 @@ async function getMessages({ }: { conversationKey: string; messageId: string | null; -}): Promise> { +}): Promise<{ + messagesProps: Array; + quotesProps: Record; +}> { const beforeTimestamp = Date.now(); const conversation = getConversationController().get(conversationKey); if (!conversation) { // no valid conversation, early return window?.log?.error('Failed to get convo on reducer.'); - return []; + return { messagesProps: [], quotesProps: {} }; } const messageSet = await Data.getMessagesByConversation(conversationKey, { messageId, }); - const messageProps: Array = messageSet.models.map(m => + const messagesProps: Array = messageSet.models.map(m => m.getMessageModelProps() ); const time = Date.now() - beforeTimestamp; - window?.log?.info(`Loading ${messageProps.length} messages took ${time}ms to load.`); - return messageProps; + window?.log?.info(`Loading ${messagesProps.length} messages took ${time}ms to load.`); + + const quotesProps: Record = {}; + messagesProps + .filter( + message => message.propsForMessage?.quote?.messageId && message.propsForMessage.quote?.sender + ) + .forEach(async message => { + const id = message.propsForMessage?.quote?.messageId; + const sender = message.propsForMessage.quote?.sender; + + // TODO use this is the renderering process + // const contact = message.findAndFormatContact(author); + // const authorName = contact?.profileName || contact?.name || ''; + + if (id && sender) { + const timestamp = Number(id); + // See if message is already in memory if not lookup in db + let results = []; + results = messagesProps.filter( + message => + message.propsForMessage.timestamp === timestamp && + message.propsForMessage.sender === sender + ); + + if (results.length) { + message = results[0]; + } else { + const dbResult = ( + await Data.getMessageBySenderAndTimestamp({ source: sender, timestamp }) + )?.getMessageModelProps(); + if (dbResult) { + message = dbResult; + } + } + quotesProps[`${timestamp}-${sender}`] = message; + } + }); + + return { messagesProps, quotesProps }; } export type SortedMessageModelProps = MessageModelPropsWithoutConvoProps & { @@ -391,7 +435,7 @@ export const fetchTopMessagesForConversation = createAsyncThunk( window.log.info('fetchTopMessagesForConversation: we are already at the top'); return null; } - const messagesProps = await getMessages({ + const { messagesProps } = await getMessages({ conversationKey, messageId: oldTopMessageId, }); @@ -428,7 +472,7 @@ export const fetchBottomMessagesForConversation = createAsyncThunk( window.log.info('fetchBottomMessagesForConversation: we are already at the bottom'); return null; } - const messagesProps = await getMessages({ + const { messagesProps } = await getMessages({ conversationKey, messageId: oldBottomMessageId, }); @@ -448,6 +492,7 @@ export function getEmptyConversationState(): ConversationsStateType { return { conversationLookup: {}, messages: [], + quotes: {}, messageDetailProps: undefined, showRightPanel: false, selectedMessageIds: [], @@ -753,6 +798,7 @@ const conversationsSlice = createSlice({ firstUnreadIdOnOpen: string | undefined; mostRecentMessageIdOnOpen: string | null; initialMessages: Array; + initialQuotes: Record; }> ) { // this is quite hacky, but we don't want to show the showScrollButton if we have only a small amount of messages, @@ -776,6 +822,7 @@ const conversationsSlice = createSlice({ selectedConversation: action.payload.conversationKey, firstUnreadMessageId: action.payload.firstUnreadIdOnOpen, messages: action.payload.initialMessages, + quotes: action.payload.initialQuotes, areMoreMessagesBeingFetched: false, showRightPanel: false, @@ -803,6 +850,7 @@ const conversationsSlice = createSlice({ mostRecentMessageIdOnOpen: string | null; initialMessages: Array; + initialQuotes: Record; }> ) { return { @@ -811,6 +859,7 @@ const conversationsSlice = createSlice({ mostRecentMessageIdOnOpen: action.payload.mostRecentMessageIdOnOpen, areMoreMessagesBeingFetched: false, messages: action.payload.initialMessages, + quotes: action.payload.initialQuotes, showScrollButton: Boolean( action.payload.messageIdToNavigateTo !== action.payload.mostRecentMessageIdOnOpen ), @@ -1040,7 +1089,7 @@ export async function openConversationWithMessages(args: { const firstUnreadIdOnOpen = await Data.getFirstUnreadMessageIdInConversation(conversationKey); const mostRecentMessageIdOnOpen = await Data.getLastMessageIdInConversation(conversationKey); - const initialMessages = await getMessages({ + const { messagesProps: initialMessages, quotesProps: initialQuotes } = await getMessages({ conversationKey, messageId: messageId || null, }); @@ -1051,6 +1100,7 @@ export async function openConversationWithMessages(args: { firstUnreadIdOnOpen, mostRecentMessageIdOnOpen, initialMessages, + initialQuotes, }) ); } @@ -1062,7 +1112,10 @@ export async function openConversationToSpecificMessage(args: { }) { const { conversationKey, messageIdToNavigateTo, shouldHighlightMessage } = args; - const messagesAroundThisMessage = await getMessages({ + const { + messagesProps: messagesAroundThisMessage, + quotesProps: quotesAroundThisMessage, + } = await getMessages({ conversationKey, messageId: messageIdToNavigateTo, }); @@ -1077,6 +1130,7 @@ export async function openConversationToSpecificMessage(args: { mostRecentMessageIdOnOpen, shouldHighlightMessage, initialMessages: messagesAroundThisMessage, + initialQuotes: quotesAroundThisMessage, }) ); }