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

[Proposal] Autofill Hints #373

Open
5 of 10 tasks
coen22 opened this issue Apr 20, 2022 · 5 comments
Open
5 of 10 tasks

[Proposal] Autofill Hints #373

coen22 opened this issue Apr 20, 2022 · 5 comments
Labels
in-progress new proposal A fully fleshed out proposal describing a new feature in syntactic and semantic detail

Comments

@coen22
Copy link

coen22 commented Apr 20, 2022

Autofill Hints

  • Proposed
  • Prototype: Not Started
  • Implementation: Xamarin Version Exists and can be ported over.
    • iOS Support
    • Android Support
    • macOS Support (currently not working, requires fix in MAUI)
    • Windows Support
  • Unit Tests: Not Started
  • Sample: Not Started
  • Documentation: Not Started

Summary

I would like to request to add autofill to MCT. Autofill is common in HTML, where the browsers remembers a user's details and fills them in. This is also possible on the OS level in Android, iOS and (I think also) macOS.

Motivation

It's nice for users to log in with a tap on their screen and it makes it easier to sign up for within an app.

Detailed Design

I've included the implementation that I have in Xamarin Forms.
The namespaces have already been renamed.

This is the API class.

using System;
using Xamarin.Forms; // should become Miscrosoft.Maui

namespace CommunityToolkit.Maui.Effects
{

    public class AutofillEffect : RoutingEffect {

        public AutofillContentType Type { get; set; }

        public AutofillEffect() : base(nameof(AutofillEffect)) {}

    }

    // TODO extend with all possibilities
    public enum AutofillContentType {
        None,
        Username,
        Password,
        NewPassword,
        Email,
        FirstName,
        Phone
    }
}

The Android class:

using System;
using System.Linq;
using Android.OS;
using Android.Views;
using Android.Widget;
using CommunityToolkit.Maui.Effects;
using CommunityToolkit.Maui.Android.Effects;
using Xamarin.Forms.Platform.Android;

[assembly: Xamarin.Forms.ResolutionGroupName("CommunityToolkit")]
[assembly: Xamarin.Forms.ExportEffect(typeof(AndroidAutofillEffect), "AutofillEffect")]

namespace CommunityToolkit.Maui.Android.Effects {

    public class AndroidAutofillEffect : PlatformEffect {

        protected override void OnAttached() {
            var effect = (AutofillEffect) Element.Effects.FirstOrDefault(e => e is AutofillEffect);
            if (effect != null
                && Build.VERSION.SdkInt >= BuildVersionCodes.O
                && Control is EditText editText) {
                switch (effect.Type) {
                    case AutofillContentType.Username:
                        editText.ImportantForAutofill = ImportantForAutofill.Yes;
                        editText.SetAutofillHints(View.AutofillHintUsername);
                        break;
                    case AutofillContentType.Password:
                        editText.ImportantForAutofill = ImportantForAutofill.Yes;
                        editText.SetAutofillHints(View.AutofillHintPassword);
                        break;
                    case AutofillContentType.Email:
                        editText.ImportantForAutofill = ImportantForAutofill.Yes;
                        editText.SetAutofillHints(View.AutofillHintEmailAddress);
                        break;
                    case AutofillContentType.FirstName:
                        editText.ImportantForAutofill = ImportantForAutofill.Yes;
                        editText.SetAutofillHints(View.AutofillHintName); // Not implemented
                        break;
                    case AutofillContentType.Phone:
                        editText.ImportantForAutofill = ImportantForAutofill.Yes;
                        editText.SetAutofillHints(View.AutofillHintPhone);
                        break;
                    default:
                        editText.ImportantForAutofill = ImportantForAutofill.Auto;
                        editText.SetAutofillHints(autofillHints: null);
                        break;
                }
            }
        }

        protected override void OnDetached() {
            if (Build.VERSION.SdkInt >= BuildVersionCodes.O
                && Control is EditText editText) {
                editText.ImportantForAutofill = ImportantForAutofill.Auto;
                editText.SetAutofillHints(autofillHints: null);
            }
        }
    }
}

The iOS (and similarly macOS) class:

using System.Linq;
using Foundation;
using UIKit;
using CommunityToolkit.Maui.Effects;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS; 

[assembly: ExportEffect(typeof(AppleAutofillEffect), "AutofillEffect")]

public class AppleAutofillEffect : PlatformEffect {

