From e19989a1cbf1e6d69a4947ed3385f273f320a8f2 Mon Sep 17 00:00:00 2001 From: Nurhan Turgut Date: Thu, 19 Dec 2019 14:55:36 -0800 Subject: [PATCH 1/3] fixing long press by listening click --- .../src/engine/text_editing/text_editing.dart | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart index 589bc5da4d6cf..bf8bf4adcbc29 100644 --- a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart +++ b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart @@ -5,7 +5,7 @@ part of engine; /// Make the content editable span visible to facilitate debugging. -const bool _debugVisibleTextEditing = false; +const bool _debugVisibleTextEditing = true; /// The `keyCode` of the "Enter" key. const int _kReturnKeyCode = 13; @@ -552,6 +552,20 @@ class IOSTextEditingStrategy extends DefaultTextEditingStrategy { _positionInputElementTimer?.cancel(); _positionInputElementTimer = Timer(_delayBeforePositioning, () { _canPosition = true; + + _subscriptions.add(domElement.onClick.listen((_) { + if (_canPosition) { + // this means already positioned. + domElement.style.transform = 'translate(-9999px, -9999px)'; + _canPosition = false; + + _positionInputElementTimer?.cancel(); + _positionInputElementTimer = Timer(_delayBeforePositioning, () { + _canPosition = true; + positionElement(); + }); + } + })); positionElement(); }); })); From 00c22692a253645bf16d80a36ab3a081f70a8b0c Mon Sep 17 00:00:00 2001 From: Nurhan Turgut Date: Thu, 19 Dec 2019 17:34:27 -0800 Subject: [PATCH 2/3] documenting the code. creating a new method --- .../src/engine/text_editing/text_editing.dart | 54 +++++++++++++------ 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart index bf8bf4adcbc29..b16122d54763f 100644 --- a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart +++ b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart @@ -5,7 +5,7 @@ part of engine; /// Make the content editable span visible to facilitate debugging. -const bool _debugVisibleTextEditing = true; +const bool _debugVisibleTextEditing = false; /// The `keyCode` of the "Enter" key. const int _kReturnKeyCode = 13; @@ -552,21 +552,8 @@ class IOSTextEditingStrategy extends DefaultTextEditingStrategy { _positionInputElementTimer?.cancel(); _positionInputElementTimer = Timer(_delayBeforePositioning, () { _canPosition = true; - - _subscriptions.add(domElement.onClick.listen((_) { - if (_canPosition) { - // this means already positioned. - domElement.style.transform = 'translate(-9999px, -9999px)'; - _canPosition = false; - - _positionInputElementTimer?.cancel(); - _positionInputElementTimer = Timer(_delayBeforePositioning, () { - _canPosition = true; - positionElement(); - }); - } - })); positionElement(); + _addTapListener(); }); })); @@ -594,6 +581,43 @@ class IOSTextEditingStrategy extends DefaultTextEditingStrategy { _positionInputElementTimer?.cancel(); _positionInputElementTimer = null; } + + /// On iOS long press works differently than a single tap. + /// + /// On a normal tap the virtual keyboard comes up and users can enter text + /// using the keyboard. + /// + /// The long press on the other hand focuses on the element without bringing + /// up the virtual keyboard. It allows the users to modify the field by using + /// copy/cut/select/paste etc. + /// + /// After a long press [domElement] is positioned to the correct place. If the + /// user later single-tap on the [domElement] the virtual keyboard will come + /// and might shift the page up. + /// + /// In order to prevent this shift, on a `click` event the position of the + /// element is again set somewhere outside of the page and + /// [_positionInputElementTimer] timer is restarted. The element will be + /// placed to its correct position after [_delayBeforePositioning]. + void _addTapListener() { + _subscriptions.add(domElement.onClick.listen((_) { + // Check if the element is already positioned. If not this does not fall + // under `The user was using the long press, now they want to enter text + // via keyboard` journey. + if (_canPosition) { + // Re-place the element somewhere outside of the screen. + domElement.style.transform = 'translate(-9999px, -9999px)'; + _canPosition = false; + + // Re-configure the timer to place the element. + _positionInputElementTimer?.cancel(); + _positionInputElementTimer = Timer(_delayBeforePositioning, () { + _canPosition = true; + positionElement(); + }); + } + })); + } } /// Android behaviour for text editing. From 72622a0c86ad506f3937906d3cc4ac62b520c13f Mon Sep 17 00:00:00 2001 From: Nurhan Turgut Date: Fri, 20 Dec 2019 08:49:00 -0800 Subject: [PATCH 3/3] addressing reviewer comments --- .../src/engine/text_editing/text_editing.dart | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart index b16122d54763f..450de827e367f 100644 --- a/lib/web_ui/lib/src/engine/text_editing/text_editing.dart +++ b/lib/web_ui/lib/src/engine/text_editing/text_editing.dart @@ -549,14 +549,11 @@ class IOSTextEditingStrategy extends DefaultTextEditingStrategy { // Position the DOM element after it is focused. _subscriptions.add(domElement.onFocus.listen((_) { // Cancel previous timer if exists. - _positionInputElementTimer?.cancel(); - _positionInputElementTimer = Timer(_delayBeforePositioning, () { - _canPosition = true; - positionElement(); - _addTapListener(); - }); + _schedulePositioning(); })); + _addTapListener(); + // On iOS, blur is trigerred if the virtual keyboard is closed or the // browser is sent to background or the browser tab is changed. // @@ -606,18 +603,21 @@ class IOSTextEditingStrategy extends DefaultTextEditingStrategy { // via keyboard` journey. if (_canPosition) { // Re-place the element somewhere outside of the screen. - domElement.style.transform = 'translate(-9999px, -9999px)'; - _canPosition = false; + initializeElementPosition(); // Re-configure the timer to place the element. - _positionInputElementTimer?.cancel(); - _positionInputElementTimer = Timer(_delayBeforePositioning, () { - _canPosition = true; - positionElement(); - }); + _schedulePositioning(); } })); } + + void _schedulePositioning() { + _positionInputElementTimer?.cancel(); + _positionInputElementTimer = Timer(_delayBeforePositioning, () { + _canPosition = true; + positionElement(); + }); + } } /// Android behaviour for text editing.