signal-desktop/ts/state/smart/TimelineItem.tsx

219 lines
7.6 KiB
TypeScript
Raw Normal View History

2023-01-03 19:55:46 +00:00
// Copyright 2019 Signal Messenger, LLC
2020-10-30 20:34:04 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
import type { RefObject } from 'react';
import React from 'react';
import { useSelector } from 'react-redux';
import { TimelineItem } from '../../components/conversation/TimelineItem';
import type { WidthBreakpoint } from '../../components/_util';
import { useProxySelector } from '../../hooks/useProxySelector';
import { useConversationsActions } from '../ducks/conversations';
import { useComposerActions } from '../ducks/composer';
import { useGlobalModalActions } from '../ducks/globalModals';
import { useAccountsActions } from '../ducks/accounts';
import { useLightboxActions } from '../ducks/lightbox';
import { useStoriesActions } from '../ducks/stories';
import { useCallingActions } from '../ducks/calling';
2021-11-17 21:11:46 +00:00
import { getPreferredBadgeSelector } from '../selectors/badges';
2023-04-03 20:16:27 +00:00
import {
getIntl,
getInteractionMode,
getTheme,
getPlatform,
} from '../selectors/user';
2023-03-20 22:23:53 +00:00
import { getTargetedMessage } from '../selectors/conversations';
2022-12-23 00:32:03 +00:00
import { getTimelineItem } from '../selectors/timeline';
import {
areMessagesInSameGroup,
shouldCurrentMessageHideMetadata,
UnreadIndicatorPlacement,
} from '../../util/timelineUtil';
2020-09-09 02:25:05 +00:00
import { SmartContactName } from './ContactName';
2021-06-01 20:45:43 +00:00
import { SmartUniversalTimerNotification } from './UniversalTimerNotification';
import { isSameDay } from '../../util/timestamp';
import { renderAudioAttachment } from './renderAudioAttachment';
import { renderEmojiPicker } from './renderEmojiPicker';
import { renderReactionPicker } from './renderReactionPicker';
2020-09-09 02:25:05 +00:00
type ExternalProps = {
containerElementRef: RefObject<HTMLElement>;
containerWidthBreakpoint: WidthBreakpoint;
conversationId: string;
2022-01-26 23:05:26 +00:00
isOldestTimelineItem: boolean;
messageId: string;
nextMessageId: undefined | string;
previousMessageId: undefined | string;
unreadIndicatorPlacement: undefined | UnreadIndicatorPlacement;
};
function renderContact(contactId: string): JSX.Element {
return <SmartContactName contactId={contactId} />;
2020-09-09 02:25:05 +00:00
}
2021-06-01 20:45:43 +00:00
function renderUniversalTimerNotification(): JSX.Element {
return <SmartUniversalTimerNotification />;
}
export function SmartTimelineItem(props: ExternalProps): JSX.Element {
const {
containerElementRef,
containerWidthBreakpoint,
conversationId,
2022-01-26 23:05:26 +00:00
isOldestTimelineItem,
messageId,
nextMessageId,
previousMessageId,
unreadIndicatorPlacement,
} = props;
const i18n = useSelector(getIntl);
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
const interactionMode = useSelector(getInteractionMode);
const theme = useSelector(getTheme);
2023-04-03 20:16:27 +00:00
const platform = useSelector(getPlatform);
const item = useProxySelector(getTimelineItem, messageId);
const previousItem = useProxySelector(getTimelineItem, previousMessageId);
const nextItem = useProxySelector(getTimelineItem, nextMessageId);
2023-03-20 22:23:53 +00:00
const targetedMessage = useSelector(getTargetedMessage);
const isTargeted = Boolean(
targetedMessage && messageId === targetedMessage.id
);
2019-11-07 21:36:16 +00:00
const isNextItemCallingNotification = nextItem?.type === 'callHistory';
const shouldCollapseAbove = areMessagesInSameGroup(
previousItem,
unreadIndicatorPlacement === UnreadIndicatorPlacement.JustAbove,
item
);
const shouldCollapseBelow = areMessagesInSameGroup(
item,
unreadIndicatorPlacement === UnreadIndicatorPlacement.JustBelow,
nextItem
);
const shouldHideMetadata = shouldCurrentMessageHideMetadata(
shouldCollapseBelow,
item,
nextItem
);
const shouldRenderDateHeader =
isOldestTimelineItem ||
Boolean(
item &&
previousItem &&
// This comparison avoids strange header behavior for out-of-order messages.
item.timestamp > previousItem.timestamp &&
!isSameDay(previousItem.timestamp, item.timestamp)
);
const {
blockGroupLinkRequests,
2023-03-20 22:23:53 +00:00
clearTargetedMessage: clearSelectedMessage,
doubleCheckMissingQuoteReference,
kickOffAttachmentDownload,
markAttachmentAsCorrupted,
messageExpanded,
openGiftBadge,
pushPanelForConversation,
copyMessageText,
retryDeleteForEveryone,
retryMessageSend,
saveAttachment,
2023-03-20 22:23:53 +00:00
targetMessage,
toggleSelectMessage,
setMessageToEdit,
showConversation,
showExpiredIncomingTapToViewToast,
showExpiredOutgoingTapToViewToast,
showSpoiler,
startConversation,
} = useConversationsActions();
const { reactToMessage, scrollToQuotedMessage, setQuoteByMessageId } =
useComposerActions();
const {
showContactModal,
2023-03-27 23:48:57 +00:00
showEditHistoryModal,
toggleDeleteMessagesModal,
2023-03-20 22:23:53 +00:00
toggleForwardMessagesModal,
toggleSafetyNumberModal,
} = useGlobalModalActions();
const { checkForAccount } = useAccountsActions();
const { showLightbox, showLightboxForViewOnceMedia } = useLightboxActions();
const { viewStory } = useStoriesActions();
const {
onOutgoingAudioCallInConversation,
onOutgoingVideoCallInConversation,
returnToActiveCall,
} = useCallingActions();
return (
<TimelineItem
item={item}
id={messageId}
containerElementRef={containerElementRef}
containerWidthBreakpoint={containerWidthBreakpoint}
conversationId={conversationId}
getPreferredBadge={getPreferredBadge}
isNextItemCallingNotification={isNextItemCallingNotification}
2023-03-20 22:23:53 +00:00
isTargeted={isTargeted}
renderAudioAttachment={renderAudioAttachment}
renderContact={renderContact}
renderEmojiPicker={renderEmojiPicker}
renderReactionPicker={renderReactionPicker}
renderUniversalTimerNotification={renderUniversalTimerNotification}
shouldCollapseAbove={shouldCollapseAbove}
shouldCollapseBelow={shouldCollapseBelow}
shouldHideMetadata={shouldHideMetadata}
shouldRenderDateHeader={shouldRenderDateHeader}
2023-03-27 23:48:57 +00:00
showEditHistoryModal={showEditHistoryModal}
i18n={i18n}
interactionMode={interactionMode}
theme={theme}
2023-04-03 20:16:27 +00:00
platform={platform}
blockGroupLinkRequests={blockGroupLinkRequests}
checkForAccount={checkForAccount}
2023-03-20 22:23:53 +00:00
clearTargetedMessage={clearSelectedMessage}
doubleCheckMissingQuoteReference={doubleCheckMissingQuoteReference}
kickOffAttachmentDownload={kickOffAttachmentDownload}
markAttachmentAsCorrupted={markAttachmentAsCorrupted}
messageExpanded={messageExpanded}
openGiftBadge={openGiftBadge}
pushPanelForConversation={pushPanelForConversation}
reactToMessage={reactToMessage}
copyMessageText={copyMessageText}
onOutgoingAudioCallInConversation={onOutgoingAudioCallInConversation}
onOutgoingVideoCallInConversation={onOutgoingVideoCallInConversation}
retryDeleteForEveryone={retryDeleteForEveryone}
retryMessageSend={retryMessageSend}
returnToActiveCall={returnToActiveCall}
saveAttachment={saveAttachment}
scrollToQuotedMessage={scrollToQuotedMessage}
2023-03-20 22:23:53 +00:00
targetMessage={targetMessage}
setQuoteByMessageId={setQuoteByMessageId}
setMessageToEdit={setMessageToEdit}
showContactModal={showContactModal}
showConversation={showConversation}
showExpiredIncomingTapToViewToast={showExpiredIncomingTapToViewToast}
showExpiredOutgoingTapToViewToast={showExpiredOutgoingTapToViewToast}
showLightbox={showLightbox}
showLightboxForViewOnceMedia={showLightboxForViewOnceMedia}
showSpoiler={showSpoiler}
startConversation={startConversation}
toggleDeleteMessagesModal={toggleDeleteMessagesModal}
2023-03-20 22:23:53 +00:00
toggleForwardMessagesModal={toggleForwardMessagesModal}
toggleSafetyNumberModal={toggleSafetyNumberModal}
viewStory={viewStory}
2023-03-20 22:23:53 +00:00
toggleSelectMessage={toggleSelectMessage}
/>
);
}