improvement: Add a button to add a Custom filter to the Home screen

This commit is contained in:
Artem Chepurnoy 2024-03-07 12:13:23 +02:00
parent 81d98764ea
commit f423826252
No known key found for this signature in database
GPG Key ID: FAC37D0CF674043E
8 changed files with 110 additions and 18 deletions

View File

@ -1,19 +1,17 @@
package com.artemchep.keyguard
import android.content.Context
import android.content.Intent
import androidx.core.content.ContextCompat
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.lifecycle.lifecycleScope
import com.artemchep.bindin.bindBlock
import com.artemchep.keyguard.android.BaseApp
import com.artemchep.keyguard.android.MainActivity
import com.artemchep.keyguard.android.downloader.journal.DownloadRepository
import com.artemchep.keyguard.android.downloader.worker.AttachmentDownloadAllWorker
import com.artemchep.keyguard.android.passkeysModule
import com.artemchep.keyguard.android.util.ShortcutIds
import com.artemchep.keyguard.android.util.ShortcutInfo
import com.artemchep.keyguard.billing.BillingManager
import com.artemchep.keyguard.billing.BillingManagerImpl
import com.artemchep.keyguard.common.AppWorker
@ -250,7 +248,7 @@ class Main : BaseApp(), DIAware {
.map { it.id }
.toSet()
val newDynamicShortcutsIds = filters
.map { it.id }
.map { ShortcutIds.forFilter(it.id) }
.toSet()
oldDynamicShortcutsIds - newDynamicShortcutsIds
}
@ -260,18 +258,11 @@ class Main : BaseApp(), DIAware {
}
val shortcuts = filters
.map {
val intent = MainActivity.getIntent(this@Main).apply {
action = Intent.ACTION_VIEW
putExtra("customFilter", it.id)
}
val icon = IconCompat.createWithResource(this@Main, com.artemchep.keyguard.common.R.drawable.ic_shortcut_keyguard)
ShortcutInfoCompat.Builder(this@Main, it.id)
.setIcon(icon)
.setShortLabel(it.name)
.setIntent(intent)
.addCapabilityBinding("actions.intent.OPEN_APP_FEATURE")
.build()
.map { filter ->
ShortcutInfo.forFilter(
context = this@Main,
filter = filter,
)
}
ShortcutManagerCompat.addDynamicShortcuts(this@Main, shortcuts)
}

View File

@ -0,0 +1,35 @@
package com.artemchep.keyguard.android.util
import android.content.Context
import android.content.Intent
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.graphics.drawable.IconCompat
import com.artemchep.keyguard.android.MainActivity
import com.artemchep.keyguard.common.R
import com.artemchep.keyguard.common.model.DCipherFilter
object ShortcutIds {
fun forFilter(filterId: String): String {
return "filter=$filterId"
}
}
object ShortcutInfo {
fun forFilter(
context: Context,
filter: DCipherFilter,
): ShortcutInfoCompat {
val id = ShortcutIds.forFilter(filter.id)
val intent = MainActivity.getIntent(context).apply {
action = Intent.ACTION_VIEW
putExtra("customFilter", filter.id)
}
val icon = IconCompat.createWithResource(context, R.drawable.ic_shortcut_keyguard)
return ShortcutInfoCompat.Builder(context, id)
.setIcon(icon)
.setShortLabel(filter.name)
.setIntent(intent)
.addCapabilityBinding("actions.intent.OPEN_APP_FEATURE")
.build()
}
}

View File

@ -0,0 +1,33 @@
package com.artemchep.keyguard.feature.filter.util
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.AddToHomeScreen
import androidx.core.content.pm.ShortcutManagerCompat
import com.artemchep.keyguard.android.util.ShortcutInfo
import com.artemchep.keyguard.common.model.DCipherFilter
import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope
import com.artemchep.keyguard.res.Res
import com.artemchep.keyguard.ui.FlatItemAction
import com.artemchep.keyguard.ui.icons.iconSmall
context(RememberStateFlowScope)
actual fun CipherFilterUtil.addShortcutActionOrNull(
filter: DCipherFilter,
): FlatItemAction? {
val androidContext = context.context
if (!ShortcutManagerCompat.isRequestPinShortcutSupported(androidContext)) {
return null
}
val shortcut = ShortcutInfo.forFilter(
context = androidContext,
filter = filter,
)
return FlatItemAction(
leading = iconSmall(Icons.AutoMirrored.Outlined.AddToHomeScreen),
title = translate(Res.strings.add_to_home_screen),
onClick = {
ShortcutManagerCompat.requestPinShortcut(androidContext, shortcut, null)
},
)
}

