Commit 93f718b3 authored by Dan Field's avatar Dan Field Committed by Flutter GitHub Bot

Fix requestExistingInputState response (#47472)

parent cc1c9649
...@@ -753,6 +753,9 @@ abstract class TextInputClient { ...@@ -753,6 +753,9 @@ abstract class TextInputClient {
/// Updates the floating cursor position and state. /// Updates the floating cursor position and state.
void updateFloatingCursor(RawFloatingCursorPoint point); void updateFloatingCursor(RawFloatingCursorPoint point);
/// The current state of the [TextEditingValue] held by this client.
TextEditingValue get currentTextEditingValue;
/// Platform notified framework of closed connection. /// Platform notified framework of closed connection.
/// ///
/// [TextInputClient] should cleanup its connection and finalize editing. /// [TextInputClient] should cleanup its connection and finalize editing.
...@@ -1036,7 +1039,6 @@ class TextInput { ...@@ -1036,7 +1039,6 @@ class TextInput {
TextInputConnection _currentConnection; TextInputConnection _currentConnection;
TextInputConfiguration _currentConfiguration; TextInputConfiguration _currentConfiguration;
TextEditingValue _currentTextEditingValue;
Future<dynamic> _handleTextInputInvocation(MethodCall methodCall) async { Future<dynamic> _handleTextInputInvocation(MethodCall methodCall) async {
if (_currentConnection == null) if (_currentConnection == null)
...@@ -1048,9 +1050,9 @@ class TextInput { ...@@ -1048,9 +1050,9 @@ class TextInput {
if (method == 'TextInputClient.requestExistingInputState') { if (method == 'TextInputClient.requestExistingInputState') {
assert(_currentConnection._client != null); assert(_currentConnection._client != null);
_attach(_currentConnection, _currentConfiguration); _attach(_currentConnection, _currentConfiguration);
// This will be null if we've never had a call to [_setEditingState]. final TextEditingValue editingValue = _currentConnection._client.currentTextEditingValue;
if (_currentTextEditingValue != null) { if (editingValue != null) {
_setEditingState(_currentTextEditingValue); _setEditingState(editingValue);
} }
return; return;
} }
...@@ -1110,7 +1112,6 @@ class TextInput { ...@@ -1110,7 +1112,6 @@ class TextInput {
'TextInput.setEditingState', 'TextInput.setEditingState',
value.toJSON(), value.toJSON(),
); );
_currentTextEditingValue = value;
} }
void _show() { void _show() {
......
...@@ -1202,6 +1202,9 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien ...@@ -1202,6 +1202,9 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
TextEditingValue _lastKnownRemoteTextEditingValue; TextEditingValue _lastKnownRemoteTextEditingValue;
@override
TextEditingValue get currentTextEditingValue => _value;
@override @override
void updateEditingValue(TextEditingValue value) { void updateEditingValue(TextEditingValue value) {
// Since we still have to support keyboard select, this is the best place // Since we still have to support keyboard select, this is the best place
......
...@@ -13,12 +13,10 @@ void main() { ...@@ -13,12 +13,10 @@ void main() {
group('TextInput message channels', () { group('TextInput message channels', () {
FakeTextChannel fakeTextChannel; FakeTextChannel fakeTextChannel;
FakeTextInputClient client;
setUp(() { setUp(() {
fakeTextChannel = FakeTextChannel((MethodCall call) async {}); fakeTextChannel = FakeTextChannel((MethodCall call) async {});
TextInput.setChannel(fakeTextChannel); TextInput.setChannel(fakeTextChannel);
client = FakeTextInputClient();
}); });
tearDown(() { tearDown(() {
...@@ -27,6 +25,7 @@ void main() { ...@@ -27,6 +25,7 @@ void main() {
}); });
test('text input client handler responds to reattach with setClient', () async { test('text input client handler responds to reattach with setClient', () async {
final FakeTextInputClient client = FakeTextInputClient(const TextEditingValue(text: 'test1'));
TextInput.attach(client, client.configuration); TextInput.attach(client, client.configuration);
fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[ fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]), MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
...@@ -34,39 +33,31 @@ void main() { ...@@ -34,39 +33,31 @@ void main() {
fakeTextChannel.incoming(const MethodCall('TextInputClient.requestExistingInputState', null)); fakeTextChannel.incoming(const MethodCall('TextInputClient.requestExistingInputState', null));
expect(fakeTextChannel.outgoingCalls.length, 2); expect(fakeTextChannel.outgoingCalls.length, 3);
fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[ fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[
// From original attach // From original attach
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]), MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
// From requestExistingInputState // From requestExistingInputState
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]), MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
MethodCall('TextInput.setEditingState', client.currentTextEditingValue.toJSON()),
]); ]);
}); });
test('text input client handler responds to reattach with setClient and text state', () async { test('text input client handler responds to reattach with setClient (null TextEditingValue)', () async {
final TextInputConnection connection = TextInput.attach(client, client.configuration); final FakeTextInputClient client = FakeTextInputClient(null);
fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[ TextInput.attach(client, client.configuration);
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
]);
const TextEditingValue editingState = TextEditingValue(text: 'foo');
connection.setEditingState(editingState);
fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[ fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]), MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
MethodCall('TextInput.setEditingState', editingState.toJSON()),
]); ]);
fakeTextChannel.incoming(const MethodCall('TextInputClient.requestExistingInputState', null)); fakeTextChannel.incoming(const MethodCall('TextInputClient.requestExistingInputState', null));
expect(fakeTextChannel.outgoingCalls.length, 4); expect(fakeTextChannel.outgoingCalls.length, 2);
fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[ fakeTextChannel.validateOutgoingMethodCalls(<MethodCall>[
// attach // From original attach
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]), MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
// set editing state 1 // From requestExistingInputState
MethodCall('TextInput.setEditingState', editingState.toJSON()),
// both from requestExistingInputState
MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]), MethodCall('TextInput.setClient', <dynamic>[1, client.configuration.toJson()]),
MethodCall('TextInput.setEditingState', editingState.toJSON()),
]); ]);
}); });
}); });
...@@ -153,7 +144,7 @@ void main() { ...@@ -153,7 +144,7 @@ void main() {
test('TextInputClient onConnectionClosed method is called', () async { test('TextInputClient onConnectionClosed method is called', () async {
// Assemble a TextInputConnection so we can verify its change in state. // Assemble a TextInputConnection so we can verify its change in state.
final FakeTextInputClient client = FakeTextInputClient(); final FakeTextInputClient client = FakeTextInputClient(const TextEditingValue(text: 'test3'));
const TextInputConfiguration configuration = TextInputConfiguration(); const TextInputConfiguration configuration = TextInputConfiguration();
TextInput.attach(client, configuration); TextInput.attach(client, configuration);
...@@ -176,8 +167,13 @@ void main() { ...@@ -176,8 +167,13 @@ void main() {
} }
class FakeTextInputClient implements TextInputClient { class FakeTextInputClient implements TextInputClient {
FakeTextInputClient(this.currentTextEditingValue);
String latestMethodCall = ''; String latestMethodCall = '';
@override
TextEditingValue currentTextEditingValue;
@override @override
void performAction(TextInputAction action) { void performAction(TextInputAction action) {
latestMethodCall = 'performAction'; latestMethodCall = 'performAction';
...@@ -231,7 +227,6 @@ class FakeTextChannel implements MethodChannel { ...@@ -231,7 +227,6 @@ class FakeTextChannel implements MethodChannel {
@override @override
String get name => 'flutter/textinput'; String get name => 'flutter/textinput';
@override @override
void setMethodCallHandler(Future<void> Function(MethodCall call) handler) { void setMethodCallHandler(Future<void> Function(MethodCall call) handler) {
incoming = handler; incoming = handler;
...@@ -252,7 +247,7 @@ class FakeTextChannel implements MethodChannel { ...@@ -252,7 +247,7 @@ class FakeTextChannel implements MethodChannel {
if (outgoingString != expectedString) { if (outgoingString != expectedString) {
print( print(
'Index $i did not match:\n' 'Index $i did not match:\n'
' actual: ${outgoingCalls[i]}' ' actual: ${outgoingCalls[i]}\n'
' expected: ${calls[i]}'); ' expected: ${calls[i]}');
hasError = true; hasError = true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment