Updated on 2026-08-14

This commit is contained in:
Tangem 2023-02-17 15:25:36 +03:00
commit aa9f9ed884
13 changed files with 130 additions and 23 deletions

View file

@ -4,6 +4,7 @@ import com.tangem.tap.common.chat.SprinklrConfig
import org.rekotlin.Action
sealed interface SprinklrAction : Action {
data class SetConfig(val config: SprinklrConfig) : SprinklrAction
data class Init(val userId: String, val config: SprinklrConfig) : SprinklrAction
data class UpdateUrl(val url: String) : SprinklrAction
data class UpdateSprinklrDomains(val domains: List<String>) : SprinklrAction
}

View file

@ -1,7 +1,9 @@
package com.tangem.tap.features.sprinklr.redux
import com.tangem.tap.common.chat.SprinklrConfig
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.redux.AppState
import com.tangem.tap.features.sprinklr.redux.model.SprinklrUrl
import com.tangem.tap.store
import org.rekotlin.Middleware
@ -20,15 +22,21 @@ internal class SprinklrMiddleware {
private fun handleAction(action: SprinklrAction) {
when (action) {
is SprinklrAction.SetConfig -> createUrl()
is SprinklrAction.UpdateUrl -> Unit
is SprinklrAction.Init -> updateUrl(action.userId, action.config)
is SprinklrAction.UpdateUrl,
is SprinklrAction.UpdateSprinklrDomains,
-> 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"
private fun updateUrl(userId: String, config: SprinklrConfig) {
updateSprinklrDomains(config.baseUrl)
val url = SprinklrUrl.Prod(userId, config.baseUrl, config.appId).url
store.dispatchOnMain(SprinklrAction.UpdateUrl(url))
}
private fun updateSprinklrDomains(baseUrl: String) {
val domains = listOf(baseUrl, SprinklrUrl.Static.url)
store.dispatchOnMain(SprinklrAction.UpdateSprinklrDomains(domains))
}
}

View file

@ -12,8 +12,9 @@ internal object SprinklrReducer {
private fun internalReduce(action: SprinklrAction, state: SprinklrState): SprinklrState {
return when (action) {
is SprinklrAction.SetConfig -> state
is SprinklrAction.Init -> state
is SprinklrAction.UpdateUrl -> state.copy(url = action.url)
is SprinklrAction.UpdateSprinklrDomains -> state.copy(sprinklrDomains = action.domains)
}
}
}

View file

@ -2,4 +2,5 @@ package com.tangem.tap.features.sprinklr.redux
data class SprinklrState(
val url: String = "",
val sprinklrDomains: List<String> = emptyList(),
)

View file

@ -0,0 +1,27 @@
package com.tangem.tap.features.sprinklr.redux.model
internal sealed class SprinklrUrl {
abstract val url: String
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" +
"&device=$Device" +
"&enableClose=$CloseEnabled" +
"&zoom=$ZoomEnabled" +
"&locale=$locale" +
"&user_id=$userId"
companion object {
private const val Device = "MOBILE"
private const val CloseEnabled = true
private const val ZoomEnabled = false
}
}
object Static : SprinklrUrl() {
override val url: String = "live-chat-static.sprinklr.com"
}
}

View file

@ -2,9 +2,11 @@ package com.tangem.tap.features.sprinklr.ui
import android.annotation.SuppressLint
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import com.google.accompanist.web.WebView
import com.google.accompanist.web.rememberWebViewState
import com.tangem.tap.features.sprinklr.ui.webview.SprinklrWebViewClient
@SuppressLint("SetJavaScriptEnabled")
@Composable
@ -21,5 +23,6 @@ internal fun SprinklrScreenContent(
domStorageEnabled = true
}
},
client = remember { SprinklrWebViewClient(state.onNewUrl) },
)
}

View file

@ -1,6 +1,10 @@
package com.tangem.tap.features.sprinklr.ui
import com.google.accompanist.web.WebContent
internal data class SprinklrScreenState(
val initialUrl: String = "",
val sprinklrDomains: List<String> = emptyList(),
val onNavigateBack: () -> Unit = {},
val onNewUrl: WebContent.(String) -> WebContent = { this },
)

View file

@ -1,6 +1,7 @@
package com.tangem.tap.features.sprinklr.ui
import androidx.lifecycle.ViewModel
import com.google.accompanist.web.WebContent
import com.tangem.tap.common.extensions.dispatchOnMain
import com.tangem.tap.common.redux.navigation.NavigationAction
import com.tangem.tap.features.sprinklr.redux.SprinklrState
@ -22,7 +23,9 @@ internal class SprinklrViewModel : ViewModel(), StoreSubscriber<SprinklrState> {
stateInternal.update { prevState ->
prevState.copy(
initialUrl = state.url,
sprinklrDomains = state.sprinklrDomains,
onNavigateBack = this::navigateBack,
onNewUrl = { updateWebContentOrOpenExternalUrl(it) },
)
}
}
@ -41,4 +44,18 @@ 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))
this
} else when (this) {
is WebContent.Url -> copy(url = url)
else -> WebContent.Url(url)
}
}
private fun isExternalUrl(url: String): Boolean {
return state.value.sprinklrDomains.none { url.contains(it) }
}
}

View file

@ -0,0 +1,24 @@
package com.tangem.tap.features.sprinklr.ui.webview
import android.webkit.WebResourceRequest
import android.webkit.WebView
import com.google.accompanist.web.AccompanistWebViewClient
import com.google.accompanist.web.WebContent
internal class SprinklrWebViewClient(
private val onNewUrl: WebContent.(String) -> WebContent,
) : AccompanistWebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
// If the url hasn't changed, this is probably an internal event like
// a javascript reload. We should let it happen.
if (view?.url == request?.url.toString()) {
return false
}
request?.let {
state.content = onNewUrl(state.content, it.url.toString())
}
return true
}
}