Standardize on showConversation function, delete unused functions

This commit is contained in:
Scott Nonnenberg 2022-12-14 11:05:32 -08:00 committed by GitHub
parent 1dc3ed914f
commit f2f1c3c021
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 174 additions and 198 deletions

View file

@ -158,6 +158,8 @@ import type AccountManager from './textsecure/AccountManager';
import { onStoryRecipientUpdate } from './util/onStoryRecipientUpdate'; import { onStoryRecipientUpdate } from './util/onStoryRecipientUpdate';
import { StoryViewModeType, StoryViewTargetType } from './types/Stories'; import { StoryViewModeType, StoryViewTargetType } from './types/Stories';
import { downloadOnboardingStory } from './util/downloadOnboardingStory'; import { downloadOnboardingStory } from './util/downloadOnboardingStory';
import { clearConversationDraftAttachments } from './util/clearConversationDraftAttachments';
import { removeLinkPreview } from './services/LinkPreview';
const MAX_ATTACHMENT_DOWNLOAD_AGE = 3600 * 72 * 1000; const MAX_ATTACHMENT_DOWNLOAD_AGE = 3600 * 72 * 1000;
@ -1545,10 +1547,9 @@ export async function startApp(): Promise<void> {
showToast(ToastConversationArchived, { showToast(ToastConversationArchived, {
undo: () => { undo: () => {
conversation.setArchived(false); conversation.setArchived(false);
window.Whisper.events.trigger( window.reduxActions.conversations.showConversation({
'showConversation', conversationId: conversation.get('id'),
conversation.get('id') });
);
}, },
}); });
@ -1702,7 +1703,7 @@ export async function startApp(): Promise<void> {
!shiftKey && !shiftKey &&
(key === 'p' || key === 'P') (key === 'p' || key === 'P')
) { ) {
conversation.trigger('remove-link-review'); removeLinkPreview();
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
@ -1716,7 +1717,10 @@ export async function startApp(): Promise<void> {
shiftKey && shiftKey &&
(key === 'p' || key === 'P') (key === 'p' || key === 'P')
) { ) {
conversation.trigger('remove-all-draft-attachments'); clearConversationDraftAttachments(
conversation.id,
conversation.get('draftAttachments')
);
event.preventDefault(); event.preventDefault();
event.stopPropagation(); event.stopPropagation();
@ -1924,7 +1928,10 @@ export async function startApp(): Promise<void> {
viewTarget: StoryViewTargetType.Replies, viewTarget: StoryViewTargetType.Replies,
}); });
} else { } else {
window.Whisper.events.trigger('showConversation', id, messageId); window.reduxActions.conversations.showConversation({
conversationId: id,
messageId,
});
} }
} else { } else {
window.reduxActions.app.openInbox(); window.reduxActions.app.openInbox();

View file

@ -167,20 +167,20 @@ export function AddUserToAnotherGroupModal({
> >
<ConversationList <ConversationList
dimensions={contentRect.bounds} dimensions={contentRect.bounds}
rowCount={filteredConversations.length}
getRow={handleGetRow}
shouldRecomputeRowHeights={false}
showConversation={noop}
getPreferredBadge={() => undefined} getPreferredBadge={() => undefined}
getRow={handleGetRow}
i18n={i18n} i18n={i18n}
theme={theme} lookupConversationWithoutUuid={async _ => undefined}
onClickArchiveButton={noop} onClickArchiveButton={noop}
onClickContactCheckbox={noop} onClickContactCheckbox={noop}
onSelectConversation={setSelectedGroupId} onSelectConversation={setSelectedGroupId}
showChooseGroupMembers={noop} rowCount={filteredConversations.length}
lookupConversationWithoutUuid={async _ => undefined}
showUserNotFoundModal={noop}
setIsFetchingUUID={noop} setIsFetchingUUID={noop}
shouldRecomputeRowHeights={false}
showChooseGroupMembers={noop}
showConversation={noop}
showUserNotFoundModal={noop}
theme={theme}
/> />
</div> </div>
)} )}

View file

