From 6c291e38c4e1cbe453cbd233f2c2d74992bf3c0f Mon Sep 17 00:00:00 2001 From: yougotwill Date: Mon, 5 Aug 2024 14:20:15 +1000 Subject: [PATCH] fix: disable attachments and voice messages and warn a user when starting a new convo even if they haven't sent a message request yet --- ts/components/conversation/MessageRequestButtons.tsx | 8 ++++++-- ts/components/conversation/SubtleNotification.tsx | 3 ++- .../conversation/composition/CompositionButtons.tsx | 5 ++++- .../conversation/header/ConversationHeader.tsx | 8 ++++++-- .../leftpane/conversation-list-item/MessageItem.tsx | 4 +++- ts/hooks/useParamSelector.ts | 4 +++- ts/models/conversation.ts | 12 +++++++++++- 7 files changed, 35 insertions(+), 9 deletions(-) diff --git a/ts/components/conversation/MessageRequestButtons.tsx b/ts/components/conversation/MessageRequestButtons.tsx index 13872f90d..ffdc58b7c 100644 --- a/ts/components/conversation/MessageRequestButtons.tsx +++ b/ts/components/conversation/MessageRequestButtons.tsx @@ -6,7 +6,10 @@ import { declineConversationWithConfirm, } from '../../interactions/conversationInteractions'; import { getConversationController } from '../../session/conversations'; -import { hasSelectedConversationIncomingMessages } from '../../state/selectors/conversations'; +import { + getSelectedHasMessages, + hasSelectedConversationIncomingMessages, +} from '../../state/selectors/conversations'; import { useSelectedConversationKey } from '../../state/selectors/selectedConversation'; import { SessionButton, SessionButtonColor } from '../basic/SessionButton'; import { @@ -78,9 +81,10 @@ const handleAcceptConversationRequest = async (convoId: string) => { export const ConversationMessageRequestButtons = () => { const selectedConvoId = useSelectedConversationKey(); + const hasMessages = useSelector(getSelectedHasMessages); const hasIncomingMessages = useSelector(hasSelectedConversationIncomingMessages); const isIncomingRequest = useIsIncomingRequest(selectedConvoId); - const isOutgoingRequest = useIsOutgoingRequest(selectedConvoId); + const isOutgoingRequest = useIsOutgoingRequest(selectedConvoId, hasMessages); if (!selectedConvoId || (!isIncomingRequest && !isOutgoingRequest)) { return null; diff --git a/ts/components/conversation/SubtleNotification.tsx b/ts/components/conversation/SubtleNotification.tsx index 53813f592..6ec6080b7 100644 --- a/ts/components/conversation/SubtleNotification.tsx +++ b/ts/components/conversation/SubtleNotification.tsx @@ -35,7 +35,8 @@ const TextInner = styled.div` */ export const ConversationOutgoingRequestExplanation = () => { const selectedConversation = useSelectedConversationKey(); - const isOutgoingMessageRequest = useIsOutgoingRequest(selectedConversation); + const hasMessages = useSelector(getSelectedHasMessages); + const isOutgoingMessageRequest = useIsOutgoingRequest(selectedConversation, hasMessages); const hasIncomingMessages = useSelector(hasSelectedConversationIncomingMessages); const showMsgRequestUI = selectedConversation && isOutgoingMessageRequest; diff --git a/ts/components/conversation/composition/CompositionButtons.tsx b/ts/components/conversation/composition/CompositionButtons.tsx index 00af99e9d..47d8d0051 100644 --- a/ts/components/conversation/composition/CompositionButtons.tsx +++ b/ts/components/conversation/composition/CompositionButtons.tsx @@ -1,8 +1,10 @@ import { forwardRef } from 'react'; import styled from 'styled-components'; +import { useSelector } from 'react-redux'; import { useIsOutgoingRequest } from '../../../hooks/useParamSelector'; import { useSelectedConversationKey } from '../../../state/selectors/selectedConversation'; import { SessionIconButton } from '../../icon'; +import { getSelectedHasMessages } from '../../../state/selectors/conversations'; const StyledChatButtonContainer = styled.div<{ disabled?: boolean }>` .session-icon-button { @@ -20,7 +22,8 @@ const StyledChatButtonContainer = styled.div<{ disabled?: boolean }>` export const AddStagedAttachmentButton = (props: { onClick: () => void }) => { const selectedConvoKey = useSelectedConversationKey(); - const isOutgoingRequest = useIsOutgoingRequest(selectedConvoKey); + const hasMessages = useSelector(getSelectedHasMessages); + const isOutgoingRequest = useIsOutgoingRequest(selectedConvoKey, hasMessages); return ( diff --git a/ts/components/conversation/header/ConversationHeader.tsx b/ts/components/conversation/header/ConversationHeader.tsx index 238c7aba6..0097b6e90 100644 --- a/ts/components/conversation/header/ConversationHeader.tsx +++ b/ts/components/conversation/header/ConversationHeader.tsx @@ -1,5 +1,8 @@ import { useDispatch, useSelector } from 'react-redux'; -import { isMessageSelectionMode } from '../../../state/selectors/conversations'; +import { + getSelectedHasMessages, + isMessageSelectionMode, +} from '../../../state/selectors/conversations'; import { openRightPanel } from '../../../state/ducks/conversations'; @@ -13,7 +16,8 @@ import { ConversationHeaderTitle } from './ConversationHeaderTitle'; export const ConversationHeaderWithDetails = () => { const isSelectionMode = useSelector(isMessageSelectionMode); const selectedConvoKey = useSelectedConversationKey(); - const isOutgoingRequest = useIsOutgoingRequest(selectedConvoKey); + const hasMessages = useSelector(getSelectedHasMessages); + const isOutgoingRequest = useIsOutgoingRequest(selectedConvoKey, hasMessages); const dispatch = useDispatch(); diff --git a/ts/components/leftpane/conversation-list-item/MessageItem.tsx b/ts/components/leftpane/conversation-list-item/MessageItem.tsx index a1e653137..1cf873f5e 100644 --- a/ts/components/leftpane/conversation-list-item/MessageItem.tsx +++ b/ts/components/leftpane/conversation-list-item/MessageItem.tsx @@ -18,6 +18,7 @@ import { MessageBody } from '../../conversation/message/message-content/MessageB import { SessionIcon } from '../../icon'; import { InteractionItem } from './InteractionItem'; import { LastMessageStatusType } from '../../../state/ducks/types'; +import { getSelectedHasMessages } from '../../../state/selectors/conversations'; export const MessageItem = () => { const conversationId = useConvoIdFromContext(); @@ -27,7 +28,8 @@ export const MessageItem = () => { const hasUnread = useHasUnread(conversationId); const isConvoTyping = useIsTyping(conversationId); const isMessageRequest = useSelector(getIsMessageRequestOverlayShown); - const isOutgoingRequest = useIsOutgoingRequest(conversationId); + const hasMessages = useSelector(getSelectedHasMessages); + const isOutgoingRequest = useIsOutgoingRequest(conversationId, hasMessages); const isSearchingMode = useSelector(isSearching); diff --git a/ts/hooks/useParamSelector.ts b/ts/hooks/useParamSelector.ts index e51be0c27..cd212c4d1 100644 --- a/ts/hooks/useParamSelector.ts +++ b/ts/hooks/useParamSelector.ts @@ -194,11 +194,12 @@ export function useIsIncomingRequest(convoId?: string) { ); } -export function useIsOutgoingRequest(convoId?: string) { +export function useIsOutgoingRequest(convoId?: string, hasMessages?: boolean) { const convoProps = useConversationPropsById(convoId); if (!convoProps) { return false; } + return Boolean( convoProps && hasValidOutgoingRequestValues({ @@ -208,6 +209,7 @@ export function useIsOutgoingRequest(convoId?: string) { isPrivate: convoProps.isPrivate || false, isBlocked: convoProps.isBlocked || false, activeAt: convoProps.activeAt || 0, + hasMessages, }) ); } diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index 2f512c9e2..381b794b0 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -2588,6 +2588,7 @@ export function hasValidOutgoingRequestValues({ isBlocked, isPrivate, activeAt, + hasMessages, }: { isMe: boolean; isApproved: boolean; @@ -2595,10 +2596,19 @@ export function hasValidOutgoingRequestValues({ isBlocked: boolean; isPrivate: boolean; activeAt: number; + hasMessages?: boolean; }): boolean { const isActive = activeAt && isFinite(activeAt) && activeAt > 0; - return Boolean(!isMe && isApproved && isPrivate && !isBlocked && !didApproveMe && isActive); + // Started a new message, but haven't sent a message yet + const emptyConvo = + !hasMessages && !isMe && !isApproved && isPrivate && !isBlocked && !didApproveMe && !!isActive; + + // Started a new message, and sent a message + const sentOutgoingRequest = + !isMe && isApproved && isPrivate && !isBlocked && !didApproveMe && !!isActive; + + return emptyConvo || sentOutgoingRequest; } /**