Fix forwarding attachments that haven't been downloaded
This commit is contained in:
parent
ac76271772
commit
0db5a3b888
3 changed files with 155 additions and 85 deletions
|
@ -36,9 +36,11 @@ import {
|
|||
MESSAGE_CHANGED,
|
||||
MESSAGE_DELETED,
|
||||
MESSAGE_EXPIRED,
|
||||
actions as conversationsActions,
|
||||
} from './conversations';
|
||||
import { SHOW_TOAST } from './toast';
|
||||
import type { ShowToastActionType } from './toast';
|
||||
import { isDownloaded } from '../../types/Attachment';
|
||||
|
||||
// State
|
||||
|
||||
|
@ -564,6 +566,14 @@ function toggleForwardMessagesModal(
|
|||
);
|
||||
}
|
||||
|
||||
const attachments = message.get('attachments') ?? [];
|
||||
|
||||
if (!attachments.every(isDownloaded)) {
|
||||
dispatch(
|
||||
conversationsActions.kickOffAttachmentDownload({ messageId })
|
||||
);
|
||||
}
|
||||
|
||||
const messagePropsSelector = getMessagePropsSelector(getState());
|
||||
const messageProps = messagePropsSelector(message.attributes);
|
||||
|
||||
|
@ -832,6 +842,21 @@ export function confirmAuthorizeArtCreator(): ThunkAction<
|
|||
};
|
||||
}
|
||||
|
||||
function copyOverMessageAttributesIntoForwardMessages(
|
||||
messagesProps: ReadonlyArray<ForwardMessagePropsType>,
|
||||
attributes: ReadonlyDeep<MessageAttributesType>
|
||||
): ReadonlyArray<ForwardMessagePropsType> {
|
||||
return messagesProps.map(messageProps => {
|
||||
if (messageProps.id !== attributes.id) {
|
||||
return messageProps;
|
||||
}
|
||||
return {
|
||||
...messageProps,
|
||||
attachments: attributes.attachments,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
// Reducer
|
||||
|
||||
export function getEmptyState(): GlobalModalsStateType {
|
||||
|
@ -1099,15 +1124,35 @@ export function reducer(
|
|||
};
|
||||
}
|
||||
|
||||
if (state.forwardMessagesProps != null) {
|
||||
if (action.type === MESSAGE_CHANGED) {
|
||||
if (
|
||||
!state.forwardMessagesProps.messages.some(message => {
|
||||
return message.id === action.payload.id;
|
||||
})
|
||||
) {
|
||||
return state;
|
||||
}
|
||||
|
||||
return {
|
||||
...state,
|
||||
forwardMessagesProps: {
|
||||
...state.forwardMessagesProps,
|
||||
messages: copyOverMessageAttributesIntoForwardMessages(
|
||||
state.forwardMessagesProps.messages,
|
||||
action.payload.data
|
||||
),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (state.editHistoryMessages != null) {
|
||||
if (
|
||||
action.type === MESSAGE_CHANGED ||
|
||||
action.type === MESSAGE_DELETED ||
|
||||
action.type === MESSAGE_EXPIRED
|
||||
) {
|
||||
if (!state.editHistoryMessages) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (action.type === MESSAGE_DELETED || action.type === MESSAGE_EXPIRED) {
|
||||
const hasMessageId = state.editHistoryMessages.some(
|
||||
edit => edit.id === action.payload.id
|
||||
|
@ -1136,9 +1181,8 @@ export function reducer(
|
|||
return state;
|
||||
}
|
||||
|
||||
const nextEditHistoryMessages = copyOverMessageAttributesIntoEditHistory(
|
||||
action.payload.data
|
||||
);
|
||||
const nextEditHistoryMessages =
|
||||
copyOverMessageAttributesIntoEditHistory(action.payload.data);
|
||||
|
||||
if (!nextEditHistoryMessages) {
|
||||
return state;
|
||||
|
@ -1150,6 +1194,7 @@ export function reducer(
|
|||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
|
|
@ -3,12 +3,16 @@
|
|||
|
||||
import React, { useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import type { ForwardMessagesPropsType } from '../ducks/globalModals';
|
||||
import type {
|
||||
ForwardMessagePropsType,
|
||||
ForwardMessagesPropsType,
|
||||
} from '../ducks/globalModals';
|
||||
import type { StateType } from '../reducer';
|
||||
import * as log from '../../logging/log';
|
||||
import { ForwardMessagesModal } from '../../components/ForwardMessagesModal';
|
||||
import { LinkPreviewSourceType } from '../../types/LinkPreview';
|
||||
import * as Errors from '../../types/errors';
|
||||
import type { GetConversationByIdType } from '../selectors/conversations';
|
||||
import {
|
||||
getAllComposableConversations,
|
||||
getConversationSelector,
|
||||
|
@ -31,12 +35,53 @@ import { useLinkPreviewActions } from '../ducks/linkPreviews';
|
|||
import { SmartCompositionTextArea } from './CompositionTextArea';
|
||||
import { useToastActions } from '../ducks/toast';
|
||||
import { hydrateRanges } from '../../types/BodyRange';
|
||||
import { isDownloaded } from '../../types/Attachment';
|
||||
|
||||
function toMessageForwardDraft(
|
||||
props: ForwardMessagePropsType,
|
||||
getConversation: GetConversationByIdType
|
||||
): MessageForwardDraft {
|
||||
return {
|
||||
attachments: props.attachments ?? [],
|
||||
bodyRanges: hydrateRanges(props.bodyRanges, getConversation),
|
||||
hasContact: Boolean(props.contact),
|
||||
isSticker: Boolean(props.isSticker),
|
||||
messageBody: props.text,
|
||||
originalMessageId: props.id,
|
||||
previews: props.previews ?? [],
|
||||
};
|
||||
}
|
||||
|
||||
export function SmartForwardMessagesModal(): JSX.Element | null {
|
||||
const forwardMessagesProps = useSelector<
|
||||
StateType,
|
||||
ForwardMessagesPropsType | undefined
|
||||
>(state => state.globalModals.forwardMessagesProps);
|
||||
|
||||
if (forwardMessagesProps == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
!forwardMessagesProps.messages.every(message => {
|
||||
return message.attachments?.every(isDownloaded) ?? true;
|
||||
})
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<SmartForwardMessagesModalInner
|
||||
forwardMessagesProps={forwardMessagesProps}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function SmartForwardMessagesModalInner({
|
||||
forwardMessagesProps,
|
||||
}: {
|
||||
forwardMessagesProps: ForwardMessagesPropsType;
|
||||
}): JSX.Element | null {
|
||||
const candidateConversations = useSelector(getAllComposableConversations);
|
||||
const getPreferredBadge = useSelector(getPreferredBadgeSelector);
|
||||
const getConversation = useSelector(getConversationSelector);
|
||||
|
@ -51,19 +96,9 @@ export function SmartForwardMessagesModal(): JSX.Element | null {
|
|||
|
||||
const [drafts, setDrafts] = useState<ReadonlyArray<MessageForwardDraft>>(
|
||||
() => {
|
||||
return (
|
||||
forwardMessagesProps?.messages.map((props): MessageForwardDraft => {
|
||||
return {
|
||||
attachments: props.attachments ?? [],
|
||||
bodyRanges: hydrateRanges(props.bodyRanges, getConversation),
|
||||
hasContact: Boolean(props.contact),
|
||||
isSticker: Boolean(props.isSticker),
|
||||
messageBody: props.text,
|
||||
originalMessageId: props.id,
|
||||
previews: props.previews ?? [],
|
||||
};
|
||||
}) ?? []
|
||||
);
|
||||
return forwardMessagesProps.messages.map((props): MessageForwardDraft => {
|
||||
return toMessageForwardDraft(props, getConversation);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
import { orderBy } from 'lodash';
|
||||
import type { AttachmentType } from '../types/Attachment';
|
||||
import { isVoiceMessage } from '../types/Attachment';
|
||||
import { isVoiceMessage, isDownloaded } from '../types/Attachment';
|
||||
import type {
|
||||
LinkPreviewType,
|
||||
LinkPreviewWithHydratedData,
|
||||
|
@ -57,41 +57,31 @@ export function isDraftEditable(draft: MessageForwardDraft): boolean {
|
|||
return true;
|
||||
}
|
||||
|
||||
export function isDraftForwardable(draft: MessageForwardDraft): boolean {
|
||||
const messageLength = draft.messageBody?.length ?? 0;
|
||||
if (messageLength > 0) {
|
||||
return true;
|
||||
}
|
||||
if (draft.isSticker) {
|
||||
return true;
|
||||
}
|
||||
if (draft.hasContact) {
|
||||
return true;
|
||||
}
|
||||
const attachmentsLength = draft.attachments?.length ?? 0;
|
||||
if (attachmentsLength > 0) {
|
||||
return true;
|
||||
}
|
||||
function isDraftEmpty(draft: MessageForwardDraft) {
|
||||
const { messageBody, attachments, isSticker, hasContact } = draft;
|
||||
if (isSticker || hasContact) {
|
||||
return false;
|
||||
}
|
||||
if (attachments != null && attachments.length > 0) {
|
||||
return false;
|
||||
}
|
||||
if (messageBody != null && messageBody.length > 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function isMessageForwardable(message: MessageAttributesType): boolean {
|
||||
const { body, attachments, sticker, contact } = message;
|
||||
const messageLength = body?.length ?? 0;
|
||||
if (messageLength > 0) {
|
||||
return true;
|
||||
}
|
||||
if (sticker) {
|
||||
return true;
|
||||
}
|
||||
if (contact?.length) {
|
||||
return true;
|
||||
}
|
||||
const attachmentsLength = attachments?.length ?? 0;
|
||||
if (attachmentsLength > 0) {
|
||||
return true;
|
||||
}
|
||||
export function isDraftForwardable(draft: MessageForwardDraft): boolean {
|
||||
const { attachments } = draft;
|
||||
if (isDraftEmpty(draft)) {
|
||||
return false;
|
||||
}
|
||||
if (attachments != null && attachments.length > 0) {
|
||||
if (!attachments.every(isDownloaded)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function sortByMessageOrder<T>(
|
||||
|
|
Loading…
Reference in a new issue