diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 34d26a35ae..b9af199725 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -194,6 +194,7 @@ dependencies { } implementation(Library.accompanistAppCompatTheme) implementation(Library.accompanistSystemUiController) + implementation(Library.accompanistWebView) implementation(Library.xmlShimmer) implementation(Library.viewBindingDelegate) implementation(Library.armadillo) diff --git a/app/src/main/assets/tangem-app-config b/app/src/main/assets/tangem-app-config index 2b8aa19f58..f5f6ac9548 160000 --- a/app/src/main/assets/tangem-app-config +++ b/app/src/main/assets/tangem-app-config @@ -1 +1 @@ -Subproject commit 2b8aa19f58e17a78015629943d49df0da0b4fd4b +Subproject commit f5f6ac954894ef66331db8fe383b9773feb69ef4 diff --git a/app/src/main/java/com/tangem/tap/TapApplication.kt b/app/src/main/java/com/tangem/tap/TapApplication.kt index 78cf3956f2..8f6a026ae5 100644 --- a/app/src/main/java/com/tangem/tap/TapApplication.kt +++ b/app/src/main/java/com/tangem/tap/TapApplication.kt @@ -187,7 +187,7 @@ class TapApplication : Application(), ImageLoaderFactory { private fun initWithConfigDependency(config: Config) { shopService = TangemShopService(this, config.shopify!!) initAnalytics(this, config) - initFeedbackManager(this, preferencesStorage, foregroundActivityObserver) + initFeedbackManager(this, preferencesStorage, foregroundActivityObserver, store) } private fun initAnalytics(application: Application, config: Config) { @@ -213,6 +213,7 @@ class TapApplication : Application(), ImageLoaderFactory { context: Context, preferencesStorage: PreferencesStorage, foregroundActivityObserver: ForegroundActivityObserver, + store: Store, ) { fun initAdditionalFeedbackInfo(context: Context): AdditionalFeedbackInfo = AdditionalFeedbackInfo().apply { appVersion = try { @@ -246,7 +247,7 @@ class TapApplication : Application(), ImageLoaderFactory { val feedbackManager = FeedbackManager( infoHolder = additionalFeedbackInfo, logCollector = tangemLogCollector, - chatManager = ChatManager(preferencesStorage, foregroundActivityObserver), + chatManager = ChatManager(preferencesStorage, foregroundActivityObserver, store), ) store.dispatch(GlobalAction.SetFeedbackManager(feedbackManager)) } diff --git a/app/src/main/java/com/tangem/tap/common/chat/ChatConfig.kt b/app/src/main/java/com/tangem/tap/common/chat/ChatConfig.kt index 32aab191db..01b80c8cc6 100644 --- a/app/src/main/java/com/tangem/tap/common/chat/ChatConfig.kt +++ b/app/src/main/java/com/tangem/tap/common/chat/ChatConfig.kt @@ -19,6 +19,10 @@ data class ZendeskConfig( val url: String, ) : ChatConfig +@JsonClass(generateAdapter = true) data class SprinklrConfig( + @Json(name = "appID") val appId: String, + @Json(name = "baseURL") + val baseUrl: String, ) : ChatConfig \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/chat/ChatManager.kt b/app/src/main/java/com/tangem/tap/common/chat/ChatManager.kt index 951cf75294..324b6c9095 100644 --- a/app/src/main/java/com/tangem/tap/common/chat/ChatManager.kt +++ b/app/src/main/java/com/tangem/tap/common/chat/ChatManager.kt @@ -5,18 +5,21 @@ import com.tangem.tap.ForegroundActivityObserver import com.tangem.tap.common.chat.opener.ChatOpener import com.tangem.tap.common.chat.opener.implementation.SprinklrChatOpener import com.tangem.tap.common.chat.opener.implementation.ZendeskChatOpener +import com.tangem.tap.common.redux.AppState import com.tangem.tap.persistence.PreferencesStorage +import org.rekotlin.Store class ChatManager( private val preferencesStorage: PreferencesStorage, private val foregroundActivityObserver: ForegroundActivityObserver, + private val store: Store, ) { private val openers = mutableMapOf() fun open(config: ChatConfig, feedbackDataBuilder: (Context) -> String) { val opener = openers.getOrPut(config) { when (config) { - is SprinklrConfig -> SprinklrChatOpener() + is SprinklrConfig -> SprinklrChatOpener(config, store) is ZendeskConfig -> ZendeskChatOpener(config, preferencesStorage, foregroundActivityObserver) } } diff --git a/app/src/main/java/com/tangem/tap/common/chat/opener/implementation/SprinklrChatOpener.kt b/app/src/main/java/com/tangem/tap/common/chat/opener/implementation/SprinklrChatOpener.kt index a231a4816f..0b58d26a14 100644 --- a/app/src/main/java/com/tangem/tap/common/chat/opener/implementation/SprinklrChatOpener.kt +++ b/app/src/main/java/com/tangem/tap/common/chat/opener/implementation/SprinklrChatOpener.kt @@ -1,10 +1,21 @@ package com.tangem.tap.common.chat.opener.implementation import android.content.Context +import com.tangem.tap.common.chat.SprinklrConfig import com.tangem.tap.common.chat.opener.ChatOpener +import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.common.redux.AppState +import com.tangem.tap.common.redux.navigation.AppScreen +import com.tangem.tap.common.redux.navigation.NavigationAction +import com.tangem.tap.features.sprinklr.redux.SprinklrAction +import org.rekotlin.Store -internal class SprinklrChatOpener : ChatOpener { +internal class SprinklrChatOpener( + private val config: SprinklrConfig, + private val store: Store, +) : ChatOpener { override fun open(feedbackDataBuilder: (Context) -> String) { - // TODO: Open activity with Sprinklr WebView, will be in further MRs + store.dispatch(SprinklrAction.SetConfig(config)) + store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Sprinklr)) } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/compose/Button.kt b/app/src/main/java/com/tangem/tap/common/compose/Button.kt index b20f7470b8..fe5aa7979a 100644 --- a/app/src/main/java/com/tangem/tap/common/compose/Button.kt +++ b/app/src/main/java/com/tangem/tap/common/compose/Button.kt @@ -12,9 +12,7 @@ import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.Scaffold import androidx.compose.material.Text -import androidx.compose.material.ripple.LocalRippleTheme import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -133,18 +131,6 @@ fun ClearButton( } } -/** - * Used for disable ripple if button is enable = false - */ -@Composable -fun ToggledRippleTheme( - isEnabled: Boolean, - content: @Composable () -> Unit, -) { - val theme = LocalRippleTheme provides if (isEnabled) LocalRippleTheme.current else NoRippleTheme() - CompositionLocalProvider(theme) { content() } -} - @Preview @Composable fun ButtonTest() { diff --git a/app/src/main/java/com/tangem/tap/common/compose/Theme.kt b/app/src/main/java/com/tangem/tap/common/compose/Theme.kt deleted file mode 100644 index f0afe076ba..0000000000 --- a/app/src/main/java/com/tangem/tap/common/compose/Theme.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.tangem.tap.common.compose - -import androidx.compose.material.ripple.RippleAlpha -import androidx.compose.material.ripple.RippleTheme -import androidx.compose.runtime.Composable -import androidx.compose.ui.graphics.Color - -/** -[REDACTED_AUTHOR] - */ -class NoRippleTheme : RippleTheme { - @Composable - override fun defaultColor() = Color.Unspecified - - @Composable - override fun rippleAlpha(): RippleAlpha = RippleAlpha(0.0f, 0.0f, 0.0f, 0.0f) -} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt index 711e7ed172..21dd970381 100644 --- a/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt +++ b/app/src/main/java/com/tangem/tap/common/extensions/Navigation.kt @@ -25,6 +25,7 @@ import com.tangem.tap.features.onboarding.products.wallet.ui.OnboardingWalletFra import com.tangem.tap.features.saveWallet.ui.SaveWalletBottomSheetFragment import com.tangem.tap.features.send.ui.SendFragment import com.tangem.tap.features.shop.ui.ShopFragment +import com.tangem.tap.features.sprinklr.ui.SprinklrFragment import com.tangem.tap.features.tokens.addCustomToken.AddCustomTokenFragment import com.tangem.tap.features.tokens.ui.AddTokensFragment import com.tangem.tap.features.wallet.ui.WalletDetailsFragment @@ -120,5 +121,6 @@ private fun fragmentFactory(screen: AppScreen): Fragment { AppScreen.Welcome -> WelcomeFragment() AppScreen.SaveWallet -> SaveWalletBottomSheetFragment() AppScreen.WalletSelector -> WalletSelectorBottomSheetFragment() + AppScreen.Sprinklr -> SprinklrFragment() } } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt index f03dfc70ca..3bcb47a092 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppReducer.kt @@ -13,11 +13,12 @@ import com.tangem.tap.features.onboarding.products.wallet.redux.OnboardingWallet import com.tangem.tap.features.saveWallet.redux.SaveWalletReducer import com.tangem.tap.features.send.redux.reducers.SendScreenReducer import com.tangem.tap.features.shop.redux.ShopReducer +import com.tangem.tap.features.sprinklr.redux.SprinklrReducer import com.tangem.tap.features.tokens.redux.TokensReducer import com.tangem.tap.features.wallet.redux.reducers.WalletReducer -import com.tangem.tap.proxy.AppStateHolder import com.tangem.tap.features.walletSelector.redux.WalletSelectorReducer import com.tangem.tap.features.welcome.redux.WelcomeReducer +import com.tangem.tap.proxy.AppStateHolder import org.rekotlin.Action fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder): AppState { @@ -42,6 +43,7 @@ fun appReducer(action: Action, state: AppState?, appStateHolder: AppStateHolder) welcomeState = WelcomeReducer.reduce(action, state), saveWalletState = SaveWalletReducer.reduce(action, state), walletSelectorState = WalletSelectorReducer.reduce(action, state), + sprinklrState = SprinklrReducer.reduce(action, state), ) } diff --git a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt index 9f7c34b90f..3e0d617fb2 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/AppState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/AppState.kt @@ -31,6 +31,8 @@ import com.tangem.tap.features.send.redux.middlewares.SendMiddleware import com.tangem.tap.features.send.redux.states.SendState import com.tangem.tap.features.shop.redux.ShopMiddleware import com.tangem.tap.features.shop.redux.ShopState +import com.tangem.tap.features.sprinklr.redux.SprinklrMiddleware +import com.tangem.tap.features.sprinklr.redux.SprinklrState import com.tangem.tap.features.tokens.redux.TokensMiddleware import com.tangem.tap.features.tokens.redux.TokensState import com.tangem.tap.features.wallet.redux.WalletState @@ -60,6 +62,7 @@ data class AppState( val welcomeState: WelcomeState = WelcomeState(), val saveWalletState: SaveWalletState = SaveWalletState(), val walletSelectorState: WalletSelectorState = WalletSelectorState(), + val sprinklrState: SprinklrState = SprinklrState(), ) : StateType { val domainState: DomainState @@ -94,6 +97,7 @@ data class AppState( WalletSelectorMiddleware().middleware, LockUserWalletsTimerMiddleware().middleware, AccessCodeRequestPolicyMiddleware().middleware, + SprinklrMiddleware().middleware, ) } } diff --git a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt index ed9a9e3850..4696b4a6f8 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/global/GlobalMidlleware.kt @@ -9,7 +9,6 @@ import com.tangem.domain.common.LogConfig import com.tangem.domain.common.ProductType import com.tangem.domain.common.ScanResponse import com.tangem.domain.common.extensions.withMainContext -import com.tangem.tap.common.chat.SprinklrConfig import com.tangem.tap.common.extensions.dispatchDebugErrorNotification import com.tangem.tap.common.extensions.dispatchDialogShow import com.tangem.tap.common.extensions.dispatchOnMain @@ -111,7 +110,7 @@ private fun handleAction(action: Action, appState: () -> AppState?, dispatch: Di // if config not set -> try to get it based on a scanResponse.productType val unsafeChatConfig = action.chatConfig ?: when { - scanResponse?.isSaltPay() == true -> config.saltPayConfig?.sprinklrAppID?.let(::SprinklrConfig) + scanResponse?.isSaltPay() == true -> config.saltPayConfig?.sprinklr else -> config.zendesk } diff --git a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt index cf60dc79f6..3f313ef210 100644 --- a/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt +++ b/app/src/main/java/com/tangem/tap/common/redux/navigation/NavigationState.kt @@ -26,4 +26,5 @@ enum class AppScreen( Welcome, SaveWallet(isDialogFragment = true), WalletSelector(isDialogFragment = true), + Sprinklr, } \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayConfig.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayConfig.kt index 412087154d..8d1ee55a33 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayConfig.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/SaltPayConfig.kt @@ -1,19 +1,20 @@ package com.tangem.tap.features.onboarding.products.wallet.saltPay +import com.tangem.tap.common.chat.SprinklrConfig import org.spongycastle.util.encoders.Base64.toBase64String /** [REDACTED_AUTHOR] */ data class SaltPayConfig( - val sprinklrAppID: String, + val sprinklr: SprinklrConfig, val kycProvider: KYCProvider, val credentials: Credentials, ) { companion object { fun stub(): SaltPayConfig { return SaltPayConfig( - sprinklrAppID = "", + sprinklr = SprinklrConfig("", ""), kycProvider = KYCProvider("", "", "", ""), credentials = Credentials("", ""), ) diff --git a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/NoFundsForActivationDialog.kt b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/NoFundsForActivationDialog.kt index edaf0567a1..a75c0e9e5c 100644 --- a/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/NoFundsForActivationDialog.kt +++ b/app/src/main/java/com/tangem/tap/features/onboarding/products/wallet/saltPay/dialog/NoFundsForActivationDialog.kt @@ -4,7 +4,6 @@ import android.app.Dialog import android.content.Context import androidx.appcompat.app.AlertDialog import com.tangem.common.extensions.guard -import com.tangem.tap.common.chat.SprinklrConfig import com.tangem.tap.common.extensions.dispatchDebugErrorNotification import com.tangem.tap.common.feedback.SupportInfo import com.tangem.tap.common.redux.global.GlobalAction @@ -21,14 +20,14 @@ class NoFundsForActivationDialog { setTitle(R.string.saltpay_error_no_gas_title) setMessage(R.string.saltpay_error_no_gas_message) setPositiveButton(R.string.chat_button_title) { _, _ -> - val sprinklrAppId = store.state.globalState.configManager?.config + val sprinklrConfig = store.state.globalState.configManager?.config ?.saltPayConfig - ?.sprinklrAppID + ?.sprinklr .guard { store.dispatchDebugErrorNotification("SaltPayConfig not initialized") return@setPositiveButton } - store.dispatch(GlobalAction.OpenChat(SupportInfo(), SprinklrConfig(sprinklrAppId))) + store.dispatch(GlobalAction.OpenChat(SupportInfo(), sprinklrConfig)) } setNegativeButton(R.string.common_cancel) { _, _ -> } diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrAction.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrAction.kt new file mode 100644 index 0000000000..3c5571db9a --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrAction.kt @@ -0,0 +1,9 @@ +package com.tangem.tap.features.sprinklr.redux + +import com.tangem.tap.common.chat.SprinklrConfig +import org.rekotlin.Action + +sealed interface SprinklrAction : Action { + data class SetConfig(val config: SprinklrConfig) : SprinklrAction + data class UpdateUrl(val url: String) : SprinklrAction +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrMiddleware.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrMiddleware.kt new file mode 100644 index 0000000000..8fd0798a25 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrMiddleware.kt @@ -0,0 +1,34 @@ +package com.tangem.tap.features.sprinklr.redux + +import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.common.redux.AppState +import com.tangem.tap.store +import org.rekotlin.Middleware + +internal class SprinklrMiddleware { + val middleware: Middleware = { _, appStateProvider -> + { next -> + { action -> + val appState = appStateProvider() + if (action is SprinklrAction && appState != null) { + handleAction(action) + } + next(action) + } + } + } + + private fun handleAction(action: SprinklrAction) { + when (action) { + is SprinklrAction.SetConfig -> createUrl() + is SprinklrAction.UpdateUrl -> Unit + } + } + + private fun createUrl() { + // TODO: Create Sprinklr URL, will be in further MRs + val url = "https://prod-live-chat.sprinklr.com/" + + "page?appId=60c1d169c96beb5bf5a326f3_app_950954&device=MOBILE&enableClose=true&zoom=false" + store.dispatchOnMain(SprinklrAction.UpdateUrl(url)) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrReducer.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrReducer.kt new file mode 100644 index 0000000000..44e2e33785 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrReducer.kt @@ -0,0 +1,19 @@ +package com.tangem.tap.features.sprinklr.redux + +import com.tangem.tap.common.redux.AppState +import org.rekotlin.Action + +internal object SprinklrReducer { + fun reduce(action: Action, state: AppState): SprinklrState { + return if (action is SprinklrAction) { + internalReduce(action, state.sprinklrState) + } else state.sprinklrState + } + + private fun internalReduce(action: SprinklrAction, state: SprinklrState): SprinklrState { + return when (action) { + is SprinklrAction.SetConfig -> state + is SprinklrAction.UpdateUrl -> state.copy(url = action.url) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrState.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrState.kt new file mode 100644 index 0000000000..8323b35fd0 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/redux/SprinklrState.kt @@ -0,0 +1,5 @@ +package com.tangem.tap.features.sprinklr.redux + +data class SprinklrState( + val url: String = "", +) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrFragment.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrFragment.kt new file mode 100644 index 0000000000..f029d4fa9b --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrFragment.kt @@ -0,0 +1,31 @@ +package com.tangem.tap.features.sprinklr.ui + +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.systemBarsPadding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Modifier +import androidx.fragment.app.viewModels +import com.tangem.core.ui.fragments.ComposeFragment + +internal class SprinklrFragment : ComposeFragment() { + private val viewModel by viewModels() + + @Composable + override fun provideState(): State { + return viewModel.state.collectAsState() + } + + @Composable + override fun ScreenContent(modifier: Modifier, state: SprinklrScreenState) { + BackHandler(onBack = state.onNavigateBack) + SprinklrScreenContent( + modifier = modifier + .systemBarsPadding() + .imePadding(), + state = state, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenContent.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenContent.kt new file mode 100644 index 0000000000..3cc36f08f7 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenContent.kt @@ -0,0 +1,25 @@ +package com.tangem.tap.features.sprinklr.ui + +import android.annotation.SuppressLint +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.google.accompanist.web.WebView +import com.google.accompanist.web.rememberWebViewState + +@SuppressLint("SetJavaScriptEnabled") +@Composable +internal fun SprinklrScreenContent( + state: SprinklrScreenState, + modifier: Modifier = Modifier, +) { + WebView( + modifier = modifier, + state = rememberWebViewState(url = state.initialUrl), + onCreated = { webView -> + with(webView.settings) { + javaScriptEnabled = true + domStorageEnabled = true + } + }, + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenState.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenState.kt new file mode 100644 index 0000000000..c1b5540b10 --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrScreenState.kt @@ -0,0 +1,6 @@ +package com.tangem.tap.features.sprinklr.ui + +internal data class SprinklrScreenState( + val initialUrl: String = "", + val onNavigateBack: () -> Unit = {}, +) \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrViewModel.kt b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrViewModel.kt new file mode 100644 index 0000000000..2da7f8c31d --- /dev/null +++ b/app/src/main/java/com/tangem/tap/features/sprinklr/ui/SprinklrViewModel.kt @@ -0,0 +1,44 @@ +package com.tangem.tap.features.sprinklr.ui + +import androidx.lifecycle.ViewModel +import com.tangem.tap.common.extensions.dispatchOnMain +import com.tangem.tap.common.redux.navigation.NavigationAction +import com.tangem.tap.features.sprinklr.redux.SprinklrState +import com.tangem.tap.store +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import org.rekotlin.StoreSubscriber + +internal class SprinklrViewModel : ViewModel(), StoreSubscriber { + private val stateInternal = MutableStateFlow(SprinklrScreenState()) + val state = stateInternal.asStateFlow() + + init { + subscribeToStoreChanges() + } + + override fun newState(state: SprinklrState) { + stateInternal.update { prevState -> + prevState.copy( + initialUrl = state.url, + onNavigateBack = this::navigateBack, + ) + } + } + + override fun onCleared() { + store.unsubscribe(this) + } + + private fun subscribeToStoreChanges() { + store.subscribe(this) { appState -> + appState.skip { old, new -> old.sprinklrState == new.sprinklrState } + .select { it.sprinklrState } + } + } + + private fun navigateBack() { + store.dispatchOnMain(NavigationAction.PopBackTo()) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt index 93066fc926..2fbbfe4ca5 100644 --- a/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt +++ b/app/src/main/java/com/tangem/tap/features/tokens/addCustomToken/compose/AddCustomTokenScreen.kt @@ -55,7 +55,6 @@ import com.tangem.domain.redux.domainStore import com.tangem.tap.common.compose.AddCustomTokenWarning import com.tangem.tap.common.compose.ClosePopupTrigger import com.tangem.tap.common.compose.ComposeDialogManager -import com.tangem.tap.common.compose.ToggledRippleTheme import com.tangem.tap.common.compose.keyboardAsState import com.tangem.tap.domain.moduleMessage.ModuleMessageConverter import com.tangem.tap.features.tokens.addCustomToken.compose.test.TestCase @@ -66,7 +65,7 @@ import kotlinx.coroutines.launch /** [REDACTED_AUTHOR] */ -private class AddCustomTokenScreen {} // for simple search +private class AddCustomTokenScreen // for simple search @OptIn(ExperimentalMaterialApi::class) @Composable @@ -91,11 +90,13 @@ fun AddCustomTokenScreen( }, sheetPeekHeight = 0.dp, ) { - Column() { - TestCasesList(onItemClick = { - selectedTestCase.value = it - toggleBottomSheet() - }) + Column { + TestCasesList( + onItemClick = { + selectedTestCase.value = it + toggleBottomSheet() + }, + ) ScreenContent(state, closePopupTrigger) } } @@ -228,23 +229,21 @@ private fun AddCustomTokenFab( FloatingActionButtonDefaults.elevation() } - ToggledRippleTheme(isEnabled) { - ExtendedFloatingActionButton( - modifier = modifier, - icon = { - Icon( - imageVector = Icons.Filled.Add, - tint = contentColor, - contentDescription = "Add", - ) - }, - text = { Text(text = stringResource(id = R.string.common_add)) }, - onClick = { if (isEnabled) onClick() }, - backgroundColor = backgroundColor, - contentColor = contentColor, - elevation = elevation, - ) - } + ExtendedFloatingActionButton( + modifier = modifier, + icon = { + Icon( + imageVector = Icons.Filled.Add, + tint = contentColor, + contentDescription = "Add", + ) + }, + text = { Text(text = stringResource(id = R.string.common_add)) }, + onClick = { if (isEnabled) onClick() }, + backgroundColor = backgroundColor, + contentColor = contentColor, + elevation = elevation, + ) } data class ScreenFieldData( diff --git a/app/src/main/res/xml/network_security_config.xml b/app/src/main/res/xml/network_security_config.xml index 2bbb4f525b..d5f3e649d4 100644 --- a/app/src/main/res/xml/network_security_config.xml +++ b/app/src/main/res/xml/network_security_config.xml @@ -16,4 +16,6 @@ - \ No newline at end of file + + + diff --git a/buildSrc/src/main/java/Dependency.kt b/buildSrc/src/main/java/Dependency.kt index 5e9f38e8c8..fbf55749b4 100644 --- a/buildSrc/src/main/java/Dependency.kt +++ b/buildSrc/src/main/java/Dependency.kt @@ -30,6 +30,7 @@ object Library { const val accompanistAppCompatTheme = "com.google.accompanist:accompanist-appcompat-theme:" + Versions.accompanist const val accompanistSystemUiController = "com.google.accompanist:accompanist-systemuicontroller:" + Versions.accompanist + const val accompanistWebView = "com.google.accompanist:accompanist-webview:" + Versions.accompanist const val amplitude = "com.amplitude:android-sdk:" + Versions.amplitude const val appsflyer = "com.appsflyer:af-android-sdk:" + Versions.appsflyer const val armadillo = "at.favre.lib:armadillo:" + Versions.armadillo diff --git a/buildSrc/src/main/java/Versions.kt b/buildSrc/src/main/java/Versions.kt index 3ea750baf4..e587a75fd6 100644 --- a/buildSrc/src/main/java/Versions.kt +++ b/buildSrc/src/main/java/Versions.kt @@ -23,7 +23,7 @@ object Versions { // endregion Compose // region Other libraries - const val accompanist = "0.23.0" + const val accompanist = "0.28.0" const val amplitude = "2.36.1" const val appsflyer = "6.5.1" const val armadillo = "0.9.0"