Unverified Commit 9c32e5a1 authored by Renzo Olivares's avatar Renzo Olivares Committed by GitHub

Add enableIMEPersonalizedLearning flag to TextField and TextFormField (#87002)

* Add requestPrivacy parameter to TextField

* remove logs

* No need to pass _Editable requestPrivacy for now

* Forgot from last commit

* Add requestPrivacy flag to text form field

* Update docs

* Add requestPrivacy to CupertinoTextField

* Add test to verify requestPrivacy flag is sent to engine properly

* update docs

* fix tests

* rename requestPrivacy to enableIMEPersonalizedLearning

* Update text_input.dart

* default to true

* Have diagnostic properties default to true for enableIMEPersonalizedLearning
parent ade9f6a9
......@@ -219,7 +219,8 @@ class CupertinoTextField extends StatefulWidget {
/// The [autocorrect], [autofocus], [clearButtonMode], [dragStartBehavior],
/// [expands], [maxLengthEnforced], [obscureText], [prefixMode], [readOnly],
/// [scrollPadding], [suffixMode], [textAlign], [selectionHeightStyle],
/// [selectionWidthStyle], and [enableSuggestions] properties must not be null.
/// [selectionWidthStyle], [enableSuggestions], and [enableIMEPersonalizedLearning]
/// properties must not be null.
///
/// See also:
///
......@@ -294,6 +295,7 @@ class CupertinoTextField extends StatefulWidget {
this.scrollPhysics,
this.autofillHints,
this.restorationId,
this.enableIMEPersonalizedLearning = true,
}) : assert(textAlign != null),
assert(readOnly != null),
assert(autofocus != null),
......@@ -335,6 +337,7 @@ class CupertinoTextField extends StatefulWidget {
!identical(keyboardType, TextInputType.text),
'Use keyboardType TextInputType.multiline when using TextInputAction.newline on a multiline TextField.',
),
assert(enableIMEPersonalizedLearning != null),
keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
toolbarOptions = toolbarOptions ?? (obscureText ?
const ToolbarOptions(
......@@ -448,6 +451,7 @@ class CupertinoTextField extends StatefulWidget {
this.scrollPhysics,
this.autofillHints,
this.restorationId,
this.enableIMEPersonalizedLearning = true,
}) : assert(textAlign != null),
assert(readOnly != null),
assert(autofocus != null),
......@@ -489,6 +493,7 @@ class CupertinoTextField extends StatefulWidget {
!identical(keyboardType, TextInputType.text),
'Use keyboardType TextInputType.multiline when using TextInputAction.newline on a multiline TextField.',
),
assert(enableIMEPersonalizedLearning != null),
keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
toolbarOptions = toolbarOptions ?? (obscureText ?
const ToolbarOptions(
......@@ -784,6 +789,9 @@ class CupertinoTextField extends StatefulWidget {
/// {@macro flutter.material.textfield.restorationId}
final String? restorationId;
/// {@macro flutter.services.TextInputConfiguration.enableIMEPersonalizedLearning}
final bool enableIMEPersonalizedLearning;
@override
State<CupertinoTextField> createState() => _CupertinoTextFieldState();
......@@ -825,6 +833,7 @@ class CupertinoTextField extends StatefulWidget {
properties.add(EnumProperty<TextAlign>('textAlign', textAlign, defaultValue: TextAlign.start));
properties.add(DiagnosticsProperty<TextAlignVertical>('textAlignVertical', textAlignVertical, defaultValue: null));
properties.add(EnumProperty<TextDirection>('textDirection', textDirection, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('enableIMEPersonalizedLearning', enableIMEPersonalizedLearning, defaultValue: true));
}
}
......@@ -1221,6 +1230,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with Restoratio
enableInteractiveSelection: widget.enableInteractiveSelection,
autofillHints: widget.autofillHints,
restorationId: 'editable',
enableIMEPersonalizedLearning: widget.enableIMEPersonalizedLearning,
),
),
),
......
......@@ -325,8 +325,8 @@ class TextField extends StatefulWidget {
///
/// The [textAlign], [autofocus], [obscureText], [readOnly], [autocorrect],
/// [maxLengthEnforced], [scrollPadding], [maxLines], [maxLength],
/// [selectionHeightStyle], [selectionWidthStyle], and [enableSuggestions]
/// arguments must not be null.
/// [selectionHeightStyle], [selectionWidthStyle], [enableSuggestions], and
/// [enableIMEPersonalizedLearning] arguments must not be null.
///
/// See also:
///
......@@ -390,6 +390,7 @@ class TextField extends StatefulWidget {
this.scrollPhysics,
this.autofillHints,
this.restorationId,
this.enableIMEPersonalizedLearning = true,
}) : assert(textAlign != null),
assert(readOnly != null),
assert(autofocus != null),
......@@ -429,6 +430,7 @@ class TextField extends StatefulWidget {
!identical(keyboardType, TextInputType.text),
'Use keyboardType TextInputType.multiline when using TextInputAction.newline on a multiline TextField.',
),
assert(enableIMEPersonalizedLearning != null),
keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
toolbarOptions = toolbarOptions ?? (obscureText ?
const ToolbarOptions(
......@@ -821,6 +823,9 @@ class TextField extends StatefulWidget {
/// {@endtemplate}
final String? restorationId;
/// {@macro flutter.services.TextInputConfiguration.enableIMEPersonalizedLearning}
final bool enableIMEPersonalizedLearning;
@override
State<TextField> createState() => _TextFieldState();
......@@ -861,6 +866,7 @@ class TextField extends StatefulWidget {
properties.add(DiagnosticsProperty<TextSelectionControls>('selectionControls', selectionControls, defaultValue: null));
properties.add(DiagnosticsProperty<ScrollController>('scrollController', scrollController, defaultValue: null));
properties.add(DiagnosticsProperty<ScrollPhysics>('scrollPhysics', scrollPhysics, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('enableIMEPersonalizedLearning', enableIMEPersonalizedLearning, defaultValue: true));
}
}
......@@ -1263,6 +1269,7 @@ class _TextFieldState extends State<TextField> with RestorationMixin implements
autofillHints: widget.autofillHints,
autocorrectionTextRectColor: autocorrectionTextRectColor,
restorationId: 'editable',
enableIMEPersonalizedLearning: widget.enableIMEPersonalizedLearning,
),
),
);
......
......@@ -196,6 +196,7 @@ class TextFormField extends FormField<String> {
AutovalidateMode? autovalidateMode,
ScrollController? scrollController,
String? restorationId,
bool enableIMEPersonalizedLearning = true,
}) : assert(initialValue == null || controller == null),
assert(textAlign != null),
assert(autofocus != null),
......@@ -230,6 +231,7 @@ class TextFormField extends FormField<String> {
assert(!obscureText || maxLines == 1, 'Obscured fields cannot be multiline.'),
assert(maxLength == null || maxLength == TextField.noMaxLength || maxLength > 0),
assert(enableInteractiveSelection != null),
assert(enableIMEPersonalizedLearning != null),
super(
key: key,
restorationId: restorationId,
......@@ -299,6 +301,7 @@ class TextFormField extends FormField<String> {
buildCounter: buildCounter,
autofillHints: autofillHints,
scrollController: scrollController,
enableIMEPersonalizedLearning: enableIMEPersonalizedLearning,
),
);
},
......
......@@ -466,6 +466,7 @@ class TextInputConfiguration {
this.keyboardAppearance = Brightness.light,
this.textCapitalization = TextCapitalization.none,
this.autofillConfiguration,
this.enableIMEPersonalizedLearning = true,
}) : assert(inputType != null),
assert(obscureText != null),
smartDashesType = smartDashesType ?? (obscureText ? SmartDashesType.disabled : SmartDashesType.enabled),
......@@ -474,7 +475,8 @@ class TextInputConfiguration {
assert(enableSuggestions != null),
assert(keyboardAppearance != null),
assert(inputAction != null),
assert(textCapitalization != null);
assert(textCapitalization != null),
assert(enableIMEPersonalizedLearning != null);
/// The type of information for which to optimize the text input control.
final TextInputType inputType;
......@@ -590,6 +592,20 @@ class TextInputConfiguration {
/// Defaults to [Brightness.light].
final Brightness keyboardAppearance;
/// {@template flutter.services.TextInputConfiguration.enableIMEPersonalizedLearning}
/// Whether to enable that the IME update personalized data such as typing
/// history and user dictionary data.
///
/// This flag only affects Android. On iOS, there is no equivalent flag.
///
/// Defaults to true. Cannot be null.
///
/// See also:
///
/// * <https://developer.android.com/reference/android/view/inputmethod/EditorInfo#IME_FLAG_NO_PERSONALIZED_LEARNING>
/// {@endtemplate}
final bool enableIMEPersonalizedLearning;
/// Returns a representation of this object as a JSON object.
Map<String, dynamic> toJson() {
return <String, dynamic>{
......@@ -604,6 +620,7 @@ class TextInputConfiguration {
'inputAction': inputAction.toString(),
'textCapitalization': textCapitalization.toString(),
'keyboardAppearance': keyboardAppearance.toString(),
'enableIMEPersonalizedLearning': enableIMEPersonalizedLearning,
if (autofillConfiguration != null) 'autofill': autofillConfiguration!.toJson(),
};
}
......
......@@ -426,8 +426,8 @@ class EditableText extends StatefulWidget {
/// [style], [cursorColor], [cursorOpacityAnimates],[backgroundCursorColor],
/// [enableSuggestions], [paintCursorAboveText], [selectionHeightStyle],
/// [selectionWidthStyle], [textAlign], [dragStartBehavior], [scrollPadding],
/// [dragStartBehavior], [toolbarOptions], [rendererIgnoresPointer], and
/// [readOnly] arguments must not be null.
/// [dragStartBehavior], [toolbarOptions], [rendererIgnoresPointer],
/// [readOnly], and [enableIMEPersonalizedLearning] arguments must not be null.
EditableText({
Key? key,
required this.controller,
......@@ -495,6 +495,7 @@ class EditableText extends StatefulWidget {
this.clipBehavior = Clip.hardEdge,
this.restorationId,
this.scrollBehavior,
this.enableIMEPersonalizedLearning = true,
}) : assert(controller != null),
assert(focusNode != null),
assert(obscuringCharacter != null && obscuringCharacter.length == 1),
......@@ -537,6 +538,7 @@ class EditableText extends StatefulWidget {
!readOnly || autofillHints == null,
"Read-only fields can't have autofill hints.",
),
assert(enableIMEPersonalizedLearning != null),
_strutStyle = strutStyle,
keyboardType = keyboardType ?? _inferKeyboardType(autofillHints: autofillHints, maxLines: maxLines),
inputFormatters = maxLines == 1
......@@ -1346,6 +1348,9 @@ class EditableText extends StatefulWidget {
/// than 1.
final ScrollBehavior? scrollBehavior;
/// {@macro flutter.services.TextInputConfiguration.enableIMEPersonalizedLearning}
final bool enableIMEPersonalizedLearning;
// Infer the keyboard type of an `EditableText` if it's not specified.
static TextInputType _inferKeyboardType({
required Iterable<String>? autofillHints,
......@@ -1513,6 +1518,7 @@ class EditableText extends StatefulWidget {
properties.add(DiagnosticsProperty<ScrollPhysics>('scrollPhysics', scrollPhysics, defaultValue: null));
properties.add(DiagnosticsProperty<Iterable<String>>('autofillHints', autofillHints, defaultValue: null));
properties.add(DiagnosticsProperty<TextHeightBehavior>('textHeightBehavior', textHeightBehavior, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('enableIMEPersonalizedLearning', enableIMEPersonalizedLearning, defaultValue: true));
}
}
......@@ -2607,6 +2613,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
autofillHints: widget.autofillHints?.toList(growable: false) ?? <String>[],
currentEditingValue: currentTextEditingValue,
),
enableIMEPersonalizedLearning: widget.enableIMEPersonalizedLearning,
);
}
......
......@@ -199,6 +199,7 @@ void main() {
expect(editableText.obscureText, isFalse);
expect(editableText.autocorrect, isTrue);
expect(editableText.enableSuggestions, isTrue);
expect(editableText.enableIMEPersonalizedLearning, isTrue);
expect(editableText.textAlign, TextAlign.start);
expect(editableText.cursorWidth, 2.0);
expect(editableText.cursorHeight, isNull);
......@@ -576,6 +577,36 @@ void main() {
expect(tester.testTextInput.setClientArgs!['enableSuggestions'], enableSuggestions);
});
testWidgets('enableIMEPersonalizedLearning flag is sent to the engine properly', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController();
const bool enableIMEPersonalizedLearning = false;
await tester.pumpWidget(
MediaQuery(
data: const MediaQueryData(devicePixelRatio: 1.0),
child: Directionality(
textDirection: TextDirection.ltr,
child: FocusScope(
node: focusScopeNode,
autofocus: true,
child: EditableText(
controller: controller,
backgroundCursorColor: Colors.grey,
focusNode: focusNode,
enableIMEPersonalizedLearning: enableIMEPersonalizedLearning,
style: textStyle,
cursorColor: cursorColor,
),
),
),
),
);
await tester.tap(find.byType(EditableText));
await tester.showKeyboard(find.byType(EditableText));
await tester.idle();
expect(tester.testTextInput.setClientArgs!['enableIMEPersonalizedLearning'], enableIMEPersonalizedLearning);
});
group('smartDashesType and smartQuotesType', () {
testWidgets('sent to the engine properly', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController();
......
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