Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Added autofill functionality #16227

Closed
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ public static Configuration fromJson(@NonNull JSONObject json) throws JSONExcept
TextCapitalization.fromValue(json.getString("textCapitalization")),
InputType.fromJson(json.getJSONObject("inputType")),
inputAction,
json.isNull("actionLabel") ? null : json.getString("actionLabel")
json.isNull("actionLabel") ? null : json.getString("actionLabel"),
json.isNull("textContentType") ? null : TextContentType.fromValue(json.getString("textContentType"))
);
}

Expand Down Expand Up @@ -328,6 +329,8 @@ private static Integer inputActionFromTextInputAction(@NonNull String inputActio
public final Integer inputAction;
@Nullable
public final String actionLabel;
@Nullable
public final TextContentType textContentType;

public Configuration(
boolean obscureText,
Expand All @@ -336,7 +339,8 @@ public Configuration(
@NonNull TextCapitalization textCapitalization,
@NonNull InputType inputType,
@Nullable Integer inputAction,
@Nullable String actionLabel
@Nullable String actionLabel,
@Nullable TextContentType textContentType
) {
this.obscureText = obscureText;
this.autocorrect = autocorrect;
Expand All @@ -345,6 +349,7 @@ public Configuration(
this.inputType = inputType;
this.inputAction = inputAction;
this.actionLabel = actionLabel;
this.textContentType = textContentType;
}
}

Expand Down Expand Up @@ -406,6 +411,95 @@ static TextInputType fromValue(@NonNull String encodedName) throws NoSuchFieldEx
}
}

/**
* Types of text content for auto-full functionality
ganttastic marked this conversation as resolved.
Show resolved Hide resolved
*/
public enum TextContentType {
NAME("TextContentType.name"),
NAME_PREFIX("TextContentType.namePrefix"),
GIVEN_NAME("TextContentType.givenName"),
MIDDLE_NAME("TextContentType.middleName"),
FAMILY_NAME("TextContentType.familyName"),
NAME_SUFFIX("TextContentType.nameSuffix"),
FULL_STREET_ADDRESS("TextContentType.fullStreetAddress"),
ADDRESS_LINE_1("TextContentType.addressLine1"),
ADDRESS_LINE_2("TextContentType.addressLine2"),
ADDRESS_CITY("TextContentType.addressCity"),
ADDRESS_STATE("TextContentType.addressState"),
COUNTRY_NAME("TextContentType.countryName"),
POSTAL_CODE("TextContentType.postalCode"),
TELEPHONE_NUMBER("TextContentType.telephoneNumber"),
EMAIL_ADDRESS("TextContentType.emailAddress"),
CREDIT_CARD_NUMBER("TextContentType.creditCardNumber"),
USERNAME("TextContentType.username"),
PASSWORD("TextContentType.password"),
NEW_PASSWORD("TextContentType.newPassword"),
ONE_TIME_CODE("TextContentType.oneTimeCode");

static TextContentType fromValue(@NonNull String encodedName) throws NoSuchFieldException {
for (TextContentType textContentType : TextContentType.values()) {
if (textContentType.encodedName.equals(encodedName)) {
return textContentType;
}
}
throw new NoSuchFieldException("No such TextContentType: " + encodedName);
}

@NonNull
private final String encodedName;

TextContentType(@NonNull String encodedName) {
this.encodedName = encodedName;
}

public String hintConstantValue() {
switch (this) {
case NAME:
return "personName";
case NAME_PREFIX:
return "personNamePrefix";
case GIVEN_NAME:
return "personGivenName";
case MIDDLE_NAME:
return "personMiddleName";
case FAMILY_NAME:
return "personFamilyName";
case NAME_SUFFIX:
return "personNameSuffix";
case FULL_STREET_ADDRESS:
return "postalAddress";
case ADDRESS_LINE_1:
return "streetAddress";
case ADDRESS_LINE_2:
return "extendedAddress";
case ADDRESS_CITY:
return "addressLocality";
case ADDRESS_STATE:
return "addressRegion";
case COUNTRY_NAME:
return "addressCountry";
case POSTAL_CODE:
return "postalCode";
case TELEPHONE_NUMBER:
return "phoneNumber";
case EMAIL_ADDRESS:
return "emailAddress";
case CREDIT_CARD_NUMBER:
return "creditCardNumber";
case USERNAME:
return "username";
case PASSWORD:
return "password";
case NEW_PASSWORD:
return "newPassword";
case ONE_TIME_CODE:
return "smsOTPCode";
}

return null;
}
}

