Updated on 2026-08-14
This commit is contained in:
commit
3efdb25a4e
33 changed files with 452 additions and 26 deletions
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.tap.common.settings
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.provider.Settings
|
||||
import com.tangem.core.navigation.settings.SettingsManager
|
||||
|
||||
internal class IntentSettingsManager(val context: Context) : SettingsManager {
|
||||
override fun openSettings() {
|
||||
val openSettingsIntent = Intent(
|
||||
Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
|
||||
Uri.fromParts("package", context.packageName, null),
|
||||
)
|
||||
context.startActivity(openSettingsIntent)
|
||||
}
|
||||
}
|
||||
|
|
@ -3,10 +3,12 @@ package com.tangem.tap.di
|
|||
import android.content.Context
|
||||
import com.tangem.core.navigation.feedback.FeedbackManager
|
||||
import com.tangem.core.navigation.finisher.AppFinisher
|
||||
import com.tangem.core.navigation.settings.SettingsManager
|
||||
import com.tangem.core.navigation.share.ShareManager
|
||||
import com.tangem.core.navigation.url.UrlOpener
|
||||
import com.tangem.tap.common.feedback.ProxyFeedbackManager
|
||||
import com.tangem.tap.common.finisher.AndroidAppFinisher
|
||||
import com.tangem.tap.common.settings.IntentSettingsManager
|
||||
import com.tangem.tap.common.share.IntentShareManager
|
||||
import com.tangem.tap.common.url.CustomTabsUrlOpener
|
||||
import dagger.Module
|
||||
|
|
@ -35,4 +37,8 @@ internal object UtilsModule {
|
|||
@Provides
|
||||
@Singleton
|
||||
fun provideAppFinisher(@ApplicationContext context: Context): AppFinisher = AndroidAppFinisher(context)
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSettingsManager(@ApplicationContext context: Context): SettingsManager = IntentSettingsManager(context)
|
||||
}
|
||||
|
|
@ -96,17 +96,17 @@ object PreferencesKeys {
|
|||
fun getStart2CoinTOSAcceptedKey(region: String?) = booleanPreferencesKey(name = "start2Coin_tos_accepted_$region")
|
||||
|
||||
// region Permission
|
||||
fun getShouldShowPermission(permission: Int) = booleanPreferencesKey("shouldShowPushPermission_$permission")
|
||||
fun getShouldShowPermission(permission: String) = booleanPreferencesKey("shouldShowPushPermission_$permission")
|
||||
|
||||
fun getShouldShowInitialPermissionScreen(permission: Int) =
|
||||
fun getShouldShowInitialPermissionScreen(permission: String) =
|
||||
booleanPreferencesKey("shouldShowInitialPushPermissionScreen_$permission")
|
||||
|
||||
fun getIsFirstTimeAskingPermission(permission: Int) =
|
||||
fun getIsFirstTimeAskingPermission(permission: String) =
|
||||
booleanPreferencesKey("shouldAskInitialPushPermission_$permission")
|
||||
|
||||
fun getPermissionLaunchCount(permission: Int) = intPreferencesKey("pushPermissionLaunchCount_$permission")
|
||||
fun getPermissionLaunchCount(permission: String) = intPreferencesKey("pushPermissionLaunchCount_$permission")
|
||||
|
||||
fun getPermissionDaysCount(permission: Int) = longPreferencesKey("pushPermissionDaysCount_$permission")
|
||||
fun getPermissionDaysCount(permission: String) = longPreferencesKey("pushPermissionDaysCount_$permission")
|
||||
// endregion
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,5 +42,9 @@
|
|||
{
|
||||
"name": "DETAILS_REDESIGN_ENABLED",
|
||||
"version": "undefined"
|
||||
},
|
||||
{
|
||||
"name": "PUSH_NOTIFICATIONS_ENABLED",
|
||||
"version": "undefined"
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package com.tangem.core.navigation.settings
|
||||
|
||||
class DummySettingsManager : SettingsManager {
|
||||
override fun openSettings() { /* no-op */ }
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package com.tangem.core.navigation.settings
|
||||
|
||||
interface SettingsManager {
|
||||
fun openSettings()
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ dependencies {
|
|||
|
||||
/** Other libraries */
|
||||
implementation(deps.compose.accompanist.systemUiController)
|
||||
implementation(deps.compose.accompanist.permission)
|
||||
implementation(deps.material)
|
||||
implementation(deps.compose.shimmer)
|
||||
implementation(deps.kotlin.immutable.collections)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
package com.tangem.core.ui.utils
|
||||
|
||||
import android.Manifest
|
||||
import android.os.Build
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.MutableState
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.google.accompanist.permissions.shouldShowRationale
|
||||
|
||||
/**
|
||||
* Returns push permission requester.
|
||||
* Handles granting permission from app settings.
|
||||
*/
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
fun requestPushPermission(
|
||||
isFirstTimeAsking: Boolean,
|
||||
isClicked: MutableState<Boolean>,
|
||||
onAllow: () -> Unit,
|
||||
onDeny: () -> Unit,
|
||||
onOpenSettings: () -> Unit,
|
||||
): () -> Unit {
|
||||
val permissionState = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
val permission = Manifest.permission.POST_NOTIFICATIONS
|
||||
val tempPermissionState = rememberPermissionState(permission = permission)
|
||||
rememberPermissionState(permission = permission) {
|
||||
when {
|
||||
it -> onAllow()
|
||||
!tempPermissionState.status.shouldShowRationale && !isFirstTimeAsking -> onOpenSettings()
|
||||
else -> onDeny()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
// Check if user granted permission and close bottom sheet
|
||||
LaunchedEffect(key1 = permissionState?.status, isClicked) {
|
||||
if (!isClicked.value) return@LaunchedEffect
|
||||
if (permissionState?.status?.isGranted == true) {
|
||||
onAllow()
|
||||
} else {
|
||||
onDeny()
|
||||
}
|
||||
}
|
||||
|
||||
return if (permissionState == null) {
|
||||
onOpenSettings
|
||||
} else {
|
||||
permissionState::launchPermissionRequest
|
||||
}
|
||||
}
|
||||
|
|
@ -16,26 +16,27 @@ internal class DefaultPermissionRepository(
|
|||
private val appPreferencesStore: AppPreferencesStore,
|
||||
) : PermissionRepository {
|
||||
|
||||
override suspend fun shouldInitiallyShowPermissionScreen(permission: Int): Boolean {
|
||||
override suspend fun shouldInitiallyShowPermissionScreen(permission: String): Boolean {
|
||||
val key = getShouldShowInitialPermissionScreen(permission)
|
||||
val initialPermissionScreen = appPreferencesStore.getSyncOrDefault(key = key, default = true)
|
||||
if (initialPermissionScreen) appPreferencesStore.store(key = key, value = false)
|
||||
return initialPermissionScreen
|
||||
}
|
||||
|
||||
override suspend fun isFirstTimeAskingPermission(permission: Int): Boolean = appPreferencesStore.getSyncOrDefault(
|
||||
key = getIsFirstTimeAskingPermission(permission),
|
||||
default = true,
|
||||
)
|
||||
override suspend fun isFirstTimeAskingPermission(permission: String): Boolean =
|
||||
appPreferencesStore.getSyncOrDefault(
|
||||
key = getIsFirstTimeAskingPermission(permission),
|
||||
default = true,
|
||||
)
|
||||
|
||||
override suspend fun setFirstTimeAskingPermission(permission: Int, value: Boolean) {
|
||||
override suspend fun setFirstTimeAskingPermission(permission: String, value: Boolean) {
|
||||
appPreferencesStore.store(
|
||||
key = getIsFirstTimeAskingPermission(permission),
|
||||
value = value,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun shouldAskPermission(permission: Int): Boolean {
|
||||
override suspend fun shouldAskPermission(permission: String): Boolean {
|
||||
val shouldAskPermission = appPreferencesStore.getSyncOrDefault(getShouldShowPermission(permission), true)
|
||||
val delayedLaunches = appPreferencesStore.getSyncOrDefault(getPermissionLaunchCount(permission), 0)
|
||||
val delayedDays = appPreferencesStore.getSyncOrDefault(getPermissionDaysCount(permission), 0)
|
||||
|
|
@ -47,11 +48,11 @@ internal class DefaultPermissionRepository(
|
|||
return shouldAskPermission && isDaysDelayed && isLaunchesDelayed
|
||||
}
|
||||
|
||||
override suspend fun neverAskPermission(permission: Int) {
|
||||
override suspend fun neverAskPermission(permission: String) {
|
||||
appPreferencesStore.store(key = getShouldShowPermission(permission), value = false)
|
||||
}
|
||||
|
||||
override suspend fun delayPermissionAsking(permission: Int) {
|
||||
override suspend fun delayPermissionAsking(permission: String) {
|
||||
appPreferencesStore.editData {
|
||||
val appLaunchCounter = it.getOrDefault(PreferencesKeys.APP_LAUNCH_COUNT_KEY, 0)
|
||||
val nowMillis = SystemClock.elapsedRealtime()
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class DelayPermissionRequestUseCase(
|
|||
private val repository: PermissionRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(permission: Int): Either<Throwable, Unit> = Either.catch {
|
||||
suspend operator fun invoke(permission: String): Either<Throwable, Unit> = Either.catch {
|
||||
repository.delayPermissionAsking(permission)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import com.tangem.domain.settings.repositories.PermissionRepository
|
|||
|
||||
class IsFirstTimeAskingPermissionUseCase(private val repository: PermissionRepository) {
|
||||
|
||||
suspend operator fun invoke(permission: Int): Either<Throwable, Boolean> = Either.catch {
|
||||
suspend operator fun invoke(permission: String): Either<Throwable, Boolean> = Either.catch {
|
||||
repository.isFirstTimeAskingPermission(permission)
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ class NeverRequestPermissionUseCase(
|
|||
private val repository: PermissionRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(permission: Int): Either<Throwable, Unit> = Either.catch {
|
||||
suspend operator fun invoke(permission: String): Either<Throwable, Unit> = Either.catch {
|
||||
repository.neverAskPermission(permission)
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import com.tangem.domain.settings.repositories.PermissionRepository
|
|||
|
||||
class SetFirstTimeAskingPermissionUseCase(private val repository: PermissionRepository) {
|
||||
|
||||
suspend operator fun invoke(permission: Int): Either<Throwable, Unit> = Either.catch {
|
||||
suspend operator fun invoke(permission: String): Either<Throwable, Unit> = Either.catch {
|
||||
repository.setFirstTimeAskingPermission(permission, false)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,5 +6,5 @@ class ShouldAskPermissionUseCase(
|
|||
private val repository: PermissionRepository,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(permission: Int): Boolean = repository.shouldAskPermission(permission)
|
||||
suspend operator fun invoke(permission: String): Boolean = repository.shouldAskPermission(permission)
|
||||
}
|
||||
|
|
@ -5,7 +5,7 @@ import com.tangem.domain.settings.repositories.PermissionRepository
|
|||
|
||||
class ShouldInitiallyAskPermissionUseCase(private val repository: PermissionRepository) {
|
||||
|
||||
suspend operator fun invoke(permission: Int): Either<Throwable, Boolean> = Either.catch {
|
||||
suspend operator fun invoke(permission: String): Either<Throwable, Boolean> = Either.catch {
|
||||
repository.shouldInitiallyShowPermissionScreen(permission)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,34 +6,34 @@ interface PermissionRepository {
|
|||
* Return true if should display screen ONCE asking to allow [permission].
|
||||
* False otherwise or screen already was displayed
|
||||
*/
|
||||
suspend fun shouldInitiallyShowPermissionScreen(permission: Int): Boolean
|
||||
suspend fun shouldInitiallyShowPermissionScreen(permission: String): Boolean
|
||||
|
||||
/**
|
||||
* Indicates which time [permission] was asked via platform dialog.
|
||||
* NOTE: Use this method to indicate either reroute to settings or display platform dialog.
|
||||
*/
|
||||
suspend fun isFirstTimeAskingPermission(permission: Int): Boolean
|
||||
suspend fun isFirstTimeAskingPermission(permission: String): Boolean
|
||||
|
||||
/**
|
||||
* Sets value indicating that [permission] was asked via platform dialog.
|
||||
* NOTE: Use this method to indicate either reroute to settings or display platform dialog.
|
||||
*/
|
||||
suspend fun setFirstTimeAskingPermission(permission: Int, value: Boolean)
|
||||
suspend fun setFirstTimeAskingPermission(permission: String, value: Boolean)
|
||||
|
||||
/**
|
||||
* Is clear to ask [permission].
|
||||
* User could already granted or permanently denied permission
|
||||
* Or there is an active delay before next request
|
||||
*/
|
||||
suspend fun shouldAskPermission(permission: Int): Boolean
|
||||
suspend fun shouldAskPermission(permission: String): Boolean
|
||||
|
||||
/**
|
||||
* Permanently deny [permission] and never request again
|
||||
*/
|
||||
suspend fun neverAskPermission(permission: Int)
|
||||
suspend fun neverAskPermission(permission: String)
|
||||
|
||||
/**
|
||||
* Delay next [permission] request for some time or active sessions
|
||||
*/
|
||||
suspend fun delayPermissionAsking(permission: Int)
|
||||
suspend fun delayPermissionAsking(permission: String)
|
||||
}
|
||||
1
features/push-notifications/api/.gitignore
vendored
Normal file
1
features/push-notifications/api/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
15
features/push-notifications/api/build.gradle.kts
Normal file
15
features/push-notifications/api/build.gradle.kts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.features.pushnotifications.api"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
/** AndroidX */
|
||||
implementation(deps.androidx.fragment.ktx)
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.features.pushnotifications.api.featuretoggles
|
||||
|
||||
/**
|
||||
* Push notifications feature toggles
|
||||
*/
|
||||
interface PushNotificationsFeatureToggles {
|
||||
/** Availability of push notifications */
|
||||
val isRedesignedSendEnabled: Boolean
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.features.pushnotifications.api.navigation
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
|
||||
interface PushNotificationsRouter {
|
||||
|
||||
fun entryFragment(): Fragment
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package com.tangem.features.pushnotifications.api.utils
|
||||
|
||||
import android.Manifest
|
||||
import android.os.Build
|
||||
|
||||
val PUSH_PERMISSION = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
} else {
|
||||
"android.permission.POST_NOTIFICATIONS"
|
||||
}
|
||||
1
features/push-notifications/impl/.gitignore
vendored
Normal file
1
features/push-notifications/impl/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
45
features/push-notifications/impl/build.gradle.kts
Normal file
45
features/push-notifications/impl/build.gradle.kts
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
plugins {
|
||||
alias(deps.plugins.android.library)
|
||||
alias(deps.plugins.kotlin.android)
|
||||
alias(deps.plugins.kotlin.kapt)
|
||||
alias(deps.plugins.hilt.android)
|
||||
id("configuration")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "com.tangem.feature.pushnotifications.impl"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
/** AndroidX */
|
||||
implementation(deps.androidx.fragment.ktx)
|
||||
implementation(deps.androidx.activity.compose)
|
||||
|
||||
/** Compose */
|
||||
implementation(deps.compose.foundation)
|
||||
implementation(deps.compose.accompanist.systemUiController)
|
||||
implementation(deps.compose.accompanist.permission)
|
||||
|
||||
/** Other dependencies */
|
||||
implementation(deps.timber)
|
||||
implementation(deps.arrow.core)
|
||||
implementation(deps.kotlin.immutable.collections)
|
||||
|
||||
/** Core modules */
|
||||
implementation(projects.core.ui)
|
||||
implementation(projects.core.featuretoggles)
|
||||
|
||||
/** Common modules */
|
||||
implementation(projects.common.routing)
|
||||
|
||||
/** Domain module */
|
||||
implementation(projects.domain.settings)
|
||||
|
||||
/** Feature modules */
|
||||
implementation(projects.features.pushNotifications.api)
|
||||
|
||||
/** DI */
|
||||
implementation(deps.hilt.android)
|
||||
implementation(project(":core:navigation"))
|
||||
kapt(deps.hilt.kapt)
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package com.tangem.features.pushnotifications.impl
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.tangem.core.ui.UiDependencies
|
||||
import com.tangem.core.ui.components.NavigationBar3ButtonsScrim
|
||||
import com.tangem.core.ui.screen.ComposeFragment
|
||||
import com.tangem.features.pushnotifications.impl.presentation.ui.PushNotificationsScreen
|
||||
import com.tangem.features.pushnotifications.impl.presentation.viewmodel.PushNotificationViewModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
internal class PushNotificationsFragment : ComposeFragment() {
|
||||
|
||||
@Inject
|
||||
override lateinit var uiDependencies: UiDependencies
|
||||
|
||||
private val viewModel by viewModels<PushNotificationViewModel>()
|
||||
|
||||
@Composable
|
||||
override fun ScreenContent(modifier: Modifier) {
|
||||
BackHandler(onBack = requireActivity()::finish)
|
||||
NavigationBar3ButtonsScrim()
|
||||
PushNotificationsScreen(
|
||||
onShowAllow = viewModel::onAllowPermission,
|
||||
onAllow = viewModel::onAllowedPermission,
|
||||
onLater = viewModel::onAskLater,
|
||||
onOpenSettings = viewModel::openSettings,
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
/** Create push notifications fragment instance */
|
||||
fun create(): PushNotificationsFragment = PushNotificationsFragment()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.features.pushnotifications.impl.di
|
||||
|
||||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||
import com.tangem.features.pushnotifications.api.featuretoggles.PushNotificationsFeatureToggles
|
||||
import com.tangem.features.pushnotifications.impl.featuretoggles.DefaultPushNotificationsFeatureToggles
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* DI module provides implementation of [PushNotificationsFeatureToggles]
|
||||
*/
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
internal object PushNotificationsFeatureTogglesModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideSendFeatureToggles(featureTogglesManager: FeatureTogglesManager): PushNotificationsFeatureToggles {
|
||||
return DefaultPushNotificationsFeatureToggles(featureTogglesManager = featureTogglesManager)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.features.pushnotifications.impl.di
|
||||
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter
|
||||
import com.tangem.features.pushnotifications.impl.navigation.DefaultPushNotificationsRouter
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ActivityComponent
|
||||
import dagger.hilt.android.scopes.ActivityScoped
|
||||
|
||||
/**
|
||||
* DI module provides implementation of [PushNotificationsRouter]
|
||||
*/
|
||||
@Module
|
||||
@InstallIn(ActivityComponent::class)
|
||||
object PushNotificationsModule {
|
||||
|
||||
@Provides
|
||||
@ActivityScoped
|
||||
fun provideDisclaimerRouter(appRouter: AppRouter): PushNotificationsRouter {
|
||||
return DefaultPushNotificationsRouter(appRouter)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.features.pushnotifications.impl.featuretoggles
|
||||
|
||||
import com.tangem.core.featuretoggle.manager.FeatureTogglesManager
|
||||
import com.tangem.features.pushnotifications.api.featuretoggles.PushNotificationsFeatureToggles
|
||||
|
||||
internal class DefaultPushNotificationsFeatureToggles(
|
||||
private val featureTogglesManager: FeatureTogglesManager,
|
||||
) : PushNotificationsFeatureToggles {
|
||||
override val isRedesignedSendEnabled: Boolean
|
||||
get() = featureTogglesManager.isFeatureEnabled("PUSH_NOTIFICATIONS_ENABLED")
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.features.pushnotifications.impl.navigation
|
||||
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.tangem.common.routing.AppRoute
|
||||
import com.tangem.common.routing.AppRouter
|
||||
import com.tangem.features.pushnotifications.impl.PushNotificationsFragment
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class DefaultPushNotificationsRouter @Inject constructor(
|
||||
private val appRouter: AppRouter,
|
||||
) : InnerPushNotificationsRouter {
|
||||
|
||||
override fun entryFragment(): Fragment = PushNotificationsFragment.create()
|
||||
|
||||
override fun openHome() {
|
||||
appRouter.push(AppRoute.Home)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package com.tangem.features.pushnotifications.impl.navigation
|
||||
|
||||
import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter
|
||||
|
||||
interface InnerPushNotificationsRouter : PushNotificationsRouter {
|
||||
|
||||
fun openHome()
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
package com.tangem.features.pushnotifications.impl.presentation.ui
|
||||
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.tangem.core.ui.components.showcase.Showcase
|
||||
import com.tangem.core.ui.components.showcase.model.ShowcaseButtonModel
|
||||
import com.tangem.core.ui.components.showcase.model.ShowcaseItemModel
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.utils.requestPushPermission
|
||||
import com.tangem.feature.pushnotifications.impl.R
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun PushNotificationsScreen(
|
||||
onShowAllow: () -> Unit,
|
||||
onAllow: () -> Unit,
|
||||
onLater: () -> Unit,
|
||||
onOpenSettings: () -> Unit,
|
||||
) {
|
||||
val isClicked = remember { mutableStateOf(false) }
|
||||
val requestPushPermission = requestPushPermission(
|
||||
isFirstTimeAsking = true,
|
||||
isClicked = isClicked,
|
||||
onAllow = onAllow,
|
||||
onDeny = onLater,
|
||||
onOpenSettings = onOpenSettings,
|
||||
)
|
||||
|
||||
Showcase(
|
||||
headerIconRes = R.drawable.ic_notifications_unread_24,
|
||||
headerText = resourceReference(R.string.user_push_notification_agreement_header),
|
||||
showcaseItems = persistentListOf(
|
||||
ShowcaseItemModel(
|
||||
R.drawable.ic_rocket_launch_24,
|
||||
resourceReference(R.string.user_push_notification_agreement_argument_one),
|
||||
),
|
||||
ShowcaseItemModel(
|
||||
R.drawable.ic_storefront_24,
|
||||
resourceReference(R.string.user_push_notification_agreement_argument_two),
|
||||
),
|
||||
),
|
||||
primaryButton = ShowcaseButtonModel(
|
||||
buttonText = resourceReference(R.string.common_allow),
|
||||
onClick = {
|
||||
isClicked.value = true
|
||||
onShowAllow()
|
||||
requestPushPermission()
|
||||
},
|
||||
),
|
||||
secondaryButton = ShowcaseButtonModel(
|
||||
buttonText = resourceReference(R.string.common_later),
|
||||
onClick = onLater,
|
||||
),
|
||||
modifier = Modifier.systemBarsPadding(),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package com.tangem.features.pushnotifications.impl.presentation.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.tangem.core.navigation.settings.SettingsManager
|
||||
import com.tangem.domain.settings.DelayPermissionRequestUseCase
|
||||
import com.tangem.domain.settings.NeverRequestPermissionUseCase
|
||||
import com.tangem.domain.settings.SetFirstTimeAskingPermissionUseCase
|
||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||
import com.tangem.features.pushnotifications.impl.navigation.DefaultPushNotificationsRouter
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
internal class PushNotificationViewModel @Inject constructor(
|
||||
private val setFirstTimeAskingPermissionUseCase: SetFirstTimeAskingPermissionUseCase,
|
||||
private val delayPermissionRequestUseCase: DelayPermissionRequestUseCase,
|
||||
private val neverRequestPermissionUseCase: NeverRequestPermissionUseCase,
|
||||
private val router: DefaultPushNotificationsRouter,
|
||||
private val settingsManager: SettingsManager,
|
||||
) : ViewModel(), PushNotificationsClickIntents {
|
||||
|
||||
override fun onAskLater() {
|
||||
viewModelScope.launch {
|
||||
delayPermissionRequestUseCase(PUSH_PERMISSION)
|
||||
setFirstTimeAskingPermissionUseCase(PUSH_PERMISSION)
|
||||
}
|
||||
router.openHome()
|
||||
}
|
||||
|
||||
override fun onAllowPermission() {
|
||||
viewModelScope.launch {
|
||||
setFirstTimeAskingPermissionUseCase(PUSH_PERMISSION)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAllowedPermission() {
|
||||
viewModelScope.launch {
|
||||
neverRequestPermissionUseCase(PUSH_PERMISSION)
|
||||
}
|
||||
router.openHome()
|
||||
}
|
||||
|
||||
override fun openSettings() = settingsManager.openSettings()
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.features.pushnotifications.impl.presentation.viewmodel
|
||||
|
||||
internal interface PushNotificationsClickIntents {
|
||||
fun onAskLater()
|
||||
|
||||
fun onAllowPermission()
|
||||
|
||||
fun onAllowedPermission()
|
||||
|
||||
fun openSettings()
|
||||
}
|
||||
|
|
@ -180,6 +180,9 @@ include(":features:details:impl")
|
|||
|
||||
include(":features:disclaimer:api")
|
||||
include(":features:disclaimer:impl")
|
||||
|
||||
include(":features:push-notifications:api")
|
||||
include(":features:push-notifications:impl")
|
||||
// endregion Feature modules
|
||||
|
||||
// region Domain modules
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue