Compare commits

...

11 Commits
3.0.3 ... 3.0.4

Author SHA1 Message Date
J-Jamet
045049243c Merge branch 'release/3.0.4' 2021-12-09 20:10:57 +01:00
J-Jamet
b9813a3494 Upgrade version code 2021-12-09 19:54:12 +01:00
J-Jamet
9b42a93ce1 Change lock button 2021-12-09 19:49:38 +01:00
J-Jamet
8502bceef1 Fix search 2021-12-09 18:38:38 +01:00
J-Jamet
663387476f Change select entry min height 2021-12-09 14:33:07 +01:00
J-Jamet
daafd83df9 Better extra key implementation 2021-12-09 14:29:41 +01:00
J-Jamet
f780f2725b Fix compat inline suggestions request 2021-12-09 14:15:40 +01:00
J-Jamet
483aca871a Upgrade to version 3.0.4 and fix inline autofill suggestion #1165 2021-12-09 13:38:42 +01:00
J-Jamet
352e709c3b Merge branch 'master' into develop 2021-12-09 11:53:40 +01:00
J-Jamet
629057b2c1 Fix autofill exception #1173 2021-12-09 11:46:39 +01:00
J-Jamet
0e5f53596d Merge tag '3.0.3' into develop
3.0.3
2021-12-08 17:58:49 +01:00
25 changed files with 266 additions and 278 deletions

View File

@@ -1,3 +1,7 @@
KeePassDX(3.0.4)
* Fix autofill inline bugs #1173 #1165
* Small UI change
KeePassDX(3.0.3)
* Change default Argon2 parameters #1098
* Add & edit custom icon name #976

View File

