Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[#156101143][#156213326] Feature chat mentions upgrade #20

Merged
merged 7 commits into from
Mar 23, 2018
73 changes: 61 additions & 12 deletions src/MentionsTextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default class MentionsTextInput extends Component {
textInputHeight: '',
suggestionRowHeight: new Animated.Value(0),
text: this.props.value ? this.props.value : '',
selection: null,
};

this.lastTextLength = 0;
Expand All @@ -37,9 +38,7 @@ export default class MentionsTextInput extends Component {
}

componentWillMount() {
this.setState({
textInputHeight: this.props.textInputMinHeight
});
this.setState({ textInputHeight: this.props.textInputMinHeight });
}

reloadTriggerMatrix(text) {
Expand Down Expand Up @@ -371,6 +370,31 @@ export default class MentionsTextInput extends Component {
}
}

setSelection(start, end = start) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what are start and end?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the start and end of the selection!

Copy link
Author

@armandgray armandgray Mar 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

eg: 1234 -> you could select the chars from 0, 4

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh so these are indices, that wasn't too clear, but was able to gather from context. Might be useful to use flowtypes to say that they're numbers, e.g. start: number, end: number=start

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe call it setSelectionFromIndices?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its called selection its a prop

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the name is consistent with the name of the prop and the name of the passed param to onSelectionChange

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ie selection: {start, end} is what RN has set as the naming convention

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gotcha

if (this._textInput) {
this._textInput.focus();
this.setState({ selection: { start, end } });
}
}

updateStateForDeletedTrigger(text, selectionIndex) {
this.didTextChange = true;
this.didDeleteTriggerKeyword = true;
this.shouldDeleteTriggerOnBackspace = false;
this.handleTriggerMatrixShiftLeft(selectionIndex - 1, this.getSubsequentTriggerIndex(selectionIndex), 1);

if (this.props.onChangeText) {
this.props.onChangeText(text);
}

this.setState({
text: text,
}, () => {
this.setSelection(selectionIndex + 1);
this.startTracking(selectionIndex);
});
}

deleteTriggerKeyword(index, addSpace) {
const start = this.triggerMatrix[index][0];
const end = this.triggerMatrix[index][1];
Expand All @@ -382,17 +406,12 @@ export default class MentionsTextInput extends Component {
const preTriggerText = this.state.text.slice(0, start + 1);
const postTriggerText = this.state.text.slice(end, this.state.text.length);
const space = postTriggerText.length && addSpace ? ' ' : '';
const text = preTriggerText + space + postTriggerText;

this.handleTriggerDeletion(index);

setTimeout(() => {
this.didTextChange = true;
this.didDeleteTriggerKeyword = true;
this.shouldDeleteTriggerOnBackspace = false;
this.handleTriggerMatrixShiftLeft(start - 1, this.getSubsequentTriggerIndex(start), 1);
this.setState({ text: preTriggerText + space + postTriggerText }, () => {
this.startTracking(start);
});
this.updateStateForDeletedTrigger(text, start);
}, SET_STATE_DELAY);
}

Expand Down Expand Up @@ -483,7 +502,31 @@ export default class MentionsTextInput extends Component {
}
}

handleSelectionChange(selection = {start: 0, end: 0}) {
wasLastSelectionIndexOne() {
return this.state.selection && this.state.selection.start == 1;
}

isZeroWithText(selection) {
return Platform.OS == 'ios' && selection.start == 0 && selection.start == selection.end
&& this.state.text.length != 0;
}

isUnchangedSelectionState(selection) {
return this.state.selection && selection && selection.start == this.state.selection.start
&& selection.end == this.state.selection.end;
}

shouldUpdateSelectionState(selection) {
return selection && this.state.text && !this.isUnchangedSelectionState(selection) && !this.didDeleteTriggerKeyword
&& selection.start <= this.state.text.length
&& (!this.isZeroWithText(selection) || this.wasLastSelectionIndexOne());
}

handleSelectionChange(selection) {
if (this.shouldUpdateSelectionState(selection)) {
this.setSelection(selection.start, selection.end);
}

this.isSelectionChangeHandled = true;
this.didDeleteTriggerKeyword = false;

Expand Down Expand Up @@ -526,12 +569,17 @@ export default class MentionsTextInput extends Component {
return !text1 && text2.length > 1 || text1.length < text2.length - 1;
}

hasNewLineChar(text) {
return text && text.length > 0 && text[text.length - 1] == '\n'
|| text.indexOf('\n') !== -1;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two checks at the end seem redundant, it looks like you could get rid of the text[text.length - 1] == '\n'?

}

onChangeText(text) {
if (this.isResetting) {
return;
}

if (text && text.length > 0 && text[text.length - 1] == '\n') {
if (this.hasNewLineChar(text)) {
this.props.onKeyPress({ nativeEvent: { key: "Enter" } });
return;
}
Expand Down Expand Up @@ -593,6 +641,7 @@ export default class MentionsTextInput extends Component {
onContentSizeChange={this.onContentSizeChange.bind(this)}
ref={component => this._textInput = component}
accessibilityLabel={ 'chat_input_text' }
selection={ this.state.text && this.state.text.length > 0 ? this.state.selection : { start: 0, end: 0 } }
onChangeText={this.onChangeText.bind(this)}
onSelectionChange={(event) => { this.onSelectionChange(event.nativeEvent.selection); }}
disableFullscreenUI={!!this.props.disableFullscreenUI}
Expand Down