You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
session-desktop/ts/components/conversation/message/message-content/MessageQuote.tsx

111 lines
3.6 KiB
TypeScript

import { isEmpty, toNumber } from 'lodash';
import React from 'react';
import { useSelector } from 'react-redux';
import { Data } from '../../../../data/data';
import { MessageRenderingProps } from '../../../../models/messageType';
import { ToastUtils } from '../../../../session/utils';
import { openConversationToSpecificMessage } from '../../../../state/ducks/conversations';
import { StateType } from '../../../../state/reducer';
import { useMessageDirection } from '../../../../state/selectors';
import {
getMessageQuoteProps,
isMessageDetailView,
} from '../../../../state/selectors/conversations';
import { Quote } from './quote/Quote';
type Props = {
messageId: string;
};
export type MessageQuoteSelectorProps = Pick<MessageRenderingProps, 'quote' | 'direction'>;
export const MessageQuote = (props: Props) => {
const selected = useSelector((state: StateType) => getMessageQuoteProps(state, props.messageId));
const direction = useMessageDirection(props.messageId);
const isMessageDetailViewMode = useSelector(isMessageDetailView);
if (!selected || isEmpty(selected)) {
return null;
}
const quote = selected ? selected.quote : undefined;
if (!quote || isEmpty(quote)) {
return null;
}
const quoteNotFound = Boolean(
quote.referencedMessageNotFound || !quote?.author || !quote.id || !quote.convoId
);
const onQuoteClick = async (event: React.MouseEvent<HTMLDivElement>) => {
event.preventDefault();
event.stopPropagation();
if (!quote) {
ToastUtils.pushOriginalNotFound();
window.log.warn('onQuoteClick: quote not valid');
return;
}
if (isMessageDetailViewMode) {
// trying to scroll while in the container while the message detail view is shown has unknown effects
return;
}
let conversationKey = String(quote.convoId);
let messageIdToNavigateTo = String(quote.id);
let quoteNotFoundInDB = false;
// If the quote is not found in memory, we try to find it in the DB
if (quoteNotFound && quote.id && quote.author) {
// We always look for the quote by sentAt timestamp, for opengroups, closed groups and session chats
// this will return an array of sent messages by id that we have locally.
const quotedMessagesCollection = await Data.getMessagesBySenderAndSentAt([
{
timestamp: toNumber(quote.id),
source: quote.author,
},
]);
if (quotedMessagesCollection?.length) {
const quotedMessage = quotedMessagesCollection.at(0);
// If found, we navigate to the quoted message which also refreshes the message quote component
if (quotedMessage) {
conversationKey = String(quotedMessage.get('conversationId'));
messageIdToNavigateTo = String(quotedMessage.id);
} else {
quoteNotFoundInDB = true;
}
} else {
quoteNotFoundInDB = true;
}
}
// For simplicity's sake, we show the 'not found' toast no matter what if we were
// not able to find the referenced message when the quote was received or if the conversation no longer exists.
if (quoteNotFoundInDB) {
ToastUtils.pushOriginalNotFound();
return;
}
void openConversationToSpecificMessage({
conversationKey,
messageIdToNavigateTo,
shouldHighlightMessage: true,
});
};
return (
<Quote
onClick={e => void onQuoteClick(e)}
text={quote?.text}
attachment={quote?.attachment}
isIncoming={direction === 'incoming'}
author={quote.author}
referencedMessageNotFound={quoteNotFound}
isFromMe={Boolean(quote.isFromMe)}
/>
);
};