Skip to content

Commit

Permalink
Fixed double sending of onTextChange events (#365)
Browse files Browse the repository at this point in the history
* Fixed TextInput issues: clear() method, cursor reposition in mutiline, addes submitShortcut prop, removed double event sending
  • Loading branch information
vkjr authored Oct 25, 2018
1 parent 24a17d9 commit 8d26d71
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 20 deletions.
6 changes: 6 additions & 0 deletions Libraries/Components/TextInput/TextInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,10 +172,15 @@ type AndroidProps = $ReadOnly<{|
inlineImagePadding?: ?number,
|}>;

type DesktopProps = $ReadOnly<{|
submitShortcut?: ?object,
|}>;

type Props = $ReadOnly<{|
...ViewProps,
...IOSProps,
...AndroidProps,
...DesktopProps,
autoCapitalize?: ?AutoCapitalize,
autoCorrect?: ?boolean,
autoFocus?: ?boolean,
Expand Down Expand Up @@ -786,6 +791,7 @@ const TextInput = createReactClass({
'username',
'password',
]),
submitShortcut: PropTypes.object,
},
getDefaultProps(): Object {
return {
Expand Down
22 changes: 18 additions & 4 deletions ReactQt/runtime/src/componentmanagers/textinputmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ QStringList TextInputManager::customDirectEventTypes() {
}

void TextInputManager::sendTextEditedToJs(QQuickItem* textInput) {
sendTextInputEvent(textInput, EVENT_ON_TEXT_CHANGE);
QString text = textInput->property("text").toString();
sendTextInputEvent(textInput, EVENT_ON_TEXT_CHANGE, QVariantMap{{"text", text}});
}

void TextInputManager::sendSelectionChangeToJs(QQuickItem* textInput) {
Expand Down Expand Up @@ -90,7 +91,7 @@ void TextInputManager::sendOnFocusToJs(QQuickItem* textInput) {
sendTextInputEvent(textInput, EVENT_ON_FOCUS);
}

void TextInputManager::sendOnKeyPressToJs(QQuickItem* textInput, QString keyText, QStringList modifiers) {
void TextInputManager::sendOnKeyPressToJs(QQuickItem* textInput, QString keyText, QVariantList modifiers) {
sendTextInputEvent(textInput, EVENT_ON_KEY_PRESS, QVariantMap{{"key", keyText}, {"modifiers", modifiers}});
}

Expand All @@ -100,20 +101,33 @@ void TextInputManager::sendOnContentSizeChange(QQuickItem* textInput, double wid
QVariantMap{{"contentSize", QVariantMap{{"width", width}, {"height", height}}}});
}

bool TextInputManager::onKeyPressed(QQuickItem* textInput,
QString keyText,
QVariantList modifiers,
QString submitKeyText,
QVariantList submitModifiers) {
if (!submitKeyText.isEmpty() && (keyText == submitKeyText) && (modifiers == submitModifiers)) {
sendOnSubmitEditingToJs(textInput);
return true;
} else {
sendOnKeyPressToJs(textInput, keyText, modifiers);
return false;
}
}

void TextInputManager::sendTextInputEvent(QQuickItem* textInput, QString eventName, QVariantMap additionalEventData) {
if (!textInput)
return;

QString text = textInput->property("text").toString();
int parentTag = tag(textInput->parentItem());

QVariantMap eventData = QVariantMap{{"target", parentTag}, {"text", text}};
QVariantMap eventData = QVariantMap{{"target", parentTag}};
if (!additionalEventData.isEmpty()) {
for (auto iterator = additionalEventData.constBegin(); iterator != additionalEventData.constEnd(); ++iterator) {
eventData.insert(iterator.key(), iterator.value());
}
}

notifyJsAboutEvent(parentTag, eventName, eventData);
}

Expand Down
7 changes: 6 additions & 1 deletion ReactQt/runtime/src/componentmanagers/textinputmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,13 @@ public slots:
void sendOnSubmitEditingToJs(QQuickItem* textInput);
void sendOnEndEditingToJs(QQuickItem* textInput);
void sendOnFocusToJs(QQuickItem* textInput);
void sendOnKeyPressToJs(QQuickItem* textInput, QString keyText, QStringList modifiers);
void sendOnKeyPressToJs(QQuickItem* textInput, QString keyText, QVariantList modifiers);
void sendOnContentSizeChange(QQuickItem* textInput, double width, double height);
bool onKeyPressed(QQuickItem* textInput,
QString keyText,
QVariantList modifiers,
QString submitKeyText,
QVariantList submitModifiers);

private:
virtual QString qmlComponentFile(const QVariantMap& properties) const override;
Expand Down
39 changes: 36 additions & 3 deletions ReactQt/runtime/src/qml/ReactTextInput.qml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import QtQuick 2.7
import QtQuick 2.7
import QtQuick.Controls 2.2
import React 0.1 as React
import "../js/utils.js" as Utils
Expand All @@ -8,7 +8,7 @@ Item {
property var textInputManager: null
property var textInputControl: null

property string p_text: textInputControl ? textInputControl.text : ""
property string p_text : textInputControl ? textInputControl.text : ""
property color p_color
property bool p_multiline: false
property bool p_onChange: false
Expand All @@ -27,12 +27,45 @@ Item {
property string p_fontWeight
property int p_fontWeightEnum
property bool p_autoFocus: false

property var p_submitShortcut: defaultShortcut(p_multiline)

property var flexbox: React.Flexbox {control: textInputRoot; viewManager: textInputManager}
property bool jsTextChange: false

function defaultShortcut(multiline) {
if(multiline)
return {key: "", modifiers: []};
else
return {key: "Enter", modifiers: []};
}

objectName: p_nativeID

onP_textChanged: {
if(textInputControl) {
jsTextChange = true

if(p_multiline) {
var oldCursorPos = textInputControl.cursorPosition
var cursorAtEnd = (textInputControl.textAreaLength === textInputControl.cursorPosition)
textInputControl.text = p_text

var cursorPos;
if(cursorAtEnd)
cursorPos = textInputControl.textAreaLength
else
cursorPos = Math.min(oldCursorPos, textInputControl.textAreaLength)

textInputControl.cursorPosition = cursorPos
}
else {
textInputControl.text = p_text
}

jsTextChange = false
}
}

onP_fontWeightChanged: {
switch(p_fontWeight) {
case "100": p_fontWeightEnum = Font.Thin; break;
Expand Down
22 changes: 16 additions & 6 deletions ReactQt/runtime/src/qml/ReactTextInputArea.qml
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ import "../js/utils.js" as Utils
Flickable {
id: textField
property var textInputRoot: parent
property alias cursorPosition: textArea.cursorPosition
property alias text: textArea.text
property alias textAreaLength: textArea.length
anchors.fill: textInputRoot
ScrollBar.vertical: ScrollBar {}

TextArea.flickable: TextArea {

id: textArea
text: textInputRoot.p_text
color: textInputRoot.p_color
placeholderText: textInputRoot.p_placeholderText
selectionColor: textInputRoot.p_selectionColor
Expand All @@ -37,17 +38,26 @@ Flickable {
radius: textInputRoot.p_borderRadius
}

onTextChanged: textInputRoot.textInputManager.sendTextEditedToJs(textField)
onTextChanged: {
if(!textInputRoot.jsTextChange) {
textInputRoot.textInputManager.sendTextEditedToJs(textField)
}
}
onCursorPositionChanged: textInputRoot.textInputManager.sendSelectionChangeToJs(textField)
Keys.onPressed: textInputManager.sendOnKeyPressToJs(textField,
textInputRoot.keyText(event.key, event.text),
textInputRoot.keyModifiers(event.modifiers))
Keys.onPressed: {
var keyText = textInputRoot.keyText(event.key, event.text);
var modifiers = textInputRoot.keyModifiers(event.modifiers);
event.accepted = textInputManager.onKeyPressed(textField,
keyText,
modifiers,
textInputRoot.p_submitShortcut.key,
textInputRoot.p_submitShortcut.modifiers)
}
onContentSizeChanged: {
if(textInputManager)
textInputManager.sendOnContentSizeChange(textField, contentWidth, contentHeight)
}
onEditingFinished: {
textInputManager.sendOnSubmitEditingToJs(textField)
textInputManager.sendOnEndEditingToJs(textField)
}

Expand Down
21 changes: 15 additions & 6 deletions ReactQt/runtime/src/qml/ReactTextInputField.qml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ TextField {
property var textInputRoot: parent

anchors.fill: textInputRoot
text: textInputRoot.p_text
color: textInputRoot.p_color
placeholderText: textInputRoot.p_placeholderText
selectionColor: textInputRoot.p_selectionColor
Expand All @@ -32,17 +31,27 @@ TextField {
radius: textInputRoot.p_borderRadius
}

onTextChanged: textInputManager.sendTextEditedToJs(textField)
onTextChanged: {
if(!textInputRoot.jsTextChange) {
textInputRoot.textInputManager.sendTextEditedToJs(textField)
}
}
onCursorPositionChanged: textInputManager.sendSelectionChangeToJs(textField)
onAccepted: textInputManager.sendOnSubmitEditingToJs(textField)
onEditingFinished: textInputManager.sendOnEndEditingToJs(textField)
onContentSizeChanged: {
if(textInputManager)
textInputManager.sendOnContentSizeChange(textField, contentWidth, contentHeight)
}
Keys.onPressed: textInputManager.sendOnKeyPressToJs(textField,
textInputRoot.keyText(event.key, event.text),
textInputRoot.keyModifiers(event.modifiers))
Keys.onPressed: {

var keyText = textInputRoot.keyText(event.key, event.text);
var modifiers = textInputRoot.keyModifiers(event.modifiers);
event.accepted = textInputManager.onKeyPressed(textField,
keyText,
modifiers,
textInputRoot.p_submitShortcut.key,
textInputRoot.p_submitShortcut.modifiers)
}

onFocusChanged: {
if (focus) {
Expand Down

0 comments on commit 8d26d71

Please sign in to comment.