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 @@ -16,6 +16,7 @@ } from 'react-native'; import { TextInputKeyboardMangerIOS } from 'react-native-keyboard-input'; import Animated, { EasingNode } from 'react-native-reanimated'; +import type { SelectionChangeEvent } from 'react-native/Libraries/Components/TextInput/TextInput'; import { useDispatch } from 'react-redux'; import { @@ -144,10 +145,18 @@ +userSearchIndex: SearchIndex, +threadMembers: $ReadOnlyArray, }; + +export type Selection = $ReadOnly<{ + start: number, + end: number, +}>; + type State = { +text: string, +textEdited: boolean, +buttonsExpanded: boolean, + +selection: Selection, + +controlSelection: boolean, }; class ChatInputBar extends React.PureComponent { textInput: ?React.ElementRef; @@ -170,6 +179,8 @@ text: props.draft, textEdited: false, buttonsExpanded: true, + selection: { start: 0, end: 0 }, + controlSelection: false, }; this.setUpActionIconAnimations(); @@ -568,6 +579,10 @@ allowImagePasteForThreadID={this.props.threadInfo.id} value={this.state.text} onChangeText={this.updateText} + selection={ + this.state.controlSelection ? this.state.selection : undefined + } + onSelectionChange={this.updateSelection} placeholder="Send a message..." placeholderTextColor={this.props.colors.listInputButton} multiline={true} @@ -605,10 +620,20 @@ }; updateText = (text: string) => { - this.setState({ text, textEdited: true }); + this.setState({ text, textEdited: true, controlSelection: false }); this.saveDraft(text); }; + updateSelection: (event: SelectionChangeEvent) => void = event => { + this.setState({ + selection: { + start: event.nativeEvent.selection.start, + end: event.nativeEvent.selection.end, + }, + controlSelection: false, + }); + }; + saveDraft = _throttle(text => { this.props.dispatch({ type: updateDraftActionType, diff --git a/native/components/clearable-text-input.js b/native/components/clearable-text-input.js --- a/native/components/clearable-text-input.js +++ b/native/components/clearable-text-input.js @@ -9,4 +9,6 @@ textInputRef: (textInput: ?React.ElementRef) => mixed, onChangeText: $NonMaybeType<$PropertyType>, value: $NonMaybeType<$PropertyType>, + onSelectionChange: $PropertyType, + selection?: $NonMaybeType<$PropertyType>, }; diff --git a/native/components/clearable-text-input.react.ios.js b/native/components/clearable-text-input.react.ios.js --- a/native/components/clearable-text-input.react.ios.js +++ b/native/components/clearable-text-input.react.ios.js @@ -154,6 +154,7 @@ {...props} style={[props.style, styles.invisibleTextInput]} onChangeText={this.onOldInputChangeText} + onSelectionChange={this.props.onSelectionChange} onKeyPress={this.onOldInputKeyPress} onBlur={this.onOldInputBlur} onFocus={this.onOldInputFocus} @@ -167,6 +168,7 @@ onFocus={this.onFocus} onBlur={this.onBlur} onChangeText={this.props.onChangeText} + onSelectionChange={this.props.onSelectionChange} key={this.state.textInputKey} ref={this.textInputRef} />, diff --git a/native/components/clearable-text-input.react.js b/native/components/clearable-text-input.react.js --- a/native/components/clearable-text-input.react.js +++ b/native/components/clearable-text-input.react.js @@ -60,6 +60,7 @@