diff --git a/native/chat/chat-input-bar.react.js b/native/chat/chat-input-bar.react.js --- a/native/chat/chat-input-bar.react.js +++ b/native/chat/chat-input-bar.react.js @@ -82,7 +82,11 @@ import SelectableTextInput from '../components/selectable-text-input.react'; import { SingleLine } from '../components/single-line.react.js'; import SWMansionIcon from '../components/swmansion-icon.react.js'; -import { type InputState, InputStateContext } from '../input/input-state.js'; +import { + type InputState, + InputStateContext, + type EditInputBarMessageParameters, +} from '../input/input-state.js'; import KeyboardInputHost from '../keyboard/keyboard-input-host.react.js'; import { type KeyboardState, @@ -312,13 +316,13 @@ componentDidMount() { if (this.props.isActive) { - this.addReplyListener(); + this.addEditInputMessageListener(); } } componentWillUnmount() { if (this.props.isActive) { - this.removeReplyListener(); + this.removeEditInputMessageListener(); } } @@ -339,9 +343,9 @@ this.setState({ text: this.props.draft }); } if (this.props.isActive && !prevProps.isActive) { - this.addReplyListener(); + this.addEditInputMessageListener(); } else if (!this.props.isActive && prevProps.isActive) { - this.removeReplyListener(); + this.removeEditInputMessageListener(); } const currentText = trimMessage(this.state.text); @@ -375,20 +379,22 @@ } } - addReplyListener() { + addEditInputMessageListener() { invariant( this.props.inputState, - 'inputState should be set in addReplyListener', + 'inputState should be set in addEditInputMessageListener', ); - this.props.inputState.addReplyListener(this.focusAndUpdateText); + this.props.inputState.addEditInputMessageListener(this.focusAndUpdateText); } - removeReplyListener() { + removeEditInputMessageListener() { invariant( this.props.inputState, - 'inputState should be set in removeReplyListener', + 'inputState should be set in removeEditInputMessageListener', + ); + this.props.inputState.removeEditInputMessageListener( + this.focusAndUpdateText, ); - this.props.inputState.removeReplyListener(this.focusAndUpdateText); } setIOSKeyboardHeight() { @@ -713,9 +719,12 @@ this.focusAndUpdateButtonsVisibility(); }; - focusAndUpdateText = (text: string) => { + focusAndUpdateText = (params: EditInputBarMessageParameters) => { + const { message: text, mode } = params; const currentText = this.state.text; - if (!currentText.startsWith(text)) { + if (mode === 'replace') { + this.updateText(text); + } else if (!currentText.startsWith(text)) { const prependedText = text.concat(currentText); this.updateText(prependedText); } diff --git a/native/chat/composed-message.react.js b/native/chat/composed-message.react.js --- a/native/chat/composed-message.react.js +++ b/native/chat/composed-message.react.js @@ -203,7 +203,10 @@ const { inputState, item } = this.props; invariant(inputState, 'inputState should be set in reply'); invariant(item.messageInfo.text, 'text should be set in reply'); - inputState.addReply(createMessageReply(item.messageInfo.text)); + inputState.editInputMessage({ + message: createMessageReply(item.messageInfo.text), + mode: 'prepend', + }); }; } diff --git a/native/chat/message-list-container.react.js b/native/chat/message-list-container.react.js --- a/native/chat/message-list-container.react.js +++ b/native/chat/message-list-container.react.js @@ -317,7 +317,7 @@ (text: string) => setUsernameInputText(text), [], ); - const { addReply } = inputState; + const { editInputMessage } = inputState; const resolveToUser = React.useCallback( (user: AccountUserInfo) => { const resolvedThreadInfo = existingThreadInfoFinder({ @@ -328,11 +328,11 @@ resolvedThreadInfo, 'resolvedThreadInfo must be specified in messageListContainer', ); - addReply(''); + editInputMessage({ message: '', mode: 'prepend' }); setBaseThreadInfo(resolvedThreadInfo); setParams({ searching: false, threadInfo: resolvedThreadInfo }); }, - [setParams, existingThreadInfoFinder, addReply], + [existingThreadInfoFinder, editInputMessage, setParams], ); const messageListData = useNativeMessageListData({ diff --git a/native/chat/text-message-tooltip-modal.react.js b/native/chat/text-message-tooltip-modal.react.js --- a/native/chat/text-message-tooltip-modal.react.js +++ b/native/chat/text-message-tooltip-modal.react.js @@ -39,7 +39,10 @@ inputState, 'inputState should be set in TextMessageTooltipModal.onPressReply', ); - inputState.addReply(createMessageReply(text)); + inputState.editInputMessage({ + message: createMessageReply(text), + mode: 'prepend', + }); }, [inputState, text]); const renderReplyIcon = React.useCallback( style => , diff --git a/native/input/input-state-container.react.js b/native/input/input-state-container.react.js --- a/native/input/input-state-container.react.js +++ b/native/input/input-state-container.react.js @@ -95,6 +95,7 @@ import { useIsReportEnabled } from 'lib/utils/report-utils.js'; import { + type EditInputBarMessageParameters, type EditState, InputStateContext, type PendingMultimediaUploads, @@ -165,7 +166,9 @@ }; sendCallbacks: Array<() => void> = []; activeURIs = new Map(); - replyCallbacks: Array<(message: string) => void> = []; + editInputBarCallbacks: Array< + (params: EditInputBarMessageParameters) => void, + > = []; pendingThreadCreations = new Map>(); pendingThreadUpdateHandlers = new Map mixed>(); @@ -391,9 +394,9 @@ pendingUploads, sendTextMessage: this.sendTextMessage, sendMultimediaMessage: this.sendMultimediaMessage, - addReply: this.addReply, - addReplyListener: this.addReplyListener, - removeReplyListener: this.removeReplyListener, + editInputMessage: this.editInputMessage, + addEditInputMessageListener: this.addEditInputMessageListener, + removeEditInputMessageListener: this.removeEditInputMessageListener, messageHasUploadFailure: this.messageHasUploadFailure, retryMessage: this.retryMessage, registerSendCallback: this.registerSendCallback, @@ -1192,12 +1195,16 @@ return values(pendingUploads).some(upload => upload.failed); }; - addReply = (message: string) => { - this.replyCallbacks.forEach(addReplyCallback => addReplyCallback(message)); + editInputMessage = (params: EditInputBarMessageParameters) => { + this.editInputBarCallbacks.forEach(addEditInputBarCallback => + addEditInputBarCallback(params), + ); }; - addReplyListener = (callbackReply: (message: string) => void) => { - this.replyCallbacks.push(callbackReply); + addEditInputMessageListener = ( + callbackEditInputBar: (params: EditInputBarMessageParameters) => void, + ) => { + this.editInputBarCallbacks.push(callbackEditInputBar); }; setEditedMessage = (editedMessage: ?MessageInfo) => { @@ -1206,9 +1213,11 @@ }); }; - removeReplyListener = (callbackReply: (message: string) => void) => { - this.replyCallbacks = this.replyCallbacks.filter( - candidate => candidate !== callbackReply, + removeEditInputMessageListener = ( + callbackEditInputBar: (params: EditInputBarMessageParameters) => void, + ) => { + this.editInputBarCallbacks = this.editInputBarCallbacks.filter( + candidate => candidate !== callbackEditInputBar, ); }; diff --git a/native/input/input-state.js b/native/input/input-state.js --- a/native/input/input-state.js +++ b/native/input/input-state.js @@ -27,6 +27,11 @@ +editedMessage: ?MessageInfo, }; +export type EditInputBarMessageParameters = { + +message: string, + +mode: 'prepend' | 'replace', +}; + export type InputState = { +pendingUploads: PendingMultimediaUploads, +sendTextMessage: ( @@ -38,9 +43,13 @@ selections: $ReadOnlyArray, threadInfo: ThreadInfo, ) => Promise, - +addReply: (text: string) => void, - +addReplyListener: ((message: string) => void) => void, - +removeReplyListener: ((message: string) => void) => void, + +editInputMessage: (params: EditInputBarMessageParameters) => void, + +addEditInputMessageListener: ( + (params: EditInputBarMessageParameters) => void, + ) => void, + +removeEditInputMessageListener: ( + (params: EditInputBarMessageParameters) => void, + ) => void, +messageHasUploadFailure: (localMessageID: string) => boolean, +retryMessage: ( localMessageID: string,