Updated on 2026-08-14

This commit is contained in:
Tangem 2023-02-21 13:04:40 +03:00
commit 39d212a493
12 changed files with 89 additions and 73 deletions

View file

@ -138,9 +138,12 @@
<activity android:name="com.tangem.tap.common.qrCodeScan.ScanQrCodeActivity" />
<activity android:name="zendesk.messaging.MessagingActivity"
<activity
android:name="zendesk.messaging.MessagingActivity"
android:theme="@style/ZendeskTheme" />
<activity android:name="com.tangem.tap.features.sprinklr.ui.SprinklrActivity" />
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"

View file

@ -20,7 +20,7 @@ class ChatManager(
fun open(config: ChatConfig, feedbackDataBuilder: (Context) -> String) {
val opener = openers.getOrPut(config) {
when (config) {
is SprinklrConfig -> SprinklrChatOpener(getSprinklrUserId(), config, store)
is SprinklrConfig -> SprinklrChatOpener(getSprinklrUserId(), config, store, foregroundActivityObserver)
is ZendeskConfig -> ZendeskChatOpener(getZendeskUserId(), config, foregroundActivityObserver)
}
}

View file

@ -1,22 +1,27 @@
package com.tangem.tap.common.chat.opener.implementation
import android.content.Context
import android.content.Intent
import com.tangem.tap.ForegroundActivityObserver
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 com.tangem.tap.features.sprinklr.ui.SprinklrActivity
import com.tangem.tap.withForegroundActivity
import org.rekotlin.Store
internal class SprinklrChatOpener(
private val userId: String,
private val config: SprinklrConfig,
private val store: Store<AppState>,
private val foregroundActivityObserver: ForegroundActivityObserver,
) : ChatOpener {
override fun open(feedbackDataBuilder: (Context) -> String) {
store.dispatch(SprinklrAction.Init(userId, config))
store.dispatchOnMain(NavigationAction.NavigateTo(AppScreen.Sprinklr))
foregroundActivityObserver.withForegroundActivity { activity ->
val intent = Intent(activity, SprinklrActivity::class.java)
activity.startActivity(intent)
}
}
}

View file

@ -25,7 +25,6 @@ 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
@ -121,6 +120,5 @@ private fun fragmentFactory(screen: AppScreen): Fragment {
AppScreen.Welcome -> WelcomeFragment()
AppScreen.SaveWallet -> SaveWalletBottomSheetFragment()
AppScreen.WalletSelector -> WalletSelectorBottomSheetFragment()
AppScreen.Sprinklr -> SprinklrFragment()
}
}

View file

@ -26,5 +26,4 @@ enum class AppScreen(
Welcome,
SaveWallet(isDialogFragment = true),
WalletSelector(isDialogFragment = true),
Sprinklr,
}

View file

@ -6,8 +6,8 @@ internal sealed class SprinklrUrl {
class Prod(userId: String, baseUrl: String, appId: String) : SprinklrUrl() {
private val locale = java.util.Locale.getDefault().language
override val url: String = "$baseUrl/page?" +
"appId=$appId" +
override val url: String = "$baseUrl/page" +
"?appId=$appId" +
"&device=$Device" +
"&enableClose=$CloseEnabled" +
"&zoom=$ZoomEnabled" +

View file

@ -2,23 +2,26 @@ package com.tangem.tap.features.sprinklr.ui
import android.os.Bundle
import androidx.activity.compose.BackHandler
import androidx.activity.viewModels
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.analytics.Analytics
import com.tangem.core.ui.fragments.ComposeFragment
import com.tangem.core.ui.fragments.ComposeActivity
import com.tangem.tap.common.analytics.events.Chat
internal class SprinklrFragment : ComposeFragment<SprinklrScreenState>() {
internal class SprinklrActivity : ComposeActivity<SprinklrScreenState>() {
private val viewModel by viewModels<SprinklrViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Analytics.send(Chat.ScreenOpened())
viewModel.setNavigateBackCallback {
this.finish()
}
}
@Composable

View file

@ -24,7 +24,6 @@ internal class SprinklrViewModel : ViewModel(), StoreSubscriber<SprinklrState> {
prevState.copy(
initialUrl = state.url,
sprinklrDomains = state.sprinklrDomains,
onNavigateBack = this::navigateBack,
onNewUrl = { updateWebContentOrOpenExternalUrl(it) },
)
}
@ -34,6 +33,14 @@ internal class SprinklrViewModel : ViewModel(), StoreSubscriber<SprinklrState> {
store.unsubscribe(this)
}
fun setNavigateBackCallback(callback: () -> Unit) {
stateInternal.update { prevState ->
prevState.copy(
onNavigateBack = callback,
)
}
}
private fun subscribeToStoreChanges() {
store.subscribe(this) { appState ->
appState.skip { old, new -> old.sprinklrState == new.sprinklrState }
@ -41,10 +48,6 @@ internal class SprinklrViewModel : ViewModel(), StoreSubscriber<SprinklrState> {
}
}
private fun navigateBack() {
store.dispatchOnMain(NavigationAction.PopBackTo())
}
private fun WebContent.updateWebContentOrOpenExternalUrl(url: String): WebContent {
return if (isExternalUrl(url)) {
store.dispatchOnMain(NavigationAction.OpenUrl(url))

View file

@ -0,0 +1,11 @@
package com.tangem.core.ui.fragments
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
abstract class ComposeActivity<ScreenState> : AppCompatActivity(), ComposeScreen<ScreenState> {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(createComposeView(context = this))
}
}

View file

@ -10,8 +10,6 @@ import androidx.annotation.FloatRange
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import com.google.android.material.bottomsheet.BottomSheetBehavior
@ -20,7 +18,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.tangem.core.ui.R
import com.tangem.core.ui.res.TangemTheme
abstract class ComposeBottomSheetFragment<ScreenState> : BottomSheetDialogFragment() {
abstract class ComposeBottomSheetFragment<ScreenState> : BottomSheetDialogFragment(), ComposeScreen<ScreenState> {
open val initialBottomSheetState = BottomSheetBehavior.STATE_EXPANDED
@FloatRange(from = 0.0, to = 1.0)
@ -47,7 +45,7 @@ abstract class ComposeBottomSheetFragment<ScreenState> : BottomSheetDialogFragme
return dialog
}
private fun createComposeView(context: Context): View {
override fun createComposeView(context: Context): View {
return ComposeView(context).apply {
setContent {
TangemTheme {
@ -67,13 +65,4 @@ abstract class ComposeBottomSheetFragment<ScreenState> : BottomSheetDialogFragme
}
}
}
@Composable
protected abstract fun provideState(): State<ScreenState>
@Composable
protected abstract fun ScreenContent(
modifier: Modifier,
state: ScreenState,
)
}

View file

@ -1,21 +1,12 @@
package com.tangem.core.ui.fragments
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
abstract class ComposeFragment<ScreenState> : Fragment() {
abstract class ComposeFragment<ScreenState> : Fragment(), ComposeScreen<ScreenState> {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@ -23,35 +14,4 @@ abstract class ComposeFragment<ScreenState> : Fragment() {
): View {
return createComposeView(inflater.context)
}
private fun createComposeView(context: Context): View {
return ComposeView(context).apply {
setContent {
TangemTheme {
val backgroundColor = TangemTheme.colors.background.primary
SystemBarsEffect {
setSystemBarsColor(
color = backgroundColor,
)
}
ScreenContent(
modifier = Modifier
.fillMaxSize()
.background(color = backgroundColor),
state = provideState().value,
)
}
}
}
}
@Composable
protected abstract fun provideState(): State<ScreenState>
@Composable
protected abstract fun ScreenContent(
modifier: Modifier,
state: ScreenState,
)
}

View file

@ -0,0 +1,45 @@
package com.tangem.core.ui.fragments
import android.content.Context
import android.view.View
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import com.tangem.core.ui.components.SystemBarsEffect
import com.tangem.core.ui.res.TangemTheme
internal interface ComposeScreen<ScreenState> {
fun createComposeView(context: Context): View {
return ComposeView(context).apply {
setContent {
TangemTheme {
val backgroundColor = TangemTheme.colors.background.primary
SystemBarsEffect {
setSystemBarsColor(
color = backgroundColor,
)
}
ScreenContent(
modifier = Modifier
.fillMaxSize()
.background(color = backgroundColor),
state = provideState().value,
)
}
}
}
}
@Composable
fun provideState(): State<ScreenState>
@Composable
fun ScreenContent(
modifier: Modifier,
state: ScreenState,
)
}