View File

@ -17,6 +17,7 @@ import com.artemchep.keyguard.feature.attachments.SelectableItemStateRaw
import com.artemchep.keyguard.feature.crashlytics.crashlyticsAttempt
import com.artemchep.keyguard.feature.filter.CipherFiltersRoute
import com.artemchep.keyguard.feature.filter.util.CipherFilterUtil
import com.artemchep.keyguard.feature.filter.util.addShortcutActionOrNull
import com.artemchep.keyguard.feature.filter.view.CipherFilterViewDialogRoute
import com.artemchep.keyguard.feature.filter.view.CipherFilterViewFullRoute
import com.artemchep.keyguard.feature.generator.wordlist.util.WordlistUtil
@ -211,8 +212,13 @@ fun produceCipherFiltersListState(
val actions = buildContextItems {
if (selectedItems.size == 1) {
val selectedItem = selectedItems.first()
section {
this += CipherFilterUtil.addShortcutActionOrNull(
filter = selectedItem,
)
}
section {
val selectedItem = selectedItems.first()
this += FlatItemAction(
icon = Icons.Outlined.Edit,
title = translate(Res.strings.edit),

View File

@ -11,13 +11,18 @@ import com.artemchep.keyguard.common.service.filter.model.RenameCipherFilterRequ
import com.artemchep.keyguard.feature.confirmation.ConfirmationResult
import com.artemchep.keyguard.feature.confirmation.ConfirmationRoute
import com.artemchep.keyguard.feature.confirmation.createConfirmationDialogIntent
import com.artemchep.keyguard.feature.filter.CipherFiltersRoute
import com.artemchep.keyguard.feature.navigation.NavigationIntent
import com.artemchep.keyguard.feature.navigation.registerRouteResultReceiver
import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope
import com.artemchep.keyguard.feature.navigation.state.TranslatorScope
import com.artemchep.keyguard.res.Res
import com.artemchep.keyguard.ui.FlatItemAction
import com.artemchep.keyguard.ui.icons.ChevronIcon
import com.artemchep.keyguard.ui.icons.KeyguardCipherFilter
import com.artemchep.keyguard.ui.icons.KeyguardWordlist
import com.artemchep.keyguard.ui.icons.icon
import com.artemchep.keyguard.ui.icons.iconSmall
object CipherFilterUtil {
context(RememberStateFlowScope)
@ -92,3 +97,8 @@ object CipherFilterUtil {
navigate(intent)
}
}
context(RememberStateFlowScope)
expect fun CipherFilterUtil.addShortcutActionOrNull(
filter: DCipherFilter,
): FlatItemAction?

View File

@ -20,6 +20,7 @@ import com.artemchep.keyguard.common.usecase.GetOrganizations
import com.artemchep.keyguard.common.usecase.GetProfiles
import com.artemchep.keyguard.common.util.flow.foldAsList
import com.artemchep.keyguard.feature.filter.util.CipherFilterUtil
import com.artemchep.keyguard.feature.filter.util.addShortcutActionOrNull
import com.artemchep.keyguard.feature.home.vault.model.FilterItem
import com.artemchep.keyguard.feature.home.vault.screen.FilterSection
import com.artemchep.keyguard.feature.navigation.state.navigatePopSelf
@ -264,6 +265,11 @@ fun produceCipherFilterViewState(
filter
?: return@run persistentListOf()
buildContextItems {
section {
this += CipherFilterUtil.addShortcutActionOrNull(
filter = filter,
)
}
section {
this += FlatItemAction(
icon = Icons.Outlined.Edit,

View File

@ -142,6 +142,7 @@
<string name="ignored_alerts">Ignored alerts</string>
<string name="api_key">API key</string>
<string name="domain">Domain</string>
<string name="add_to_home_screen">Add to Home screen</string>
<string name="edit">Edit</string>
<string name="delete">Delete</string>
<string name="remove">Remove</string>

View File

@ -0,0 +1,10 @@
package com.artemchep.keyguard.feature.filter.util
import com.artemchep.keyguard.common.model.DCipherFilter
import com.artemchep.keyguard.feature.navigation.state.RememberStateFlowScope
import com.artemchep.keyguard.ui.FlatItemAction
context(RememberStateFlowScope)
actual fun CipherFilterUtil.addShortcutActionOrNull(
filter: DCipherFilter,
): FlatItemAction? = null