@@ -11,8 +11,8 @@ android {
applicationId "com.kunzisoft.keepass"
minSdkVersion 15
targetSdkVersion 30
versionCode = 90
versionName = "3.0.3"
versionCode = 91
versionName = "3.0.4"
multiDexEnabled true
testApplicationId = "com.kunzisoft.keepass.tests"

View File

@@ -24,7 +24,7 @@ import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.os.Build
import android.view.inputmethod.InlineSuggestionsRequest
import android.os.Bundle
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.annotation.RequiresApi
@@ -32,8 +32,9 @@ import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.SpecialMode
import com.kunzisoft.keepass.activities.legacy.DatabaseModeActivity
import com.kunzisoft.keepass.autofill.AutofillComponent
import com.kunzisoft.keepass.autofill.AutofillHelper
import com.kunzisoft.keepass.autofill.AutofillHelper.EXTRA_INLINE_SUGGESTIONS_REQUEST
import com.kunzisoft.keepass.autofill.CompatInlineSuggestionsRequest
import com.kunzisoft.keepass.autofill.KeeAutofillService
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.search.SearchHelper
@@ -64,17 +65,37 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
EntrySelectionHelper.retrieveSpecialModeFromIntent(intent).let { specialMode ->
when (specialMode) {
SpecialMode.SELECTION -> {
// Build search param
val searchInfo = SearchInfo().apply {
applicationId = intent.getStringExtra(KEY_SEARCH_APPLICATION_ID)
webDomain = intent.getStringExtra(KEY_SEARCH_DOMAIN)
webScheme = intent.getStringExtra(KEY_SEARCH_SCHEME)
manualSelection = intent.getBooleanExtra(KEY_MANUAL_SELECTION, false)
}
SearchInfo.getConcreteWebDomain(this, searchInfo.webDomain) { concreteWebDomain ->
searchInfo.webDomain = concreteWebDomain
launchSelection(database, searchInfo)
intent.getBundleExtra(KEY_SELECTION_BUNDLE)?.let { bundle ->
// To pass extra inline request
var compatInlineSuggestionsRequest: CompatInlineSuggestionsRequest? = null
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
compatInlineSuggestionsRequest = bundle.getParcelable(KEY_INLINE_SUGGESTION)
}
// Build search param
bundle.getParcelable<SearchInfo>(KEY_SEARCH_INFO)?.let { searchInfo ->
SearchInfo.getConcreteWebDomain(
this,
searchInfo.webDomain
) { concreteWebDomain ->
// Pass extra for Autofill (EXTRA_ASSIST_STRUCTURE)
val assistStructure = AutofillHelper
.retrieveAutofillComponent(intent)
?.assistStructure
val newAutofillComponent = if (assistStructure != null) {
AutofillComponent(
assistStructure,
compatInlineSuggestionsRequest
)
} else {
null
}
searchInfo.webDomain = concreteWebDomain
launchSelection(database, newAutofillComponent, searchInfo)
}
}
}
// Remove bundle
intent.removeExtra(KEY_SELECTION_BUNDLE)
}
SpecialMode.REGISTRATION -> {
// To register info
@@ -95,10 +116,8 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
}
private fun launchSelection(database: Database?,
autofillComponent: AutofillComponent?,
searchInfo: SearchInfo) {
// Pass extra for Autofill (EXTRA_ASSIST_STRUCTURE)
val autofillComponent = AutofillHelper.retrieveAutofillComponent(intent)
if (autofillComponent == null) {
setResult(Activity.RESULT_CANCELED)
finish()
@@ -194,30 +213,25 @@ class AutofillLauncherActivity : DatabaseModeActivity() {
companion object {
private const val KEY_MANUAL_SELECTION = "KEY_MANUAL_SELECTION"
private const val KEY_SEARCH_APPLICATION_ID = "KEY_SEARCH_APPLICATION_ID"
private const val KEY_SEARCH_DOMAIN = "KEY_SEARCH_DOMAIN"
private const val KEY_SEARCH_SCHEME = "KEY_SEARCH_SCHEME"
private const val KEY_SELECTION_BUNDLE = "KEY_SELECTION_BUNDLE"
private const val KEY_SEARCH_INFO = "KEY_SEARCH_INFO"
private const val KEY_INLINE_SUGGESTION = "KEY_INLINE_SUGGESTION"
private const val KEY_REGISTER_INFO = "KEY_REGISTER_INFO"
fun getPendingIntentForSelection(context: Context,
searchInfo: SearchInfo? = null,
inlineSuggestionsRequest: InlineSuggestionsRequest? = null): PendingIntent {
compatInlineSuggestionsRequest: CompatInlineSuggestionsRequest? = null): PendingIntent {
return PendingIntent.getActivity(context, 0,
// Doesn't work with Parcelable (don't know why?)
// Doesn't work with direct extra Parcelable (don't know why?)
// Wrap into a bundle to bypass the problem
Intent(context, AutofillLauncherActivity::class.java).apply {
searchInfo?.let {
putExtra(KEY_SEARCH_APPLICATION_ID, it.applicationId)
putExtra(KEY_SEARCH_DOMAIN, it.webDomain)
putExtra(KEY_SEARCH_SCHEME, it.webScheme)
putExtra(KEY_MANUAL_SELECTION, it.manualSelection)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
inlineSuggestionsRequest?.let {
putExtra(EXTRA_INLINE_SUGGESTIONS_REQUEST, it)
putExtra(KEY_SELECTION_BUNDLE, Bundle().apply {
putParcelable(KEY_SEARCH_INFO, searchInfo)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
putParcelable(KEY_INLINE_SUGGESTION, compatInlineSuggestionsRequest)
}
}
})
},
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// TODO Mutable

View File

@@ -335,6 +335,29 @@ class GroupActivity : DatabaseLockActivity(),
return rootContainerView
}
private fun loadGroup(database: Database?) {
when {
Intent.ACTION_SEARCH == intent.action -> {
finishNodeAction()
val searchString =
intent.getStringExtra(SearchManager.QUERY)?.trim { it <= ' ' } ?: ""
mGroupViewModel.loadGroupFromSearch(
database,
searchString,
PreferencesUtil.omitBackup(this)
)
}
mCurrentGroupState == null -> {
mRootGroup?.let { rootGroup ->
mGroupViewModel.loadGroup(database, rootGroup, 0)
}
}
else -> {
mGroupViewModel.loadGroup(database, mCurrentGroupState)
}
}
}
override fun onDatabaseRetrieved(database: Database?) {
super.onDatabaseRetrieved(database)
@@ -344,13 +367,7 @@ class GroupActivity : DatabaseLockActivity(),
&& database?.isRecycleBinEnabled == true
mRootGroup = database?.rootGroup
if (mCurrentGroupState == null) {
mRootGroup?.let { rootGroup ->
mGroupViewModel.loadGroup(database, rootGroup, 0)
}
} else {
mGroupViewModel.loadGroup(database, mCurrentGroupState)
}
loadGroup(database)
// Search suggestion
database?.let {
@@ -463,16 +480,7 @@ class GroupActivity : DatabaseLockActivity(),
}
// To transform KEY_SEARCH_INFO in ACTION_SEARCH
transformSearchInfoIntent(intent)
if (Intent.ACTION_SEARCH == intent.action) {
finishNodeAction()
val searchString =
intent.getStringExtra(SearchManager.QUERY)?.trim { it <= ' ' } ?: ""
mGroupViewModel.loadGroupFromSearch(
mDatabase,
searchString,
PreferencesUtil.omitBackup(this)
)
}
loadGroup(mDatabase)
}
}
@@ -1008,7 +1016,7 @@ class GroupActivity : DatabaseLockActivity(),
if (!sortMenuEducationPerformed) {
// lockMenuEducationPerformed
val lockButtonView = findViewById<View>(R.id.lock_button_icon)
val lockButtonView = findViewById<View>(R.id.lock_button)
lockButtonView != null
&& groupActivityEducation.checkAndPerformedLockMenuEducation(
lockButtonView,
@@ -1081,22 +1089,6 @@ class GroupActivity : DatabaseLockActivity(),
}
}
@Suppress("DEPRECATION")
override fun startActivityForResult(intent: Intent, requestCode: Int, options: Bundle?) {
/*
* ACTION_SEARCH automatically forces a new task. This occurs when you open a kdb file in
* another app such as Files or GoogleDrive and then Search for an entry. Here we remove the
* FLAG_ACTIVITY_NEW_TASK flag bit allowing search to open it's activity in the current task.
*/
if (Intent.ACTION_SEARCH == intent.action) {
var flags = intent.flags
flags = flags and Intent.FLAG_ACTIVITY_NEW_TASK.inv()
intent.flags = flags
}
super.startActivityForResult(intent, requestCode, options)
}
private fun removeSearch() {
intent.removeExtra(AUTO_SEARCH_KEY)
if (Intent.ACTION_SEARCH == intent.action) {

View File

@@ -4,4 +4,4 @@ import android.app.assist.AssistStructure
import android.view.inputmethod.InlineSuggestionsRequest
data class AutofillComponent(val assistStructure: AssistStructure,
val inlineSuggestionsRequest: InlineSuggestionsRequest?)
val compatInlineSuggestionsRequest: CompatInlineSuggestionsRequest?)

View File

@@ -34,7 +34,6 @@ import android.service.autofill.InlinePresentation
import android.util.Log
import android.view.autofill.AutofillManager
import android.view.autofill.AutofillValue
import android.view.inputmethod.InlineSuggestionsRequest
import android.widget.RemoteViews
import android.widget.Toast
import android.widget.inline.InlinePresentationSpec
@@ -63,7 +62,7 @@ import com.kunzisoft.keepass.utils.LOCK_ACTION
object AutofillHelper {
private const val EXTRA_ASSIST_STRUCTURE = AutofillManager.EXTRA_ASSIST_STRUCTURE
const val EXTRA_INLINE_SUGGESTIONS_REQUEST = "com.kunzisoft.keepass.autofill.INLINE_SUGGESTIONS_REQUEST"
private const val EXTRA_INLINE_SUGGESTIONS_REQUEST = "com.kunzisoft.keepass.autofill.INLINE_SUGGESTIONS_REQUEST"
fun retrieveAutofillComponent(intent: Intent?): AutofillComponent? {
intent?.getParcelableExtra<AssistStructure?>(EXTRA_ASSIST_STRUCTURE)?.let { assistStructure ->
@@ -112,7 +111,7 @@ object AutofillHelper {
database: Database,
entryInfo: EntryInfo,
struct: StructureParser.Result,
inlinePresentation: InlinePresentation?): Dataset? {
additionalBuild: ((build: Dataset.Builder) -> Unit)? = null): Dataset? {
val title = makeEntryTitle(entryInfo)
val views = newRemoteViews(context, database, title, entryInfo.icon)
val builder = Dataset.Builder(views)
@@ -201,11 +200,7 @@ object AutofillHelper {
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
inlinePresentation?.let {
builder.setInlinePresentation(it)
}
}
additionalBuild?.invoke(builder)
return try {
builder.build()
@@ -236,44 +231,51 @@ object AutofillHelper {
@SuppressLint("RestrictedApi")
private fun buildInlinePresentationForEntry(context: Context,
database: Database,
inlineSuggestionsRequest: InlineSuggestionsRequest,
compatInlineSuggestionsRequest: CompatInlineSuggestionsRequest,
positionItem: Int,
entryInfo: EntryInfo): InlinePresentation? {
val inlinePresentationSpecs = inlineSuggestionsRequest.inlinePresentationSpecs
val maxSuggestion = inlineSuggestionsRequest.maxSuggestionCount
compatInlineSuggestionsRequest.inlineSuggestionsRequest?.let { inlineSuggestionsRequest ->
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,
0,
Intent(context, AutofillSettingsActivity::class.java),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
0
})
return InlinePresentation(
// Build the content for IME UI
val pendingIntent = PendingIntent.getActivity(
context,
0,
Intent(context, AutofillSettingsActivity::class.java),
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PendingIntent.FLAG_IMMUTABLE
} else {
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)
})
setStartIcon(
Icon.createWithResource(context, R.mipmap.ic_launcher_round).apply {
setTintBlendMode(BlendMode.DST)
})
buildIconFromEntry(context, database, entryInfo)?.let { icon ->
setEndIcon(icon.apply {
setTintBlendMode(BlendMode.DST)
})
}
}.build().slice, inlinePresentationSpec, false)
}.build().slice, inlinePresentationSpec, false
)
}
}
return null
}
@@ -303,7 +305,7 @@ object AutofillHelper {
database: Database,
entriesInfo: List<EntryInfo>,
parseResult: StructureParser.Result,
inlineSuggestionsRequest: InlineSuggestionsRequest?): FillResponse? {
compatInlineSuggestionsRequest: CompatInlineSuggestionsRequest?): FillResponse? {
val responseBuilder = FillResponse.Builder()
// Add Header
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
@@ -324,7 +326,7 @@ object AutofillHelper {
// Add inline suggestion for new IME and dataset
var numberInlineSuggestions = 0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
inlineSuggestionsRequest?.let {
compatInlineSuggestionsRequest?.inlineSuggestionsRequest?.let { inlineSuggestionsRequest ->
numberInlineSuggestions = minOf(inlineSuggestionsRequest.maxSuggestionCount, entriesInfo.size)
if (PreferencesUtil.isAutofillManualSelectionEnable(context)) {
if (entriesInfo.size >= inlineSuggestionsRequest.maxSuggestionCount) {
@@ -336,14 +338,19 @@ object AutofillHelper {
}
entriesInfo.forEachIndexed { _, entry ->
val inlinePresentation = if (numberInlineSuggestions > 0 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
inlineSuggestionsRequest?.let {
buildInlinePresentationForEntry(context, database, inlineSuggestionsRequest, numberInlineSuggestions--, entry)
}
if (numberInlineSuggestions > 0
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& compatInlineSuggestionsRequest != null) {
responseBuilder.addDataset(buildDataset(context, database, entry, parseResult) { builder ->
buildInlinePresentationForEntry(context, database,
compatInlineSuggestionsRequest, numberInlineSuggestions--, entry
)?.let { inlinePresentation ->
builder.setInlinePresentation(inlinePresentation)
}
})
} else {
null
responseBuilder.addDataset(buildDataset(context, database, entry, parseResult))
}
responseBuilder.addDataset(buildDataset(context, database, entry, parseResult, inlinePresentation))
}
if (PreferencesUtil.isAutofillManualSelectionEnable(context)) {
@@ -355,14 +362,14 @@ object AutofillHelper {
}
val manualSelectionView = RemoteViews(context.packageName, R.layout.item_autofill_select_entry)
val pendingIntent = AutofillLauncherActivity.getPendingIntentForSelection(context,
searchInfo, inlineSuggestionsRequest)
searchInfo, compatInlineSuggestionsRequest)
parseResult.allAutofillIds().let { autofillIds ->
autofillIds.forEach { id ->
val builder = Dataset.Builder(manualSelectionView)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
inlineSuggestionsRequest?.let {
compatInlineSuggestionsRequest?.inlineSuggestionsRequest?.let { inlineSuggestionsRequest ->
val inlinePresentationSpec = inlineSuggestionsRequest.inlinePresentationSpecs[0]
val inlinePresentation = buildInlinePresentationForManualSelection(context, inlinePresentationSpec, pendingIntent)
inlinePresentation?.let {
@@ -407,11 +414,11 @@ object AutofillHelper {
StructureParser(structure).parse()?.let { result ->
// New Response
val response = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val inlineSuggestionsRequest = activity.intent?.getParcelableExtra<InlineSuggestionsRequest?>(EXTRA_INLINE_SUGGESTIONS_REQUEST)
if (inlineSuggestionsRequest != null) {
val compatInlineSuggestionsRequest = activity.intent?.getParcelableExtra<CompatInlineSuggestionsRequest?>(EXTRA_INLINE_SUGGESTIONS_REQUEST)
if (compatInlineSuggestionsRequest != null) {
Toast.makeText(activity.applicationContext, R.string.autofill_inline_suggestions_keyboard, Toast.LENGTH_SHORT).show()
}
buildResponse(activity, database, entriesInfo, result, inlineSuggestionsRequest)
buildResponse(activity, database, entriesInfo, result, compatInlineSuggestionsRequest)
} else {
buildResponse(activity, database, entriesInfo, result, null)
}
@@ -464,7 +471,7 @@ object AutofillHelper {
intent.putExtra(EXTRA_ASSIST_STRUCTURE, autofillComponent.assistStructure)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& PreferencesUtil.isAutofillInlineSuggestionsEnable(activity)) {
autofillComponent.inlineSuggestionsRequest?.let {
autofillComponent.compatInlineSuggestionsRequest?.let {
intent.putExtra(EXTRA_INLINE_SUGGESTIONS_REQUEST, it)
}
}

View File

@@ -0,0 +1,83 @@
/*
* Copyright 2021 Jeremy Jamet / Kunzisoft.
*
* This file is part of KeePassDX.
*
* KeePassDX is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* KeePassDX is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with KeePassDX. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.kunzisoft.keepass.autofill
import android.annotation.TargetApi
import android.os.Build
import android.os.Parcel
import android.os.Parcelable
import android.service.autofill.FillRequest
import android.view.inputmethod.InlineSuggestionsRequest
import androidx.annotation.RequiresApi
/**
* Utility class only to prevent java.lang.NoClassDefFoundError for old Android version and new lib compilation
*/
@RequiresApi(Build.VERSION_CODES.O)
class CompatInlineSuggestionsRequest : Parcelable {
@TargetApi(Build.VERSION_CODES.R)
var inlineSuggestionsRequest: InlineSuggestionsRequest? = null
private set
constructor(fillRequest: FillRequest) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
this.inlineSuggestionsRequest = fillRequest.inlineSuggestionsRequest
} else {
this.inlineSuggestionsRequest = null
}
}
@RequiresApi(Build.VERSION_CODES.R)
constructor(inlineSuggestionsRequest: InlineSuggestionsRequest?) {
this.inlineSuggestionsRequest = inlineSuggestionsRequest
}
constructor(parcel: Parcel) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
this.inlineSuggestionsRequest =
parcel.readParcelable(FillRequest::class.java.classLoader)
}
else {
this.inlineSuggestionsRequest = null
}
}
override fun writeToParcel(parcel: Parcel, flags: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
parcel.writeParcelable(inlineSuggestionsRequest, flags)
}
}
override fun describeContents(): Int {
return 0
}
companion object CREATOR : Parcelable.Creator<CompatInlineSuggestionsRequest> {
override fun createFromParcel(parcel: Parcel): CompatInlineSuggestionsRequest {
return CompatInlineSuggestionsRequest(parcel)
}
override fun newArray(size: Int): Array<CompatInlineSuggestionsRequest?> {
return arrayOfNulls(size)
}
}
}

View File

@@ -109,7 +109,7 @@ class KeeAutofillService : AutofillService() {
searchInfo.webDomain = webDomainWithoutSubDomain
val inlineSuggestionsRequest = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& autofillInlineSuggestionsEnabled) {
request.inlineSuggestionsRequest
CompatInlineSuggestionsRequest(request)
} else {
null
}
@@ -127,7 +127,7 @@ class KeeAutofillService : AutofillService() {
private fun launchSelection(database: Database?,
searchInfo: SearchInfo,
parseResult: StructureParser.Result,
inlineSuggestionsRequest: InlineSuggestionsRequest?,
inlineSuggestionsRequest: CompatInlineSuggestionsRequest?,
callback: FillCallback) {
SearchHelper.checkAutoSearchInfo(this,
database,
@@ -155,7 +155,7 @@ class KeeAutofillService : AutofillService() {
private fun showUIForEntrySelection(parseResult: StructureParser.Result,
database: Database?,
searchInfo: SearchInfo,
inlineSuggestionsRequest: InlineSuggestionsRequest?,
inlineSuggestionsRequest: CompatInlineSuggestionsRequest?,
callback: FillCallback) {
parseResult.allAutofillIds().let { autofillIds ->
if (autofillIds.isNotEmpty()) {
@@ -249,7 +249,7 @@ class KeeAutofillService : AutofillService() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
&& autofillInlineSuggestionsEnabled) {
var inlinePresentation: InlinePresentation? = null
inlineSuggestionsRequest?.let {
inlineSuggestionsRequest?.inlineSuggestionsRequest?.let { inlineSuggestionsRequest ->
val inlinePresentationSpecs = inlineSuggestionsRequest.inlinePresentationSpecs
if (inlineSuggestionsRequest.maxSuggestionCount > 0
&& inlinePresentationSpecs.size > 0) {
@@ -281,8 +281,9 @@ class KeeAutofillService : AutofillService() {
}
// Build response
responseBuilder.setAuthentication(autofillIds, intentSender, remoteViewsUnlock, inlinePresentation)
} else {
responseBuilder.setAuthentication(autofillIds, intentSender, remoteViewsUnlock)
}
responseBuilder.setAuthentication(autofillIds, intentSender, remoteViewsUnlock)
callback.onSuccess(responseBuilder.build())
}
}

View File

@@ -119,7 +119,7 @@ class GroupActivityEducation(activity: Activity)
.outerCircleColorInt(getCircleColor())
.outerCircleAlpha(getCircleAlpha())
.textColorInt(getTextColor())
.tintTarget(true)
.tintTarget(false)
.cancelable(true),
object : TapTargetView.Listener() {
override fun onTargetClick(view: TapTargetView) {

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="?attr/colorAccentLight" android:state_pressed="true" />
<item android:color="@color/white_grey_darker" android:state_enabled="false" />
<item android:color="?attr/colorAccent" android:state_enabled="true" />
</selector>

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="@color/white"
tools:targetApi="lollipop">
<item>
<shape>
<corners
android:topLeftRadius="0dp"
android:topRightRadius="40dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
<solid android:color="?attr/colorAccent"/>
</shape>
</item>
</ripple>

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:color="@color/white"
tools:targetApi="lollipop">
<item>
<shape>
<stroke
android:width="1dp"
android:color="?attr/textColorInverse" />
<corners
android:topLeftRadius="0dp"
android:topRightRadius="40dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
<solid
android:color="@color/transparent"/>
</shape>
</item>
</ripple>

View File

@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_pressed="true">
<shape>
<corners
android:topLeftRadius="0dp"
android:topRightRadius="40dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
<padding
android:left="4dp"
android:right="12dp"
android:top="18dp"
android:bottom="8dp"/>
<solid android:color="@color/orange_light"/>
</shape>
</item>
<item>
<shape>
<corners
android:topLeftRadius="0dp"
android:topRightRadius="40dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
<padding
android:left="4dp"
android:right="12dp"
android:top="18dp"
android:bottom="8dp"/>
<solid android:color="@color/orange"/>
</shape>
</item>
</selector>

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/white">
<item>
<shape>
<stroke
android:width="1dp"
android:color="@color/white_grey" />
<corners
android:topLeftRadius="0dp"
android:topRightRadius="40dp"
android:bottomLeftRadius="0dp"
android:bottomRightRadius="0dp"/>
<solid
android:color="@color/transparent"/>
</shape>
</item>
</selector>

View File

@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<group
android:scaleX="0.8"
android:scaleY="0.8"
android:pivotX="12"
android:pivotY="12">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"/>
</group>
</vector>

View File

@@ -138,8 +138,8 @@
<include
layout="@layout/view_button_lock"
android:layout_width="@dimen/lock_button_size"
android:layout_height="@dimen/lock_button_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="start|bottom" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -100,8 +100,8 @@
<include
layout="@layout/view_button_lock"
android:layout_width="@dimen/lock_button_size"
android:layout_height="@dimen/lock_button_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />

View File

@@ -132,6 +132,7 @@
android:orientation="vertical"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_below="@+id/toolbar">
<FrameLayout
android:id="@+id/nodes_list_fragment_container"
android:layout_width="match_parent"
@@ -168,8 +169,8 @@
<include
layout="@layout/view_button_lock"
android:layout_width="@dimen/lock_button_size"
android:layout_height="@dimen/lock_button_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/>
</RelativeLayout>

View File

@@ -59,8 +59,8 @@
<include
layout="@layout/view_button_lock"
android:layout_width="@dimen/lock_button_size"
android:layout_height="@dimen/lock_button_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -42,8 +42,8 @@
<include
layout="@layout/view_button_lock"
android:layout_width="@dimen/lock_button_size"
android:layout_height="@dimen/lock_button_size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_gravity="start|bottom" />

View File

@@ -18,7 +18,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/windowBackground"
android:minHeight="36dp"
android:minHeight="48dp"
android:orientation="horizontal">
<ImageView
android:layout_width="24dp"

View File

@@ -1,48 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<FrameLayout
android:id="@+id/lock_button"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/lock_button_background"
android:layout_width="@dimen/lock_button_size"
android:layout_height="@dimen/lock_button_size"
android:layout_marginStart="-2dp"
android:layout_marginLeft="-2dp"
android:layout_marginBottom="-2dp"
tools:targetApi="lollipop"
android:elevation="4dp"
style="@style/KeepassDXStyle.Special.Button.Background"
android:layout_gravity="bottom|start"
android:contentDescription="@string/menu_lock" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/lock_button_stroke"
android:layout_width="@dimen/lock_button_size"
android:layout_height="@dimen/lock_button_size"
android:layout_marginStart="-2dp"
android:layout_marginLeft="-2dp"
android:layout_marginBottom="-2dp"
tools:targetApi="lollipop"
android:elevation="4dp"
style="@style/KeepassDXStyle.Special.Button.Stroke"
android:layout_gravity="bottom|start"
android:contentDescription="@string/menu_lock" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/lock_button_icon"
android:layout_width="@dimen/lock_button_size"
android:layout_height="@dimen/lock_button_size"
android:paddingBottom="6dp"
android:paddingTop="16dp"
android:paddingStart="4dp"
android:paddingLeft="4dp"
android:paddingEnd="12dp"
android:paddingRight="12dp"
tools:targetApi="lollipop"
android:elevation="4dp"
android:src="@drawable/ic_lock_white_24dp"
android:tint="@color/white"
android:layout_gravity="bottom|start"
android:contentDescription="@string/menu_lock" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/lock_button"
style="@style/KeepassDXStyle.Fab.Special"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fabSize="mini"
android:layout_margin="8dp"
android:contentDescription="@string/lock"
android:src="@drawable/ic_lock_white_padding_24dp"
xmlns:app="http://schemas.android.com/apk/res-auto" />
</FrameLayout>

View File

@@ -443,21 +443,14 @@
<item name="backgroundTint">?android:attr/windowBackground</item>
</style>
<!-- Special button Style -->
<style name="KeepassDXStyle.Special.Button.Background" parent="KeepassDXStyle.v21.Button">
<item name="android:background">@drawable/btn_special_start_bottom_background</item>
<item name="backgroundTint">@color/background_special_button_color</item>
</style>
<style name="KeepassDXStyle.Special.Button.Stroke" parent="KeepassDXStyle.v21.Button">
<item name="android:background">@drawable/btn_special_start_bottom_stroke</item>
<item name="backgroundTint">@color/white</item>
<item name="backgroundTintMode">src_atop</item>
</style>
<!-- FAB -->
<style name="KeepassDXStyle.v21.Fab" parent="KeepassDXStyle.Light.v21" />
<style name="KeepassDXStyle.Fab" parent="KeepassDXStyle.v21.Fab">
</style>
<style name="KeepassDXStyle.Fab.Special" parent="KeepassDXStyle.v21.Fab">
<item name="backgroundTint">?attr/colorPrimary</item>
<item name="tint">?attr/textColorInverse</item>
</style>
<!-- Menu FAB -->
<style name="KeepassDXStyle.v21.FabMenu" parent="KeepassDXStyle.TextAppearance.Default.TextOnPrimary">

View File

@@ -0,0 +1,2 @@
* Fix autofill inline bugs #1173 #1165
* Small UI change

View File

@@ -0,0 +1,2 @@
* Résolution de bogues du remplissage automatique uniligne #1173 #1165
* Petit changement dans l'interface utilisateur