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 @@ -165,13 +165,14 @@ text: string, ) => Promise, +navigation: ?ChatNavigationProp<'MessageList'>, + +isFocused?: boolean, }; type State = { +text: string, +textEdited: boolean, +buttonsExpanded: boolean, +selectionState: SyncedSelectionData, - +isExitingEditMode: boolean, + +isExitingDuringEditMode: boolean, }; class ChatInputBar extends React.PureComponent { textInput: ?React.ElementRef; @@ -198,7 +199,7 @@ textEdited: false, buttonsExpanded: true, selectionState: { text: props.draft, selection: { start: 0, end: 0 } }, - isExitingEditMode: false, + isExitingDuringEditMode: false, }; this.setUpActionIconAnimations(); @@ -404,6 +405,22 @@ this.expandButtons(); this.setIOSKeyboardHeight(); } + + if (!this.props.isFocused && prevProps.isFocused && this.isEditMode()) { + this.setState( + { text: this.props.draft, isExitingDuringEditMode: true }, + this.exitEditMode, + ); + } + if (this.props.isFocused && !prevProps.isFocused) { + this.setState({ isExitingDuringEditMode: false }); + } + if ( + this.props.inputState?.editState.editedMessage && + !prevProps.inputState?.editState.editedMessage + ) { + this.blockNavigation(); + } } addEditInputMessageListener() { @@ -725,8 +742,11 @@ }; updateText = (text: string) => { + if (this.state.isExitingDuringEditMode) { + return; + } this.setState({ text, textEdited: true }); - if (this.isEditMode() || this.state.isExitingEditMode) { + if (this.isEditMode()) { return; } this.saveDraft(text); @@ -840,6 +860,41 @@ return text !== originalText; }; + unblockNavigation = () => { + if (!this.props.navigation) { + return; + } + this.props.navigation.setParams({ removeEditMode: null }); + }; + + removeEditMode = action => { + if (!this.props.navigation) { + return; + } + if (this.state.isExitingDuringEditMode) { + return; + } + const { navigation: nav } = this.props; + const unblockAndDispatch = () => { + this.unblockNavigation(); + nav.dispatch(action); + }; + if (!this.isMessageEdited()) { + unblockAndDispatch(); + return; + } + exitEditAlert(unblockAndDispatch); + }; + + blockNavigation = () => { + if (!this.props.navigation) { + return; + } + this.props.navigation.setParams({ + removeEditMode: this.removeEditMode, + }); + }; + editMessage = async (messageID: string, text: string) => { if (!this.isMessageEdited()) { this.exitEditMode(); @@ -885,6 +940,7 @@ exitEditMode = () => { this.props.inputState?.setEditedMessage(null, () => { + this.unblockNavigation(); this.updateText(this.props.draft); this.focusAndUpdateButtonsVisibility(); this.updateSendButton(this.props.draft); @@ -899,7 +955,7 @@ e.preventDefault(); const saveExit = () => { this.props.inputState?.setEditedMessage(null, () => { - this.setState({ isExitingEditMode: true }, () => { + this.setState({ isExitingDuringEditMode: true }, () => { if (!this.props.navigation) { return; } @@ -1108,6 +1164,7 @@ +onInputBarLayout?: (event: LayoutEvent) => mixed, +openCamera: () => mixed, +navigation?: ChatNavigationProp<'MessageList'>, + +isFocused?: boolean, }; function ConnectedChatInputBarBase(props: ConnectedChatInputBarBaseProps) { const navContext = React.useContext(NavContext); @@ -1298,12 +1355,15 @@ }); }, [keyboardState, navigation, route.key, threadInfo]); + const isFocused = props.navigation.isFocused(); + return ( ); }); diff --git a/native/chat/chat-router.js b/native/chat/chat-router.js --- a/native/chat/chat-router.js +++ b/native/chat/chat-router.js @@ -128,7 +128,19 @@ ); return baseGetStateForAction(clearedState, navigateAction, options); } else { - return baseGetStateForAction(lastState, action, options); + const result = baseGetStateForAction(lastState, action, options); + if ( + result !== null && + result?.index && + result.index > lastState.index && + lastState.routes[lastState.index].params?.removeEditMode + ) { + const removeEditMode: Function = + lastState.routes[lastState.index].params?.removeEditMode; + removeEditMode(action); + return lastState; + } + return result; } }, actionCreators: { diff --git a/native/chat/message-list-types.js b/native/chat/message-list-types.js --- a/native/chat/message-list-types.js +++ b/native/chat/message-list-types.js @@ -7,6 +7,7 @@ import type { ThreadInfo } from 'lib/types/thread-types.js'; import { type UserInfo } from 'lib/types/user-types.js'; +import type { ChatRouterNavigationAction } from './chat-router.js'; import type { MarkdownRules } from '../markdown/rules.react.js'; import { useTextMessageRulesFunc } from '../markdown/rules.react.js'; import { MessageListRouteName } from '../navigation/route-names.js'; @@ -15,6 +16,7 @@ +threadInfo: ThreadInfo, +pendingPersonalThreadUserInfo?: UserInfo, +searching?: boolean, + +removeEditMode?: ?(ChatRouterNavigationAction) => void, }; export type MessageListContextType = {