@ -2,7 +2,10 @@
// SPDX-License-Identifier: AGPL-3.0-only // SPDX-License-Identifier: AGPL-3.0-only
import React, { useState } from 'react'; 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 { Intl } from './Intl';
import type { LocalizerType, ThemeType } from '../types/Util'; import type { LocalizerType, ThemeType } from '../types/Util';
import { Modal } from './Modal'; import { Modal } from './Modal';
@ -11,14 +14,14 @@ import { ConversationListItem } from './conversationList/ConversationListItem';
type PropsType = { type PropsType = {
groupAdmins: Array<ConversationType>; groupAdmins: Array<ConversationType>;
i18n: LocalizerType; i18n: LocalizerType;
openConversation: (conversationId: string) => unknown; showConversation: ShowConversationType;
theme: ThemeType; theme: ThemeType;
}; };
export function AnnouncementsOnlyGroupBanner({ export function AnnouncementsOnlyGroupBanner({
groupAdmins, groupAdmins,
i18n, i18n,
openConversation, showConversation,
theme, theme,
}: PropsType): JSX.Element { }: PropsType): JSX.Element {
const [isShowingAdmins, setIsShowingAdmins] = useState(false); const [isShowingAdmins, setIsShowingAdmins] = useState(false);
@ -35,13 +38,13 @@ export function AnnouncementsOnlyGroupBanner({
{groupAdmins.map(admin => ( {groupAdmins.map(admin => (
<ConversationListItem <ConversationListItem
{...admin} {...admin}
i18n={i18n}
onClick={() => {
openConversation(admin.id);
}}
draftPreview="" draftPreview=""
i18n={i18n}
lastMessage={undefined} lastMessage={undefined}
lastUpdated={undefined} lastUpdated={undefined}
onClick={() => {
showConversation({ conversationId: admin.id });
}}
theme={theme} theme={theme}
/> />
))} ))}

View file

@ -117,8 +117,8 @@ const useProps = (overrideProps: Partial<Props> = {}): Props => ({
), ),
areWeAdmin: boolean('areWeAdmin', Boolean(overrideProps.areWeAdmin)), areWeAdmin: boolean('areWeAdmin', Boolean(overrideProps.areWeAdmin)),
groupAdmins: [], groupAdmins: [],
openConversation: action('openConversation'),
onCancelJoinRequest: action('onCancelJoinRequest'), onCancelJoinRequest: action('onCancelJoinRequest'),
showConversation: action('showConversation'),
// SMS-only // SMS-only
isSMSOnly: overrideProps.isSMSOnly || false, isSMSOnly: overrideProps.isSMSOnly || false,
isFetchingUUID: overrideProps.isFetchingUUID || false, isFetchingUUID: overrideProps.isFetchingUUID || false,

View file

@ -40,7 +40,10 @@ import type {
import { isImageAttachment } from '../types/Attachment'; import { isImageAttachment } from '../types/Attachment';
import { AudioCapture } from './conversation/AudioCapture'; import { AudioCapture } from './conversation/AudioCapture';
import { CompositionUpload } from './CompositionUpload'; 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 { EmojiPickDataType } from './emoji/EmojiPicker';
import type { LinkPreviewType } from '../types/message/LinkPreviews'; import type { LinkPreviewType } from '../types/message/LinkPreviews';
@ -117,7 +120,6 @@ export type OwnProps = Readonly<{
voiceNoteAttachment?: InMemoryAttachmentDraftType; voiceNoteAttachment?: InMemoryAttachmentDraftType;
} }
): unknown; ): unknown;
openConversation(conversationId: string): unknown;
quotedMessageId?: string; quotedMessageId?: string;
quotedMessageProps?: Omit< quotedMessageProps?: Omit<
QuoteProps, QuoteProps,
@ -131,6 +133,7 @@ export type OwnProps = Readonly<{
messageId: string | undefined messageId: string | undefined
): unknown; ): unknown;
shouldSendHighQualityAttachments: boolean; shouldSendHighQualityAttachments: boolean;
showConversation: ShowConversationType;
startRecording: () => unknown; startRecording: () => unknown;
theme: ThemeType; theme: ThemeType;
}>; }>;
@ -257,7 +260,7 @@ export function CompositionArea({
areWeAdmin, areWeAdmin,
groupAdmins, groupAdmins,
onCancelJoinRequest, onCancelJoinRequest,
openConversation, showConversation,
// SMS-only contacts // SMS-only contacts
isSMSOnly, isSMSOnly,
isFetchingUUID, isFetchingUUID,
@ -594,7 +597,7 @@ export function CompositionArea({
<AnnouncementsOnlyGroupBanner <AnnouncementsOnlyGroupBanner
groupAdmins={groupAdmins} groupAdmins={groupAdmins}
i18n={i18n} i18n={i18n}
openConversation={openConversation} showConversation={showConversation}
theme={theme} theme={theme}
/> />
); );

View file

@ -135,10 +135,6 @@ export function Inbox({
prevConversation.trigger('unload', 'force unload requested'); prevConversation.trigger('unload', 'force unload requested');
} }
function onShowConversation(id: string, messageId?: string): void {
showConversation({ conversationId: id, messageId });
}
function packInstallFailed() { function packInstallFailed() {
showToast(ToastStickerPackInstallFailed); showToast(ToastStickerPackInstallFailed);
} }
@ -147,14 +143,12 @@ export function Inbox({
window.Whisper.events.on('pack-install-failed', packInstallFailed); window.Whisper.events.on('pack-install-failed', packInstallFailed);
window.Whisper.events.on('refreshConversation', refreshConversation); window.Whisper.events.on('refreshConversation', refreshConversation);
window.Whisper.events.on('setupAsNewDevice', unload); window.Whisper.events.on('setupAsNewDevice', unload);
window.Whisper.events.on('showConversation', onShowConversation);
return () => { return () => {
window.Whisper.events.off('loadingProgress', setLoadingMessageCount); window.Whisper.events.off('loadingProgress', setLoadingMessageCount);
window.Whisper.events.off('pack-install-failed', packInstallFailed); window.Whisper.events.off('pack-install-failed', packInstallFailed);
window.Whisper.events.off('refreshConversation', refreshConversation); window.Whisper.events.off('refreshConversation', refreshConversation);
window.Whisper.events.off('setupAsNewDevice', unload); window.Whisper.events.off('setupAsNewDevice', unload);
window.Whisper.events.off('showConversation', onShowConversation);
}; };
}, [prevConversation, showConversation]); }, [prevConversation, showConversation]);

View file

