Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fixed double sending of onTextChange events #365

Merged
merged 8 commits into from
Oct 25, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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