Unverified Commit a039b2ca authored by Justin McCandless's avatar Justin McCandless Committed by GitHub

Revert "Revert "obscureText and enableInteractiveSelection defaults"" (#25342)

* Revert "Add imports section to sample code templates, and more docs. (#25184)"

This reverts commit 95b01247.

* Revert "Use stderr instead of stdout to contain errors in flutter attach test (#25305)"

This reverts commit 2b819dd2.

* Revert "Allow detection of taps on TabBar (#23919)"

This reverts commit 01694ab6.

* Revert "a549981da Roll src/third_party/skia a69b10312977..5eb29448dfbd (1 commits) (flutter/engine#7211) (#25333)"

This reverts commit a37099f3.

* Revert "Revert "obscureText and enableInteractiveSelection defaults (#24527)" (#25335)"

This reverts commit c5457068.

* Password fields are no longer selectable nor copiable
parent b18a2b17
......@@ -126,8 +126,6 @@ void main() {
actions: <AndroidSemanticsAction>[
AndroidSemanticsAction.click,
AndroidSemanticsAction.accessibilityFocus,
AndroidSemanticsAction.setSelection,
AndroidSemanticsAction.copy,
],
));
......@@ -143,8 +141,6 @@ void main() {
actions: <AndroidSemanticsAction>[
AndroidSemanticsAction.click,
AndroidSemanticsAction.accessibilityFocus,
AndroidSemanticsAction.setSelection,
AndroidSemanticsAction.copy,
],
));
});
......
......@@ -93,8 +93,8 @@ class TextField extends StatefulWidget {
/// switch to the [decoration.errorStyle] when the limit is exceeded.
///
/// The [textAlign], [autofocus], [obscureText], [autocorrect],
/// [maxLengthEnforced], [scrollPadding], [maxLines], [maxLength],
/// and [enableInteractiveSelection] arguments must not be null.
/// [maxLengthEnforced], [scrollPadding], [maxLines], and [maxLength]
/// arguments must not be null.
///
/// See also:
///
......@@ -127,7 +127,7 @@ class TextField extends StatefulWidget {
this.cursorColor,
this.keyboardAppearance,
this.scrollPadding = const EdgeInsets.all(20.0),
this.enableInteractiveSelection = true,
this.enableInteractiveSelection,
this.onTap,
}) : assert(textAlign != null),
assert(autofocus != null),
......@@ -138,7 +138,6 @@ class TextField extends StatefulWidget {
assert(maxLines == null || maxLines > 0),
assert(maxLength == null || maxLength == TextField.noMaxLength || maxLength > 0),
keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
assert(enableInteractiveSelection != null),
super(key: key);
/// Controls the text being edited.
......@@ -340,6 +339,11 @@ class TextField extends StatefulWidget {
/// {@macro flutter.widgets.editableText.enableInteractiveSelection}
final bool enableInteractiveSelection;
/// {@macro flutter.rendering.editable.selectionEnabled}
bool get selectionEnabled {
return enableInteractiveSelection ?? !obscureText;
}
/// Called when the user taps on this textfield.
///
/// The textfield builds a [GestureDetector] to handle input events like tap,
......@@ -517,7 +521,7 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
}
void _handleTap() {
if (widget.enableInteractiveSelection)
if (widget.selectionEnabled)
_renderEditable.handleTap();
_requestKeyboard();
_confirmCurrentSplash();
......@@ -530,7 +534,7 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
}
void _handleLongPress() {
if (widget.enableInteractiveSelection)
if (widget.selectionEnabled)
_renderEditable.handleLongPress();
_confirmCurrentSplash();
}
......@@ -608,7 +612,7 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
autocorrect: widget.autocorrect,
maxLines: widget.maxLines,
selectionColor: themeData.textSelectionColor,
selectionControls: widget.enableInteractiveSelection
selectionControls: widget.selectionEnabled
? (themeData.platform == TargetPlatform.iOS
? cupertinoTextSelectionControls
: materialTextSelectionControls)
......
......@@ -129,8 +129,6 @@ class RenderEditable extends RenderBox {
///
/// The [offset] is required and must not be null. You can use [new
/// ViewportOffset.zero] if you have no need for scrolling.
///
/// The [enableInteractiveSelection] argument must not be null.
RenderEditable({
TextSpan text,
@required TextDirection textDirection,
......@@ -151,8 +149,8 @@ class RenderEditable extends RenderBox {
Locale locale,
double cursorWidth = 1.0,
Radius cursorRadius,
bool enableInteractiveSelection,
EdgeInsets floatingCursorAddedMargin = const EdgeInsets.fromLTRB(3, 6, 3, 6),
bool enableInteractiveSelection = true,
@required this.textSelectionDelegate,
}) : assert(textAlign != null),
assert(textDirection != null, 'RenderEditable created without a textDirection.'),
......@@ -161,7 +159,6 @@ class RenderEditable extends RenderBox {
assert(offset != null),
assert(ignorePointer != null),
assert(obscureText != null),
assert(enableInteractiveSelection != null),
assert(textSelectionDelegate != null),
_textPainter = TextPainter(
text: text,
......@@ -756,6 +753,22 @@ class RenderEditable extends RenderBox {
markNeedsSemanticsUpdate();
}
/// {@template flutter.rendering.editable.selectionEnabled}
/// True if interactive selection is enabled based on the values of
/// [enableInteractiveSelection] and [obscureText].
///
/// By default [enableInteractiveSelection] is null, obscureText is false,
/// and this method returns true.
/// If [enableInteractiveSelection] is null and obscureText is true, then this
/// method returns false. This is the common case for password fields.
/// If [enableInteractiveSelection] is non-null then its value is returned. An
/// app might set it to true to enable interactive selection for a password
/// field, or to false to unconditionally disable interactive selection.
/// {@endtemplate}
bool get selectionEnabled {
return enableInteractiveSelection ?? !obscureText;
}
@override
void describeSemanticsConfiguration(SemanticsConfiguration config) {
super.describeSemanticsConfiguration(config);
......@@ -769,10 +782,10 @@ class RenderEditable extends RenderBox {
..isFocused = hasFocus
..isTextField = true;
if (hasFocus && enableInteractiveSelection)
if (hasFocus && selectionEnabled)
config.onSetSelection = _handleSetSelection;
if (enableInteractiveSelection && _selection?.isValid == true) {
if (selectionEnabled && _selection?.isValid == true) {
config.textSelection = _selection;
if (_textPainter.getOffsetBefore(_selection.extentOffset) != null) {
config
......
......@@ -184,8 +184,7 @@ class EditableText extends StatefulWidget {
/// default to [TextInputType.multiline].
///
/// The [controller], [focusNode], [style], [cursorColor], [backgroundCursorColor],
/// [textAlign], [rendererIgnoresPointer], and [enableInteractiveSelection]
/// arguments must not be null.
/// [textAlign], and [rendererIgnoresPointer] arguments must not be null.
EditableText({
Key key,
@required this.controller,
......@@ -216,7 +215,7 @@ class EditableText extends StatefulWidget {
this.cursorRadius,
this.scrollPadding = const EdgeInsets.all(20.0),
this.keyboardAppearance = Brightness.light,
this.enableInteractiveSelection = true,
this.enableInteractiveSelection,
}) : assert(controller != null),
assert(focusNode != null),
assert(obscureText != null),
......@@ -229,7 +228,6 @@ class EditableText extends StatefulWidget {
assert(autofocus != null),
assert(rendererIgnoresPointer != null),
assert(scrollPadding != null),
assert(enableInteractiveSelection != null),
keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
inputFormatters = maxLines == 1
? (
......@@ -479,6 +477,11 @@ class EditableText extends StatefulWidget {
/// Defaults to false, resulting in a typical blinking cursor.
static bool debugDeterministicCursor = false;
/// {@macro flutter.rendering.editable.selectionEnabled}
bool get selectionEnabled {
return enableInteractiveSelection ?? !obscureText;
}
@override
EditableTextState createState() => EditableTextState();
......@@ -1013,19 +1016,19 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
}
VoidCallback _semanticsOnCopy(TextSelectionControls controls) {
return widget.enableInteractiveSelection && _hasFocus && controls?.canCopy(this) == true
return widget.selectionEnabled && _hasFocus && controls?.canCopy(this) == true
? () => controls.handleCopy(this)
: null;
}
VoidCallback _semanticsOnCut(TextSelectionControls controls) {
return widget.enableInteractiveSelection && _hasFocus && controls?.canCut(this) == true
return widget.selectionEnabled && _hasFocus && controls?.canCut(this) == true
? () => controls.handleCut(this)
: null;
}
VoidCallback _semanticsOnPaste(TextSelectionControls controls) {
return widget.enableInteractiveSelection &&_hasFocus && controls?.canPaste(this) == true
return widget.selectionEnabled &&_hasFocus && controls?.canPaste(this) == true
? () => controls.handlePaste(this)
: null;
}
......@@ -1136,11 +1139,10 @@ class _Editable extends LeafRenderObjectWidget {
this.rendererIgnoresPointer = false,
this.cursorWidth,
this.cursorRadius,
this.enableInteractiveSelection = true,
this.enableInteractiveSelection,
this.textSelectionDelegate,
}) : assert(textDirection != null),
assert(rendererIgnoresPointer != null),
assert(enableInteractiveSelection != null),
super(key: key);
final TextSpan textSpan;
......
......@@ -658,6 +658,66 @@ void main() {
// End the test here to ensure the animation is properly disposed of.
});
testWidgets('An obscured TextField is not selectable by default', (WidgetTester tester) async {
// This is a regression test for
// https://github.com/flutter/flutter/issues/24100
final TextEditingController controller = TextEditingController();
Widget buildFrame(bool obscureText, bool enableInteractiveSelection) {
return overlay(
child: TextField(
controller: controller,
obscureText: obscureText,
enableInteractiveSelection: enableInteractiveSelection,
),
);
}
// Obscure text and don't enable or disable selection
await tester.pumpWidget(buildFrame(true, null));
await tester.enterText(find.byType(TextField), 'abcdefghi');
await skipPastScrollingAnimation(tester);
expect(controller.selection.isCollapsed, true);
// Long press doesn't select anything
final Offset ePos = textOffsetToPosition(tester, 1);
final TestGesture gesture = await tester.startGesture(ePos, pointer: 7);
await tester.pump(const Duration(seconds: 2));
await gesture.up();
await tester.pump();
expect(controller.selection.isCollapsed, true);
});
testWidgets('An obscured TextField is selectable when enabled', (WidgetTester tester) async {
// This is a regression test for
// https://github.com/flutter/flutter/issues/24100
final TextEditingController controller = TextEditingController();
Widget buildFrame(bool obscureText, bool enableInteractiveSelection) {
return overlay(
child: TextField(
controller: controller,
obscureText: obscureText,
enableInteractiveSelection: enableInteractiveSelection,
),
);
}
// Explicitly allow selection on obscured text
await tester.pumpWidget(buildFrame(true, true));
await tester.enterText(find.byType(TextField), 'abcdefghi');
await skipPastScrollingAnimation(tester);
expect(controller.selection.isCollapsed, true);
// Long press does select text
final Offset ePos2 = textOffsetToPosition(tester, 1);
final TestGesture gesture2 = await tester.startGesture(ePos2, pointer: 7);
await tester.pump(const Duration(seconds: 2));
await gesture2.up();
await tester.pump();
expect(controller.selection.isCollapsed, false);
});
testWidgets('Multiline text will wrap up to maxLines', (WidgetTester tester) async {
final Key textFieldKey = UniqueKey();
......
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