Skip to content

Conversation

@justinmc
Copy link
Contributor

@justinmc justinmc commented Nov 14, 2019

Description

Flutter does not allow configuration of UITextSmartQuotesType and UITextSmartDashesType. This is a problem because it can result in weird punctuation characters being entered into password fields, among other things.

This PR will expose two new boolean parameters on all text fields: enableSmartQuotes and enableSmartDashes. These will cause their corresponding type to be set in iOS, and in Android they will be ignored.

They will both default to true, except on obscured text fields, where they will default to false.

Related Issues

Closes #26684.
Depends on engine PR flutter/engine#13863.

Tests

I test that the engine receives these parameters properly and that they default to the correct value in EditableText.

@justinmc justinmc added a: text input Entering text in a text field or keyboard related problems platform-ios iOS applications specifically framework flutter/packages/flutter repository. See also f: labels. work in progress; do not review labels Nov 14, 2019
@justinmc justinmc self-assigned this Nov 14, 2019
@fluttergithubbot fluttergithubbot added the f: material design flutter/packages/flutter/material repository. label Nov 14, 2019
@fluttergithubbot
Copy link
Contributor

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@justinmc justinmc changed the title WIP iOS smart quote/dash configuration iOS smart quote/dash configuration Nov 15, 2019
@fluttergithubbot fluttergithubbot added the f: cupertino flutter/packages/flutter/cupertino repository label Nov 15, 2019
final bool autocorrect;

/// {@template flutter.services.textInput.enableSmartDashes}
/// Whether to allow the platform to automatically format dashes.
Copy link
Contributor

Choose a reason for hiding this comment

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

It may be useful to explicitly explain what this is doing other than this very short. How is it being formatted?

/// {@template flutter.services.textInput.enableSmartDashes}
/// Whether to allow the platform to automatically format dashes.
///
/// This flag only affects iOS. It sets UITextSmartDashesType in the engine.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not clear on what we generally do in cases where API is platform specific. I feel like additions like this lead to confusing API, where many properties may end up being useless when a developer is using it.

You should double check on the policy here. Preferably, we can do something less iOS specific, but IDK If that is possible here.

Copy link
Contributor

Choose a reason for hiding this comment

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

@Hixie Thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

If it's even remotely reasonable to come up with a way to make it platform-agnostic (bearing in mind that over time we're going to support many platforms beyond iOS and Android), then we should attempt to make the code platform-agnostic, even if it only currently works on one platform.

If something really is just platform-specific, then that's fine.

/// Whether to allow the platform to automatically format dashes.
///
/// This flag only affects iOS. It sets UITextSmartDashesType in the engine.
/// When true, it passes UITextSmartDashesTypeYes, and when false, it passes
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be worth documenting the iOS SDK version constraint on both flags.

/// * [enableSmartQuotes]
/// * <https://developer.apple.com/documentation/uikit/uitextinputtraits>
/// {@endtemplate}
final bool enableSmartDashes;
Copy link
Contributor

Choose a reason for hiding this comment

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

The engine implementation seems to toggle between default and no. Is there a way for users to set the trait to UITextSmartQuotesType.yes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point, there is no way right now... I was under the impression that "yes" and "default" were the same, but could that ever change, or is there any other reason to explicitly allow "yes"? https://developer.apple.com/documentation/uikit/uitextsmartdashestype?language=objc

Copy link
Contributor

Choose a reason for hiding this comment

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

There seems to be a very slight difference between yes and default, but "default" and "no" should cover most use cases:

This option selectively enables the smart dash behavior based on the keyboard type. For example, smart dashes are disabled for email address and password keyboards.

Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like having an enum rather than a bool would make this possible to extend later, even if we only support two values today.

/// character will be automatically replaced by a left or right double quote
/// depending on its position in a word.
///
/// Defaults to true, unless obscureText is true, when it defaults to false.
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:

Suggested change
/// Defaults to true, unless obscureText is true, when it defaults to false.
/// Defaults to true, unless [obscureText] is true, when it defaults to false.

///
/// This flag only affects iOS. It sets UITextSmartQuotesType in the engine.
/// When true, it passes UITextSmartQuotesTypeYes, and when false, it passes
/// UITextSmartQuotesTypeNo.
Copy link
Contributor

