Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1a87baf

Browse files
docs
1 parent ecaec5a commit 1a87baf

10 files changed

+419
-249
lines changed

packages/flutter/lib/src/services/autofill.dart

Lines changed: 98 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:ui';
6+
57
import 'package:flutter/foundation.dart';
68
import 'text_input.dart';
79

@@ -751,13 +753,15 @@ class AutofillConfiguration {
751753
abstract class AutofillClient {
752754
/// The unique identifier of this [AutofillClient].
753755
///
754-
/// Must not be null and the identifier must not be changed.
756+
/// Must not be null and the identifier must not change during its entire
757+
/// lifespan.
755758
String get autofillId;
756759

757760
/// The [TextInputConfiguration] that describes this [AutofillClient].
758761
///
759762
/// In order to participate in autofill, its
760-
/// [TextInputConfiguration.autofillConfiguration] must not be null.
763+
/// [TextInputConfiguration.autofillConfiguration] must not be null and
764+
/// the [AutofillConfiguration.enabled] parameter must be true.
761765
TextInputConfiguration get textInputConfiguration;
762766

763767
/// Requests this [AutofillClient] update its [TextEditingValue] to the given
@@ -769,7 +773,7 @@ abstract class AutofillClient {
769773
///
770774
/// {@template flutter.services.AutofillScope}
771775
/// [AutofillClient]s within the same [AutofillScope] are isolated from other
772-
/// input fields during autofill. That is, when an autofillable [TextInputClient]
776+
/// input fields during autofill. That is, when an autofill-enabled input field
773777
/// gains focus, only the [AutofillClient]s within the same [AutofillScope] will
774778
/// be visible to the autofill service, in the same order as they appear in
775779
/// [AutofillScope.autofillClients].
@@ -779,8 +783,8 @@ abstract class AutofillClient {
779783
/// [AutofillScope.getAutofillClient].
780784
///
781785
/// An [AutofillClient] that's not tied to any [AutofillScope] will only
782-
/// participate in autofill if the autofill is directly triggered by its own
783-
/// [TextInputClient].
786+
/// participate in autofill if the autofill is directly triggered by the input
787+
/// field it represents.
784788
/// {@endtemplate}
785789
abstract class AutofillScope {
786790
/// Gets the [AutofillClient] associated with the given [autofillId], in
@@ -803,39 +807,111 @@ abstract class AutofillScope {
803807
/// [TextInputClient] wishes to participate in autofill.
804808
TextInputConnection attach(TextInputClient trigger, TextInputConfiguration configuration);
805809

810+
/// Creates a new [TextInputConfiguration] by adding autofill information to
811+
/// the supplied [TextInputConfiguration].
812+
///
813+
/// This method is typically called when the user triggers autofill in a
814+
/// Flutter text field. It helps the platform autofill service collect the
815+
/// autofill information on related text fields, to better understand the
816+
/// expected content type of these text fields.
806817
TextInputConfiguration createAutofillConfiguration(TextInputConfiguration configuration);
807818
}
808819

809820
@immutable
810-
class _AutofillScopeTextInputConfiguration extends TextInputConfiguration {
811-
_AutofillScopeTextInputConfiguration({
821+
class _AutofillScopeTextInputConfiguration implements TextInputConfiguration {
822+
const _AutofillScopeTextInputConfiguration({
812823
required this.allConfigurations,
813-
required TextInputConfiguration currentClientConfiguration,
824+
required this.currentClientConfiguration,
814825
}) : assert(allConfigurations != null),
815-
assert(currentClientConfiguration != null),
816-
super(inputType: currentClientConfiguration.inputType,
817-
obscureText: currentClientConfiguration.obscureText,
818-
autocorrect: currentClientConfiguration.autocorrect,
819-
smartDashesType: currentClientConfiguration.smartDashesType,
820-
smartQuotesType: currentClientConfiguration.smartQuotesType,
821-
enableSuggestions: currentClientConfiguration.enableSuggestions,
822-
inputAction: currentClientConfiguration.inputAction,
823-
textCapitalization: currentClientConfiguration.textCapitalization,
824-
keyboardAppearance: currentClientConfiguration.keyboardAppearance,
825-
actionLabel: currentClientConfiguration.actionLabel,
826-
autofillConfiguration: currentClientConfiguration.autofillConfiguration,
827-
);
826+
assert(currentClientConfiguration != null);
828827

828+
final TextInputConfiguration currentClientConfiguration;
829829
final Iterable<TextInputConfiguration> allConfigurations;
830830

831+
@override
832+
String? get actionLabel => currentClientConfiguration.actionLabel;
833+
@override
834+
bool get autocorrect => currentClientConfiguration.autocorrect;
835+
@override
836+
AutofillConfiguration get autofillConfiguration => currentClientConfiguration.autofillConfiguration;
837+
@override
838+
bool get enableDeltaModel => currentClientConfiguration.enableDeltaModel;
839+
840+
@override
841+
bool get enableIMEPersonalizedLearning => currentClientConfiguration.enableIMEPersonalizedLearning;
842+
843+
@override
844+
bool get enableSuggestions => currentClientConfiguration.enableSuggestions;
845+
846+
@override
847+
TextInputAction get inputAction => currentClientConfiguration.inputAction;
848+
849+
@override
850+
TextInputType get inputType => currentClientConfiguration.inputType;
851+
852+
@override
853+
Brightness get keyboardAppearance => currentClientConfiguration.keyboardAppearance;
854+
855+
@override
856+
bool get obscureText => currentClientConfiguration.obscureText;
857+
858+
@override
859+
bool get readOnly => currentClientConfiguration.readOnly;
860+
861+
@override
862+
SmartDashesType get smartDashesType => currentClientConfiguration.smartDashesType;
863+
864+
@override
865+
SmartQuotesType get smartQuotesType => currentClientConfiguration.smartQuotesType;
866+
867+
@override
868+
TextCapitalization get textCapitalization => currentClientConfiguration.textCapitalization;
869+
831870
@override
832871
Map<String, dynamic> toJson() {
833-
final Map<String, dynamic> result = super.toJson();
872+
final Map<String, dynamic> result = currentClientConfiguration.toJson();
834873
result['fields'] = allConfigurations
835874
.map((TextInputConfiguration configuration) => configuration.toJson())
836875
.toList(growable: false);
837876
return result;
838877
}
878+
879+
@override
880+
TextInputConfiguration copyWith({
881+
TextInputType? inputType,
882+
bool? readOnly,
883+
bool? obscureText,
884+
bool? autocorrect,
885+
SmartDashesType? smartDashesType,
886+
SmartQuotesType? smartQuotesType,
887+
bool? enableSuggestions,
888+
String? actionLabel,
889+
TextInputAction? inputAction,
890+
Brightness? keyboardAppearance,
891+
TextCapitalization? textCapitalization,
892+
bool? enableIMEPersonalizedLearning,
893+
AutofillConfiguration? autofillConfiguration,
894+
bool? enableDeltaModel,
895+
}) {
896+
return _AutofillScopeTextInputConfiguration(
897+
allConfigurations: allConfigurations,
898+
currentClientConfiguration: currentClientConfiguration.copyWith(
899+
inputType: inputType,
900+
readOnly: readOnly,
901+
obscureText: obscureText,
902+
autocorrect: autocorrect,
903+
smartDashesType: smartDashesType,
904+
smartQuotesType: smartQuotesType,
905+
enableSuggestions: enableSuggestions,
906+
inputAction: inputAction,
907+
textCapitalization: textCapitalization,
908+
keyboardAppearance: keyboardAppearance,
909+
enableIMEPersonalizedLearning: enableIMEPersonalizedLearning,
910+
autofillConfiguration: autofillConfiguration,
911+
enableDeltaModel: enableDeltaModel,
912+
),
913+
);
914+
}
839915
}
840916

841917
/// A partial implementation of [AutofillScope].

packages/flutter/lib/src/services/text_editing_intents.dart

Lines changed: 102 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,11 @@ import 'package:flutter/services.dart';
77

88
import 'intents.dart';
99

10-
/// An [Intent] to send the inpput event straight to the engine.
10+
/// An [Intent] to send the input event straight to the engine.
1111
///
12-
/// Text input widgets should typically use this [Intent] instead of
13-
/// [DoNothingIntent], to indicate the text-input-related event that triggered
14-
/// the [Intent] should be handled by the engine instead of the Flutter
15-
/// framework.
12+
/// This [Intent] is currently used by [DefaultTextEditingShortcuts] to indicate
13+
/// the key events that was bound to a particular shortcut should be handled
14+
/// by the platform's text input system, instead of the Flutter framework.
1615
///
1716
/// See also:
1817
///
@@ -22,16 +21,18 @@ class DoNothingAndStopPropagationTextIntent extends Intent {
2221
const DoNothingAndStopPropagationTextIntent();
2322
}
2423

25-
/// An [Intent] that represent a command that isn't recognized by the Flutter
26-
/// framework.
24+
/// An [Intent] representing an unrecognized text input command sent by the
25+
/// platform's text input plugin.
2726
///
2827
/// {@template flutter.services.textEditingIntents.privateCommands}
29-
/// Some input method editors may define "private" commands to implement
28+
/// Some input method editors (IMEs) may define "private" commands to implement
3029
/// domain-specific features that are only known between certain input methods
3130
/// and their clients.
3231
///
33-
/// For instance, on Android there is `InputConnection.performPrivateCommand`,
34-
/// and on macOS there is `-[NSTextInputClient doCommandBySelector:]`.
32+
/// For instance, on Android, the IME can send app-private commands via
33+
/// [`InputConnection.performPrivateCommand`](https://developer.android.com/reference/android/view/inputmethod/InputConnection#performPrivateCommand(java.lang.String,%20android.os.Bundle)),
34+
/// and on macOS input fields receives "dynamic" commands in the form of selectors:
35+
/// [`-[NSTextInputClient doCommandBySelector:]`](https://developer.apple.com/documentation/appkit/nstextinputclient/1438256-docommand).
3536
/// {@endtemplate}
3637
class PerformPrivateTextInputCommandIntent extends Intent {
3738
/// Creates a [PerformPrivateTextInputCommandIntent], using the unrecognized
@@ -268,41 +269,104 @@ class UpdateSelectionIntent extends Intent {
268269
final SelectionChangedCause cause;
269270
}
270271

272+
/// An [Intent] that represents an autofill attempt made by the system's
273+
/// autofill service.
274+
///
275+
/// On platforms where autofill is not distinguishable from regular user input,
276+
/// autofill may be interpreted as a [UpdateTextEditingValueIntent] instead
277+
/// of a [PerformAutofillIntent].
271278
class PerformAutofillIntent extends Intent {
279+
/// Creates a [PerformAutofillIntent].
272280
const PerformAutofillIntent(this.autofillValue);
273281

282+
/// The [TextEditingValue]s to be autofilled.
283+
///
284+
/// The map is keyed by [AutofillClient.autofillId] which is the unique
285+
/// identifier of an autofill-enabled text input field.
274286
final Map<String, TextEditingValue> autofillValue;
275287
}
276288

289+
/// An [Intent] that represents a [TextInputAction].
277290
class PerformIMEActionIntent extends Intent {
291+
/// Creates a [PerformIMEActionIntent].
278292
const PerformIMEActionIntent(this.textInputAction);
279293

294+
/// The [TextInputAction] to be performed.
280295
final TextInputAction textInputAction;
281296
}
282297

298+
/// An [Intent] that represents a user action that replaces the content of an
299+
/// editable text field with a different [TextEditingValue].
300+
///
301+
/// One example of such user actions is autofill, where the existing text in
302+
/// the text field gets erased and replaced with the autofilled value. For
303+
/// granular changes made to the text field, such as text deletion and text
304+
/// insertion, use [UpdateTextEditingValueWtihDeltasIntent] if possible.
305+
///
306+
/// See also:
307+
///
308+
/// * [UpdateTextEditingValueWtihDeltasIntent], which makes partial updates
309+
/// to the content of an editable text field.
283310
class UpdateTextEditingValueIntent extends Intent {
284-
UpdateTextEditingValueIntent(this.newValue, {
311+
/// Creates a [UpdateTextEditingValueIntent].
312+
const UpdateTextEditingValueIntent(this.newValue, {
285313
this.cause = SelectionChangedCause.keyboard,
286314
});
287315

316+
/// The new [TextEditingValue] of the target text field.
288317
final TextEditingValue newValue;
318+
319+
/// {@macro flutter.widgets.TextEditingIntents.cause}
289320
final SelectionChangedCause cause;
290321
}
291322

323+
/// An [Intent] that represents a user action, a sequence of user actions that
324+
/// cause granular changes to be made to the current [TextEditingValue] of an
325+
/// editable text field.
326+
///
327+
/// This [Intent] should typically be used over [UpdateTextEditingValueIntent]
328+
/// if the user action does not completely replaces the contexts of the text
329+
/// field in one go, such as inserting text at the caret location.
330+
///
331+
/// See also:
332+
/// * [UpdateTextEditingValueIntent] which represents a single action that
333+
/// replaces the entire text field with a new [TextEditingValue].
292334
class UpdateTextEditingValueWtihDeltasIntent extends Intent {
293-
UpdateTextEditingValueWtihDeltasIntent(this. deltas, {
335+
/// Creates an [UpdateTextEditingValueWtihDeltasIntent].
336+
const UpdateTextEditingValueWtihDeltasIntent(this. deltas, {
294337
this.cause = SelectionChangedCause.keyboard
295338
});
296339

340+
/// The [TextEditingDelta] sequence that represents the user initiated text
341+
/// changes.
297342
final Iterable<TextEditingDelta> deltas;
343+
344+
/// {@macro flutter.widgets.TextEditingIntents.cause}
298345
final SelectionChangedCause cause;
299346
}
300347

348+
/// An [Intent] that represents the state of the [TextInputConnection] has
349+
/// changed on the platform's text input plugin side.
301350
class TextInputConnectionControlIntent extends Intent {
302351
const TextInputConnectionControlIntent._(this._controlCode);
303352
final int _controlCode;
304353

354+
/// The platform's text input plugin has closed the current
355+
/// [TextInputConnection].
356+
///
357+
/// The input field that initiated the [TextInputConnection] should properly
358+
/// close the connection and finalize editing upon receiving this [Intent].
305359
static const TextInputConnectionControlIntent close = TextInputConnectionControlIntent._(0);
360+
361+
/// The platform's text input plugin has requested a reconnect for the current
362+
/// [TextInputConnection].
363+
///
364+
/// The platform's text input plugin sends this command when it loses its
365+
/// state (for example when it had to restart). The input field should
366+
/// typically call [TextInput.attachConnection] using the existing
367+
/// [TextInputConnection] object, then call
368+
/// [TextInputConnection.setEditingState] to send the current
369+
/// [TextEditingValue] of the connected text field to the platform.
306370
static const TextInputConnectionControlIntent reconnect = TextInputConnectionControlIntent._(1);
307371

308372
@override
@@ -315,13 +379,37 @@ class TextInputConnectionControlIntent extends Intent {
315379
}
316380
}
317381

382+
/// An [Intent] triggered by user actions that initiate, update or end an iOS
383+
/// floating cursor session.
384+
///
385+
/// When the user performs a two-finger pan gesture to pick up the cursor, UIKit
386+
/// initiates a floating cursor session that allows the user to move the cursor
387+
/// freely using the pan gesture.
388+
///
389+
/// This [Intent] will be sent to the text field whenever the state of the
390+
/// floating cursor changes. Text field implementers should provide visual
391+
/// feedback in response to these changes, should they choose to support
392+
/// floating cursor on iOS.
318393
class UpdateFloatingCursorIntent extends Intent {
394+
/// Creates a [UpdateFloatingCursorIntent].
319395
const UpdateFloatingCursorIntent(this.floatingCursorPoint);
396+
397+
/// The state of the current floating cursor session reported by the iOS text
398+
/// input control.
320399
final RawFloatingCursorPoint floatingCursorPoint;
321400
}
322401

323-
class HighlightAutocorrectTextRangeIntent extends Intent {
324-
const HighlightAutocorrectTextRangeIntent(this.highlightRange);
402+
/// An [Intent] triggers when iOS detects misspelled words or text replacement
403+
/// candidates in recently typed text.
404+
///
405+
/// See also:
406+
///
407+
/// * [iOS text replacement and autocorrect](https://support.apple.com/en-us/HT207525).
408+
class HighlightiOSReplacementRangeIntent extends Intent {
409+
/// Creates a [HighlightiOSReplacementRangeIntent].
410+
const HighlightiOSReplacementRangeIntent(this.highlightRange);
325411

412+
/// The range of the text in the text field needs to be highlighted to
413+
/// indicate of the range of autocorrect.
326414
final TextRange highlightRange;
327415
}

0 commit comments

Comments
 (0)