Ensure consistency in forwarding logic
This commit is contained in:
parent
38666fe0a4
commit
15263c2d16
9 changed files with 72 additions and 9 deletions
|
@ -199,6 +199,7 @@ export type OwnProps = Readonly<{
|
||||||
props: SmartCompositionRecordingDraftProps
|
props: SmartCompositionRecordingDraftProps
|
||||||
) => JSX.Element | null;
|
) => JSX.Element | null;
|
||||||
selectedMessageIds: ReadonlyArray<string> | undefined;
|
selectedMessageIds: ReadonlyArray<string> | undefined;
|
||||||
|
areSelectedMessagesForwardable: boolean | undefined;
|
||||||
toggleSelectMode: (on: boolean) => void;
|
toggleSelectMode: (on: boolean) => void;
|
||||||
toggleForwardMessagesModal: (
|
toggleForwardMessagesModal: (
|
||||||
payload: ForwardMessagesPayload,
|
payload: ForwardMessagesPayload,
|
||||||
|
@ -367,6 +368,7 @@ export const CompositionArea = memo(function CompositionArea({
|
||||||
renderSmartCompositionRecordingDraft,
|
renderSmartCompositionRecordingDraft,
|
||||||
// Selected messages
|
// Selected messages
|
||||||
selectedMessageIds,
|
selectedMessageIds,
|
||||||
|
areSelectedMessagesForwardable,
|
||||||
toggleSelectMode,
|
toggleSelectMode,
|
||||||
toggleForwardMessagesModal,
|
toggleForwardMessagesModal,
|
||||||
// DraftGifMessageSendModal
|
// DraftGifMessageSendModal
|
||||||
|
@ -906,6 +908,7 @@ export const CompositionArea = memo(function CompositionArea({
|
||||||
<SelectModeActions
|
<SelectModeActions
|
||||||
i18n={i18n}
|
i18n={i18n}
|
||||||
selectedMessageIds={selectedMessageIds}
|
selectedMessageIds={selectedMessageIds}
|
||||||
|
areSelectedMessagesForwardable={areSelectedMessagesForwardable === true}
|
||||||
onExitSelectMode={() => {
|
onExitSelectMode={() => {
|
||||||
toggleSelectMode(false);
|
toggleSelectMode(false);
|
||||||
}}
|
}}
|
||||||
|
|
|
@ -74,6 +74,7 @@ const defaultMessageProps: TimelineMessagesProps = {
|
||||||
}),
|
}),
|
||||||
canCopy: true,
|
canCopy: true,
|
||||||
canEditMessage: true,
|
canEditMessage: true,
|
||||||
|
canForward: true,
|
||||||
canReact: true,
|
canReact: true,
|
||||||
canReply: true,
|
canReply: true,
|
||||||
canRetry: true,
|
canRetry: true,
|
||||||
|
|
|
@ -12,6 +12,7 @@ const MAX_FORWARD_COUNT = 30;
|
||||||
|
|
||||||
type SelectModeActionsProps = Readonly<{
|
type SelectModeActionsProps = Readonly<{
|
||||||
selectedMessageIds: ReadonlyArray<string>;
|
selectedMessageIds: ReadonlyArray<string>;
|
||||||
|
areSelectedMessagesForwardable: boolean;
|
||||||
onExitSelectMode: () => void;
|
onExitSelectMode: () => void;
|
||||||
onDeleteMessages: () => void;
|
onDeleteMessages: () => void;
|
||||||
onForwardMessages: () => void;
|
onForwardMessages: () => void;
|
||||||
|
@ -21,6 +22,7 @@ type SelectModeActionsProps = Readonly<{
|
||||||
|
|
||||||
export default function SelectModeActions({
|
export default function SelectModeActions({
|
||||||
selectedMessageIds,
|
selectedMessageIds,
|
||||||
|
areSelectedMessagesForwardable,
|
||||||
onExitSelectMode,
|
onExitSelectMode,
|
||||||
onDeleteMessages,
|
onDeleteMessages,
|
||||||
onForwardMessages,
|
onForwardMessages,
|
||||||
|
@ -31,7 +33,10 @@ export default function SelectModeActions({
|
||||||
const tooManyMessagesToForward =
|
const tooManyMessagesToForward =
|
||||||
selectedMessageIds.length > MAX_FORWARD_COUNT;
|
selectedMessageIds.length > MAX_FORWARD_COUNT;
|
||||||
|
|
||||||
const canForward = hasSelectedMessages && !tooManyMessagesToForward;
|
const canForward =
|
||||||
|
hasSelectedMessages &&
|
||||||
|
areSelectedMessagesForwardable &&
|
||||||
|
!tooManyMessagesToForward;
|
||||||
const canDelete = hasSelectedMessages;
|
const canDelete = hasSelectedMessages;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -51,6 +51,7 @@ function mockMessageTimelineItem(
|
||||||
canDeleteForEveryone: false,
|
canDeleteForEveryone: false,
|
||||||
canDownload: true,
|
canDownload: true,
|
||||||
canEditMessage: true,
|
canEditMessage: true,
|
||||||
|
canForward: true,
|
||||||
canReact: true,
|
canReact: true,
|
||||||
canReply: true,
|
canReply: true,
|
||||||
canRetry: true,
|
canRetry: true,
|
||||||
|
|
|
@ -255,6 +255,7 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
canReply: true,
|
canReply: true,
|
||||||
canDownload: true,
|
canDownload: true,
|
||||||
canDeleteForEveryone: overrideProps.canDeleteForEveryone || false,
|
canDeleteForEveryone: overrideProps.canDeleteForEveryone || false,
|
||||||
|
canForward: true,
|
||||||
canRetry: overrideProps.canRetry || false,
|
canRetry: overrideProps.canRetry || false,
|
||||||
canRetryDeleteForEveryone: overrideProps.canRetryDeleteForEveryone || false,
|
canRetryDeleteForEveryone: overrideProps.canRetryDeleteForEveryone || false,
|
||||||
checkForAccount: action('checkForAccount'),
|
checkForAccount: action('checkForAccount'),
|
||||||
|
@ -266,7 +267,6 @@ const createProps = (overrideProps: Partial<Props> = {}): Props => ({
|
||||||
conversationId: overrideProps.conversationId ?? '',
|
conversationId: overrideProps.conversationId ?? '',
|
||||||
conversationType: overrideProps.conversationType || 'direct',
|
conversationType: overrideProps.conversationType || 'direct',
|
||||||
contact: overrideProps.contact,
|
contact: overrideProps.contact,
|
||||||
deletedForEveryone: overrideProps.deletedForEveryone,
|
|
||||||
// disableMenu: overrideProps.disableMenu,
|
// disableMenu: overrideProps.disableMenu,
|
||||||
disableScroll: overrideProps.disableScroll,
|
disableScroll: overrideProps.disableScroll,
|
||||||
direction: overrideProps.direction || 'incoming',
|
direction: overrideProps.direction || 'incoming',
|
||||||
|
@ -796,11 +796,13 @@ export function Deleted(): JSX.Element {
|
||||||
const propsSent = createProps({
|
const propsSent = createProps({
|
||||||
conversationType: 'direct',
|
conversationType: 'direct',
|
||||||
deletedForEveryone: true,
|
deletedForEveryone: true,
|
||||||
|
canForward: false,
|
||||||
status: 'sent',
|
status: 'sent',
|
||||||
});
|
});
|
||||||
const propsSending = createProps({
|
const propsSending = createProps({
|
||||||
conversationType: 'direct',
|
conversationType: 'direct',
|
||||||
deletedForEveryone: true,
|
deletedForEveryone: true,
|
||||||
|
canForward: false,
|
||||||
status: 'sending',
|
status: 'sending',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -817,6 +819,7 @@ DeletedWithExpireTimer.args = {
|
||||||
timestamp: Date.now() - 60 * 1000,
|
timestamp: Date.now() - 60 * 1000,
|
||||||
conversationType: 'group',
|
conversationType: 'group',
|
||||||
deletedForEveryone: true,
|
deletedForEveryone: true,
|
||||||
|
canForward: false,
|
||||||
expirationLength: 5 * 60 * 1000,
|
expirationLength: 5 * 60 * 1000,
|
||||||
expirationTimestamp: Date.now() + 3 * 60 * 1000,
|
expirationTimestamp: Date.now() + 3 * 60 * 1000,
|
||||||
status: 'sent',
|
status: 'sent',
|
||||||
|
@ -2265,6 +2268,7 @@ const fullContact = {
|
||||||
export const EmbeddedContactFullContact = Template.bind({});
|
export const EmbeddedContactFullContact = Template.bind({});
|
||||||
EmbeddedContactFullContact.args = {
|
EmbeddedContactFullContact.args = {
|
||||||
contact: fullContact,
|
contact: fullContact,
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmbeddedContactAvatarUndownloaded = Template.bind({});
|
export const EmbeddedContactAvatarUndownloaded = Template.bind({});
|
||||||
|
@ -2279,6 +2283,7 @@ EmbeddedContactAvatarUndownloaded.args = {
|
||||||
isProfile: true,
|
isProfile: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
export const EmbeddedContactAvatarDownloading = Template.bind({});
|
export const EmbeddedContactAvatarDownloading = Template.bind({});
|
||||||
EmbeddedContactAvatarDownloading.args = {
|
EmbeddedContactAvatarDownloading.args = {
|
||||||
|
@ -2295,6 +2300,7 @@ EmbeddedContactAvatarDownloading.args = {
|
||||||
isProfile: true,
|
isProfile: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
export const EmbeddedContactAvatarTransientError = Template.bind({});
|
export const EmbeddedContactAvatarTransientError = Template.bind({});
|
||||||
EmbeddedContactAvatarTransientError.args = {
|
EmbeddedContactAvatarTransientError.args = {
|
||||||
|
@ -2316,6 +2322,7 @@ EmbeddedContactAvatarTransientError.args = {
|
||||||
isProfile: true,
|
isProfile: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
export const EmbeddedContactAvatarPermanentError = Template.bind({});
|
export const EmbeddedContactAvatarPermanentError = Template.bind({});
|
||||||
EmbeddedContactAvatarPermanentError.args = {
|
EmbeddedContactAvatarPermanentError.args = {
|
||||||
|
@ -2335,6 +2342,7 @@ EmbeddedContactAvatarPermanentError.args = {
|
||||||
isProfile: true,
|
isProfile: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmbeddedContactWithSendMessage = Template.bind({});
|
export const EmbeddedContactWithSendMessage = Template.bind({});
|
||||||
|
@ -2345,6 +2353,7 @@ EmbeddedContactWithSendMessage.args = {
|
||||||
serviceId: generateAci(),
|
serviceId: generateAci(),
|
||||||
},
|
},
|
||||||
direction: 'incoming',
|
direction: 'incoming',
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmbeddedContactOnlyEmail = Template.bind({});
|
export const EmbeddedContactOnlyEmail = Template.bind({});
|
||||||
|
@ -2352,6 +2361,7 @@ EmbeddedContactOnlyEmail.args = {
|
||||||
contact: {
|
contact: {
|
||||||
email: fullContact.email,
|
email: fullContact.email,
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmbeddedContactGivenName = Template.bind({});
|
export const EmbeddedContactGivenName = Template.bind({});
|
||||||
|
@ -2361,6 +2371,7 @@ EmbeddedContactGivenName.args = {
|
||||||
givenName: 'Jerry',
|
givenName: 'Jerry',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmbeddedContactOrganization = Template.bind({});
|
export const EmbeddedContactOrganization = Template.bind({});
|
||||||
|
@ -2368,6 +2379,7 @@ EmbeddedContactOrganization.args = {
|
||||||
contact: {
|
contact: {
|
||||||
organization: 'Company 5',
|
organization: 'Company 5',
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmbeddedContactGivenFamilyName = Template.bind({});
|
export const EmbeddedContactGivenFamilyName = Template.bind({});
|
||||||
|
@ -2378,6 +2390,7 @@ EmbeddedContactGivenFamilyName.args = {
|
||||||
familyName: 'FamilyName',
|
familyName: 'FamilyName',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const EmbeddedContactFamilyName = Template.bind({});
|
export const EmbeddedContactFamilyName = Template.bind({});
|
||||||
|
@ -2387,6 +2400,7 @@ EmbeddedContactFamilyName.args = {
|
||||||
familyName: 'FamilyName',
|
familyName: 'FamilyName',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GiftBadgeUnopened = Template.bind({});
|
export const GiftBadgeUnopened = Template.bind({});
|
||||||
|
@ -2397,6 +2411,7 @@ GiftBadgeUnopened.args = {
|
||||||
level: 3,
|
level: 3,
|
||||||
state: GiftBadgeStates.Unopened,
|
state: GiftBadgeStates.Unopened,
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GiftBadgeFailed = Template.bind({});
|
export const GiftBadgeFailed = Template.bind({});
|
||||||
|
@ -2404,6 +2419,7 @@ GiftBadgeFailed.args = {
|
||||||
giftBadge: {
|
giftBadge: {
|
||||||
state: GiftBadgeStates.Failed,
|
state: GiftBadgeStates.Failed,
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPreferredBadge = () => ({
|
const getPreferredBadge = () => ({
|
||||||
|
@ -2430,6 +2446,7 @@ GiftBadgeRedeemed30Days.args = {
|
||||||
level: 3,
|
level: 3,
|
||||||
state: GiftBadgeStates.Redeemed,
|
state: GiftBadgeStates.Redeemed,
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GiftBadgeRedeemed24Hours = Template.bind({});
|
export const GiftBadgeRedeemed24Hours = Template.bind({});
|
||||||
|
@ -2441,6 +2458,7 @@ GiftBadgeRedeemed24Hours.args = {
|
||||||
level: 3,
|
level: 3,
|
||||||
state: GiftBadgeStates.Redeemed,
|
state: GiftBadgeStates.Redeemed,
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GiftBadgeOpened60Minutes = Template.bind({});
|
export const GiftBadgeOpened60Minutes = Template.bind({});
|
||||||
|
@ -2452,6 +2470,7 @@ GiftBadgeOpened60Minutes.args = {
|
||||||
level: 3,
|
level: 3,
|
||||||
state: GiftBadgeStates.Opened,
|
state: GiftBadgeStates.Opened,
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GiftBadgeRedeemed1Minute = Template.bind({});
|
export const GiftBadgeRedeemed1Minute = Template.bind({});
|
||||||
|
@ -2463,6 +2482,7 @@ GiftBadgeRedeemed1Minute.args = {
|
||||||
level: 3,
|
level: 3,
|
||||||
state: GiftBadgeStates.Redeemed,
|
state: GiftBadgeStates.Redeemed,
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GiftBadgeOpenedExpired = Template.bind({});
|
export const GiftBadgeOpenedExpired = Template.bind({});
|
||||||
|
@ -2474,6 +2494,7 @@ GiftBadgeOpenedExpired.args = {
|
||||||
level: 3,
|
level: 3,
|
||||||
state: GiftBadgeStates.Opened,
|
state: GiftBadgeStates.Opened,
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const GiftBadgeMissingBadge = Template.bind({});
|
export const GiftBadgeMissingBadge = Template.bind({});
|
||||||
|
@ -2485,12 +2506,14 @@ GiftBadgeMissingBadge.args = {
|
||||||
level: 3,
|
level: 3,
|
||||||
state: GiftBadgeStates.Redeemed,
|
state: GiftBadgeStates.Redeemed,
|
||||||
},
|
},
|
||||||
|
canForward: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PaymentNotification = Template.bind({});
|
export const PaymentNotification = Template.bind({});
|
||||||
PaymentNotification.args = {
|
PaymentNotification.args = {
|
||||||
canReply: false,
|
canReply: false,
|
||||||
canReact: false,
|
canReact: false,
|
||||||
|
canForward: false,
|
||||||
payment: {
|
payment: {
|
||||||
kind: PaymentEventKind.Notification,
|
kind: PaymentEventKind.Notification,
|
||||||
note: 'Hello there',
|
note: 'Hello there',
|
||||||
|
|
|
@ -48,6 +48,7 @@ export type PropsData = {
|
||||||
canDownload: boolean;
|
canDownload: boolean;
|
||||||
canCopy: boolean;
|
canCopy: boolean;
|
||||||
canEditMessage: boolean;
|
canEditMessage: boolean;
|
||||||
|
canForward: boolean;
|
||||||
canRetry: boolean;
|
canRetry: boolean;
|
||||||
canRetryDeleteForEveryone: boolean;
|
canRetryDeleteForEveryone: boolean;
|
||||||
canReact: boolean;
|
canReact: boolean;
|
||||||
|
@ -96,6 +97,7 @@ export function TimelineMessage(props: Props): JSX.Element {
|
||||||
canDownload,
|
canDownload,
|
||||||
canCopy,
|
canCopy,
|
||||||
canEditMessage,
|
canEditMessage,
|
||||||
|
canForward,
|
||||||
canReact,
|
canReact,
|
||||||
canReply,
|
canReply,
|
||||||
canRetry,
|
canRetry,
|
||||||
|
@ -103,15 +105,11 @@ export function TimelineMessage(props: Props): JSX.Element {
|
||||||
containerElementRef,
|
containerElementRef,
|
||||||
containerWidthBreakpoint,
|
containerWidthBreakpoint,
|
||||||
conversationId,
|
conversationId,
|
||||||
deletedForEveryone,
|
|
||||||
direction,
|
direction,
|
||||||
giftBadge,
|
|
||||||
i18n,
|
i18n,
|
||||||
id,
|
id,
|
||||||
isTargeted,
|
isTargeted,
|
||||||
isTapToView,
|
|
||||||
kickOffAttachmentDownload,
|
kickOffAttachmentDownload,
|
||||||
payment,
|
|
||||||
copyMessageText,
|
copyMessageText,
|
||||||
pushPanelForConversation,
|
pushPanelForConversation,
|
||||||
reactToMessage,
|
reactToMessage,
|
||||||
|
@ -255,8 +253,6 @@ export function TimelineMessage(props: Props): JSX.Element {
|
||||||
);
|
);
|
||||||
|
|
||||||
const handleContextMenu = useHandleMessageContextMenu(menuTriggerRef);
|
const handleContextMenu = useHandleMessageContextMenu(menuTriggerRef);
|
||||||
const canForward =
|
|
||||||
!isTapToView && !deletedForEveryone && !giftBadge && !payment;
|
|
||||||
|
|
||||||
const shouldShowAdditional =
|
const shouldShowAdditional =
|
||||||
doesMessageBodyOverflow(text || '') || !isWindowWidthNotNarrow;
|
doesMessageBodyOverflow(text || '') || !isWindowWidthNotNarrow;
|
||||||
|
|
|
@ -754,6 +754,7 @@ export const getPropsForMessage = (
|
||||||
canEditMessage: canEditMessage(message),
|
canEditMessage: canEditMessage(message),
|
||||||
canDeleteForEveryone: canDeleteForEveryone(message, conversation.isMe),
|
canDeleteForEveryone: canDeleteForEveryone(message, conversation.isMe),
|
||||||
canDownload: canDownload(message, conversationSelector),
|
canDownload: canDownload(message, conversationSelector),
|
||||||
|
canForward: canForward(message),
|
||||||
canReact: canReact(message, ourConversationId, conversationSelector),
|
canReact: canReact(message, ourConversationId, conversationSelector),
|
||||||
canReply: canReply(message, ourConversationId, conversationSelector),
|
canReply: canReply(message, ourConversationId, conversationSelector),
|
||||||
canRetry: hasErrors(message),
|
canRetry: hasErrors(message),
|
||||||
|
@ -2104,6 +2105,15 @@ export function canDownload(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function canForward(message: ReadonlyMessageAttributesType): boolean {
|
||||||
|
return (
|
||||||
|
!isTapToView(message) &&
|
||||||
|
!message.deletedForEveryone &&
|
||||||
|
!message.giftBadge &&
|
||||||
|
!getPayment(message)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function getLastChallengeError(
|
export function getLastChallengeError(
|
||||||
message: Pick<MessageWithUIFieldsType, 'errors'>
|
message: Pick<MessageWithUIFieldsType, 'errors'>
|
||||||
): ShallowChallengeError | undefined {
|
): ShallowChallengeError | undefined {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
getGroupAdminsSelector,
|
getGroupAdminsSelector,
|
||||||
getHasPanelOpen,
|
getHasPanelOpen,
|
||||||
getLastEditableMessageId,
|
getLastEditableMessageId,
|
||||||
|
getMessages,
|
||||||
getSelectedMessageIds,
|
getSelectedMessageIds,
|
||||||
isMissingRequiredProfileSharing,
|
isMissingRequiredProfileSharing,
|
||||||
} from '../selectors/conversations';
|
} from '../selectors/conversations';
|
||||||
|
@ -37,7 +38,7 @@ import {
|
||||||
getShowStickersIntroduction,
|
getShowStickersIntroduction,
|
||||||
getTextFormattingEnabled,
|
getTextFormattingEnabled,
|
||||||
} from '../selectors/items';
|
} from '../selectors/items';
|
||||||
import { getPropsForQuote } from '../selectors/message';
|
import { canForward, getPropsForQuote } from '../selectors/message';
|
||||||
import {
|
import {
|
||||||
getBlessedStickerPacks,
|
getBlessedStickerPacks,
|
||||||
getInstalledStickerPacks,
|
getInstalledStickerPacks,
|
||||||
|
@ -96,6 +97,7 @@ export const SmartCompositionArea = memo(function SmartCompositionArea({
|
||||||
const emojiSkinToneDefault = useSelector(getEmojiSkinToneDefault);
|
const emojiSkinToneDefault = useSelector(getEmojiSkinToneDefault);
|
||||||
const recentEmojis = useSelector(selectRecentEmojis);
|
const recentEmojis = useSelector(selectRecentEmojis);
|
||||||
const selectedMessageIds = useSelector(getSelectedMessageIds);
|
const selectedMessageIds = useSelector(getSelectedMessageIds);
|
||||||
|
const messageLookup = useSelector(getMessages);
|
||||||
const isFormattingEnabled = useSelector(getTextFormattingEnabled);
|
const isFormattingEnabled = useSelector(getTextFormattingEnabled);
|
||||||
const lastEditableMessageId = useSelector(getLastEditableMessageId);
|
const lastEditableMessageId = useSelector(getLastEditableMessageId);
|
||||||
const receivedPacks = useSelector(getReceivedStickerPacks);
|
const receivedPacks = useSelector(getReceivedStickerPacks);
|
||||||
|
@ -133,6 +135,16 @@ export const SmartCompositionArea = memo(function SmartCompositionArea({
|
||||||
shouldSendHighQualityAttachments,
|
shouldSendHighQualityAttachments,
|
||||||
} = composerState;
|
} = composerState;
|
||||||
|
|
||||||
|
const areSelectedMessagesForwardable = useMemo(() => {
|
||||||
|
return selectedMessageIds?.every(messageId => {
|
||||||
|
const message = messageLookup[messageId];
|
||||||
|
if (!message) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return canForward(message);
|
||||||
|
});
|
||||||
|
}, [messageLookup, selectedMessageIds]);
|
||||||
|
|
||||||
const isActive = useMemo(() => {
|
const isActive = useMemo(() => {
|
||||||
return !hasGlobalModalOpen && !hasPanelOpen;
|
return !hasGlobalModalOpen && !hasPanelOpen;
|
||||||
}, [hasGlobalModalOpen, hasPanelOpen]);
|
}, [hasGlobalModalOpen, hasPanelOpen]);
|
||||||
|
@ -365,6 +377,7 @@ export const SmartCompositionArea = memo(function SmartCompositionArea({
|
||||||
sortedGroupMembers={conversation.sortedGroupMembers ?? null}
|
sortedGroupMembers={conversation.sortedGroupMembers ?? null}
|
||||||
// Select Mode
|
// Select Mode
|
||||||
selectedMessageIds={selectedMessageIds}
|
selectedMessageIds={selectedMessageIds}
|
||||||
|
areSelectedMessagesForwardable={areSelectedMessagesForwardable}
|
||||||
toggleSelectMode={toggleSelectMode}
|
toggleSelectMode={toggleSelectMode}
|
||||||
toggleForwardMessagesModal={toggleForwardMessagesModal}
|
toggleForwardMessagesModal={toggleForwardMessagesModal}
|
||||||
// DraftGifMessageSendModal
|
// DraftGifMessageSendModal
|
||||||
|
|
|
@ -23,6 +23,7 @@ import {
|
||||||
sortByMessageOrder,
|
sortByMessageOrder,
|
||||||
type ForwardMessageData,
|
type ForwardMessageData,
|
||||||
} from '../types/ForwardDraft';
|
} from '../types/ForwardDraft';
|
||||||
|
import { canForward } from '../state/selectors/message';
|
||||||
|
|
||||||
export async function maybeForwardMessages(
|
export async function maybeForwardMessages(
|
||||||
messages: Array<ForwardMessageData>,
|
messages: Array<ForwardMessageData>,
|
||||||
|
@ -36,6 +37,16 @@ export async function maybeForwardMessages(
|
||||||
.map(id => window.ConversationController.get(id))
|
.map(id => window.ConversationController.get(id))
|
||||||
.filter(isNotNil);
|
.filter(isNotNil);
|
||||||
|
|
||||||
|
const areAllMessagesForwardable = messages.every(msg =>
|
||||||
|
msg.originalMessage ? canForward(msg.originalMessage) : true
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!areAllMessagesForwardable) {
|
||||||
|
throw new Error(
|
||||||
|
'maybeForwardMessage: Attempting to forward unforwardable message(s)'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const cannotSend = conversations.some(
|
const cannotSend = conversations.some(
|
||||||
conversation =>
|
conversation =>
|
||||||
conversation?.get('announcementsOnly') && !conversation.areWeAdmin()
|
conversation?.get('announcementsOnly') && !conversation.areWeAdmin()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue