From 9a6a7097460bd7bfd34cc345fc0958251e10340c Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Thu, 17 Dec 2020 15:16:06 +0100 Subject: [PATCH] Inline presentation when sign in --- .../keepass/autofill/AutofillHelper.kt | 64 ++++++++++--------- .../keepass/autofill/KeeAutofillService.kt | 48 +++++++++++++- 2 files changed, 79 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/autofill/AutofillHelper.kt b/app/src/main/java/com/kunzisoft/keepass/autofill/AutofillHelper.kt index 02b2d333b..b0ce3a560 100644 --- a/app/src/main/java/com/kunzisoft/keepass/autofill/AutofillHelper.kt +++ b/app/src/main/java/com/kunzisoft/keepass/autofill/AutofillHelper.kt @@ -107,41 +107,41 @@ object AutofillHelper { } } + @RequiresApi(Build.VERSION_CODES.R) @SuppressLint("RestrictedApi") - private fun buildInlinePresentation(context: Context, - inlineSuggestionsRequest: InlineSuggestionsRequest, - positionItem: Int, - entryInfo: EntryInfo): InlinePresentation? { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - val inlinePresentationSpecs = inlineSuggestionsRequest.inlinePresentationSpecs - val maxSuggestion = inlineSuggestionsRequest.maxSuggestionCount + private fun buildInlinePresentationForEntry(context: Context, + inlineSuggestionsRequest: InlineSuggestionsRequest, + positionItem: Int, + entryInfo: EntryInfo): InlinePresentation? { + val inlinePresentationSpecs = inlineSuggestionsRequest.inlinePresentationSpecs + val maxSuggestion = inlineSuggestionsRequest.maxSuggestionCount - if (positionItem <= maxSuggestion-1 - && inlinePresentationSpecs.size > positionItem) { - val inlinePresentationSpec = inlinePresentationSpecs[positionItem] + if (positionItem <= maxSuggestion-1 + && inlinePresentationSpecs.size > positionItem) { + val inlinePresentationSpec = inlinePresentationSpecs[positionItem] - // Make sure that the IME spec claims support for v1 UI template. - val imeStyle = inlinePresentationSpec.style - if (!UiVersions.getVersions(imeStyle).contains(UiVersions.INLINE_UI_VERSION_1)) - return null + // Make sure that the IME spec claims support for v1 UI template. + val imeStyle = inlinePresentationSpec.style + if (!UiVersions.getVersions(imeStyle).contains(UiVersions.INLINE_UI_VERSION_1)) + return null - // Build the content for IME UI - val pendingIntent = PendingIntent.getActivity(context, 4596, Intent(), 0) - return InlinePresentation( - InlineSuggestionUi.newContentBuilder(pendingIntent).apply { - setContentDescription(context.getString(R.string.autofill_sign_in_prompt)) - setTitle(entryInfo.title) - setSubtitle(entryInfo.username) - setStartIcon(Icon.createWithResource(context, R.mipmap.ic_launcher_round).apply { + // Build the content for IME UI + // TODO Intent for long press + val pendingIntent = PendingIntent.getActivity(context, 4596, Intent(), 0) + return InlinePresentation( + InlineSuggestionUi.newContentBuilder(pendingIntent).apply { + setContentDescription(context.getString(R.string.autofill_sign_in_prompt)) + setTitle(entryInfo.title) + setSubtitle(entryInfo.username) + setStartIcon(Icon.createWithResource(context, R.mipmap.ic_launcher_round).apply { + setTintBlendMode(BlendMode.DST) + }) + buildIconFromEntry(context, entryInfo)?.let { icon -> + setEndIcon(icon.apply { setTintBlendMode(BlendMode.DST) }) - buildIconFromEntry(context, entryInfo)?.let { icon -> - setEndIcon(icon.apply { - setTintBlendMode(BlendMode.DST) - }) - } - }.build().slice, inlinePresentationSpec, false) - } + } + }.build().slice, inlinePresentationSpec, false) } return null } @@ -169,7 +169,11 @@ object AutofillHelper { // Add inline suggestion for new IME and dataset entriesInfo.forEachIndexed { index, entryInfo -> val inlinePresentation = inlineSuggestionsRequest?.let { - buildInlinePresentation(context, inlineSuggestionsRequest, index, entryInfo) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + buildInlinePresentationForEntry(context, inlineSuggestionsRequest, index, entryInfo) + } else { + null + } } responseBuilder.addDataset(buildDataset(context, entryInfo, parseResult, inlinePresentation)) } diff --git a/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.kt b/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.kt index 15b91f640..6b940a2b7 100644 --- a/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.kt +++ b/app/src/main/java/com/kunzisoft/keepass/autofill/KeeAutofillService.kt @@ -19,6 +19,10 @@ */ package com.kunzisoft.keepass.autofill +import android.app.PendingIntent +import android.content.Intent +import android.graphics.BlendMode +import android.graphics.drawable.Icon import android.os.Build import android.os.CancellationSignal import android.service.autofill.* @@ -27,6 +31,8 @@ import android.view.autofill.AutofillId import android.view.inputmethod.InlineSuggestionsRequest import android.widget.RemoteViews import androidx.annotation.RequiresApi +import androidx.autofill.inline.UiVersions +import androidx.autofill.inline.v1.InlineSuggestionUi import com.kunzisoft.keepass.R import com.kunzisoft.keepass.activities.AutofillLauncherActivity import com.kunzisoft.keepass.database.element.Database @@ -106,17 +112,20 @@ class KeeAutofillService : AutofillService() { }, { // Show UI if no search result - showUIForEntrySelection(parseResult, searchInfo, callback) + showUIForEntrySelection(parseResult, + searchInfo, inlineSuggestionsRequest, callback) }, { // Show UI if database not open - showUIForEntrySelection(parseResult, searchInfo, callback) + showUIForEntrySelection(parseResult, + searchInfo, inlineSuggestionsRequest, callback) } ) } private fun showUIForEntrySelection(parseResult: StructureParser.Result, searchInfo: SearchInfo, + inlineSuggestionsRequest: InlineSuggestionsRequest?, callback: FillCallback) { parseResult.allAutofillIds().let { autofillIds -> if (autofillIds.isNotEmpty()) { @@ -156,8 +165,41 @@ class KeeAutofillService : AutofillService() { ) } } + + // Build inline presentation + var inlinePresentation: InlinePresentation? = null + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + inlineSuggestionsRequest?.let { + val inlinePresentationSpecs = inlineSuggestionsRequest.inlinePresentationSpecs + if (inlineSuggestionsRequest.maxSuggestionCount > 0 + && inlinePresentationSpecs.size > 0) { + val inlinePresentationSpec = inlinePresentationSpecs[0] + + // Make sure that the IME spec claims support for v1 UI template. + val imeStyle = inlinePresentationSpec.style + if (UiVersions.getVersions(imeStyle).contains(UiVersions.INLINE_UI_VERSION_1)) { + // Build the content for IME UI + inlinePresentation = InlinePresentation( + // TODO Intent for long press + InlineSuggestionUi.newContentBuilder( + PendingIntent.getActivity(this, 4596, Intent(), 0)).apply { + setContentDescription(getString(R.string.autofill_sign_in_prompt)) + setTitle(getString(R.string.autofill_sign_in_prompt)) + setStartIcon(Icon.createWithResource(this@KeeAutofillService, R.mipmap.ic_launcher_round).apply { + setTintBlendMode(BlendMode.DST) + }) + }.build().slice, inlinePresentationSpec, false) + } + } + } + } + // Build response - responseBuilder.setAuthentication(autofillIds, intentSender, remoteViewsUnlock) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + responseBuilder.setAuthentication(autofillIds, intentSender, remoteViewsUnlock, inlinePresentation) + } else { + responseBuilder.setAuthentication(autofillIds, intentSender, remoteViewsUnlock) + } callback.onSuccess(responseBuilder.build()) } }