/**
* Text capitalization schemes.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,12 @@ public InputConnection createInputConnection(View view, EditorInfo outAttrs) {
outAttrs.actionId = enterAction;
}
outAttrs.imeOptions |= enterAction;

String autofillHintValue = configuration.textContentType.hintConstantValue();
if (autofillHintValue != null) {
String[] autofillHints = {autofillHintValue};
view.setAutofillHints(autofillHints);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure if this is the correct view to set the auto fill hints on.

}

InputConnectionAdaptor connection = new InputConnectionAdaptor(
view,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,75 @@ static UITextAutocapitalizationType ToUITextAutoCapitalizationType(NSDictionary*
return UITextAutocapitalizationTypeNone;
}

static UITextContentType ToUITextContentType(NSDictionary* type) API_AVAILABLE(ios(10.0)) {
NSString* contentType = type[@"textContentType"];

if ([contentType isEqualToString:@"TextContentType.name"])
return UITextContentTypeName;
if ([contentType isEqualToString:@"TextContentType.namePrefix"])
return UITextContentTypeNamePrefix;
if ([contentType isEqualToString:@"TextContentType.givenName"])
return UITextContentTypeGivenName;
if ([contentType isEqualToString:@"TextContentType.middleName"])
return UITextContentTypeMiddleName;
if ([contentType isEqualToString:@"TextContentType.familyName"])
return UITextContentTypeFamilyName;
if ([contentType isEqualToString:@"TextContentType.nameSuffix"])
return UITextContentTypeNameSuffix;
if ([contentType isEqualToString:@"TextContentType.fullStreetAddress"])
return UITextContentTypeFullStreetAddress;
if ([contentType isEqualToString:@"TextContentType.addressLine1"])
return UITextContentTypeStreetAddressLine1;
if ([contentType isEqualToString:@"TextContentType.addressLine2"])
return UITextContentTypeStreetAddressLine2;
if ([contentType isEqualToString:@"TextContentType.addressCity"])
return UITextContentTypeAddressCity;
if ([contentType isEqualToString:@"TextContentType.addressState"])
return UITextContentTypeAddressState;
if ([contentType isEqualToString:@"TextContentType.countryName"])
return UITextContentTypeCountryName;
if ([contentType isEqualToString:@"TextContentType.postalCode"])
return UITextContentTypePostalCode;
if ([contentType isEqualToString:@"TextContentType.telephoneNumber"])
return UITextContentTypeTelephoneNumber;
if ([contentType isEqualToString:@"TextContentType.emailAddress"])
return UITextContentTypeEmailAddress;
if ([contentType isEqualToString:@"TextContentType.url"])
return UITextContentTypeURL;
if ([contentType isEqualToString:@"TextContentType.creditCardNumber"])
return UITextContentTypeCreditCardNumber;
if ([contentType isEqualToString:@"TextContentType.username"]) {
if (@available(iOS 11.0, *)) {
return UITextContentTypeUsername;
} else {
return nil;
}
}
if ([contentType isEqualToString:@"TextContentType.password"]) {
if (@available(iOS 11.0, *)) {
return UITextContentTypePassword;
} else {
return nil;
}
}
if ([contentType isEqualToString:@"TextContentType.newPassword"]) {
if (@available(iOS 12.0, *)) {
return UITextContentTypeNewPassword;
} else {
return nil;
}
}
if ([contentType isEqualToString:@"TextContentType.oneTimeCode"]) {
if (@available(iOS 12.0, *)) {
return UITextContentTypeOneTimeCode;
} else {
return nil;
}
}

return nil;
}

static UIReturnKeyType ToUIReturnKeyType(NSString* inputType) {
// Where did the term "unspecified" come from? iOS has a "default" and Android
// has "unspecified." These 2 terms seem to mean the same thing but we need
Expand Down Expand Up @@ -154,6 +223,7 @@ @interface FlutterTextInputView : UIView <UITextInput>
@property(nonatomic) UITextAutocapitalizationType autocapitalizationType;
@property(nonatomic) UITextAutocorrectionType autocorrectionType;
@property(nonatomic) UITextSpellCheckingType spellCheckingType;
@property(nonatomic, copy) UITextContentType textContentType API_AVAILABLE(ios(10.0));
@property(nonatomic) BOOL enablesReturnKeyAutomatically;
@property(nonatomic) UIKeyboardAppearance keyboardAppearance;
@property(nonatomic) UIKeyboardType keyboardType;
Expand Down Expand Up @@ -195,6 +265,7 @@ - (instancetype)init {
_keyboardType = UIKeyboardTypeDefault;
_returnKeyType = UIReturnKeyDone;
_secureTextEntry = NO;
_textContentType = nil;
if (@available(iOS 11.0, *)) {
_smartQuotesType = UITextSmartQuotesTypeYes;
_smartDashesType = UITextSmartDashesTypeYes;
Expand Down Expand Up @@ -793,6 +864,9 @@ - (void)setTextInputClient:(int)client withConfiguration:(NSDictionary*)configur
_activeView.autocorrectionType = autocorrect && ![autocorrect boolValue]
? UITextAutocorrectionTypeNo
: UITextAutocorrectionTypeDefault;
if (@available(iOS 10.0, *)) {
_activeView.textContentType = ToUITextContentType(configuration);
}
[_activeView setTextInputClient:client];
[_activeView reloadInputViews];
}
Expand Down