Updated on 2026-08-14
This commit is contained in:
parent
ba32fed132
commit
9ef9542750
30 changed files with 452 additions and 157 deletions
|
|
@ -3,10 +3,16 @@ package com.tangem.tap.data
|
|||
import com.google.firebase.messaging.FirebaseMessaging
|
||||
import com.tangem.utils.notifications.PushNotificationsTokenProvider
|
||||
import kotlinx.coroutines.tasks.await
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class FirebasePushNotificationsTokenProvider @Inject constructor() : PushNotificationsTokenProvider {
|
||||
override suspend fun getToken(): String {
|
||||
return FirebaseMessaging.getInstance().token.await()
|
||||
return try {
|
||||
FirebaseMessaging.getInstance().token.await()
|
||||
} catch (ex: Exception) {
|
||||
Timber.e(ex)
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,8 @@ import com.tangem.features.nft.component.NFTComponent
|
|||
import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent
|
||||
import com.tangem.features.onramp.component.*
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacksStub
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsParams
|
||||
import com.tangem.features.send.v2.api.NFTSendComponent
|
||||
import com.tangem.features.send.v2.api.SendComponent
|
||||
import com.tangem.features.staking.api.StakingComponent
|
||||
|
|
@ -370,7 +372,9 @@ internal class ChildFactory @Inject constructor(
|
|||
is AppRoute.PushNotification -> {
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = Unit,
|
||||
params = PushNotificationsParams(
|
||||
modelCallbacks = PushNotificationsModelCallbacksStub(),
|
||||
),
|
||||
componentFactory = pushNotificationsComponentFactory,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,6 +134,18 @@ object PreferencesKeys {
|
|||
|
||||
val NOTIFICATIONS_ENABLED_STATES_KEY by lazy { stringPreferencesKey(name = "notificationsEnabledStates") }
|
||||
|
||||
val NOTIFICATIONS_AUTOMATICALLY_ENABLED_STATES_KEY by lazy {
|
||||
stringPreferencesKey(
|
||||
name = "notificationsAutomaticallyEnabledStates",
|
||||
)
|
||||
}
|
||||
|
||||
val NOTIFICATIONS_USER_ALLOW_SEND_ADDRESSES_KEY by lazy {
|
||||
booleanPreferencesKey(
|
||||
name = "userAllowSendAddresses",
|
||||
)
|
||||
}
|
||||
|
||||
val TRON_NETWORK_FEE_NOTIFICATION_SHOW_COUNT_KEY by lazy {
|
||||
intPreferencesKey(name = "tronNetworkFeeNotificationShowCount")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ fun Showcase(
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun ShowcaseButtons(
|
||||
fun ShowcaseButtons(
|
||||
primaryButtonText: TextReference,
|
||||
secondaryButtonText: TextReference,
|
||||
onPrimaryClick: () -> Unit,
|
||||
|
|
|
|||
|
|
@ -82,4 +82,36 @@ internal class DefaultNotificationsRepository @Inject constructor(
|
|||
NotificationsEligibleNetworkConverter.convert(it)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun shouldShowSubscribeOnNotificationsAfterUpdate(): Boolean {
|
||||
return appPreferencesStore.getSyncOrNull(
|
||||
key = PreferencesKeys.NOTIFICATIONS_USER_ALLOW_SEND_ADDRESSES_KEY,
|
||||
) == null
|
||||
}
|
||||
|
||||
override suspend fun isUserAllowToSubscribeOnPushNotifications(): Boolean {
|
||||
return appPreferencesStore.getSyncOrDefault(
|
||||
key = PreferencesKeys.NOTIFICATIONS_USER_ALLOW_SEND_ADDRESSES_KEY,
|
||||
default = false,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun setUserAllowToSubscribeOnPushNotifications(value: Boolean) {
|
||||
appPreferencesStore.store(PreferencesKeys.NOTIFICATIONS_USER_ALLOW_SEND_ADDRESSES_KEY, value)
|
||||
}
|
||||
|
||||
override suspend fun getWalletAutomaticallyEnabledList(): List<String> = appPreferencesStore
|
||||
.getObjectMapSync<Boolean>(PreferencesKeys.NOTIFICATIONS_AUTOMATICALLY_ENABLED_STATES_KEY).map {
|
||||
it.key
|
||||
}
|
||||
|
||||
override suspend fun setNotificationsWasEnabledAutomatically(userWalletId: String) {
|
||||
appPreferencesStore.editData {
|
||||
it.setObjectMap(
|
||||
key = PreferencesKeys.NOTIFICATIONS_AUTOMATICALLY_ENABLED_STATES_KEY,
|
||||
value = it.getObjectMap<Boolean>(PreferencesKeys.NOTIFICATIONS_AUTOMATICALLY_ENABLED_STATES_KEY)
|
||||
.plus(userWalletId to true),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -21,4 +21,14 @@ interface NotificationsRepository {
|
|||
|
||||
@Throws
|
||||
suspend fun getEligibleNetworks(): List<NotificationsEligibleNetwork>
|
||||
|
||||
suspend fun shouldShowSubscribeOnNotificationsAfterUpdate(): Boolean
|
||||
|
||||
suspend fun isUserAllowToSubscribeOnPushNotifications(): Boolean
|
||||
|
||||
suspend fun setUserAllowToSubscribeOnPushNotifications(value: Boolean)
|
||||
|
||||
suspend fun getWalletAutomaticallyEnabledList(): List<String>
|
||||
|
||||
suspend fun setNotificationsWasEnabledAutomatically(userWalletId: String)
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.domain.wallets.usecase
|
||||
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Use case for retrieving wallets where automatically enabling push notifications was not applied.
|
||||
* * This use case filters out wallets that have already had push notifications automatically enabled
|
||||
* from the complete list of user wallets, returning only those wallets that still need to have
|
||||
* push notifications automatically enabled.
|
||||
* * @property userWalletsListManager Manager for user wallets list operations
|
||||
* @property dispatchers Coroutine dispatcher provider for background operations
|
||||
*/
|
||||
class GetWalletsForAutomaticallyPushEnablingUseCase @Inject constructor(
|
||||
private val userWalletsListManager: UserWalletsListManager,
|
||||
private val dispatchers: CoroutineDispatcherProvider,
|
||||
) {
|
||||
|
||||
suspend operator fun invoke(walletsListWherePushWasEnabled: List<UserWalletId>): List<UserWalletId> =
|
||||
withContext(dispatchers.default) {
|
||||
val allLocalWallets = userWalletsListManager.userWalletsSync.map { it.walletId }
|
||||
allLocalWallets - walletsListWherePushWasEnabled.toSet()
|
||||
}
|
||||
}
|
||||
|
|
@ -37,6 +37,7 @@ dependencies {
|
|||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.card)
|
||||
implementation(projects.domain.settings)
|
||||
implementation(projects.domain.notifications)
|
||||
|
||||
/** Feature modules */
|
||||
implementation(projects.features.disclaimer.api)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.tangem.features.disclaimer.impl.entity
|
|||
internal data class DisclaimerUM(
|
||||
val url: String,
|
||||
val isTosAccepted: Boolean,
|
||||
val onAccept: (Boolean) -> Unit,
|
||||
val onAccept: () -> Unit,
|
||||
val popBack: () -> Unit,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import com.tangem.core.decompose.model.ParamsContainer
|
|||
import com.tangem.core.decompose.navigation.Router
|
||||
import com.tangem.core.navigation.finisher.AppFinisher
|
||||
import com.tangem.domain.card.repository.CardRepository
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
import com.tangem.domain.settings.NeverRequestPermissionUseCase
|
||||
import com.tangem.domain.settings.NeverToInitiallyAskPermissionUseCase
|
||||
import com.tangem.features.disclaimer.api.components.DisclaimerComponent
|
||||
|
|
@ -26,6 +27,7 @@ internal class DisclaimerModel @Inject constructor(
|
|||
private val neverToInitiallyAskPermissionUseCase: NeverToInitiallyAskPermissionUseCase,
|
||||
private val neverRequestPermissionUseCase: NeverRequestPermissionUseCase,
|
||||
private val appFinisher: AppFinisher,
|
||||
private val notificationsRepository: NotificationsRepository,
|
||||
paramsContainer: ParamsContainer,
|
||||
) : Model() {
|
||||
|
||||
|
|
@ -40,12 +42,12 @@ internal class DisclaimerModel @Inject constructor(
|
|||
),
|
||||
)
|
||||
|
||||
private fun onAccept(shouldAskPushPermission: Boolean) = modelScope.launch {
|
||||
private fun onAccept() = modelScope.launch {
|
||||
if (params.isTosAccepted) {
|
||||
router.pop()
|
||||
} else {
|
||||
cardRepository.acceptTangemTOS()
|
||||
|
||||
val shouldAskPushPermission = notificationsRepository.shouldShowSubscribeOnNotificationsAfterUpdate()
|
||||
if (shouldAskPushPermission) {
|
||||
router.push(AppRoute.PushNotification)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.testTag
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.google.accompanist.web.WebView
|
||||
import com.google.accompanist.web.WebViewNavigator
|
||||
import com.google.accompanist.web.rememberWebViewNavigator
|
||||
|
|
@ -39,7 +36,6 @@ import com.tangem.features.disclaimer.impl.R
|
|||
import com.tangem.features.disclaimer.impl.entity.DisclaimerUM
|
||||
import com.tangem.features.disclaimer.impl.entity.DummyDisclaimer
|
||||
import com.tangem.features.disclaimer.impl.local.localTermsOfServices
|
||||
import com.tangem.features.pushnotifications.api.utils.getPushPermissionOrNull
|
||||
import com.tangem.utils.coroutines.JobHolder
|
||||
import com.tangem.utils.coroutines.withDebounce
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
|
@ -167,15 +163,11 @@ private fun WebViewNavigator.loadLocalToS() {
|
|||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
private fun BoxScope.DisclaimerButton(onAccept: (Boolean) -> Unit) {
|
||||
val isPermissionGranted = getPushPermissionOrNull()?.let { permission ->
|
||||
rememberPermissionState(permission = permission).status.isGranted
|
||||
} ?: true
|
||||
private fun BoxScope.DisclaimerButton(onAccept: () -> Unit) {
|
||||
PrimaryButton(
|
||||
text = stringResourceSafe(id = R.string.common_accept),
|
||||
onClick = { onAccept(!isPermissionGranted) },
|
||||
onClick = onAccept,
|
||||
colors = ButtonColors(
|
||||
containerColor = TangemColorPalette.Light4,
|
||||
contentColor = TangemColorPalette.Dark6,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.features.pushnotifications.api
|
||||
|
||||
import com.tangem.core.decompose.factory.ComponentFactory
|
||||
import com.tangem.core.ui.decompose.ComposableBottomSheetComponent
|
||||
|
||||
interface PushNotificationsBottomSheetComponent : ComposableBottomSheetComponent {
|
||||
|
||||
interface Factory : ComponentFactory<PushNotificationsParams, PushNotificationsBottomSheetComponent>
|
||||
}
|
||||
|
|
@ -5,5 +5,5 @@ import com.tangem.core.ui.decompose.ComposableContentComponent
|
|||
|
||||
interface PushNotificationsComponent : ComposableContentComponent {
|
||||
|
||||
interface Factory : ComponentFactory<Unit, PushNotificationsComponent>
|
||||
interface Factory : ComponentFactory<PushNotificationsParams, PushNotificationsComponent>
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.features.pushnotifications.api
|
||||
|
||||
interface PushNotificationsModelCallbacks {
|
||||
fun onAllowSystemPermission()
|
||||
fun onDenySystemPermission()
|
||||
fun onDismiss()
|
||||
}
|
||||
|
||||
class PushNotificationsModelCallbacksStub(
|
||||
val onAllowSystemPermission: () -> Unit = {},
|
||||
val onDenySystemPermission: () -> Unit = {},
|
||||
val onDismiss: () -> Unit = {},
|
||||
) : PushNotificationsModelCallbacks {
|
||||
override fun onAllowSystemPermission() = onAllowSystemPermission.invoke()
|
||||
override fun onDenySystemPermission() = onDenySystemPermission.invoke()
|
||||
override fun onDismiss() = onDismiss.invoke()
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package com.tangem.features.pushnotifications.api
|
||||
|
||||
data class PushNotificationsParams(
|
||||
val isBottomSheet: Boolean = false,
|
||||
val modelCallbacks: PushNotificationsModelCallbacks,
|
||||
)
|
||||
|
|
@ -16,6 +16,8 @@ dependencies {
|
|||
implementation(deps.androidx.activity.compose)
|
||||
|
||||
/** Compose */
|
||||
implementation(deps.compose.material3)
|
||||
implementation(deps.compose.ui.tooling)
|
||||
implementation(deps.compose.foundation)
|
||||
implementation(deps.compose.accompanist.systemUiController)
|
||||
implementation(deps.compose.accompanist.permission)
|
||||
|
|
@ -39,6 +41,7 @@ dependencies {
|
|||
/** Domain module */
|
||||
implementation(projects.domain.settings)
|
||||
implementation(projects.domain.notifications.toggles)
|
||||
implementation(projects.domain.notifications)
|
||||
|
||||
/** Feature modules */
|
||||
implementation(projects.features.pushNotifications.api)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
package com.tangem.features.pushnotifications.impl
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import com.tangem.core.decompose.context.AppComponentContext
|
||||
import com.tangem.core.decompose.model.getOrCreateModel
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsBottomSheetComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsParams
|
||||
import com.tangem.features.pushnotifications.impl.model.PushNotificationsModel
|
||||
import com.tangem.features.pushnotifications.impl.presentation.ui.PushNotificationsBottomSheet
|
||||
import com.tangem.features.pushnotifications.impl.presentation.ui.PushNotificationsContent
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
||||
internal class DefaultPushNotificationsBottomSheetComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted private val params: PushNotificationsParams,
|
||||
) : PushNotificationsBottomSheetComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: PushNotificationsModel = getOrCreateModel(params)
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : PushNotificationsBottomSheetComponent.Factory {
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: PushNotificationsParams,
|
||||
): DefaultPushNotificationsBottomSheetComponent
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
params.modelCallbacks.onDismiss()
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun BottomSheet() {
|
||||
val state by model.state.collectAsState()
|
||||
val bottomSheetConfig = remember(key1 = this) {
|
||||
TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = ::dismiss,
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
)
|
||||
}
|
||||
|
||||
PushNotificationsBottomSheet(
|
||||
config = bottomSheetConfig,
|
||||
) {
|
||||
PushNotificationsContent(
|
||||
onAllowClick = model::onAllowClick,
|
||||
onLaterClick = model::onLaterClick,
|
||||
onAllowPermission = model::onAllowPermission,
|
||||
onDenyPermission = model::onDenyPermission,
|
||||
showNotificationsInfo = state.showInfoAboutNotifications,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import com.tangem.core.decompose.model.getOrCreateModel
|
|||
import com.tangem.core.ui.components.NavigationBar3ButtonsScrim
|
||||
import com.tangem.core.ui.utils.findActivity
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsParams
|
||||
import com.tangem.features.pushnotifications.impl.model.PushNotificationsModel
|
||||
import com.tangem.features.pushnotifications.impl.presentation.ui.PushNotificationsScreen
|
||||
import dagger.assisted.Assisted
|
||||
|
|
@ -19,7 +20,7 @@ import dagger.assisted.AssistedInject
|
|||
|
||||
internal class DefaultPushNotificationsComponent @AssistedInject constructor(
|
||||
@Assisted appComponentContext: AppComponentContext,
|
||||
@Assisted params: Unit,
|
||||
@Assisted private val params: PushNotificationsParams,
|
||||
) : PushNotificationsComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: PushNotificationsModel = getOrCreateModel(params)
|
||||
|
|
@ -31,8 +32,8 @@ internal class DefaultPushNotificationsComponent @AssistedInject constructor(
|
|||
BackHandler(onBack = { activity.finish() })
|
||||
NavigationBar3ButtonsScrim()
|
||||
PushNotificationsScreen(
|
||||
onRequest = model::onRequest,
|
||||
onNeverRequest = model::onNeverRequest,
|
||||
onAllowClick = model::onAllowClick,
|
||||
onLaterClick = model::onLaterClick,
|
||||
onAllowPermission = model::onAllowPermission,
|
||||
onDenyPermission = model::onDenyPermission,
|
||||
showNotificationsInfo = state.showInfoAboutNotifications,
|
||||
|
|
@ -41,6 +42,9 @@ internal class DefaultPushNotificationsComponent @AssistedInject constructor(
|
|||
|
||||
@AssistedFactory
|
||||
interface Factory : PushNotificationsComponent.Factory {
|
||||
override fun create(context: AppComponentContext, params: Unit): DefaultPushNotificationsComponent
|
||||
override fun create(
|
||||
context: AppComponentContext,
|
||||
params: PushNotificationsParams,
|
||||
): DefaultPushNotificationsComponent
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
package com.tangem.features.pushnotifications.impl.di
|
||||
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsBottomSheetComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsComponent
|
||||
import com.tangem.features.pushnotifications.impl.DefaultPushNotificationsBottomSheetComponent
|
||||
import com.tangem.features.pushnotifications.impl.DefaultPushNotificationsComponent
|
||||
import com.tangem.features.pushnotifications.impl.model.PushNotificationsModel
|
||||
import dagger.Binds
|
||||
|
|
@ -15,6 +17,11 @@ import dagger.multibindings.IntoMap
|
|||
@InstallIn(SingletonComponent::class)
|
||||
internal interface PushNotificationsModule {
|
||||
|
||||
@Binds
|
||||
fun bindBottomSheetComponentFactory(
|
||||
impl: DefaultPushNotificationsBottomSheetComponent.Factory,
|
||||
): PushNotificationsBottomSheetComponent.Factory
|
||||
|
||||
@Binds
|
||||
fun bindComponentFactory(impl: DefaultPushNotificationsComponent.Factory): PushNotificationsComponent.Factory
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package com.tangem.features.pushnotifications.impl.model
|
||||
|
||||
internal interface PushNotificationsClickIntents {
|
||||
fun onRequest()
|
||||
fun onAllowClick()
|
||||
|
||||
fun onNeverRequest()
|
||||
fun onLaterClick()
|
||||
|
||||
fun onAllowPermission()
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,12 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler
|
|||
import com.tangem.core.analytics.models.AnalyticsParam
|
||||
import com.tangem.core.decompose.di.ModelScoped
|
||||
import com.tangem.core.decompose.model.Model
|
||||
import com.tangem.core.decompose.model.ParamsContainer
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
import com.tangem.domain.notifications.toggles.NotificationsFeatureToggles
|
||||
import com.tangem.domain.settings.NeverRequestPermissionUseCase
|
||||
import com.tangem.domain.settings.NeverToInitiallyAskPermissionUseCase
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsParams
|
||||
import com.tangem.features.pushnotifications.api.analytics.PushNotificationAnalyticEvents
|
||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||
import com.tangem.features.pushnotifications.impl.presentation.state.PushNotificationsUM
|
||||
|
|
@ -19,17 +22,22 @@ import kotlinx.coroutines.flow.asStateFlow
|
|||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@Stable
|
||||
@ModelScoped
|
||||
internal class PushNotificationsModel @Inject constructor(
|
||||
paramsContainer: ParamsContainer,
|
||||
override val dispatchers: CoroutineDispatcherProvider,
|
||||
private val neverRequestPermissionUseCase: NeverRequestPermissionUseCase,
|
||||
private val neverToInitiallyAskPermissionUseCase: NeverToInitiallyAskPermissionUseCase,
|
||||
private val appRouter: AppRouter,
|
||||
private val analyticHandler: AnalyticsEventHandler,
|
||||
private val notificationsFeatureToggles: NotificationsFeatureToggles,
|
||||
private val notificationsRepository: NotificationsRepository,
|
||||
) : Model(), PushNotificationsClickIntents {
|
||||
|
||||
val params: PushNotificationsParams = paramsContainer.require()
|
||||
|
||||
private val _state = MutableStateFlow(
|
||||
PushNotificationsUM(
|
||||
showInfoAboutNotifications = notificationsFeatureToggles.isNotificationsEnabled,
|
||||
|
|
@ -38,20 +46,33 @@ internal class PushNotificationsModel @Inject constructor(
|
|||
|
||||
val state = _state.asStateFlow()
|
||||
|
||||
override fun onRequest() {
|
||||
override fun onAllowClick() {
|
||||
if (notificationsFeatureToggles.isNotificationsEnabled) {
|
||||
modelScope.launch {
|
||||
notificationsRepository.setUserAllowToSubscribeOnPushNotifications(true)
|
||||
}
|
||||
}
|
||||
analyticHandler.send(
|
||||
PushNotificationAnalyticEvents.ButtonAllow(AnalyticsParam.ScreensSources.Stories),
|
||||
)
|
||||
}
|
||||
|
||||
override fun onNeverRequest() {
|
||||
override fun onLaterClick() {
|
||||
if (notificationsFeatureToggles.isNotificationsEnabled) {
|
||||
modelScope.launch {
|
||||
notificationsRepository.setUserAllowToSubscribeOnPushNotifications(false)
|
||||
}
|
||||
}
|
||||
analyticHandler.send(
|
||||
PushNotificationAnalyticEvents.ButtonLater(AnalyticsParam.ScreensSources.Stories),
|
||||
)
|
||||
modelScope.launch {
|
||||
neverRequestPermissionUseCase(PUSH_PERMISSION)
|
||||
neverToInitiallyAskPermissionUseCase(PUSH_PERMISSION)
|
||||
appRouter.push(AppRoute.Home)
|
||||
params.modelCallbacks.onDenySystemPermission()
|
||||
if (!params.isBottomSheet) {
|
||||
appRouter.push(AppRoute.Home)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -62,7 +83,10 @@ internal class PushNotificationsModel @Inject constructor(
|
|||
modelScope.launch {
|
||||
neverRequestPermissionUseCase(PUSH_PERMISSION)
|
||||
neverToInitiallyAskPermissionUseCase(PUSH_PERMISSION)
|
||||
appRouter.push(AppRoute.Home)
|
||||
params.modelCallbacks.onAllowSystemPermission()
|
||||
if (!params.isBottomSheet) {
|
||||
appRouter.push(AppRoute.Home)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -73,7 +97,10 @@ internal class PushNotificationsModel @Inject constructor(
|
|||
modelScope.launch {
|
||||
neverRequestPermissionUseCase(PUSH_PERMISSION)
|
||||
neverToInitiallyAskPermissionUseCase(PUSH_PERMISSION)
|
||||
appRouter.push(AppRoute.Home)
|
||||
params.modelCallbacks.onDenySystemPermission()
|
||||
if (!params.isBottomSheet) {
|
||||
appRouter.push(AppRoute.Home)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
package com.tangem.features.pushnotifications.impl.presentation.ui
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.SpacerH28
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfigContent
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheet
|
||||
import com.tangem.core.ui.components.bottomsheets.modal.TangemModalBottomSheetTitle
|
||||
import com.tangem.core.ui.components.showcase.ShowcaseButtons
|
||||
import com.tangem.core.ui.components.showcase.ShowcaseContent
|
||||
import com.tangem.core.ui.components.showcase.model.ShowcaseItemModel
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.requestPushPermission
|
||||
import com.tangem.features.pushnotifications.api.utils.getPushPermissionOrNull
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun PushNotificationsBottomSheet(config: TangemBottomSheetConfig, content: @Composable () -> Unit) {
|
||||
TangemModalBottomSheet<TangemBottomSheetConfigContent>(
|
||||
config = config,
|
||||
title = {
|
||||
TangemModalBottomSheetTitle(
|
||||
endIconRes = R.drawable.ic_close_24,
|
||||
onEndClick = config.onDismissRequest,
|
||||
)
|
||||
},
|
||||
) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
internal fun PushNotificationsContent(
|
||||
onAllowClick: () -> Unit,
|
||||
onLaterClick: () -> Unit,
|
||||
onAllowPermission: () -> Unit,
|
||||
onDenyPermission: () -> Unit,
|
||||
showNotificationsInfo: Boolean,
|
||||
) {
|
||||
val requestPushPermission = requestPushPermission(
|
||||
onAllow = onAllowPermission,
|
||||
onDeny = onDenyPermission,
|
||||
pushPermission = getPushPermissionOrNull(),
|
||||
)
|
||||
|
||||
Column(modifier = Modifier.background(TangemTheme.colors.background.primary)) {
|
||||
ShowcaseContent(
|
||||
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),
|
||||
),
|
||||
).let { baseItems ->
|
||||
if (showNotificationsInfo) {
|
||||
baseItems.add(
|
||||
ShowcaseItemModel(
|
||||
R.drawable.ic_notifications_24,
|
||||
resourceReference(R.string.user_push_notification_agreement_argument_three),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
baseItems
|
||||
}
|
||||
},
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens.spacing40),
|
||||
)
|
||||
SpacerH28()
|
||||
ShowcaseButtons(
|
||||
primaryButtonText = resourceReference(R.string.common_allow),
|
||||
onPrimaryClick = {
|
||||
onAllowClick()
|
||||
requestPushPermission()
|
||||
},
|
||||
secondaryButtonText = resourceReference(R.string.common_later),
|
||||
onSecondaryClick = {
|
||||
onLaterClick()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun Preview_PushNotificationsBottomSheet() {
|
||||
TangemThemePreview {
|
||||
PushNotificationsBottomSheet(
|
||||
config = TangemBottomSheetConfig(
|
||||
isShown = true,
|
||||
onDismissRequest = {},
|
||||
content = TangemBottomSheetConfigContent.Empty,
|
||||
),
|
||||
) {
|
||||
PushNotificationsContent(
|
||||
onAllowClick = {},
|
||||
onLaterClick = {},
|
||||
onAllowPermission = {},
|
||||
onDenyPermission = {},
|
||||
showNotificationsInfo = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -14,8 +14,8 @@ import kotlinx.collections.immutable.persistentListOf
|
|||
|
||||
@Composable
|
||||
internal fun PushNotificationsScreen(
|
||||
onRequest: () -> Unit,
|
||||
onNeverRequest: () -> Unit,
|
||||
onAllowClick: () -> Unit,
|
||||
onLaterClick: () -> Unit,
|
||||
onAllowPermission: () -> Unit,
|
||||
onDenyPermission: () -> Unit,
|
||||
showNotificationsInfo: Boolean,
|
||||
|
|
@ -53,13 +53,15 @@ internal fun PushNotificationsScreen(
|
|||
primaryButton = ShowcaseButtonModel(
|
||||
buttonText = resourceReference(R.string.common_allow),
|
||||
onClick = {
|
||||
onRequest()
|
||||
onAllowClick()
|
||||
requestPushPermission()
|
||||
},
|
||||
),
|
||||
secondaryButton = ShowcaseButtonModel(
|
||||
buttonText = resourceReference(R.string.common_later),
|
||||
onClick = onNeverRequest,
|
||||
onClick = {
|
||||
onLaterClick()
|
||||
},
|
||||
),
|
||||
modifier = Modifier.systemBarsPadding(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import com.tangem.domain.models.scan.ScanResponse
|
|||
import com.tangem.domain.nft.DisableWalletNFTUseCase
|
||||
import com.tangem.domain.nft.EnableWalletNFTUseCase
|
||||
import com.tangem.domain.nft.GetWalletNFTEnabledUseCase
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
import com.tangem.domain.notifications.toggles.NotificationsFeatureToggles
|
||||
import com.tangem.domain.settings.repositories.PermissionRepository
|
||||
import com.tangem.domain.wallets.models.UserWallet
|
||||
|
|
@ -72,6 +73,7 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase,
|
||||
private val settingsManager: SettingsManager,
|
||||
private val permissionsRepository: PermissionRepository,
|
||||
private val notificationsRepository: NotificationsRepository,
|
||||
) : Model() {
|
||||
|
||||
val params: WalletSettingsComponent.Params = paramsContainer.require()
|
||||
|
|
@ -258,6 +260,7 @@ internal class WalletSettingsModel @Inject constructor(
|
|||
if (isGranted) {
|
||||
modelScope.launch {
|
||||
setNotificationsEnabledUseCase(params.userWalletId, true).onRight {
|
||||
notificationsRepository.setNotificationsWasEnabledAutomatically(params.userWalletId.stringValue)
|
||||
analyticsEventHandler.send(PushNotificationAnalyticEvents.NotificationsEnabled(true))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,6 +96,8 @@ dependencies {
|
|||
implementation(projects.domain.visa)
|
||||
implementation(projects.domain.wallets)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.domain.notifications)
|
||||
implementation(projects.domain.notifications.toggles)
|
||||
|
||||
/** Feature Apis */
|
||||
implementation(projects.features.details.api)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import com.tangem.feature.wallet.presentation.wallet.ui.WalletScreen
|
|||
import com.tangem.feature.walletsettings.component.RenameWalletComponent
|
||||
import com.tangem.features.biometry.AskBiometryComponent
|
||||
import com.tangem.features.markets.entry.MarketsEntryComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsBottomSheetComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsParams
|
||||
import dagger.assisted.Assisted
|
||||
import dagger.assisted.AssistedFactory
|
||||
import dagger.assisted.AssistedInject
|
||||
|
|
@ -32,6 +34,7 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
private val renameWalletComponentFactory: RenameWalletComponent.Factory,
|
||||
private val marketsEntryComponentFactory: MarketsEntryComponent.Factory,
|
||||
private val askBiometryComponentFactory: AskBiometryComponent.Factory,
|
||||
private val pushNotificationsBottomSheetComponent: PushNotificationsBottomSheetComponent.Factory,
|
||||
) : ComposableContentComponent, AppComponentContext by appComponentContext {
|
||||
|
||||
private val model: WalletModel = getOrCreateModel()
|
||||
|
|
@ -66,6 +69,13 @@ internal class WalletComponent @AssistedInject constructor(
|
|||
),
|
||||
)
|
||||
}
|
||||
WalletDialogConfig.AskForPushNotifications -> pushNotificationsBottomSheetComponent.create(
|
||||
context = childByContext(componentContext),
|
||||
params = PushNotificationsParams(
|
||||
isBottomSheet = true,
|
||||
modelCallbacks = model.askForPushNotificationsModelCallbacks,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import com.tangem.core.deeplink.global.ReferralDeepLink
|
|||
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||
import com.tangem.domain.common.util.cardTypesResolver
|
||||
import com.tangem.domain.nft.ObserveAndClearNFTCacheIfNeedUseCase
|
||||
import com.tangem.domain.notifications.repository.NotificationsRepository
|
||||
import com.tangem.domain.notifications.toggles.NotificationsFeatureToggles
|
||||
import com.tangem.domain.settings.*
|
||||
import com.tangem.domain.tokens.FetchCurrencyStatusUseCase
|
||||
import com.tangem.domain.tokens.RefreshMultiCurrencyWalletQuotesUseCase
|
||||
|
|
@ -25,6 +27,8 @@ import com.tangem.domain.wallets.models.UserWalletId
|
|||
import com.tangem.domain.wallets.models.isMultiCurrency
|
||||
import com.tangem.domain.wallets.usecase.GetSelectedWalletUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
|
||||
import com.tangem.domain.wallets.usecase.GetWalletsForAutomaticallyPushEnablingUseCase
|
||||
import com.tangem.domain.wallets.usecase.SetNotificationsEnabledUseCase
|
||||
import com.tangem.feature.wallet.child.wallet.model.intents.WalletClickIntents
|
||||
import com.tangem.feature.wallet.presentation.deeplink.WalletDeepLinksHandler
|
||||
import com.tangem.feature.wallet.presentation.router.InnerWalletRouter
|
||||
|
|
@ -36,7 +40,6 @@ import com.tangem.feature.wallet.presentation.wallet.domain.WalletImageResolver
|
|||
import com.tangem.feature.wallet.presentation.wallet.domain.WalletNameMigrationUseCase
|
||||
import com.tangem.feature.wallet.presentation.wallet.loaders.WalletScreenContentLoader
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletStateController
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.PushNotificationsBottomSheetConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletDialogConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.WalletEvent.DemonstrateWalletsScrollPreview.Direction
|
||||
|
|
@ -45,6 +48,7 @@ import com.tangem.feature.wallet.presentation.wallet.state.transformers.*
|
|||
import com.tangem.feature.wallet.presentation.wallet.state.utils.WalletEventSender
|
||||
import com.tangem.feature.wallet.presentation.wallet.utils.ScreenLifecycleProvider
|
||||
import com.tangem.features.biometry.AskBiometryComponent
|
||||
import com.tangem.features.pushnotifications.api.PushNotificationsModelCallbacks
|
||||
import com.tangem.features.pushnotifications.api.utils.PUSH_PERMISSION
|
||||
import com.tangem.features.pushnotifications.api.utils.getPushPermissionOrNull
|
||||
import com.tangem.utils.Provider
|
||||
|
|
@ -86,11 +90,16 @@ internal class WalletModel @Inject constructor(
|
|||
private val appRouter: AppRouter,
|
||||
private val routingFeatureToggle: RoutingFeatureToggle,
|
||||
private val observeAndClearNFTCacheIfNeedUseCase: ObserveAndClearNFTCacheIfNeedUseCase,
|
||||
private val notificationsRepository: NotificationsRepository,
|
||||
private val getWalletsListForEnablingUseCase: GetWalletsForAutomaticallyPushEnablingUseCase,
|
||||
private val setNotificationsEnabledUseCase: SetNotificationsEnabledUseCase,
|
||||
private val notificationsFeatureToggles: NotificationsFeatureToggles,
|
||||
val screenLifecycleProvider: ScreenLifecycleProvider,
|
||||
val innerWalletRouter: InnerWalletRouter,
|
||||
) : Model() {
|
||||
|
||||
val askBiometryModelCallbacks = AskBiometryModelCallbacks()
|
||||
val askForPushNotificationsModelCallbacks = AskForPushNotificationsCallbacks()
|
||||
val uiState: StateFlow<WalletScreenState> = stateHolder.uiState
|
||||
|
||||
private val walletsUpdateJobHolder = JobHolder()
|
||||
|
|
@ -113,6 +122,7 @@ internal class WalletModel @Inject constructor(
|
|||
subscribeOnSelectedWalletFlow()
|
||||
subscribeToScreenBackgroundState()
|
||||
subscribeOnPushNotificationsPermission()
|
||||
enableNotificationsIfNeeded()
|
||||
|
||||
clickIntents.initialize(innerWalletRouter, modelScope)
|
||||
}
|
||||
|
|
@ -196,20 +206,20 @@ internal class WalletModel @Inject constructor(
|
|||
|
||||
private fun subscribeOnPushNotificationsPermission() {
|
||||
modelScope.launch {
|
||||
val shouldRequestPush = shouldAskPermissionUseCase(PUSH_PERMISSION)
|
||||
val isPushPermissionAvailable = getPushPermissionOrNull() != null
|
||||
if (!shouldRequestPush || !isPushPermissionAvailable) return@launch
|
||||
val shouldAskPermission = shouldAskPermissionUseCase(PUSH_PERMISSION)
|
||||
val afterUpdate = notificationsRepository.shouldShowSubscribeOnNotificationsAfterUpdate()
|
||||
val shouldShowBottomSheet = if (notificationsFeatureToggles.isNotificationsEnabled) {
|
||||
(shouldAskPermission || afterUpdate) && !shouldShowSaveWalletScreenUseCase()
|
||||
} else {
|
||||
val isPushPermissionAvailable = getPushPermissionOrNull() != null
|
||||
shouldAskPermission && isPushPermissionAvailable
|
||||
}
|
||||
if (!shouldShowBottomSheet) return@launch
|
||||
|
||||
delay(timeMillis = 1_800)
|
||||
|
||||
stateHolder.showBottomSheet(
|
||||
content = PushNotificationsBottomSheetConfig(
|
||||
onRequest = clickIntents::onRequestPushPermission,
|
||||
onNeverRequest = { clickIntents.onNeverAskPushPermission(false) },
|
||||
onAllow = clickIntents::onAllowPushPermission,
|
||||
onDeny = clickIntents::onDenyPushPermission,
|
||||
),
|
||||
onDismiss = { clickIntents.onNeverAskPushPermission(true) },
|
||||
innerWalletRouter.dialogNavigation.activate(
|
||||
configuration = WalletDialogConfig.AskForPushNotifications,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -433,6 +443,8 @@ internal class WalletModel @Inject constructor(
|
|||
it.copy(selectedWalletIndex = action.selectedWalletIndex)
|
||||
}
|
||||
}
|
||||
|
||||
enableNotificationsIfNeeded()
|
||||
}
|
||||
|
||||
private fun deleteWallet(action: WalletsUpdateActionResolver.Action.DeleteWallet) {
|
||||
|
|
@ -526,6 +538,26 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun enableNotificationsIfNeeded() {
|
||||
if (!notificationsFeatureToggles.isNotificationsEnabled) return
|
||||
modelScope.launch {
|
||||
val isUserAllowToEnableNotifications = notificationsRepository.isUserAllowToSubscribeOnPushNotifications()
|
||||
if (isUserAllowToEnableNotifications) {
|
||||
val alreadyEnabledWallets = notificationsRepository.getWalletAutomaticallyEnabledList().map {
|
||||
UserWalletId(it)
|
||||
}
|
||||
val walletsListWhichShouldBeEnabled = getWalletsListForEnablingUseCase(alreadyEnabledWallets)
|
||||
walletsListWhichShouldBeEnabled.forEach { userWalletId ->
|
||||
setNotificationsEnabledUseCase(userWalletId, true).onRight {
|
||||
notificationsRepository.setNotificationsWasEnabledAutomatically(userWalletId.stringValue)
|
||||
}.onLeft {
|
||||
Timber.e(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class AskBiometryModelCallbacks : AskBiometryComponent.ModelCallbacks {
|
||||
override fun onAllowed() {
|
||||
analyticsEventsHandler.send(MainScreenAnalyticsEvent.EnableBiometrics(AnalyticsParam.OnOffState.On))
|
||||
|
|
@ -538,6 +570,23 @@ internal class WalletModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
inner class AskForPushNotificationsCallbacks : PushNotificationsModelCallbacks {
|
||||
|
||||
override fun onAllowSystemPermission() {
|
||||
innerWalletRouter.dialogNavigation.dismiss()
|
||||
enableNotificationsIfNeeded()
|
||||
}
|
||||
|
||||
override fun onDenySystemPermission() {
|
||||
innerWalletRouter.dialogNavigation.dismiss()
|
||||
enableNotificationsIfNeeded()
|
||||
}
|
||||
|
||||
override fun onDismiss() {
|
||||
innerWalletRouter.dialogNavigation.dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val REFRESH_WALLET_BACKGROUND_TIMER_MILLIS = 10000L
|
||||
const val EXPRESS_STATUS_UPDATE_DELAY = 10000L
|
||||
|
|
|
|||
|
|
@ -16,4 +16,7 @@ internal sealed interface WalletDialogConfig {
|
|||
|
||||
@Serializable
|
||||
data object AskForBiometry : WalletDialogConfig
|
||||
|
||||
@Serializable
|
||||
data object AskForPushNotifications : WalletDialogConfig
|
||||
}
|
||||
|
|
@ -74,7 +74,6 @@ import com.tangem.feature.wallet.impl.R
|
|||
import com.tangem.feature.wallet.presentation.common.preview.WalletScreenPreviewData.walletScreenState
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.*
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.holder.TxHistoryStateHolder
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.PushNotificationsBottomSheet
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.TokenActionsBottomSheet
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletsList
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.common.*
|
||||
|
|
@ -706,7 +705,6 @@ private fun ShowBottomSheet(bottomSheetConfig: TangemBottomSheetConfig?) {
|
|||
is ChooseAddressBottomSheetConfig -> ChooseAddressBottomSheet(config = bottomSheetConfig)
|
||||
is BalancesAndLimitsBottomSheetConfig -> BalancesAndLimitsBottomSheet(config = bottomSheetConfig)
|
||||
is VisaTxDetailsBottomSheetConfig -> VisaTxDetailsBottomSheet(config = bottomSheetConfig)
|
||||
is PushNotificationsBottomSheetConfig -> PushNotificationsBottomSheet(config = bottomSheetConfig)
|
||||
is ExpressStatusBottomSheetConfig -> ExpressStatusBottomSheet(config = bottomSheetConfig)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,111 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.components.SecondaryButton
|
||||
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
|
||||
import com.tangem.core.ui.components.bottomsheets.sheet.TangemBottomSheet
|
||||
import com.tangem.core.ui.components.showcase.ShowcaseContent
|
||||
import com.tangem.core.ui.components.showcase.model.ShowcaseItemModel
|
||||
import com.tangem.core.ui.extensions.resourceReference
|
||||
import com.tangem.core.ui.extensions.stringResourceSafe
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemThemePreview
|
||||
import com.tangem.core.ui.utils.requestPushPermission
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.model.PushNotificationsBottomSheetConfig
|
||||
import com.tangem.features.pushnotifications.api.utils.getPushPermissionOrNull
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
@Composable
|
||||
internal fun PushNotificationsBottomSheet(config: TangemBottomSheetConfig) {
|
||||
TangemBottomSheet<PushNotificationsBottomSheetConfig>(config = config) {
|
||||
PushNotificationsSheetContent(content = it, onDismiss = config.onDismissRequest)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun PushNotificationsSheetContent(content: PushNotificationsBottomSheetConfig, onDismiss: () -> Unit) {
|
||||
val requestPushPermission = requestPushPermission(
|
||||
pushPermission = getPushPermissionOrNull(),
|
||||
onAllow = {
|
||||
content.onAllow()
|
||||
onDismiss()
|
||||
},
|
||||
onDeny = {
|
||||
content.onDeny()
|
||||
onDismiss()
|
||||
},
|
||||
)
|
||||
|
||||
Column(modifier = Modifier.background(TangemTheme.colors.background.primary)) {
|
||||
ShowcaseContent(
|
||||
headerIconRes = R.drawable.ic_notifications_unread_24,
|
||||
headerText = resourceReference(R.string.user_push_notification_agreement_header),
|
||||
showcaseItems = persistentListOf(
|
||||
ShowcaseItemModel(
|
||||
iconRes = R.drawable.ic_rocket_launch_24,
|
||||
text = resourceReference(R.string.user_push_notification_agreement_argument_one),
|
||||
),
|
||||
ShowcaseItemModel(
|
||||
iconRes = R.drawable.ic_storefront_24,
|
||||
text = resourceReference(R.string.user_push_notification_agreement_argument_two),
|
||||
),
|
||||
),
|
||||
modifier = Modifier.padding(top = TangemTheme.dimens.spacing40),
|
||||
)
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing12),
|
||||
modifier = Modifier.padding(
|
||||
start = TangemTheme.dimens.spacing16,
|
||||
end = TangemTheme.dimens.spacing16,
|
||||
top = TangemTheme.dimens.spacing40,
|
||||
bottom = TangemTheme.dimens.spacing16,
|
||||
),
|
||||
) {
|
||||
SecondaryButton(
|
||||
text = stringResourceSafe(R.string.common_later),
|
||||
onClick = {
|
||||
content.onNeverRequest()
|
||||
onDismiss()
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
PrimaryButton(
|
||||
text = stringResourceSafe(R.string.common_allow),
|
||||
onClick = {
|
||||
content.onRequest()
|
||||
requestPushPermission()
|
||||
},
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
@Composable
|
||||
private fun PushNotificationsSheetContent_Preview() {
|
||||
TangemThemePreview {
|
||||
PushNotificationsSheetContent(
|
||||
PushNotificationsBottomSheetConfig(
|
||||
onRequest = {},
|
||||
onNeverRequest = {},
|
||||
onAllow = {},
|
||||
onDeny = {},
|
||||
),
|
||||
onDismiss = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
// endregion
|
||||
Loading…
Add table
Add a link
Reference in a new issue