    protected override void OnAttached() {
        var effect = (AutofillEffect)Element.Effects
            .FirstOrDefault(e => e is AutofillEffect);
        if (effect != null
            && UIDevice.CurrentDevice.CheckSystemVersion(11, 0)
            && Control is UITextField textField) {
            switch (effect.Type) {
                case AutofillContentType.Username:
                    textField.TextContentType = UITextContentType.Username;
                    break;
                case AutofillContentType.Password:
                    textField.TextContentType = UITextContentType.Password;
                    break;
                case AutofillContentType.NewPassword:
                    textField.TextContentType = UITextContentType.NewPassword;
                    break;
                case AutofillContentType.Email:
                    textField.TextContentType = UITextContentType.EmailAddress;
                    break;
                case AutofillContentType.FirstName:
                    textField.TextContentType = UITextContentType.GivenName;
                    break;
                case AutofillContentType.Phone:
                    textField.TextContentType = UITextContentType.TelephoneNumber;
                    break;
                default:
                    textField.TextContentType = NSString.Empty;
                    break;
            }
        }
    }

    protected override void OnDetached() {
        if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0)
            && Control is UITextField textField) {
            textField.TextContentType = NSString.Empty;
        }
    }
}

Usage Syntax

XAML Usage

< Entry.Effects Margin="15,5" x:Name="EmailEntry"
                          Keyboard="Email" Text="{Binding Email}"
                          ReturnType="Next"
                          Placeholder="{x:Static lang:Lang.Email}">
    <Entry.Effects>
        <controls:AutofillEffect Type="Username" />
    </Entry.Effects>
</Entry.Effects >

Drawbacks

Currently the Android C# wrapper has limited support.
The View class doesn't have all strings (e.g. AUTOFILL_HINT_PERSON_NAME_GIVEN), but they can be added manually.
https://developer.android.com/guide/topics/text/autofill-optimize

Alternatives

N/A

Unresolved Questions

What is the 'correct' way of implementing this in MAUI? (now it's XF Compat)

Does Windows have something similar to Autofill?

@coen22 coen22 added new proposal A fully fleshed out proposal describing a new feature in syntactic and semantic detail labels Apr 20, 2022
@TheCodeTraveler
Copy link
Collaborator

TheCodeTraveler commented Apr 20, 2022

Thanks @coen22! This sounds like a cool new feature that would be useful for .NET MAUI devs!

There are two changes I'd like to make to this Proposal:

  • Use Behavior instead of Effect
  • Leverage .NET MAUI Interfaces

Use Behavior instead of Effect

Effects aren't recommended for .NET MAUI.

Long story short, they were a lightweight way to add functionality to Xamarin.Forms controls to avoid the overhead of creating/writing/leveraging Custom Renderers. Since Custom Renderers no longer exist in .NET MAUI, Effects are essentially obsolete.

For the .NET MAUI Community Toolkit, we are implementing the functionality of Effects from Xamarin.CommunityToolkit by adding them as Behaviors. @pictos is leading this effort and has documented more information on it in this Proposal: #124

Leveraging .NET MAUI Interfaces

I recommend leveraging the .NET MAUI interfaces to implement/enable this AutoComplete feature for all IText elements.

This will ensure that all future/new IText elements as well as all custom-made IText elements will be able to leverage this feature.

Next Steps

I recommend opening a Discussion to chat about the API Surface and implementation for this feature. This is the best way to avoid additional rework in the future for this Proposal.

@coen22
Copy link
Author

coen22 commented Apr 20, 2022

@brminnick thank you for your feedback. I'll create a discussion.

@CorentinSwiss4
Copy link

CorentinSwiss4 commented Jan 13, 2023

@coen22 can you link the discussion if you created it ?
I'm interesting to propose on my app autofill hints one time code with sms otp.
Until now i don't find any working solutions.

Thx

@coen22
Copy link
Author

coen22 commented Jan 13, 2023

@coen22 can you link the discussion if you created it ? I'm interesting to propose on my app autofill hints one time code with sms otp. Until now i don't find any working solutions.

Thx

Here you go
#374

In your XAML just add Entry.Behaviours
Although I didn’t implement SMS OTP, you can find this page as a reference on Android
https://developer.android.com/reference/androidx/autofill/HintConstants#AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE()

@danielheddelin
Copy link

I wrote a little blog post showing how you can get OTP working on iOS:
https://danielheddelin.blogspot.com/2024/06/otp-auto-fill-entry-for-ios-with-net.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in-progress new proposal A fully fleshed out proposal describing a new feature in syntactic and semantic detail
Projects
None yet
Development

No branches or pull requests

5 participants