diff --git a/androidApp/src/main/java/com/artemchep/keyguard/Main.kt b/androidApp/src/main/java/com/artemchep/keyguard/Main.kt index 2ce3e97..1b6e7e9 100644 --- a/androidApp/src/main/java/com/artemchep/keyguard/Main.kt +++ b/androidApp/src/main/java/com/artemchep/keyguard/Main.kt @@ -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) } diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/android/util/shortcut.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/util/shortcut.kt new file mode 100644 index 0000000..e5f56eb --- /dev/null +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/android/util/shortcut.kt @@ -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() + } +} diff --git a/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.android.kt b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.android.kt new file mode 100644 index 0000000..5a1988c --- /dev/null +++ b/common/src/androidMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.android.kt @@ -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) + }, + ) +} diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListStateProducer.kt index e3d4a2f..a328c76 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/list/CipherFiltersListStateProducer.kt @@ -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), diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.kt index 5215911..dfc5df8 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.kt @@ -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? diff --git a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/view/CipherFilterViewStateProducer.kt b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/view/CipherFilterViewStateProducer.kt index 3e6dd29..cb21166 100644 --- a/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/view/CipherFilterViewStateProducer.kt +++ b/common/src/commonMain/kotlin/com/artemchep/keyguard/feature/filter/view/CipherFilterViewStateProducer.kt @@ -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, diff --git a/common/src/commonMain/resources/MR/base/strings.xml b/common/src/commonMain/resources/MR/base/strings.xml index 83f38f6..2ea9e28 100644 --- a/common/src/commonMain/resources/MR/base/strings.xml +++ b/common/src/commonMain/resources/MR/base/strings.xml @@ -142,6 +142,7 @@ Ignored alerts API key Domain + Add to Home screen Edit Delete Remove diff --git a/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.desktop.kt b/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.desktop.kt new file mode 100644 index 0000000..a8a198a --- /dev/null +++ b/common/src/desktopMain/kotlin/com/artemchep/keyguard/feature/filter/util/CipherFilterUtil.desktop.kt @@ -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