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

248 lines
7.5 KiB
TypeScript
Raw Normal View History

2023-01-03 19:55:46 +00:00
// Copyright 2019 Signal Messenger, LLC
2020-10-30 20:34:04 +00:00
// SPDX-License-Identifier: AGPL-3.0-only
2023-03-02 20:55:40 +00:00
import React from 'react';
import { connect } from 'react-redux';
import { get } from 'lodash';
import { mapDispatchToProps } from '../actions';
import type { Props as ComponentPropsType } from '../../components/CompositionArea';
import { CompositionArea } from '../../components/CompositionArea';
import type { StateType } from '../reducer';
2023-09-14 17:04:48 +00:00
import type {
DraftBodyRanges,
HydratedBodyRangesType,
} from '../../types/BodyRange';
import { isConversationSMSOnly } from '../../util/isConversationSMSOnly';
import { dropNull } from '../../util/dropNull';
2022-11-16 21:41:38 +00:00
import { imageToBlurHash } from '../../util/imageToBlurHash';
2021-11-17 18:38:52 +00:00
import { getPreferredBadgeSelector } from '../selectors/badges';
2021-04-27 22:35:35 +00:00
import { selectRecentEmojis } from '../selectors/emojis';
import {
getIntl,
getPlatform,
getTheme,
getUserConversationId,
} from '../selectors/user';
import {
getDefaultConversationColor,
getEmojiSkinTone,
getTextFormattingEnabled,
} from '../selectors/items';
import {
getConversationSelector,
2021-07-20 20:18:35 +00:00
getGroupAdminsSelector,
getHasPanelOpen,
getLastEditableMessageId,
2023-03-20 22:23:53 +00:00
getSelectedMessageIds,
isMissingRequiredProfileSharing,
} from '../selectors/conversations';
2021-06-25 16:08:16 +00:00
import { getPropsForQuote } from '../selectors/message';
import {
getBlessedStickerPacks,
getInstalledStickerPacks,
getKnownStickerPacks,
getReceivedStickerPacks,
getRecentlyInstalledStickerPack,
getRecentStickers,
} from '../selectors/stickers';
2022-11-09 02:38:19 +00:00
import { isSignalConversation } from '../../util/isSignalConversation';
import {
getComposerStateForConversationIdSelector,
2023-04-18 01:16:41 +00:00
getIsFormattingFlagEnabled,
getIsFormattingSpoilersFlagEnabled,
} from '../selectors/composer';
2023-03-02 20:55:40 +00:00
import type { SmartCompositionRecordingProps } from './CompositionRecording';
import { SmartCompositionRecording } from './CompositionRecording';
import type { SmartCompositionRecordingDraftProps } from './CompositionRecordingDraft';
import { SmartCompositionRecordingDraft } from './CompositionRecordingDraft';
2023-09-14 17:04:48 +00:00
import { hydrateRanges } from '../../types/BodyRange';
2019-08-07 00:40:25 +00:00
type ExternalProps = {
id: string;
};
2021-10-05 16:47:06 +00:00
export type CompositionAreaPropsType = ExternalProps & ComponentPropsType;
2019-08-07 00:40:25 +00:00
const mapStateToProps = (state: StateType, props: ExternalProps) => {
const { id } = props;
const platform = getPlatform(state);
2019-08-07 00:40:25 +00:00
const shouldHidePopovers = getHasPanelOpen(state);
2023-05-10 01:23:56 +00:00
2021-06-25 16:08:16 +00:00
const conversationSelector = getConversationSelector(state);
const conversation = conversationSelector(id);
2019-08-07 00:40:25 +00:00
if (!conversation) {
throw new Error(`Conversation id ${id} not found!`);
}
const {
announcementsOnly,
areWeAdmin,
draftEditMessage,
draftText,
draftBodyRanges,
} = conversation;
2019-08-07 00:40:25 +00:00
const receivedPacks = getReceivedStickerPacks(state);
const installedPacks = getInstalledStickerPacks(state);
const blessedPacks = getBlessedStickerPacks(state);
const knownPacks = getKnownStickerPacks(state);
const installedPack = getRecentlyInstalledStickerPack(state);
const recentStickers = getRecentStickers(state);
const showIntroduction = get(
state.items,
['showStickersIntroduction'],
false
);
const showPickerHint = Boolean(
get(state.items, ['showStickerPickerHint'], false) &&
receivedPacks.length > 0
);
const composerStateForConversationIdSelector =
getComposerStateForConversationIdSelector(state);
const composerState = composerStateForConversationIdSelector(id);
2021-06-25 16:08:16 +00:00
const {
attachments: draftAttachments,
focusCounter,
2022-12-08 07:43:48 +00:00
isDisabled,
2021-06-25 16:08:16 +00:00
linkPreviewLoading,
linkPreviewResult,
2022-12-08 07:43:48 +00:00
messageCompositionId,
sendCounter,
2021-06-25 16:08:16 +00:00
shouldSendHighQualityAttachments,
} = composerState;
let { quotedMessage } = composerState;
if (!quotedMessage && draftEditMessage?.quote) {
quotedMessage = {
conversationId: id,
quote: draftEditMessage.quote,
};
}
2021-06-25 16:08:16 +00:00
const recentEmojis = selectRecentEmojis(state);
2023-03-20 22:23:53 +00:00
const selectedMessageIds = getSelectedMessageIds(state);
const isFormattingEnabled = getTextFormattingEnabled(state);
const isFormattingFlagEnabled = getIsFormattingFlagEnabled(state);
const isFormattingSpoilersFlagEnabled =
getIsFormattingSpoilersFlagEnabled(state);
const lastEditableMessageId = getLastEditableMessageId(state);
2023-09-14 17:04:48 +00:00
const convertDraftBodyRangesIntoHydrated = (
bodyRanges: DraftBodyRanges | undefined
): HydratedBodyRangesType | undefined => {
return hydrateRanges(bodyRanges, conversationSelector);
};
return {
// Base
2021-09-24 20:02:30 +00:00
conversationId: id,
draftEditMessage,
focusCounter,
2022-12-08 07:43:48 +00:00
getPreferredBadge: getPreferredBadgeSelector(state),
i18n: getIntl(state),
2022-12-08 07:43:48 +00:00
isDisabled,
isFormattingEnabled,
isFormattingFlagEnabled,
isFormattingSpoilersFlagEnabled,
lastEditableMessageId,
2022-12-08 07:43:48 +00:00
messageCompositionId,
platform,
sendCounter,
2023-05-10 01:23:56 +00:00
shouldHidePopovers,
2021-11-02 23:01:13 +00:00
theme: getTheme(state),
2023-09-14 17:04:48 +00:00
convertDraftBodyRangesIntoHydrated,
2021-09-29 20:23:06 +00:00
// AudioCapture
errorDialogAudioRecorderType:
state.audioRecorder.errorDialogAudioRecorderType,
recordingState: state.audioRecorder.recordingState,
2021-06-25 16:08:16 +00:00
// AttachmentsList
draftAttachments,
2022-11-16 21:41:38 +00:00
// MediaEditor
imageToBlurHash,
2021-06-25 16:08:16 +00:00
// MediaQualitySelector
shouldSendHighQualityAttachments:
shouldSendHighQualityAttachments !== undefined
? shouldSendHighQualityAttachments
: window.storage.get('sent-media-quality') === 'high',
2021-06-25 16:08:16 +00:00
// StagedLinkPreview
linkPreviewLoading,
linkPreviewResult,
// Quote
quotedMessageId: quotedMessage?.quote?.messageId,
2021-06-25 16:08:16 +00:00
quotedMessageProps: quotedMessage
2021-08-11 23:06:20 +00:00
? getPropsForQuote(quotedMessage, {
2021-06-25 16:08:16 +00:00
conversationSelector,
2021-08-11 23:06:20 +00:00
ourConversationId: getUserConversationId(state),
defaultConversationColor: getDefaultConversationColor(state),
2021-08-11 23:06:20 +00:00
})
2021-06-25 16:08:16 +00:00
: undefined,
2023-08-16 20:54:39 +00:00
quotedMessageAuthorAci: quotedMessage?.quote?.authorAci,
quotedMessageSentAt: quotedMessage?.quote?.id,
// Emojis
recentEmojis,
skinTone: getEmojiSkinTone(state),
// Stickers
receivedPacks,
installedPack,
blessedPacks,
knownPacks,
installedPacks,
recentStickers,
showIntroduction,
showPickerHint,
2020-05-27 21:37:06 +00:00
// Message Requests
...conversation,
2020-05-27 21:37:06 +00:00
conversationType: conversation.type,
isSMSOnly: Boolean(isConversationSMSOnly(conversation)),
2022-11-09 02:38:19 +00:00
isSignalConversation: isSignalConversation(conversation),
isFetchingUUID: conversation.isFetchingUUID,
2021-11-11 22:43:05 +00:00
isMissingMandatoryProfileSharing:
isMissingRequiredProfileSharing(conversation),
2021-07-20 20:18:35 +00:00
// Groups
announcementsOnly,
areWeAdmin,
groupAdmins: getGroupAdminsSelector(state)(conversation.id),
draftText: dropNull(draftText),
2023-09-14 17:04:48 +00:00
draftBodyRanges: hydrateRanges(draftBodyRanges, conversationSelector),
2023-03-02 20:55:40 +00:00
renderSmartCompositionRecording: (
recProps: SmartCompositionRecordingProps
) => {
return <SmartCompositionRecording {...recProps} />;
},
renderSmartCompositionRecordingDraft: (
draftProps: SmartCompositionRecordingDraftProps
) => {
return <SmartCompositionRecordingDraft {...draftProps} />;
},
2023-03-20 22:23:53 +00:00
// Select Mode
selectedMessageIds,
};
};
const dispatchPropsMap = {
...mapDispatchToProps,
onSetSkinTone: (tone: number) => mapDispatchToProps.putItem('skinTone', tone),
clearShowIntroduction: () =>
mapDispatchToProps.removeItem('showStickersIntroduction'),
clearShowPickerHint: () =>
mapDispatchToProps.removeItem('showStickerPickerHint'),
onPickEmoji: mapDispatchToProps.onUseEmoji,
};
const smart = connect(mapStateToProps, dispatchPropsMap);
export const SmartCompositionArea = smart(CompositionArea);