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 @@ -162,12 +162,14 @@ messageID: string, text: string, ) => Promise, + +navigation: ?ChatNavigationProp<'MessageList'>, }; type State = { +text: string, +textEdited: boolean, +buttonsExpanded: boolean, +selectionState: SyncedSelectionData, + +isExitingEditMode: boolean, }; class ChatInputBar extends React.PureComponent { textInput: ?React.ElementRef; @@ -185,6 +187,8 @@ targetSendButtonContainerOpen: Value; sendButtonContainerStyle: AnimatedViewStyle; + clearBeforeRemoveListener: () => void; + constructor(props: Props) { super(props); this.state = { @@ -192,6 +196,7 @@ textEdited: false, buttonsExpanded: true, selectionState: { text: props.draft, selection: { start: 0, end: 0 } }, + isExitingEditMode: false, }; this.setUpActionIconAnimations(); @@ -329,12 +334,21 @@ if (this.props.isActive) { this.addEditInputMessageListener(); } + if (this.props.navigation) { + this.clearBeforeRemoveListener = this.props.navigation.addListener( + 'beforeRemove', + this.onNavigationBeforeRemove, + ); + } } componentWillUnmount() { if (this.props.isActive) { this.removeEditInputMessageListener(); } + if (this.clearBeforeRemoveListener) { + this.clearBeforeRemoveListener(); + } } componentDidUpdate(prevProps: Props, prevState: State) { @@ -701,7 +715,7 @@ updateText = (text: string) => { this.setState({ text, textEdited: true }); - if (this.isEditMode()) { + if (this.isEditMode() || this.state.isExitingEditMode) { return; } this.saveDraft(text); @@ -869,6 +883,41 @@ }); }; + onNavigationBeforeRemove = e => { + if (!this.isEditMode()) { + return; + } + const { action } = e.data; + e.preventDefault(); + const saveExit = () => { + this.props.inputState?.setEditedMessage(null, () => { + this.setState({ isExitingEditMode: true }, () => { + if (!this.props.navigation) { + return; + } + this.props.navigation.dispatch(action); + }); + }); + }; + if (!this.isMessageEdited()) { + saveExit(); + return; + } + Alert.alert( + 'Discard changes?', + 'You have unsaved changes. Are you sure to discard them and leave the ' + + 'screen?', + [ + { text: 'Don’t leave', style: 'cancel' }, + { + text: 'Discard edit', + style: 'destructive', + onPress: saveExit, + }, + ], + ); + }; + onPressJoin = () => { this.props.dispatchActionPromise(joinThreadActionTypes, this.joinAction()); }; @@ -1050,6 +1099,7 @@ ...BaseProps, +onInputBarLayout?: (event: LayoutEvent) => mixed, +openCamera: () => mixed, + +navigation?: ChatNavigationProp<'MessageList'>, }; function ConnectedChatInputBarBase(props: ConnectedChatInputBarBaseProps) { const navContext = React.useContext(NavContext); @@ -1133,6 +1183,7 @@ editedMessagePreview={editedMessagePreview} editedMessageInfo={editedMessageInfo} editMessage={editMessage} + navigation={props.navigation} /> ); } @@ -1244,6 +1295,7 @@ {...restProps} onInputBarLayout={onInputBarLayout} openCamera={openCamera} + navigation={navigation} /> ); });