rename back to current names
This commit is contained in:
242
src/keepass2android-app/services/AutofillBase/AutofillHelper.cs
Normal file
242
src/keepass2android-app/services/AutofillBase/AutofillHelper.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Service.Autofill;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using Android.Views.Autofill;
|
||||
using Android.Widget;
|
||||
using Android.Widget.Inline;
|
||||
using AndroidX.AutoFill.Inline;
|
||||
using AndroidX.AutoFill.Inline.V1;
|
||||
using keepass2android;
|
||||
using Kp2aAutofillParser;
|
||||
|
||||
namespace keepass2android.services.AutofillBase
|
||||
{
|
||||
/// <summary>
|
||||
/// This is a class containing helper methods for building Autofill Datasets and Responses.
|
||||
/// </summary>
|
||||
public class AutofillHelper
|
||||
{
|
||||
|
||||
public static InlinePresentation BuildInlinePresentation(InlinePresentationSpec inlinePresentationSpec,
|
||||
string text, string subtext, int iconId, PendingIntent pendingIntent, Context context)
|
||||
{
|
||||
if ((int)Build.VERSION.SdkInt < 30 || inlinePresentationSpec == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
//make sure we have a pendingIntent always not null
|
||||
pendingIntent ??= PendingIntent.GetService(context, 0, new Intent(),
|
||||
Util.AddMutabilityFlag(PendingIntentFlags.OneShot | PendingIntentFlags.UpdateCurrent, PendingIntentFlags.Mutable));
|
||||
|
||||
var slice = CreateInlinePresentationSlice(
|
||||
inlinePresentationSpec,
|
||||
text,
|
||||
subtext,
|
||||
iconId,
|
||||
"Autofill option",
|
||||
pendingIntent,
|
||||
context);
|
||||
if (slice != null)
|
||||
{
|
||||
return new InlinePresentation(slice, inlinePresentationSpec, false);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static Android.App.Slices.Slice CreateInlinePresentationSlice(
|
||||
InlinePresentationSpec inlinePresentationSpec,
|
||||
string text,
|
||||
string subtext,
|
||||
int iconId,
|
||||
string contentDescription,
|
||||
PendingIntent pendingIntent,
|
||||
Context context)
|
||||
{
|
||||
var imeStyle = inlinePresentationSpec.Style;
|
||||
|
||||
if (!UiVersions.GetVersions(imeStyle).Contains(UiVersions.InlineUiVersion1))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var contentBuilder = InlineSuggestionUi.NewContentBuilder(pendingIntent)
|
||||
.SetContentDescription(contentDescription);
|
||||
if (!string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
contentBuilder.SetTitle(text);
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(subtext))
|
||||
{
|
||||
contentBuilder.SetSubtitle(subtext);
|
||||
}
|
||||
if (iconId > 0)
|
||||
{
|
||||
var icon = Android.Graphics.Drawables.Icon.CreateWithResource(context, iconId);
|
||||
if (icon != null)
|
||||
{
|
||||
if (iconId == AppNames.LauncherIcon)
|
||||
{
|
||||
// Don't tint our logo
|
||||
icon.SetTintBlendMode(Android.Graphics.BlendMode.Dst);
|
||||
}
|
||||
contentBuilder.SetStartIcon(icon);
|
||||
}
|
||||
}
|
||||
return contentBuilder.Build().JavaCast<InlineSuggestionUi.Content>()?.Slice;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wraps autofill data in a LoginCredential Dataset object which can then be sent back to the
|
||||
/// client View.
|
||||
/// </summary>
|
||||
public static Dataset NewDataset(Context context,
|
||||
AutofillFieldMetadataCollection autofillFields,
|
||||
FilledAutofillFieldCollection<ViewNodeInputField> filledAutofillFieldCollection,
|
||||
IAutofillIntentBuilder intentBuilder,
|
||||
Android.Widget.Inline.InlinePresentationSpec inlinePresentationSpec)
|
||||
{
|
||||
var datasetName = filledAutofillFieldCollection.DatasetName ?? "[noname]";
|
||||
|
||||
var datasetBuilder = new Dataset.Builder(NewRemoteViews(context.PackageName, datasetName, intentBuilder.AppIconResource));
|
||||
datasetBuilder.SetId(datasetName);
|
||||
|
||||
var setValueAtLeastOnce = ApplyToFields(filledAutofillFieldCollection, autofillFields, datasetBuilder);
|
||||
AddInlinePresentation(context, inlinePresentationSpec, datasetName, datasetBuilder, intentBuilder.AppIconResource, null);
|
||||
|
||||
if (setValueAtLeastOnce)
|
||||
{
|
||||
return datasetBuilder.Build();
|
||||
}
|
||||
/*else
|
||||
{
|
||||
Kp2aLog.Log("Failed to set at least one value. #fields=" + autofillFields.GetAutofillIds().Length + " " + autofillFields.FocusedAutofillCanonicalHints);
|
||||
}*/
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates a Dataset.Builder with appropriate values for each AutofillId
|
||||
/// in a AutofillFieldMetadataCollection.
|
||||
///
|
||||
/// In other words, it constructs an autofill Dataset.Builder
|
||||
/// by applying saved values (from this FilledAutofillFieldCollection)
|
||||
/// to Views specified in a AutofillFieldMetadataCollection, which represents the current
|
||||
/// page the user is on.
|
||||
/// </summary>
|
||||
/// <returns><c>true</c>, if to fields was applyed, <c>false</c> otherwise.</returns>
|
||||
/// <param name="filledAutofillFieldCollection"></param>
|
||||
/// <param name="autofillFieldMetadataCollection">Autofill field metadata collection.</param>
|
||||
/// <param name="datasetBuilder">Dataset builder.</param>
|
||||
public static bool ApplyToFields(FilledAutofillFieldCollection<ViewNodeInputField> filledAutofillFieldCollection,
|
||||
AutofillFieldMetadataCollection autofillFieldMetadataCollection, Dataset.Builder datasetBuilder)
|
||||
{
|
||||
bool setValueAtLeastOnce = false;
|
||||
|
||||
foreach (string hint in autofillFieldMetadataCollection.AllAutofillCanonicalHints)
|
||||
{
|
||||
foreach (AutofillFieldMetadata autofillFieldMetadata in autofillFieldMetadataCollection.GetFieldsForHint(hint))
|
||||
{
|
||||
FilledAutofillField filledAutofillField;
|
||||
if (!filledAutofillFieldCollection.HintMap.TryGetValue(hint, out filledAutofillField) || (filledAutofillField == null))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var autofillId = autofillFieldMetadata.AutofillId;
|
||||
var autofillType = autofillFieldMetadata.AutofillType;
|
||||
switch (autofillType)
|
||||
{
|
||||
case AutofillType.List:
|
||||
var listValue = autofillFieldMetadata.GetAutofillOptionIndex(filledAutofillField.TextValue);
|
||||
if (listValue != -1)
|
||||
{
|
||||
datasetBuilder.SetValue(autofillId, AutofillValue.ForList(listValue));
|
||||
setValueAtLeastOnce = true;
|
||||
}
|
||||
break;
|
||||
case AutofillType.Date:
|
||||
var dateValue = filledAutofillField.DateValue;
|
||||
datasetBuilder.SetValue(autofillId, AutofillValue.ForDate((long)dateValue));
|
||||
setValueAtLeastOnce = true;
|
||||
break;
|
||||
case AutofillType.Text:
|
||||
var textValue = filledAutofillField.TextValue;
|
||||
if (textValue != null)
|
||||
{
|
||||
datasetBuilder.SetValue(autofillId, AutofillValue.ForText(textValue));
|
||||
setValueAtLeastOnce = true;
|
||||
}
|
||||
break;
|
||||
case AutofillType.Toggle:
|
||||
var toggleValue = filledAutofillField.ToggleValue;
|
||||
if (toggleValue != null)
|
||||
{
|
||||
datasetBuilder.SetValue(autofillId, AutofillValue.ForToggle(toggleValue.Value));
|
||||
setValueAtLeastOnce = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.Warn(CommonUtil.Tag, "Invalid autofill type - " + autofillType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
if (!setValueAtLeastOnce)
|
||||
{
|
||||
Kp2aLog.Log("No value set. Hint keys : " + string.Join(",", HintMap.Keys));
|
||||
foreach (string hint in autofillFieldMetadataCollection.AllAutofillCanonicalHints)
|
||||
{
|
||||
Kp2aLog.Log("No value set. Hint = " + hint);
|
||||
foreach (AutofillFieldMetadata autofillFieldMetadata in autofillFieldMetadataCollection
|
||||
.GetFieldsForHint(hint))
|
||||
{
|
||||
Kp2aLog.Log("No value set. fieldForHint = " + autofillFieldMetadata.AutofillId.ToString());
|
||||
FilledAutofillField filledAutofillField;
|
||||
if (!HintMap.TryGetValue(hint, out filledAutofillField) || (filledAutofillField == null))
|
||||
{
|
||||
Kp2aLog.Log("No value set. Hint map does not contain value, " +
|
||||
(filledAutofillField == null));
|
||||
continue;
|
||||
}
|
||||
|
||||
Kp2aLog.Log("autofill type=" + autofillFieldMetadata.AutofillType);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
return setValueAtLeastOnce;
|
||||
}
|
||||
|
||||
public static void AddInlinePresentation(Context context, InlinePresentationSpec inlinePresentationSpec,
|
||||
string datasetName, Dataset.Builder datasetBuilder, int iconId, PendingIntent pendingIntent)
|
||||
{
|
||||
if (inlinePresentationSpec != null)
|
||||
{
|
||||
var inlinePresentation = BuildInlinePresentation(inlinePresentationSpec, datasetName, "", iconId, pendingIntent, context);
|
||||
if (inlinePresentation != null)
|
||||
datasetBuilder.SetInlinePresentation(inlinePresentation);
|
||||
}
|
||||
}
|
||||
|
||||
public static RemoteViews NewRemoteViews(string packageName, string remoteViewsText,int drawableId)
|
||||
{
|
||||
RemoteViews presentation = new RemoteViews(packageName, Resource.Layout.autofill_service_list_item);
|
||||
presentation.SetTextViewText(Resource.Id.text, remoteViewsText);
|
||||
presentation.SetImageViewResource(Resource.Id.icon, drawableId);
|
||||
return presentation;
|
||||
}
|
||||
|
||||
internal static InlinePresentationSpec ExtractSpec(IList<InlinePresentationSpec> inlinePresentationSpecs, int index)
|
||||
{
|
||||
return inlinePresentationSpecs == null ? null : inlinePresentationSpecs[Math.Min(index, inlinePresentationSpecs.Count - 1)];
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user