From f2f1c3c0213286c0b64a73a6740a9ad373bc2193 Mon Sep 17 00:00:00 2001 From: Scott Nonnenberg Date: Wed, 14 Dec 2022 11:05:32 -0800 Subject: [PATCH] Standardize on showConversation function, delete unused functions --- ts/background.ts | 21 +++-- ts/components/AddUserToAnotherGroupModal.tsx | 16 ++-- .../AnnouncementsOnlyGroupBanner.tsx | 17 ++-- ts/components/CompositionArea.stories.tsx | 2 +- ts/components/CompositionArea.tsx | 11 ++- ts/components/Inbox.tsx | 6 -- ts/components/LeftPane.stories.tsx | 2 +- ts/components/LeftPane.tsx | 12 +-- ts/components/LeftPaneSearchInput.tsx | 14 +-- ts/components/StoriesSettingsModal.tsx | 8 +- ts/components/StoryViewsNRepliesModal.tsx | 2 +- .../conversation/AtMentionify.stories.tsx | 2 +- ts/components/conversation/AtMentionify.tsx | 15 ++-- ts/components/conversation/ContactModal.tsx | 4 +- .../conversation/ConversationHeader.tsx | 18 ++-- ts/components/conversation/Message.tsx | 15 ++-- ts/components/conversation/MessageBody.tsx | 34 ++++--- .../conversation/MessageBodyReadMore.tsx | 18 ++-- .../conversation/MessageDetail.stories.tsx | 2 +- ts/components/conversation/MessageDetail.tsx | 6 +- ts/components/conversation/Quote.stories.tsx | 2 +- .../conversation/Timeline.stories.tsx | 2 +- ts/components/conversation/Timeline.tsx | 2 +- .../conversation/TimelineItem.stories.tsx | 2 +- .../conversation/TimelineMessage.stories.tsx | 2 +- ts/state/ducks/composer.ts | 5 ++ ts/state/ducks/conversations.ts | 4 +- ts/state/smart/ConversationView.tsx | 1 - ts/state/smart/MessageDetail.tsx | 3 +- ts/state/smart/Timeline.tsx | 1 - ts/test-both/state/ducks/composer_test.ts | 18 ++++ ts/util/createIPCEvents.tsx | 9 +- ts/util/hasDraftAttachments.ts | 2 +- ts/util/startConversation.ts | 4 +- ts/views/conversation_view.tsx | 90 ++++--------------- 35 files changed, 174 insertions(+), 198 deletions(-) diff --git a/ts/background.ts b/ts/background.ts index 813a140ad..a83761851 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -158,6 +158,8 @@ import type AccountManager from './textsecure/AccountManager'; import { onStoryRecipientUpdate } from './util/onStoryRecipientUpdate'; import { StoryViewModeType, StoryViewTargetType } from './types/Stories'; import { downloadOnboardingStory } from './util/downloadOnboardingStory'; +import { clearConversationDraftAttachments } from './util/clearConversationDraftAttachments'; +import { removeLinkPreview } from './services/LinkPreview'; const MAX_ATTACHMENT_DOWNLOAD_AGE = 3600 * 72 * 1000; @@ -1545,10 +1547,9 @@ export async function startApp(): Promise { showToast(ToastConversationArchived, { undo: () => { conversation.setArchived(false); - window.Whisper.events.trigger( - 'showConversation', - conversation.get('id') - ); + window.reduxActions.conversations.showConversation({ + conversationId: conversation.get('id'), + }); }, }); @@ -1702,7 +1703,7 @@ export async function startApp(): Promise { !shiftKey && (key === 'p' || key === 'P') ) { - conversation.trigger('remove-link-review'); + removeLinkPreview(); event.preventDefault(); event.stopPropagation(); @@ -1716,7 +1717,10 @@ export async function startApp(): Promise { shiftKey && (key === 'p' || key === 'P') ) { - conversation.trigger('remove-all-draft-attachments'); + clearConversationDraftAttachments( + conversation.id, + conversation.get('draftAttachments') + ); event.preventDefault(); event.stopPropagation(); @@ -1924,7 +1928,10 @@ export async function startApp(): Promise { viewTarget: StoryViewTargetType.Replies, }); } else { - window.Whisper.events.trigger('showConversation', id, messageId); + window.reduxActions.conversations.showConversation({ + conversationId: id, + messageId, + }); } } else { window.reduxActions.app.openInbox(); diff --git a/ts/components/AddUserToAnotherGroupModal.tsx b/ts/components/AddUserToAnotherGroupModal.tsx index 9e79e68a4..11d4414e5 100644 --- a/ts/components/AddUserToAnotherGroupModal.tsx +++ b/ts/components/AddUserToAnotherGroupModal.tsx @@ -167,20 +167,20 @@ export function AddUserToAnotherGroupModal({ > undefined} + getRow={handleGetRow} i18n={i18n} - theme={theme} + lookupConversationWithoutUuid={async _ => undefined} onClickArchiveButton={noop} onClickContactCheckbox={noop} onSelectConversation={setSelectedGroupId} - showChooseGroupMembers={noop} - lookupConversationWithoutUuid={async _ => undefined} - showUserNotFoundModal={noop} + rowCount={filteredConversations.length} setIsFetchingUUID={noop} + shouldRecomputeRowHeights={false} + showChooseGroupMembers={noop} + showConversation={noop} + showUserNotFoundModal={noop} + theme={theme} /> )} diff --git a/ts/components/AnnouncementsOnlyGroupBanner.tsx b/ts/components/AnnouncementsOnlyGroupBanner.tsx index 83319f6f5..cd74e36d0 100644 --- a/ts/components/AnnouncementsOnlyGroupBanner.tsx +++ b/ts/components/AnnouncementsOnlyGroupBanner.tsx @@ -2,7 +2,10 @@ // SPDX-License-Identifier: AGPL-3.0-only import React, { useState } from 'react'; -import type { ConversationType } from '../state/ducks/conversations'; +import type { + ConversationType, + ShowConversationType, +} from '../state/ducks/conversations'; import { Intl } from './Intl'; import type { LocalizerType, ThemeType } from '../types/Util'; import { Modal } from './Modal'; @@ -11,14 +14,14 @@ import { ConversationListItem } from './conversationList/ConversationListItem'; type PropsType = { groupAdmins: Array; i18n: LocalizerType; - openConversation: (conversationId: string) => unknown; + showConversation: ShowConversationType; theme: ThemeType; }; export function AnnouncementsOnlyGroupBanner({ groupAdmins, i18n, - openConversation, + showConversation, theme, }: PropsType): JSX.Element { const [isShowingAdmins, setIsShowingAdmins] = useState(false); @@ -35,13 +38,13 @@ export function AnnouncementsOnlyGroupBanner({ {groupAdmins.map(admin => ( { - openConversation(admin.id); - }} draftPreview="" + i18n={i18n} lastMessage={undefined} lastUpdated={undefined} + onClick={() => { + showConversation({ conversationId: admin.id }); + }} theme={theme} /> ))} diff --git a/ts/components/CompositionArea.stories.tsx b/ts/components/CompositionArea.stories.tsx index 83cf3e9c7..eea87c052 100644 --- a/ts/components/CompositionArea.stories.tsx +++ b/ts/components/CompositionArea.stories.tsx @@ -117,8 +117,8 @@ const useProps = (overrideProps: Partial = {}): Props => ({ ), areWeAdmin: boolean('areWeAdmin', Boolean(overrideProps.areWeAdmin)), groupAdmins: [], - openConversation: action('openConversation'), onCancelJoinRequest: action('onCancelJoinRequest'), + showConversation: action('showConversation'), // SMS-only isSMSOnly: overrideProps.isSMSOnly || false, isFetchingUUID: overrideProps.isFetchingUUID || false, diff --git a/ts/components/CompositionArea.tsx b/ts/components/CompositionArea.tsx index 4c0b2747c..3b1fe3433 100644 --- a/ts/components/CompositionArea.tsx +++ b/ts/components/CompositionArea.tsx @@ -40,7 +40,10 @@ import type { import { isImageAttachment } from '../types/Attachment'; import { AudioCapture } from './conversation/AudioCapture'; import { CompositionUpload } from './CompositionUpload'; -import type { ConversationType } from '../state/ducks/conversations'; +import type { + ConversationType, + ShowConversationType, +} from '../state/ducks/conversations'; import type { EmojiPickDataType } from './emoji/EmojiPicker'; import type { LinkPreviewType } from '../types/message/LinkPreviews'; @@ -117,7 +120,6 @@ export type OwnProps = Readonly<{ voiceNoteAttachment?: InMemoryAttachmentDraftType; } ): unknown; - openConversation(conversationId: string): unknown; quotedMessageId?: string; quotedMessageProps?: Omit< QuoteProps, @@ -131,6 +133,7 @@ export type OwnProps = Readonly<{ messageId: string | undefined ): unknown; shouldSendHighQualityAttachments: boolean; + showConversation: ShowConversationType; startRecording: () => unknown; theme: ThemeType; }>; @@ -257,7 +260,7 @@ export function CompositionArea({ areWeAdmin, groupAdmins, onCancelJoinRequest, - openConversation, + showConversation, // SMS-only contacts isSMSOnly, isFetchingUUID, @@ -594,7 +597,7 @@ export function CompositionArea({ ); diff --git a/ts/components/Inbox.tsx b/ts/components/Inbox.tsx index 0e21c3e5a..718064e44 100644 --- a/ts/components/Inbox.tsx +++ b/ts/components/Inbox.tsx @@ -135,10 +135,6 @@ export function Inbox({ prevConversation.trigger('unload', 'force unload requested'); } - function onShowConversation(id: string, messageId?: string): void { - showConversation({ conversationId: id, messageId }); - } - function packInstallFailed() { showToast(ToastStickerPackInstallFailed); } @@ -147,14 +143,12 @@ export function Inbox({ window.Whisper.events.on('pack-install-failed', packInstallFailed); window.Whisper.events.on('refreshConversation', refreshConversation); window.Whisper.events.on('setupAsNewDevice', unload); - window.Whisper.events.on('showConversation', onShowConversation); return () => { window.Whisper.events.off('loadingProgress', setLoadingMessageCount); window.Whisper.events.off('pack-install-failed', packInstallFailed); window.Whisper.events.off('refreshConversation', refreshConversation); window.Whisper.events.off('setupAsNewDevice', unload); - window.Whisper.events.off('showConversation', onShowConversation); }; }, [prevConversation, showConversation]); diff --git a/ts/components/LeftPane.stories.tsx b/ts/components/LeftPane.stories.tsx index ff3a37241..3a8d4cd48 100644 --- a/ts/components/LeftPane.stories.tsx +++ b/ts/components/LeftPane.stories.tsx @@ -148,8 +148,8 @@ const useProps = (overrideProps: Partial = {}): PropsType => { getPreferredBadge={() => undefined} i18n={i18n} id={id} - showConversation={action('showConversation')} sentAt={1587358800000} + showConversation={action('showConversation')} snippet="Lorem <>ipsum<> wow" theme={ThemeType.light} to={defaultConversations[1]} diff --git a/ts/components/LeftPane.tsx b/ts/components/LeftPane.tsx index 2ada69ddc..83a0ed056 100644 --- a/ts/components/LeftPane.tsx +++ b/ts/components/LeftPane.tsx @@ -142,7 +142,6 @@ export type PropsType = { export function LeftPane({ challengeStatus, - crashReportCount, clearConversationSearch, clearGroupCreationError, clearSearch, @@ -151,9 +150,11 @@ export function LeftPane({ composeDeleteAvatarFromDisk, composeReplaceAvatar, composeSaveAvatarToDisk, + crashReportCount, createGroup, getPreferredBadge, i18n, + lookupConversationWithoutUuid, modeSpecificProps, preferredWidthFromStorage, renderCaptchaDialog, @@ -173,19 +174,18 @@ export function LeftPane({ setComposeGroupExpireTimer, setComposeGroupName, setComposeSearchTerm, + setIsFetchingUUID, showArchivedConversations, showChooseGroupMembers, + showConversation, showInbox, + showUserNotFoundModal, startComposing, startSearch, - showUserNotFoundModal, - setIsFetchingUUID, - lookupConversationWithoutUuid, - toggleConversationInChooseMembers, - showConversation, startSettingGroupMetadata, theme, toggleComposeEditingAvatar, + toggleConversationInChooseMembers, updateSearchTerm, }: PropsType): JSX.Element { const [preferredWidth, setPreferredWidth] = useState( diff --git a/ts/components/LeftPaneSearchInput.tsx b/ts/components/LeftPaneSearchInput.tsx index 564a114d8..9cf432ddd 100644 --- a/ts/components/LeftPaneSearchInput.tsx +++ b/ts/components/LeftPaneSearchInput.tsx @@ -16,15 +16,15 @@ type PropsType = { clearSearch: () => void; disabled?: boolean; i18n: LocalizerType; - searchConversation?: ConversationType; - searchTerm: string; - startSearchCounter: number; - updateSearchTerm: (searchTerm: string) => void; - showConversation: ShowConversationType; onEnterKeyDown?: ( clearSearch: () => void, showConversation: ShowConversationType ) => void; + searchConversation?: ConversationType; + searchTerm: string; + showConversation: ShowConversationType; + startSearchCounter: number; + updateSearchTerm: (searchTerm: string) => void; }; export function LeftPaneSearchInput({ @@ -32,12 +32,12 @@ export function LeftPaneSearchInput({ clearSearch, disabled, i18n, + onEnterKeyDown, searchConversation, searchTerm, + showConversation, startSearchCounter, updateSearchTerm, - showConversation, - onEnterKeyDown, }: PropsType): JSX.Element { const inputRef = useRef(null); diff --git a/ts/components/StoriesSettingsModal.tsx b/ts/components/StoriesSettingsModal.tsx index 79b6d1ecf..91c797962 100644 --- a/ts/components/StoriesSettingsModal.tsx +++ b/ts/components/StoriesSettingsModal.tsx @@ -1193,22 +1193,22 @@ export function EditDistributionListModal({ getPreferredBadge={getPreferredBadge} getRow={getRow} i18n={i18n} + lookupConversationWithoutUuid={asyncShouldNeverBeCalled} onClickArchiveButton={shouldNeverBeCalled} onClickContactCheckbox={(conversationId: string) => { toggleSelectedConversation(conversationId); }} - lookupConversationWithoutUuid={asyncShouldNeverBeCalled} - showConversation={shouldNeverBeCalled} - showUserNotFoundModal={shouldNeverBeCalled} - setIsFetchingUUID={shouldNeverBeCalled} onSelectConversation={shouldNeverBeCalled} renderMessageSearchResult={() => { shouldNeverBeCalled(); return
; }} rowCount={rowCount} + setIsFetchingUUID={shouldNeverBeCalled} shouldRecomputeRowHeights={false} showChooseGroupMembers={shouldNeverBeCalled} + showConversation={shouldNeverBeCalled} + showUserNotFoundModal={shouldNeverBeCalled} theme={ThemeType.dark} />
diff --git a/ts/components/StoryViewsNRepliesModal.tsx b/ts/components/StoryViewsNRepliesModal.tsx index 2032d0bc8..d562212b2 100644 --- a/ts/components/StoryViewsNRepliesModal.tsx +++ b/ts/components/StoryViewsNRepliesModal.tsx @@ -57,7 +57,7 @@ const MESSAGE_DEFAULT_PROPS = { markViewed: shouldNeverBeCalled, messageExpanded: shouldNeverBeCalled, // Called when clicking mention, but shouldn't do anything. - openConversation: noop, + showConversation: noop, openGiftBadge: shouldNeverBeCalled, openLink: shouldNeverBeCalled, previews: [], diff --git a/ts/components/conversation/AtMentionify.stories.tsx b/ts/components/conversation/AtMentionify.stories.tsx index 9c2257e49..d4e1dcbc5 100644 --- a/ts/components/conversation/AtMentionify.stories.tsx +++ b/ts/components/conversation/AtMentionify.stories.tsx @@ -20,7 +20,7 @@ const createProps = (overrideProps: Partial = {}): Props => ({ { incoming: 'incoming', outgoing: 'outgoing' }, overrideProps.direction || 'incoming' ), - openConversation: action('openConversation'), + showConversation: action('showConversation'), text: text('text', overrideProps.text || ''), }); diff --git a/ts/components/conversation/AtMentionify.tsx b/ts/components/conversation/AtMentionify.tsx index 5220dfdbc..c9577977a 100644 --- a/ts/components/conversation/AtMentionify.tsx +++ b/ts/components/conversation/AtMentionify.tsx @@ -13,14 +13,17 @@ import type { export type Props = { bodyRanges?: HydratedBodyRangesType; direction?: 'incoming' | 'outgoing'; - openConversation?: (conversationId: string, messageId?: string) => void; + showConversation?: (options: { + conversationId: string; + messageId?: string; + }) => unknown; text: string; }; export function AtMentionify({ bodyRanges, direction, - openConversation, + showConversation, text, }: Props): JSX.Element { if (!bodyRanges) { @@ -53,17 +56,17 @@ export function AtMentionify({ className={`MessageBody__at-mention MessageBody__at-mention--${direction}`} key={range.start} onClick={() => { - if (openConversation) { - openConversation(range.conversationID); + if (showConversation) { + showConversation({ conversationId: range.conversationID }); } }} onKeyUp={e => { if ( e.target === e.currentTarget && e.keyCode === 13 && - openConversation + showConversation ) { - openConversation(range.conversationID); + showConversation({ conversationId: range.conversationID }); } }} tabIndex={0} diff --git a/ts/components/conversation/ContactModal.tsx b/ts/components/conversation/ContactModal.tsx index 8fc6cbd5d..1cc9758e0 100644 --- a/ts/components/conversation/ContactModal.tsx +++ b/ts/components/conversation/ContactModal.tsx @@ -63,8 +63,8 @@ enum SubModalState { } export function ContactModal({ - areWeASubscriber, areWeAdmin, + areWeASubscriber, badges, contact, conversation, @@ -76,9 +76,9 @@ export function ContactModal({ removeMemberFromGroup, showConversation, theme, + toggleAddUserToAnotherGroupModal, toggleAdmin, toggleSafetyNumberModal, - toggleAddUserToAnotherGroupModal, updateConversationModelSharedGroups, viewUserStories, }: PropsType): JSX.Element { diff --git a/ts/components/conversation/ConversationHeader.tsx b/ts/components/conversation/ConversationHeader.tsx index efc97eb15..7b18df408 100644 --- a/ts/components/conversation/ConversationHeader.tsx +++ b/ts/components/conversation/ConversationHeader.tsx @@ -81,23 +81,21 @@ export type PropsDataType = { export type PropsActionsType = { destroyMessages: (conversationId: string) => void; - onSearchInConversation: () => void; - onOutgoingAudioCallInConversation: (conversationId: string) => void; - onOutgoingVideoCallInConversation: (conversationId: string) => void; - - onShowConversationDetails: () => void; - onShowAllMedia: () => void; - onShowGroupMembers: () => void; - onGoBack: () => void; - onArchive: () => void; + onGoBack: () => void; onMarkUnread: () => void; onMoveToInbox: () => void; - setMuteExpiration: (conversationId: string, seconds: number) => void; + onOutgoingAudioCallInConversation: (conversationId: string) => void; + onOutgoingVideoCallInConversation: (conversationId: string) => void; + onSearchInConversation: () => void; + onShowAllMedia: () => void; + onShowConversationDetails: () => void; + onShowGroupMembers: () => void; setDisappearingMessages: ( conversationId: string, seconds: DurationInSeconds ) => void; + setMuteExpiration: (conversationId: string, seconds: number) => void; setPinned: (conversationId: string, value: boolean) => void; viewUserStories: ViewUserStoriesActionCreatorType; }; diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 2dc19f6df..3f219f016 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -15,6 +15,7 @@ import type { ConversationTypeType, InteractionModeType, SaveAttachmentActionCreatorType, + ShowConversationType, } from '../../state/ducks/conversations'; import type { ViewStoryActionCreatorType } from '../../state/ducks/stories'; import type { ReadStatus } from '../../messages/MessageReadStatus'; @@ -299,7 +300,7 @@ export type PropsActions = { showMessageDetail: (id: string) => void; startConversation: (e164: string, uuid: UUIDStringType) => void; - openConversation: (conversationId: string, messageId?: string) => void; + showConversation: ShowConversationType; openGiftBadge: (messageId: string) => void; showContactDetail: (options: { contact: EmbeddedContactType; @@ -1709,13 +1710,13 @@ export class Message extends React.PureComponent { displayLimit, i18n, id, - messageExpanded, - openConversation, kickOffAttachmentDownload, + messageExpanded, + showConversation, status, text, - textDirection, textAttachment, + textDirection, } = this.props; const { metadataWidth } = this.state; const isRTL = textDirection === TextDirection.RightToLeft; @@ -1747,13 +1748,11 @@ export class Message extends React.PureComponent { > { if (!textAttachment) { return; @@ -1763,6 +1762,8 @@ export class Message extends React.PureComponent { messageId: id, }); }} + messageExpanded={messageExpanded} + showConversation={showConversation} text={contents || ''} textAttachment={textAttachment} /> diff --git a/ts/components/conversation/MessageBody.tsx b/ts/components/conversation/MessageBody.tsx index 2a342df87..1fd7c6769 100644 --- a/ts/components/conversation/MessageBody.tsx +++ b/ts/components/conversation/MessageBody.tsx @@ -13,31 +13,27 @@ import { Emojify } from './Emojify'; import { AddNewLines } from './AddNewLines'; import { Linkify } from './Linkify'; +import type { ShowConversationType } from '../../state/ducks/conversations'; import type { HydratedBodyRangesType, LocalizerType, RenderTextCallbackType, } from '../../types/Util'; -type OpenConversationActionType = ( - conversationId: string, - messageId?: string -) => void; - export type Props = { - direction?: 'incoming' | 'outgoing'; - text: string; author?: string; - textAttachment?: Pick; + bodyRanges?: HydratedBodyRangesType; + direction?: 'incoming' | 'outgoing'; /** If set, all emoji will be the same size. Otherwise, just one emoji will be large. */ disableJumbomoji?: boolean; /** If set, links will be left alone instead of turned into clickable `` tags. */ disableLinks?: boolean; i18n: LocalizerType; - bodyRanges?: HydratedBodyRangesType; - onIncreaseTextLength?: () => unknown; - openConversation?: OpenConversationActionType; kickOffBodyDownload?: () => void; + onIncreaseTextLength?: () => unknown; + showConversation?: ShowConversationType; + text: string; + textAttachment?: Pick; }; const renderEmoji = ({ @@ -67,17 +63,17 @@ const renderEmoji = ({ * them for you. */ export function MessageBody({ + author, bodyRanges, direction, disableJumbomoji, disableLinks, i18n, - onIncreaseTextLength, - openConversation, - text, - author, - textAttachment, kickOffBodyDownload, + onIncreaseTextLength, + showConversation, + text, + textAttachment, }: Props): JSX.Element { const hasReadMore = Boolean(onIncreaseTextLength); const textWithSuffix = @@ -100,10 +96,10 @@ export function MessageBody({ renderNonNewLine={({ text: innerText, key: innerKey }) => ( )} /> diff --git a/ts/components/conversation/MessageBodyReadMore.tsx b/ts/components/conversation/MessageBodyReadMore.tsx index 8f2339b6b..d5d3f4a54 100644 --- a/ts/components/conversation/MessageBodyReadMore.tsx +++ b/ts/components/conversation/MessageBodyReadMore.tsx @@ -9,14 +9,14 @@ import { graphemeAndLinkAwareSlice } from '../../util/graphemeAndLinkAwareSlice' export type Props = Pick< MessageBodyPropsType, + | 'bodyRanges' | 'direction' - | 'text' - | 'textAttachment' | 'disableLinks' | 'i18n' - | 'bodyRanges' - | 'openConversation' | 'kickOffBodyDownload' + | 'showConversation' + | 'text' + | 'textAttachment' > & { id: string; displayLimit?: number; @@ -38,9 +38,9 @@ export function MessageBodyReadMore({ displayLimit, i18n, id, - messageExpanded, - openConversation, kickOffBodyDownload, + messageExpanded, + showConversation, text, textAttachment, }: Props): JSX.Element { @@ -61,12 +61,12 @@ export function MessageBodyReadMore({ return ( diff --git a/ts/components/conversation/MessageDetail.stories.tsx b/ts/components/conversation/MessageDetail.stories.tsx index b20a1f4d5..65cd944de 100644 --- a/ts/components/conversation/MessageDetail.stories.tsx +++ b/ts/components/conversation/MessageDetail.stories.tsx @@ -78,7 +78,7 @@ const createProps = (overrideProps: Partial = {}): Props => ({ kickOffAttachmentDownload: action('kickOffAttachmentDownload'), markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'), markViewed: action('markViewed'), - openConversation: action('openConversation'), + showConversation: action('showConversation'), openGiftBadge: action('openGiftBadge'), openLink: action('openLink'), renderAudioAttachment: () =>
*AudioAttachment*
, diff --git a/ts/components/conversation/MessageDetail.tsx b/ts/components/conversation/MessageDetail.tsx index 0c3fdf451..74205c107 100644 --- a/ts/components/conversation/MessageDetail.tsx +++ b/ts/components/conversation/MessageDetail.tsx @@ -81,7 +81,6 @@ export type PropsBackboneActions = Pick< MessagePropsType, | 'kickOffAttachmentDownload' | 'markAttachmentAsCorrupted' - | 'openConversation' | 'openGiftBadge' | 'openLink' | 'renderAudioAttachment' @@ -98,6 +97,7 @@ export type PropsReduxActions = Pick< | 'doubleCheckMissingQuoteReference' | 'saveAttachment' | 'showContactModal' + | 'showConversation' | 'showLightbox' | 'showLightboxForViewOnceMedia' | 'viewStory' @@ -290,13 +290,13 @@ export class MessageDetail extends React.Component { kickOffAttachmentDownload, markAttachmentAsCorrupted, markViewed, - openConversation, openGiftBadge, openLink, renderAudioAttachment, saveAttachment, showContactDetail, showContactModal, + showConversation, showExpiredIncomingTapToViewToast, showExpiredOutgoingTapToViewToast, showLightbox, @@ -336,7 +336,7 @@ export class MessageDetail extends React.Component { markAttachmentAsCorrupted={markAttachmentAsCorrupted} markViewed={markViewed} messageExpanded={noop} - openConversation={openConversation} + showConversation={showConversation} openGiftBadge={openGiftBadge} openLink={openLink} renderAudioAttachment={renderAudioAttachment} diff --git a/ts/components/conversation/Quote.stories.tsx b/ts/components/conversation/Quote.stories.tsx index 1de84a4bc..4e39c4d82 100644 --- a/ts/components/conversation/Quote.stories.tsx +++ b/ts/components/conversation/Quote.stories.tsx @@ -112,7 +112,7 @@ const defaultMessageProps: TimelineMessagesProps = { markAttachmentAsCorrupted: action('default--markAttachmentAsCorrupted'), markViewed: action('default--markViewed'), messageExpanded: action('default--message-expanded'), - openConversation: action('default--openConversation'), + showConversation: action('default--showConversation'), openGiftBadge: action('openGiftBadge'), openLink: action('default--openLink'), previews: [], diff --git a/ts/components/conversation/Timeline.stories.tsx b/ts/components/conversation/Timeline.stories.tsx index afb187d7c..5fb454288 100644 --- a/ts/components/conversation/Timeline.stories.tsx +++ b/ts/components/conversation/Timeline.stories.tsx @@ -282,10 +282,10 @@ const actions = () => ({ deleteMessage: action('deleteMessage'), deleteMessageForEveryone: action('deleteMessageForEveryone'), showMessageDetail: action('showMessageDetail'), - openConversation: action('openConversation'), saveAttachment: action('saveAttachment'), showContactDetail: action('showContactDetail'), showContactModal: action('showContactModal'), + showConversation: action('showConversation'), kickOffAttachmentDownload: action('kickOffAttachmentDownload'), markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'), markViewed: action('markViewed'), diff --git a/ts/components/conversation/Timeline.tsx b/ts/components/conversation/Timeline.tsx index 64251dd14..732035fcb 100644 --- a/ts/components/conversation/Timeline.tsx +++ b/ts/components/conversation/Timeline.tsx @@ -244,8 +244,8 @@ const getActions = createSelector( 'toggleForwardMessageModal', 'deleteMessage', 'deleteMessageForEveryone', + 'showConversation', 'showMessageDetail', - 'openConversation', 'openGiftBadge', 'setQuoteByMessageId', 'showContactDetail', diff --git a/ts/components/conversation/TimelineItem.stories.tsx b/ts/components/conversation/TimelineItem.stories.tsx index 89a1be7fa..37d636b6b 100644 --- a/ts/components/conversation/TimelineItem.stories.tsx +++ b/ts/components/conversation/TimelineItem.stories.tsx @@ -78,7 +78,7 @@ const getDefaultProps = () => ({ markViewed: action('markViewed'), messageExpanded: action('messageExpanded'), showMessageDetail: action('showMessageDetail'), - openConversation: action('openConversation'), + showConversation: action('showConversation'), openGiftBadge: action('openGiftBadge'), saveAttachment: action('saveAttachment'), showContactDetail: action('showContactDetail'), diff --git a/ts/components/conversation/TimelineMessage.stories.tsx b/ts/components/conversation/TimelineMessage.stories.tsx index 0fdf55aa6..9519b2273 100644 --- a/ts/components/conversation/TimelineMessage.stories.tsx +++ b/ts/components/conversation/TimelineMessage.stories.tsx @@ -279,7 +279,7 @@ const createProps = (overrideProps: Partial = {}): Props => ({ markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'), markViewed: action('markViewed'), messageExpanded: action('messageExpanded'), - openConversation: action('openConversation'), + showConversation: action('showConversation'), openGiftBadge: action('openGiftBadge'), openLink: action('openLink'), previews: overrideProps.previews || [], diff --git a/ts/state/ducks/composer.ts b/ts/state/ducks/composer.ts index 57292027f..9d866bdf0 100644 --- a/ts/state/ducks/composer.ts +++ b/ts/state/ducks/composer.ts @@ -44,6 +44,7 @@ import { getLinkPreviewForSend, hasLinkPreviewLoaded, maybeGrabLinkPreview, + removeLinkPreview, resetLinkPreview, } from '../../services/LinkPreview'; import { getMaximumAttachmentSize } from '../../util/attachments'; @@ -789,6 +790,10 @@ function replaceAttachments( return; } + if (hasDraftAttachments(attachments, { includePending: true })) { + removeLinkPreview(); + } + dispatch({ type: REPLACE_ATTACHMENTS, payload: attachments.map(resolveDraftAttachmentOnDisk), diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 916a1ea9f..b94f8d88b 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -2860,7 +2860,9 @@ type ShowConversationArgsType = { messageId?: string; switchToAssociatedView?: boolean; }; -export type ShowConversationType = (_: ShowConversationArgsType) => unknown; +export type ShowConversationType = ( + options: ShowConversationArgsType +) => unknown; function showConversation({ conversationId, diff --git a/ts/state/smart/ConversationView.tsx b/ts/state/smart/ConversationView.tsx index 776d8f762..8ac6665d2 100644 --- a/ts/state/smart/ConversationView.tsx +++ b/ts/state/smart/ConversationView.tsx @@ -29,7 +29,6 @@ export type PropsType = { | 'onEditorStateChange' | 'onSelectMediaQuality' | 'onTextTooLong' - | 'openConversation' >; conversationHeaderProps: ConversationHeaderPropsType; timelineProps: TimelinePropsType; diff --git a/ts/state/smart/MessageDetail.tsx b/ts/state/smart/MessageDetail.tsx index 165359fdc..30ec9a252 100644 --- a/ts/state/smart/MessageDetail.tsx +++ b/ts/state/smart/MessageDetail.tsx @@ -25,6 +25,7 @@ export type OwnProps = Omit< | 'renderReactionPicker' | 'theme' | 'showContactModal' + | 'showConversation' | 'markViewed' >; @@ -41,7 +42,6 @@ const mapStateToProps = ( kickOffAttachmentDownload, markAttachmentAsCorrupted, - openConversation, openGiftBadge, openLink, showContactDetail, @@ -76,7 +76,6 @@ const mapStateToProps = ( kickOffAttachmentDownload, markAttachmentAsCorrupted, markViewed, - openConversation, openGiftBadge, openLink, renderAudioAttachment, diff --git a/ts/state/smart/Timeline.tsx b/ts/state/smart/Timeline.tsx index 94efb29e5..0ce81b87d 100644 --- a/ts/state/smart/Timeline.tsx +++ b/ts/state/smart/Timeline.tsx @@ -74,7 +74,6 @@ export type TimelinePropsType = ExternalProps & | 'loadOlderMessages' | 'markAttachmentAsCorrupted' | 'markMessageRead' - | 'openConversation' | 'openGiftBadge' | 'openLink' | 'reactToMessage' diff --git a/ts/test-both/state/ducks/composer_test.ts b/ts/test-both/state/ducks/composer_test.ts index 450561dd9..25ed893ca 100644 --- a/ts/test-both/state/ducks/composer_test.ts +++ b/ts/test-both/state/ducks/composer_test.ts @@ -3,7 +3,9 @@ import { assert } from 'chai'; import * as sinon from 'sinon'; +import { noop } from 'lodash'; +import type { ReduxActions } from '../../../state/types'; import { actions, getEmptyState, reducer } from '../../../state/ducks/composer'; import { noopAction } from '../../../state/ducks/noop'; import { reducer as rootReducer } from '../../../state/reducer'; @@ -38,6 +40,22 @@ describe('both/state/ducks/composer', () => { }; describe('replaceAttachments', () => { + let oldReduxActions: ReduxActions; + before(() => { + oldReduxActions = window.reduxActions; + window.reduxActions = { + ...oldReduxActions, + linkPreviews: { + ...oldReduxActions?.linkPreviews, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + removeLinkPreview: noop as any, + }, + }; + }); + after(() => { + window.reduxActions = oldReduxActions; + }); + it('replaces the attachments state', () => { const { replaceAttachments } = actions; const dispatch = sinon.spy(); diff --git a/ts/util/createIPCEvents.tsx b/ts/util/createIPCEvents.tsx index e49face15..1c73d7794 100644 --- a/ts/util/createIPCEvents.tsx +++ b/ts/util/createIPCEvents.tsx @@ -26,7 +26,6 @@ import type { ConversationType } from '../state/ducks/conversations'; import { calling } from '../services/calling'; import { getConversationsWithCustomColorSelector } from '../state/selectors/conversations'; import { getCustomColors } from '../state/selectors/items'; -import { trigger } from '../shims/events'; import { themeChanged } from '../shims/themeChanged'; import { renderClearingDataView } from '../shims/renderClearingDataView'; @@ -491,7 +490,9 @@ export function createIPCEvents( setIsFetchingUUID: noop, }); if (convoId) { - trigger('showConversation', convoId); + window.reduxActions.conversations.showConversation({ + conversationId: convoId, + }); return; } // We will show not found modal on error @@ -507,7 +508,9 @@ export function createIPCEvents( setIsFetchingUUID: noop, }); if (convoId) { - trigger('showConversation', convoId); + window.reduxActions.conversations.showConversation({ + conversationId: convoId, + }); return; } // We will show not found modal on error diff --git a/ts/util/hasDraftAttachments.ts b/ts/util/hasDraftAttachments.ts index b6f2e98d9..2ac7620fd 100644 --- a/ts/util/hasDraftAttachments.ts +++ b/ts/util/hasDraftAttachments.ts @@ -4,7 +4,7 @@ import type { AttachmentDraftType } from '../types/Attachment'; export function hasDraftAttachments( - draftAttachments: Array | undefined, + draftAttachments: ReadonlyArray | undefined, options: { includePending: boolean } ): boolean { if (!draftAttachments) { diff --git a/ts/util/startConversation.ts b/ts/util/startConversation.ts index 23fea087e..3c729717d 100644 --- a/ts/util/startConversation.ts +++ b/ts/util/startConversation.ts @@ -15,5 +15,7 @@ export function startConversation(e164: string, uuid: UUIDStringType): void { `startConversation failed given ${e164}/${uuid} combination` ); - window.Whisper.events.trigger('showConversation', conversation.id); + window.reduxActions.conversations.showConversation({ + conversationId: conversation.id, + }); } diff --git a/ts/views/conversation_view.tsx b/ts/views/conversation_view.tsx index ca8d913d4..4f2f213cc 100644 --- a/ts/views/conversation_view.tsx +++ b/ts/views/conversation_view.tsx @@ -37,7 +37,6 @@ import { ToastReactionFailed } from '../components/ToastReactionFailed'; import { ToastTapToViewExpiredIncoming } from '../components/ToastTapToViewExpiredIncoming'; import { ToastTapToViewExpiredOutgoing } from '../components/ToastTapToViewExpiredOutgoing'; import { ToastCannotOpenGiftBadge } from '../components/ToastCannotOpenGiftBadge'; -import { deleteDraftAttachment } from '../util/deleteDraftAttachment'; import { retryMessageSend } from '../util/retryMessageSend'; import { isNotNil } from '../util/isNotNil'; import { openLinkInWebBrowser } from '../util/openLinkInWebBrowser'; @@ -55,7 +54,7 @@ import { import { SECOND } from '../util/durations'; import { startConversation } from '../util/startConversation'; import { longRunningTaskWrapper } from '../util/longRunningTaskWrapper'; -import { hasDraftAttachments } from '../util/hasDraftAttachments'; +import { clearConversationDraftAttachments } from '../util/clearConversationDraftAttachments'; import type { BackbonePanelRenderType, PanelRenderType } from '../types/Panels'; import { PanelType, isPanelHandledByReact } from '../types/Panels'; @@ -80,7 +79,6 @@ type MessageActionsType = { options: Readonly<{ messageId: string }> ) => unknown; markAttachmentAsCorrupted: (options: AttachmentOptions) => unknown; - openConversation: (conversationId: string, messageId?: string) => unknown; openGiftBadge: (messageId: string) => unknown; openLink: (url: string) => unknown; reactToMessage: ( @@ -150,27 +148,18 @@ export class ConversationView extends window.Backbone.View { }); this.listenTo(this.model, 'show-message-details', this.showMessageDetail); this.listenTo(this.model, 'delete-message', this.deleteMessage); - this.listenTo(this.model, 'remove-link-review', removeLinkPreview); - this.listenTo( - this.model, - 'remove-all-draft-attachments', - this.clearAttachments - ); + + this.listenTo(this.model, 'pushPanel', this.pushPanel); + this.listenTo(this.model, 'popPanel', this.popPanel); this.render(); this.setupConversationView(); - this.updateAttachmentsView(); - this.listenTo(this.model, 'pushPanel', this.pushPanel); - this.listenTo(this.model, 'popPanel', this.popPanel); - } - - override events(): Record { - return { - drop: 'onDrop', - paste: 'onPaste', - }; + window.reduxActions.composer.replaceAttachments( + this.model.get('id'), + this.model.get('draftAttachments') || [] + ); } // We need this ignore because the backbone types really want this to be a string @@ -231,7 +220,9 @@ export class ConversationView extends window.Backbone.View { showToast(ToastConversationArchived, { undo: () => { this.model.setArchived(false); - this.openConversation(this.model.get('id')); + window.reduxActions.conversations.showConversation({ + conversationId: this.model.id, + }); }, }); }, @@ -373,7 +364,11 @@ export class ConversationView extends window.Backbone.View { }); }, - onClearAttachments: this.clearAttachments.bind(this), + onClearAttachments: () => + clearConversationDraftAttachments( + this.model.id, + this.model.get('draftAttachments') + ), onSelectMediaQuality: (isHQ: boolean) => { window.reduxActions.composer.setMediaQualitySetting(isHQ); }, @@ -382,8 +377,6 @@ export class ConversationView extends window.Backbone.View { suspendLinkPreviews(); removeLinkPreview(); }, - - openConversation: this.openConversation.bind(this), }; // createConversationView root @@ -423,9 +416,6 @@ export class ConversationView extends window.Backbone.View { const showMessageDetail = (messageId: string) => { this.showMessageDetail(messageId); }; - const openConversation = (conversationId: string, messageId?: string) => { - this.openConversation(conversationId, messageId); - }; const showContactDetail = (options: { contact: EmbeddedContactType; signalAccount?: { @@ -485,7 +475,6 @@ export class ConversationView extends window.Backbone.View { downloadNewVersion, kickOffAttachmentDownload, markAttachmentAsCorrupted, - openConversation, openGiftBadge, openLink, reactToMessage, @@ -530,8 +519,7 @@ export class ConversationView extends window.Backbone.View { }); } - // We don't wait here; we need to take down the view - this.saveModel(); + window.Signal.Data.updateConversation(this.model.attributes); this.model.updateLastMessage(); } @@ -560,10 +548,6 @@ export class ConversationView extends window.Backbone.View { this.remove(); } - async saveModel(): Promise { - window.Signal.Data.updateConversation(this.model.attributes); - } - async onOpened(messageId: string): Promise { this.model.onOpenStart(); @@ -1171,17 +1155,6 @@ export class ConversationView extends window.Backbone.View { return view; } - async openConversation( - conversationId: string, - messageId?: string - ): Promise { - window.Whisper.events.trigger( - 'showConversation', - conversationId, - messageId - ); - } - pushPanel(panel: PanelRenderType): void { if (isPanelHandledByReact(panel)) { return; @@ -1286,35 +1259,6 @@ export class ConversationView extends window.Backbone.View { // Backup, in case things go wrong with the transitionend event timeout = setTimeout(removePanel, SECOND); } - - async clearAttachments(): Promise { - const draftAttachments = this.model.get('draftAttachments') || []; - this.model.set({ - draftAttachments: [], - draftChanged: true, - }); - - this.updateAttachmentsView(); - - // We're fine doing this all at once; at most it should be 32 attachments - await Promise.all([ - this.saveModel(), - Promise.all( - draftAttachments.map(attachment => deleteDraftAttachment(attachment)) - ), - ]); - } - - updateAttachmentsView(): void { - const draftAttachments = this.model.get('draftAttachments') || []; - window.reduxActions.composer.replaceAttachments( - this.model.get('id'), - draftAttachments - ); - if (hasDraftAttachments(this.model.attributes, { includePending: true })) { - removeLinkPreview(); - } - } } window.Whisper.ConversationView = ConversationView;