@ -148,8 +148,8 @@ const useProps = (overrideProps: Partial<PropsType> = {}): PropsType => {
getPreferredBadge={() => undefined} getPreferredBadge={() => undefined}
i18n={i18n} i18n={i18n}
id={id} id={id}
showConversation={action('showConversation')}
sentAt={1587358800000} sentAt={1587358800000}
showConversation={action('showConversation')}
snippet="Lorem <<left>>ipsum<<right>> wow" snippet="Lorem <<left>>ipsum<<right>> wow"
theme={ThemeType.light} theme={ThemeType.light}
to={defaultConversations[1]} to={defaultConversations[1]}

View file

@ -142,7 +142,6 @@ export type PropsType = {
export function LeftPane({ export function LeftPane({
challengeStatus, challengeStatus,
crashReportCount,
clearConversationSearch, clearConversationSearch,
clearGroupCreationError, clearGroupCreationError,
clearSearch, clearSearch,
@ -151,9 +150,11 @@ export function LeftPane({
composeDeleteAvatarFromDisk, composeDeleteAvatarFromDisk,
composeReplaceAvatar, composeReplaceAvatar,
composeSaveAvatarToDisk, composeSaveAvatarToDisk,
crashReportCount,
createGroup, createGroup,
getPreferredBadge, getPreferredBadge,
i18n, i18n,
lookupConversationWithoutUuid,
modeSpecificProps, modeSpecificProps,
preferredWidthFromStorage, preferredWidthFromStorage,
renderCaptchaDialog, renderCaptchaDialog,
@ -173,19 +174,18 @@ export function LeftPane({
setComposeGroupExpireTimer, setComposeGroupExpireTimer,
setComposeGroupName, setComposeGroupName,
setComposeSearchTerm, setComposeSearchTerm,
setIsFetchingUUID,
showArchivedConversations, showArchivedConversations,
showChooseGroupMembers, showChooseGroupMembers,
showConversation,
showInbox, showInbox,
showUserNotFoundModal,
startComposing, startComposing,
startSearch, startSearch,
showUserNotFoundModal,
setIsFetchingUUID,
lookupConversationWithoutUuid,
toggleConversationInChooseMembers,
showConversation,
startSettingGroupMetadata, startSettingGroupMetadata,
theme, theme,
toggleComposeEditingAvatar, toggleComposeEditingAvatar,
toggleConversationInChooseMembers,
updateSearchTerm, updateSearchTerm,
}: PropsType): JSX.Element { }: PropsType): JSX.Element {
const [preferredWidth, setPreferredWidth] = useState( const [preferredWidth, setPreferredWidth] = useState(

View file

@ -16,15 +16,15 @@ type PropsType = {
clearSearch: () => void; clearSearch: () => void;
disabled?: boolean; disabled?: boolean;
i18n: LocalizerType; i18n: LocalizerType;
searchConversation?: ConversationType;
searchTerm: string;
startSearchCounter: number;
updateSearchTerm: (searchTerm: string) => void;
showConversation: ShowConversationType;
onEnterKeyDown?: ( onEnterKeyDown?: (
clearSearch: () => void, clearSearch: () => void,
showConversation: ShowConversationType showConversation: ShowConversationType
) => void; ) => void;
searchConversation?: ConversationType;
searchTerm: string;
showConversation: ShowConversationType;
startSearchCounter: number;
updateSearchTerm: (searchTerm: string) => void;
}; };
export function LeftPaneSearchInput({ export function LeftPaneSearchInput({
@ -32,12 +32,12 @@ export function LeftPaneSearchInput({
clearSearch, clearSearch,
disabled, disabled,
i18n, i18n,
onEnterKeyDown,
searchConversation, searchConversation,
searchTerm, searchTerm,
showConversation,
startSearchCounter, startSearchCounter,
updateSearchTerm, updateSearchTerm,
showConversation,
onEnterKeyDown,
}: PropsType): JSX.Element { }: PropsType): JSX.Element {
const inputRef = useRef<null | HTMLInputElement>(null); const inputRef = useRef<null | HTMLInputElement>(null);

View file

@ -1193,22 +1193,22 @@ export function EditDistributionListModal({
getPreferredBadge={getPreferredBadge} getPreferredBadge={getPreferredBadge}
getRow={getRow} getRow={getRow}
i18n={i18n} i18n={i18n}
lookupConversationWithoutUuid={asyncShouldNeverBeCalled}
onClickArchiveButton={shouldNeverBeCalled} onClickArchiveButton={shouldNeverBeCalled}
onClickContactCheckbox={(conversationId: string) => { onClickContactCheckbox={(conversationId: string) => {
toggleSelectedConversation(conversationId); toggleSelectedConversation(conversationId);
}} }}
lookupConversationWithoutUuid={asyncShouldNeverBeCalled}
showConversation={shouldNeverBeCalled}
showUserNotFoundModal={shouldNeverBeCalled}
setIsFetchingUUID={shouldNeverBeCalled}
onSelectConversation={shouldNeverBeCalled} onSelectConversation={shouldNeverBeCalled}
renderMessageSearchResult={() => { renderMessageSearchResult={() => {
shouldNeverBeCalled(); shouldNeverBeCalled();
return <div />; return <div />;
}} }}
rowCount={rowCount} rowCount={rowCount}
setIsFetchingUUID={shouldNeverBeCalled}
shouldRecomputeRowHeights={false} shouldRecomputeRowHeights={false}
showChooseGroupMembers={shouldNeverBeCalled} showChooseGroupMembers={shouldNeverBeCalled}
showConversation={shouldNeverBeCalled}
showUserNotFoundModal={shouldNeverBeCalled}
theme={ThemeType.dark} theme={ThemeType.dark}
/> />
</div> </div>

View file

@ -57,7 +57,7 @@ const MESSAGE_DEFAULT_PROPS = {
markViewed: shouldNeverBeCalled, markViewed: shouldNeverBeCalled,
messageExpanded: shouldNeverBeCalled, messageExpanded: shouldNeverBeCalled,
// Called when clicking mention, but shouldn't do anything. // Called when clicking mention, but shouldn't do anything.
openConversation: noop, showConversation: noop,
openGiftBadge: shouldNeverBeCalled, openGiftBadge: shouldNeverBeCalled,
openLink: shouldNeverBeCalled, openLink: shouldNeverBeCalled,
previews: [], previews: [],

View file

@ -20,7 +20,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
{ incoming: 'incoming', outgoing: 'outgoing' }, { incoming: 'incoming', outgoing: 'outgoing' },
overrideProps.direction || 'incoming' overrideProps.direction || 'incoming'
), ),
openConversation: action('openConversation'), showConversation: action('showConversation'),
text: text('text', overrideProps.text || ''), text: text('text', overrideProps.text || ''),
}); });

View file

@ -13,14 +13,17 @@ import type {
export type Props = { export type Props = {
bodyRanges?: HydratedBodyRangesType; bodyRanges?: HydratedBodyRangesType;
direction?: 'incoming' | 'outgoing'; direction?: 'incoming' | 'outgoing';
openConversation?: (conversationId: string, messageId?: string) => void; showConversation?: (options: {
conversationId: string;
messageId?: string;
}) => unknown;
text: string; text: string;
}; };
export function AtMentionify({ export function AtMentionify({
bodyRanges, bodyRanges,
direction, direction,
openConversation, showConversation,
text, text,
}: Props): JSX.Element { }: Props): JSX.Element {
if (!bodyRanges) { if (!bodyRanges) {
@ -53,17 +56,17 @@ export function AtMentionify({
className={`MessageBody__at-mention MessageBody__at-mention--${direction}`} className={`MessageBody__at-mention MessageBody__at-mention--${direction}`}
key={range.start} key={range.start}
onClick={() => { onClick={() => {
if (openConversation) { if (showConversation) {
openConversation(range.conversationID); showConversation({ conversationId: range.conversationID });
} }
}} }}
onKeyUp={e => { onKeyUp={e => {
if ( if (
e.target === e.currentTarget && e.target === e.currentTarget &&
e.keyCode === 13 && e.keyCode === 13 &&
openConversation showConversation
) { ) {
openConversation(range.conversationID); showConversation({ conversationId: range.conversationID });
} }
}} }}
tabIndex={0} tabIndex={0}

View file

@ -63,8 +63,8 @@ enum SubModalState {
} }
export function ContactModal({ export function ContactModal({
areWeASubscriber,
areWeAdmin, areWeAdmin,
areWeASubscriber,
badges, badges,
contact, contact,
conversation, conversation,
@ -76,9 +76,9 @@ export function ContactModal({
removeMemberFromGroup, removeMemberFromGroup,
showConversation, showConversation,
theme, theme,
toggleAddUserToAnotherGroupModal,
toggleAdmin, toggleAdmin,
toggleSafetyNumberModal, toggleSafetyNumberModal,
toggleAddUserToAnotherGroupModal,
updateConversationModelSharedGroups, updateConversationModelSharedGroups,
viewUserStories, viewUserStories,
}: PropsType): JSX.Element { }: PropsType): JSX.Element {

View file

@ -81,23 +81,21 @@ export type PropsDataType = {
export type PropsActionsType = { export type PropsActionsType = {
destroyMessages: (conversationId: string) => void; destroyMessages: (conversationId: string) => void;
onSearchInConversation: () => void;
onOutgoingAudioCallInConversation: (conversationId: string) => void;
onOutgoingVideoCallInConversation: (conversationId: string) => void;
onShowConversationDetails: () => void;
onShowAllMedia: () => void;
onShowGroupMembers: () => void;
onGoBack: () => void;
onArchive: () => void; onArchive: () => void;
onGoBack: () => void;
onMarkUnread: () => void; onMarkUnread: () => void;
onMoveToInbox: () => 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: ( setDisappearingMessages: (
conversationId: string, conversationId: string,
seconds: DurationInSeconds seconds: DurationInSeconds
) => void; ) => void;
setMuteExpiration: (conversationId: string, seconds: number) => void;
setPinned: (conversationId: string, value: boolean) => void; setPinned: (conversationId: string, value: boolean) => void;
viewUserStories: ViewUserStoriesActionCreatorType; viewUserStories: ViewUserStoriesActionCreatorType;
}; };

View file

@ -15,6 +15,7 @@ import type {
ConversationTypeType, ConversationTypeType,
InteractionModeType, InteractionModeType,
SaveAttachmentActionCreatorType, SaveAttachmentActionCreatorType,
ShowConversationType,
} from '../../state/ducks/conversations'; } from '../../state/ducks/conversations';
import type { ViewStoryActionCreatorType } from '../../state/ducks/stories'; import type { ViewStoryActionCreatorType } from '../../state/ducks/stories';
import type { ReadStatus } from '../../messages/MessageReadStatus'; import type { ReadStatus } from '../../messages/MessageReadStatus';
@ -299,7 +300,7 @@ export type PropsActions = {
showMessageDetail: (id: string) => void; showMessageDetail: (id: string) => void;
startConversation: (e164: string, uuid: UUIDStringType) => void; startConversation: (e164: string, uuid: UUIDStringType) => void;
openConversation: (conversationId: string, messageId?: string) => void; showConversation: ShowConversationType;
openGiftBadge: (messageId: string) => void; openGiftBadge: (messageId: string) => void;
showContactDetail: (options: { showContactDetail: (options: {
contact: EmbeddedContactType; contact: EmbeddedContactType;
@ -1709,13 +1710,13 @@ export class Message extends React.PureComponent<Props, State> {
displayLimit, displayLimit,
i18n, i18n,
id, id,
messageExpanded,
openConversation,
kickOffAttachmentDownload, kickOffAttachmentDownload,
messageExpanded,
showConversation,
status, status,
text, text,
textDirection,
textAttachment, textAttachment,
textDirection,
} = this.props; } = this.props;
const { metadataWidth } = this.state; const { metadataWidth } = this.state;
const isRTL = textDirection === TextDirection.RightToLeft; const isRTL = textDirection === TextDirection.RightToLeft;
@ -1747,13 +1748,11 @@ export class Message extends React.PureComponent<Props, State> {
> >
<MessageBodyReadMore <MessageBodyReadMore
bodyRanges={bodyRanges} bodyRanges={bodyRanges}
disableLinks={!this.areLinksEnabled()}
direction={direction} direction={direction}
disableLinks={!this.areLinksEnabled()}
displayLimit={displayLimit} displayLimit={displayLimit}
i18n={i18n} i18n={i18n}
id={id} id={id}
messageExpanded={messageExpanded}
openConversation={openConversation}
kickOffBodyDownload={() => { kickOffBodyDownload={() => {
if (!textAttachment) { if (!textAttachment) {
return; return;
@ -1763,6 +1762,8 @@ export class Message extends React.PureComponent<Props, State> {
messageId: id, messageId: id,
}); });
}} }}
messageExpanded={messageExpanded}
showConversation={showConversation}
text={contents || ''} text={contents || ''}
textAttachment={textAttachment} textAttachment={textAttachment}
/> />

View file

@ -13,31 +13,27 @@ import { Emojify } from './Emojify';
import { AddNewLines } from './AddNewLines'; import { AddNewLines } from './AddNewLines';
import { Linkify } from './Linkify'; import { Linkify } from './Linkify';
import type { ShowConversationType } from '../../state/ducks/conversations';
import type { import type {
HydratedBodyRangesType, HydratedBodyRangesType,
LocalizerType, LocalizerType,
RenderTextCallbackType, RenderTextCallbackType,
} from '../../types/Util'; } from '../../types/Util';
type OpenConversationActionType = (
conversationId: string,
messageId?: string
) => void;
export type Props = { export type Props = {
direction?: 'incoming' | 'outgoing';
text: string;
author?: string; author?: string;
textAttachment?: Pick<AttachmentType, 'pending' | 'digest' | 'key'>; bodyRanges?: HydratedBodyRangesType;
direction?: 'incoming' | 'outgoing';
/** If set, all emoji will be the same size. Otherwise, just one emoji will be large. */ /** If set, all emoji will be the same size. Otherwise, just one emoji will be large. */
disableJumbomoji?: boolean; disableJumbomoji?: boolean;
/** If set, links will be left alone instead of turned into clickable `<a>` tags. */ /** If set, links will be left alone instead of turned into clickable `<a>` tags. */
disableLinks?: boolean; disableLinks?: boolean;
i18n: LocalizerType; i18n: LocalizerType;
bodyRanges?: HydratedBodyRangesType;
onIncreaseTextLength?: () => unknown;
openConversation?: OpenConversationActionType;
kickOffBodyDownload?: () => void; kickOffBodyDownload?: () => void;
onIncreaseTextLength?: () => unknown;
showConversation?: ShowConversationType;
text: string;
textAttachment?: Pick<AttachmentType, 'pending' | 'digest' | 'key'>;
}; };
const renderEmoji = ({ const renderEmoji = ({
@ -67,17 +63,17 @@ const renderEmoji = ({
* them for you. * them for you.
*/ */
export function MessageBody({ export function MessageBody({
author,
bodyRanges, bodyRanges,
direction, direction,
disableJumbomoji, disableJumbomoji,
disableLinks, disableLinks,
i18n, i18n,
onIncreaseTextLength,
openConversation,
text,
author,
textAttachment,
kickOffBodyDownload, kickOffBodyDownload,
onIncreaseTextLength,
showConversation,
text,
textAttachment,
}: Props): JSX.Element { }: Props): JSX.Element {
const hasReadMore = Boolean(onIncreaseTextLength); const hasReadMore = Boolean(onIncreaseTextLength);
const textWithSuffix = const textWithSuffix =
@ -100,10 +96,10 @@ export function MessageBody({
renderNonNewLine={({ text: innerText, key: innerKey }) => ( renderNonNewLine={({ text: innerText, key: innerKey }) => (
<AtMentionify <AtMentionify
key={innerKey} key={innerKey}
direction={direction}
text={innerText}
bodyRanges={bodyRanges} bodyRanges={bodyRanges}
openConversation={openConversation} direction={direction}
showConversation={showConversation}
text={innerText}
/> />
)} )}
/> />

View file

@ -9,14 +9,14 @@ import { graphemeAndLinkAwareSlice } from '../../util/graphemeAndLinkAwareSlice'
export type Props = Pick< export type Props = Pick<
MessageBodyPropsType, MessageBodyPropsType,
| 'bodyRanges'
| 'direction' | 'direction'
| 'text'
| 'textAttachment'
| 'disableLinks' | 'disableLinks'
| 'i18n' | 'i18n'
| 'bodyRanges'
| 'openConversation'
| 'kickOffBodyDownload' | 'kickOffBodyDownload'
| 'showConversation'
| 'text'
| 'textAttachment'
> & { > & {
id: string; id: string;
displayLimit?: number; displayLimit?: number;
@ -38,9 +38,9 @@ export function MessageBodyReadMore({
displayLimit, displayLimit,
i18n, i18n,
id, id,
messageExpanded,
openConversation,
kickOffBodyDownload, kickOffBodyDownload,
messageExpanded,
showConversation,
text, text,
textAttachment, textAttachment,
}: Props): JSX.Element { }: Props): JSX.Element {
@ -61,12 +61,12 @@ export function MessageBodyReadMore({
return ( return (
<MessageBody <MessageBody
bodyRanges={bodyRanges} bodyRanges={bodyRanges}
disableLinks={disableLinks}
direction={direction} direction={direction}
disableLinks={disableLinks}
i18n={i18n} i18n={i18n}
onIncreaseTextLength={onIncreaseTextLength}
openConversation={openConversation}
kickOffBodyDownload={kickOffBodyDownload} kickOffBodyDownload={kickOffBodyDownload}
onIncreaseTextLength={onIncreaseTextLength}
showConversation={showConversation}
text={slicedText} text={slicedText}
textAttachment={textAttachment} textAttachment={textAttachment}
/> />

View file

@ -78,7 +78,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
kickOffAttachmentDownload: action('kickOffAttachmentDownload'), kickOffAttachmentDownload: action('kickOffAttachmentDownload'),
markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'), markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'),
markViewed: action('markViewed'), markViewed: action('markViewed'),
openConversation: action('openConversation'), showConversation: action('showConversation'),
openGiftBadge: action('openGiftBadge'), openGiftBadge: action('openGiftBadge'),
openLink: action('openLink'), openLink: action('openLink'),
renderAudioAttachment: () => <div>*AudioAttachment*</div>, renderAudioAttachment: () => <div>*AudioAttachment*</div>,

View file

@ -81,7 +81,6 @@ export type PropsBackboneActions = Pick<
MessagePropsType, MessagePropsType,
| 'kickOffAttachmentDownload' | 'kickOffAttachmentDownload'
| 'markAttachmentAsCorrupted' | 'markAttachmentAsCorrupted'
| 'openConversation'
| 'openGiftBadge' | 'openGiftBadge'
| 'openLink' | 'openLink'
| 'renderAudioAttachment' | 'renderAudioAttachment'
@ -98,6 +97,7 @@ export type PropsReduxActions = Pick<
| 'doubleCheckMissingQuoteReference' | 'doubleCheckMissingQuoteReference'
| 'saveAttachment' | 'saveAttachment'
| 'showContactModal' | 'showContactModal'
| 'showConversation'
| 'showLightbox' | 'showLightbox'
| 'showLightboxForViewOnceMedia' | 'showLightboxForViewOnceMedia'
| 'viewStory' | 'viewStory'
@ -290,13 +290,13 @@ export class MessageDetail extends React.Component<Props> {
kickOffAttachmentDownload, kickOffAttachmentDownload,
markAttachmentAsCorrupted, markAttachmentAsCorrupted,
markViewed, markViewed,
openConversation,
openGiftBadge, openGiftBadge,
openLink, openLink,
renderAudioAttachment, renderAudioAttachment,
saveAttachment, saveAttachment,
showContactDetail, showContactDetail,
showContactModal, showContactModal,
showConversation,
showExpiredIncomingTapToViewToast, showExpiredIncomingTapToViewToast,
showExpiredOutgoingTapToViewToast, showExpiredOutgoingTapToViewToast,
showLightbox, showLightbox,
@ -336,7 +336,7 @@ export class MessageDetail extends React.Component<Props> {
markAttachmentAsCorrupted={markAttachmentAsCorrupted} markAttachmentAsCorrupted={markAttachmentAsCorrupted}
markViewed={markViewed} markViewed={markViewed}
messageExpanded={noop} messageExpanded={noop}
openConversation={openConversation} showConversation={showConversation}
openGiftBadge={openGiftBadge} openGiftBadge={openGiftBadge}
openLink={openLink} openLink={openLink}
renderAudioAttachment={renderAudioAttachment} renderAudioAttachment={renderAudioAttachment}

View file

@ -112,7 +112,7 @@ const defaultMessageProps: TimelineMessagesProps = {
markAttachmentAsCorrupted: action('default--markAttachmentAsCorrupted'), markAttachmentAsCorrupted: action('default--markAttachmentAsCorrupted'),
markViewed: action('default--markViewed'), markViewed: action('default--markViewed'),
messageExpanded: action('default--message-expanded'), messageExpanded: action('default--message-expanded'),
openConversation: action('default--openConversation'), showConversation: action('default--showConversation'),
openGiftBadge: action('openGiftBadge'), openGiftBadge: action('openGiftBadge'),
openLink: action('default--openLink'), openLink: action('default--openLink'),
previews: [], previews: [],

View file

@ -282,10 +282,10 @@ const actions = () => ({
deleteMessage: action('deleteMessage'), deleteMessage: action('deleteMessage'),
deleteMessageForEveryone: action('deleteMessageForEveryone'), deleteMessageForEveryone: action('deleteMessageForEveryone'),
showMessageDetail: action('showMessageDetail'), showMessageDetail: action('showMessageDetail'),
openConversation: action('openConversation'),
saveAttachment: action('saveAttachment'), saveAttachment: action('saveAttachment'),
showContactDetail: action('showContactDetail'), showContactDetail: action('showContactDetail'),
showContactModal: action('showContactModal'), showContactModal: action('showContactModal'),
showConversation: action('showConversation'),
kickOffAttachmentDownload: action('kickOffAttachmentDownload'), kickOffAttachmentDownload: action('kickOffAttachmentDownload'),
markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'), markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'),
markViewed: action('markViewed'), markViewed: action('markViewed'),

View file

@ -244,8 +244,8 @@ const getActions = createSelector(
'toggleForwardMessageModal', 'toggleForwardMessageModal',
'deleteMessage', 'deleteMessage',
'deleteMessageForEveryone', 'deleteMessageForEveryone',
'showConversation',
'showMessageDetail', 'showMessageDetail',
'openConversation',
'openGiftBadge', 'openGiftBadge',
'setQuoteByMessageId', 'setQuoteByMessageId',
'showContactDetail', 'showContactDetail',

View file

@ -78,7 +78,7 @@ const getDefaultProps = () => ({
markViewed: action('markViewed'), markViewed: action('markViewed'),
messageExpanded: action('messageExpanded'), messageExpanded: action('messageExpanded'),
showMessageDetail: action('showMessageDetail'), showMessageDetail: action('showMessageDetail'),
openConversation: action('openConversation'), showConversation: action('showConversation'),
openGiftBadge: action('openGiftBadge'), openGiftBadge: action('openGiftBadge'),
saveAttachment: action('saveAttachment'), saveAttachment: action('saveAttachment'),
showContactDetail: action('showContactDetail'), showContactDetail: action('showContactDetail'),

View file

@ -279,7 +279,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'), markAttachmentAsCorrupted: action('markAttachmentAsCorrupted'),
markViewed: action('markViewed'), markViewed: action('markViewed'),
messageExpanded: action('messageExpanded'), messageExpanded: action('messageExpanded'),
openConversation: action('openConversation'), showConversation: action('showConversation'),
openGiftBadge: action('openGiftBadge'), openGiftBadge: action('openGiftBadge'),
openLink: action('openLink'), openLink: action('openLink'),
previews: overrideProps.previews || [], previews: overrideProps.previews || [],

View file

@ -44,6 +44,7 @@ import {
getLinkPreviewForSend, getLinkPreviewForSend,
hasLinkPreviewLoaded, hasLinkPreviewLoaded,
maybeGrabLinkPreview, maybeGrabLinkPreview,
removeLinkPreview,
resetLinkPreview, resetLinkPreview,
} from '../../services/LinkPreview'; } from '../../services/LinkPreview';
import { getMaximumAttachmentSize } from '../../util/attachments'; import { getMaximumAttachmentSize } from '../../util/attachments';
@ -789,6 +790,10 @@ function replaceAttachments(
return; return;
} }
if (hasDraftAttachments(attachments, { includePending: true })) {
removeLinkPreview();
}
dispatch({ dispatch({
type: REPLACE_ATTACHMENTS, type: REPLACE_ATTACHMENTS,
payload: attachments.map(resolveDraftAttachmentOnDisk), payload: attachments.map(resolveDraftAttachmentOnDisk),

View file

@ -2860,7 +2860,9 @@ type ShowConversationArgsType = {
messageId?: string; messageId?: string;
switchToAssociatedView?: boolean; switchToAssociatedView?: boolean;
}; };
export type ShowConversationType = (_: ShowConversationArgsType) => unknown; export type ShowConversationType = (
options: ShowConversationArgsType
) => unknown;
function showConversation({ function showConversation({
conversationId, conversationId,

View file

@ -29,7 +29,6 @@ export type PropsType = {
| 'onEditorStateChange' | 'onEditorStateChange'
| 'onSelectMediaQuality' | 'onSelectMediaQuality'
| 'onTextTooLong' | 'onTextTooLong'
| 'openConversation'
>; >;
conversationHeaderProps: ConversationHeaderPropsType; conversationHeaderProps: ConversationHeaderPropsType;
timelineProps: TimelinePropsType; timelineProps: TimelinePropsType;

View file

@ -25,6 +25,7 @@ export type OwnProps = Omit<
| 'renderReactionPicker' | 'renderReactionPicker'
| 'theme' | 'theme'
| 'showContactModal' | 'showContactModal'
| 'showConversation'
| 'markViewed' | 'markViewed'
>; >;
@ -41,7 +42,6 @@ const mapStateToProps = (
kickOffAttachmentDownload, kickOffAttachmentDownload,
markAttachmentAsCorrupted, markAttachmentAsCorrupted,
openConversation,
openGiftBadge, openGiftBadge,
openLink, openLink,
showContactDetail, showContactDetail,
@ -76,7 +76,6 @@ const mapStateToProps = (
kickOffAttachmentDownload, kickOffAttachmentDownload,
markAttachmentAsCorrupted, markAttachmentAsCorrupted,
markViewed, markViewed,
openConversation,
openGiftBadge, openGiftBadge,
openLink, openLink,
renderAudioAttachment, renderAudioAttachment,

View file

@ -74,7 +74,6 @@ export type TimelinePropsType = ExternalProps &
| 'loadOlderMessages' | 'loadOlderMessages'
| 'markAttachmentAsCorrupted' | 'markAttachmentAsCorrupted'
| 'markMessageRead' | 'markMessageRead'
| 'openConversation'
| 'openGiftBadge' | 'openGiftBadge'
| 'openLink' | 'openLink'
| 'reactToMessage' | 'reactToMessage'

View file

@ -3,7 +3,9 @@
import { assert } from 'chai'; import { assert } from 'chai';
import * as sinon from 'sinon'; import * as sinon from 'sinon';
import { noop } from 'lodash';
import type { ReduxActions } from '../../../state/types';
import { actions, getEmptyState, reducer } from '../../../state/ducks/composer'; import { actions, getEmptyState, reducer } from '../../../state/ducks/composer';
import { noopAction } from '../../../state/ducks/noop'; import { noopAction } from '../../../state/ducks/noop';
import { reducer as rootReducer } from '../../../state/reducer'; import { reducer as rootReducer } from '../../../state/reducer';
@ -38,6 +40,22 @@ describe('both/state/ducks/composer', () => {
}; };
describe('replaceAttachments', () => { 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', () => { it('replaces the attachments state', () => {
const { replaceAttachments } = actions; const { replaceAttachments } = actions;
const dispatch = sinon.spy(); const dispatch = sinon.spy();

View file

@ -26,7 +26,6 @@ import type { ConversationType } from '../state/ducks/conversations';
import { calling } from '../services/calling'; import { calling } from '../services/calling';
import { getConversationsWithCustomColorSelector } from '../state/selectors/conversations'; import { getConversationsWithCustomColorSelector } from '../state/selectors/conversations';
import { getCustomColors } from '../state/selectors/items'; import { getCustomColors } from '../state/selectors/items';
import { trigger } from '../shims/events';
import { themeChanged } from '../shims/themeChanged'; import { themeChanged } from '../shims/themeChanged';
import { renderClearingDataView } from '../shims/renderClearingDataView'; import { renderClearingDataView } from '../shims/renderClearingDataView';
@ -491,7 +490,9 @@ export function createIPCEvents(
setIsFetchingUUID: noop, setIsFetchingUUID: noop,
}); });
if (convoId) { if (convoId) {
trigger('showConversation', convoId); window.reduxActions.conversations.showConversation({
conversationId: convoId,
});
return; return;
} }
// We will show not found modal on error // We will show not found modal on error
@ -507,7 +508,9 @@ export function createIPCEvents(
setIsFetchingUUID: noop, setIsFetchingUUID: noop,
}); });
if (convoId) { if (convoId) {
trigger('showConversation', convoId); window.reduxActions.conversations.showConversation({
conversationId: convoId,
});
return; return;
} }
// We will show not found modal on error // We will show not found modal on error

View file

@ -4,7 +4,7 @@
import type { AttachmentDraftType } from '../types/Attachment'; import type { AttachmentDraftType } from '../types/Attachment';
export function hasDraftAttachments( export function hasDraftAttachments(
draftAttachments: Array<AttachmentDraftType> | undefined, draftAttachments: ReadonlyArray<AttachmentDraftType> | undefined,
options: { includePending: boolean } options: { includePending: boolean }
): boolean { ): boolean {
if (!draftAttachments) { if (!draftAttachments) {

View file

@ -15,5 +15,7 @@ export function startConversation(e164: string, uuid: UUIDStringType): void {
`startConversation failed given ${e164}/${uuid} combination` `startConversation failed given ${e164}/${uuid} combination`
); );
window.Whisper.events.trigger('showConversation', conversation.id); window.reduxActions.conversations.showConversation({
conversationId: conversation.id,
});
} }

View file

@ -37,7 +37,6 @@ import { ToastReactionFailed } from '../components/ToastReactionFailed';
import { ToastTapToViewExpiredIncoming } from '../components/ToastTapToViewExpiredIncoming'; import { ToastTapToViewExpiredIncoming } from '../components/ToastTapToViewExpiredIncoming';
import { ToastTapToViewExpiredOutgoing } from '../components/ToastTapToViewExpiredOutgoing'; import { ToastTapToViewExpiredOutgoing } from '../components/ToastTapToViewExpiredOutgoing';
import { ToastCannotOpenGiftBadge } from '../components/ToastCannotOpenGiftBadge'; import { ToastCannotOpenGiftBadge } from '../components/ToastCannotOpenGiftBadge';
import { deleteDraftAttachment } from '../util/deleteDraftAttachment';
import { retryMessageSend } from '../util/retryMessageSend'; import { retryMessageSend } from '../util/retryMessageSend';
import { isNotNil } from '../util/isNotNil'; import { isNotNil } from '../util/isNotNil';
import { openLinkInWebBrowser } from '../util/openLinkInWebBrowser'; import { openLinkInWebBrowser } from '../util/openLinkInWebBrowser';
@ -55,7 +54,7 @@ import {
import { SECOND } from '../util/durations'; import { SECOND } from '../util/durations';
import { startConversation } from '../util/startConversation'; import { startConversation } from '../util/startConversation';
import { longRunningTaskWrapper } from '../util/longRunningTaskWrapper'; import { longRunningTaskWrapper } from '../util/longRunningTaskWrapper';
import { hasDraftAttachments } from '../util/hasDraftAttachments'; import { clearConversationDraftAttachments } from '../util/clearConversationDraftAttachments';
import type { BackbonePanelRenderType, PanelRenderType } from '../types/Panels'; import type { BackbonePanelRenderType, PanelRenderType } from '../types/Panels';
import { PanelType, isPanelHandledByReact } from '../types/Panels'; import { PanelType, isPanelHandledByReact } from '../types/Panels';
@ -80,7 +79,6 @@ type MessageActionsType = {
options: Readonly<{ messageId: string }> options: Readonly<{ messageId: string }>
) => unknown; ) => unknown;
markAttachmentAsCorrupted: (options: AttachmentOptions) => unknown; markAttachmentAsCorrupted: (options: AttachmentOptions) => unknown;
openConversation: (conversationId: string, messageId?: string) => unknown;
openGiftBadge: (messageId: string) => unknown; openGiftBadge: (messageId: string) => unknown;
openLink: (url: string) => unknown; openLink: (url: string) => unknown;
reactToMessage: ( reactToMessage: (
@ -150,27 +148,18 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
}); });
this.listenTo(this.model, 'show-message-details', this.showMessageDetail); this.listenTo(this.model, 'show-message-details', this.showMessageDetail);
this.listenTo(this.model, 'delete-message', this.deleteMessage); this.listenTo(this.model, 'delete-message', this.deleteMessage);
this.listenTo(this.model, 'remove-link-review', removeLinkPreview);
this.listenTo( this.listenTo(this.model, 'pushPanel', this.pushPanel);
this.model, this.listenTo(this.model, 'popPanel', this.popPanel);
'remove-all-draft-attachments',
this.clearAttachments
);
this.render(); this.render();
this.setupConversationView(); this.setupConversationView();
this.updateAttachmentsView();
this.listenTo(this.model, 'pushPanel', this.pushPanel); window.reduxActions.composer.replaceAttachments(
this.listenTo(this.model, 'popPanel', this.popPanel); this.model.get('id'),
} this.model.get('draftAttachments') || []
);
override events(): Record<string, string> {
return {
drop: 'onDrop',
paste: 'onPaste',
};
} }
// We need this ignore because the backbone types really want this to be a string // 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<ConversationModel> {
showToast(ToastConversationArchived, { showToast(ToastConversationArchived, {
undo: () => { undo: () => {
this.model.setArchived(false); 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<ConversationModel> {
}); });
}, },
onClearAttachments: this.clearAttachments.bind(this), onClearAttachments: () =>
clearConversationDraftAttachments(
this.model.id,
this.model.get('draftAttachments')
),
onSelectMediaQuality: (isHQ: boolean) => { onSelectMediaQuality: (isHQ: boolean) => {
window.reduxActions.composer.setMediaQualitySetting(isHQ); window.reduxActions.composer.setMediaQualitySetting(isHQ);
}, },
@ -382,8 +377,6 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
suspendLinkPreviews(); suspendLinkPreviews();
removeLinkPreview(); removeLinkPreview();
}, },
openConversation: this.openConversation.bind(this),
}; };
// createConversationView root // createConversationView root
@ -423,9 +416,6 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
const showMessageDetail = (messageId: string) => { const showMessageDetail = (messageId: string) => {
this.showMessageDetail(messageId); this.showMessageDetail(messageId);
}; };
const openConversation = (conversationId: string, messageId?: string) => {
this.openConversation(conversationId, messageId);
};
const showContactDetail = (options: { const showContactDetail = (options: {
contact: EmbeddedContactType; contact: EmbeddedContactType;
signalAccount?: { signalAccount?: {
@ -485,7 +475,6 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
downloadNewVersion, downloadNewVersion,
kickOffAttachmentDownload, kickOffAttachmentDownload,
markAttachmentAsCorrupted, markAttachmentAsCorrupted,
openConversation,
openGiftBadge, openGiftBadge,
openLink, openLink,
reactToMessage, reactToMessage,
@ -530,8 +519,7 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
}); });
} }
// We don't wait here; we need to take down the view window.Signal.Data.updateConversation(this.model.attributes);
this.saveModel();
this.model.updateLastMessage(); this.model.updateLastMessage();
} }
@ -560,10 +548,6 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
this.remove(); this.remove();
} }
async saveModel(): Promise<void> {
window.Signal.Data.updateConversation(this.model.attributes);
}
async onOpened(messageId: string): Promise<void> { async onOpened(messageId: string): Promise<void> {
this.model.onOpenStart(); this.model.onOpenStart();
@ -1171,17 +1155,6 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
return view; return view;
} }
async openConversation(
conversationId: string,
messageId?: string
): Promise<void> {
window.Whisper.events.trigger(
'showConversation',
conversationId,
messageId
);
}
pushPanel(panel: PanelRenderType): void { pushPanel(panel: PanelRenderType): void {
if (isPanelHandledByReact(panel)) { if (isPanelHandledByReact(panel)) {
return; return;
@ -1286,35 +1259,6 @@ export class ConversationView extends window.Backbone.View<ConversationModel> {
// Backup, in case things go wrong with the transitionend event // Backup, in case things go wrong with the transitionend event
timeout = setTimeout(removePanel, SECOND); timeout = setTimeout(removePanel, SECOND);
} }
async clearAttachments(): Promise<void> {
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; window.Whisper.ConversationView = ConversationView;