@LongCatIsLooong LongCatIsLooong Nov 20, 2019

Choose a reason for hiding this comment

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

nit:

 /// This flag only affects iOS. It sets [`UITextSmartQuotesType`](https://developer.apple.com/documentation/uikit/uitextsmartquotestype) in the engine.
 /// When true, it passes [`UITextSmartQuotesTypeYes`](https://developer.apple.com/documentation/uikit/uitextsmartquotestype/yes), and when false, it passes
 /// [`UITextSmartQuotesTypeNo`](https://developer.apple.com/documentation/uikit/uitextsmartquotestype/no).

I wonder if dart docs understands hyper links. Would be nice if we can link these uikit references to their api docs.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also doesn't it pass UITextSmartQuotesTypeDefault when true, according to the engine PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Linked and updated to "default" (however, see my question above about "yes" vs. "default").

properties.add(DiagnosticsProperty<bool>('autofocus', autofocus, defaultValue: false));
properties.add(DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false));
properties.add(DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: true));
properties.add(DiagnosticsProperty<bool>('enableSmartDashes', enableSmartDashes, defaultValue: true));
Copy link
Contributor

Choose a reason for hiding this comment

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

The defaultValue seems to be !obsecureText in the constructor. Is there a reason for the defaultValue to deviate from the constructor?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There is not, good catch. I'll change it to !obscureText.

/// characters.
///
/// See also:
/// * [enableSmartQuotes]
Copy link
Contributor

Choose a reason for hiding this comment

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

you need a blank line after See also:, see our style guide. Last sentence of https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#leave-breadcrumbs-in-the-comments (this matters because the rendering is broken otherwise).

@justinmc
Copy link
Contributor Author

justinmc commented Dec 5, 2019

Ready for re-review @LongCatIsLooong @GaryQian.

Now I'm using an enum instead of a bool to allow for more flexibility in the future. Some things to note:

  • The enum is passed to the engine as a string (i.e. "SmartQuotesType.enabled"). Is there a better way to do that? Using an index as suggested by Hixie.
  • UITextSmartDashesTypeDefault is no longer possible to set, since it doesn't really offer any difference from Yes for Flutter. We can change this in the future if we need to support finer grained control.
  • Any idea where I can declare the enums so that they're available to the user and to the necessary files? I just got a dependency loop error from the analyzer after trying to put them in widgets/basic.dart. Declaring inside the text input service and re-exporting elsewhere worked.

@Hixie
Copy link
Contributor

Hixie commented Dec 5, 2019

You can get the index for the enum value by doing .index on the enum value, that would let you pass an int instead of a string.

@Hixie
Copy link
Contributor

Hixie commented Dec 5, 2019

Re where to define them, define them in the lowest-level library that needs them (likely services), then reexport them from any library that exposes them (cupertino/text_field.dart, material/text_field.dart, widgets/editable_text.dart, etc).

@justinmc justinmc force-pushed the smart-quotes-dashes branch from d3dac89 to c01decc Compare December 10, 2019 17:06
properties.add(DiagnosticsProperty<bool>('autofocus', autofocus, defaultValue: false));
properties.add(DiagnosticsProperty<bool>('obscureText', obscureText, defaultValue: false));
properties.add(DiagnosticsProperty<bool>('autocorrect', autocorrect, defaultValue: true));
properties.add(DiagnosticsProperty<SmartDashesType>('smartDashesType', smartDashesType, defaultValue: obscureText ? SmartDashesType.disabled : SmartDashesType.enabled));
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: I think there's an EnumProperty class

@magicleon94
Copy link

Any idea on when this is gonna hit the stable channel?
Are there any workarounds to get it working on stable meanwhile?

@justinmc
Copy link
Contributor Author

It looks like it's in v1.16.3 and above, so it's in dev and beta now, and should be in the next stable release.

If you need this now but can't use dev or beta, you could cherry pick the merge commit c06bf65 into your local copy of Flutter. Not an official way of doing things but it should work.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 31, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

a: text input Entering text in a text field or keyboard related problems f: cupertino flutter/packages/flutter/cupertino repository f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels. platform-ios iOS applications specifically

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Obfuscated text fields should disable the IME autocorrect (iOS)

7 participants