NTP-75220 | decentro integration (#16683)
This commit is contained in:
@@ -92,6 +92,12 @@
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/GiAppThemeWhiteStatusBar" />
|
||||
|
||||
<activity
|
||||
android:name=".decentro.GiWebViewActivity"
|
||||
android:exported="false"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/GiAppThemeWhiteStatusBar" />
|
||||
|
||||
<activity
|
||||
android:name=".health.activity.AbhaContainerActivity"
|
||||
android:exported="false"
|
||||
|
||||
@@ -476,6 +476,12 @@ object InsuranceAnalyticsConstants {
|
||||
const val HI_HRC_FullReport_Land_Success = "HI_HRC_FullReport_Land_Success"
|
||||
const val HI_Health_Score = "HI_Health_Score"
|
||||
|
||||
const val HI_DECENTRO_KYC_SCREEN_LAND = "hi_decentro_kyc_screen_land"
|
||||
const val HI_DECENTRO_KYC_WEBVIEW_INIT = "hi_decentro_kyc_webview_init"
|
||||
const val HI_DECENTRO_KYC_NAVIGATION_LISTENER = "hi_decentro_kyc_navigation_listener"
|
||||
const val HI_DECENTRO_KYC_EXIT_DETECTED = "hi_decentro_kyc_exit_detected"
|
||||
const val HI_DECENTRO_TIMEOUT_ERROR = "hi_decentro_timeout_error"
|
||||
|
||||
// Free Insurance
|
||||
const val FREE_INSURANCE_CONTAINER = "free_insurance_container"
|
||||
const val FREE_INSURANCE_CALENDAR_SCREEN = "free_insurance_calendar"
|
||||
|
||||
@@ -355,6 +355,7 @@ class NavigationHandler @Inject constructor(private val uiControllerUtil: UiCont
|
||||
const val URL_HI_QUIZ_QUESTION_SCREEN = "hi_quiz_question_screen"
|
||||
const val URL_HI_QUIZ_RESULT_SCREEN = "hi_quiz_result_screen"
|
||||
const val URL_INSURANCE_CONTAINER = "insurance_container"
|
||||
const val URL_DECENTRO = "decentro"
|
||||
const val URL_ABHA_CONTAINER = "abha_container"
|
||||
const val URL_KYC_ACTIVITY = "kyc_activity"
|
||||
const val URL_FREE_INSURANCE_PAYMENT = "fi_payment"
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.insurance.decentro
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.google.gson.Gson
|
||||
import com.navi.base.model.CtaData
|
||||
import com.navi.insurance.analytics.InsuranceAnalyticsConstants
|
||||
import com.navi.insurance.analytics.NaviInsuranceAnalytics
|
||||
import com.navi.insurance.common.GiBaseActivity
|
||||
import com.navi.insurance.common.theme.color.GiMaterialTheme
|
||||
import com.navi.insurance.navigator.NaviInsuranceDeeplinkNavigator
|
||||
import com.navi.insurance.util.Constants
|
||||
import com.navi.insurance.util.Constants.DECENTRO_KYC_SCREEN
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@AndroidEntryPoint
|
||||
class GiWebViewActivity : GiBaseActivity() {
|
||||
private lateinit var ctaData: CtaData
|
||||
private var timeoutThresholdMs: Long = 0
|
||||
private var timeoutJob: Job? = null
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
sendEvent(InsuranceAnalyticsConstants.HI_DECENTRO_KYC_SCREEN_LAND)
|
||||
val webUrl = intent.getStringExtra(WEB_URL)
|
||||
val exitUrl = intent.getStringExtra(WEBVIEW_EXIT_URL)
|
||||
timeoutThresholdMs = intent.getStringExtra(CLOSE_TIMEOUT)?.toLong() ?: 0
|
||||
ctaData = Gson().fromJson(intent.getStringExtra(CTA_DATA).orEmpty(), CtaData::class.java)
|
||||
enableEdgeToEdge()
|
||||
startTimeout()
|
||||
setContent {
|
||||
GiMaterialTheme {
|
||||
WebViewScreen(
|
||||
url = webUrl.orEmpty(),
|
||||
exitUrl = exitUrl.orEmpty(),
|
||||
nextScreen = { nextScreen() },
|
||||
sendEvent = ::sendEvent,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
cancelTimeout()
|
||||
super.onPause()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (timeoutThresholdMs > 0) {
|
||||
startTimeout()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
cancelTimeout()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
super.onBackPressed()
|
||||
nextScreen()
|
||||
}
|
||||
|
||||
private fun startTimeout() {
|
||||
if (timeoutThresholdMs > 0) {
|
||||
cancelTimeout()
|
||||
val exceptionHandler = CoroutineExceptionHandler { _, _ ->
|
||||
sendEvent(InsuranceAnalyticsConstants.HI_DECENTRO_TIMEOUT_ERROR)
|
||||
}
|
||||
timeoutJob =
|
||||
lifecycleScope.launch(exceptionHandler) {
|
||||
delay(timeoutThresholdMs)
|
||||
nextScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun cancelTimeout() {
|
||||
timeoutJob?.cancel()
|
||||
timeoutJob = null
|
||||
}
|
||||
|
||||
private fun nextScreen() {
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(Constants.PARAMS_EXTRA, ctaData)
|
||||
sendEvent(InsuranceAnalyticsConstants.HI_DECENTRO_KYC_EXIT_DETECTED)
|
||||
NaviInsuranceDeeplinkNavigator.navigate(
|
||||
activity = this,
|
||||
ctaData = ctaData,
|
||||
bundle = bundle,
|
||||
finish = true,
|
||||
)
|
||||
}
|
||||
|
||||
private fun sendEvent(eventName: String) {
|
||||
NaviInsuranceAnalytics.postAnalyticsEvent(
|
||||
eventName = eventName,
|
||||
eventProperties = mapOf(Pair(NaviInsuranceAnalytics.SCREEN, DECENTRO_KYC_SCREEN)),
|
||||
)
|
||||
}
|
||||
|
||||
override val screenName: String
|
||||
get() = "GiWebViewActivity"
|
||||
|
||||
companion object {
|
||||
const val WEB_URL = "webUrl"
|
||||
const val WEBVIEW_EXIT_URL = "webviewExitUrl"
|
||||
const val CLOSE_TIMEOUT = "webviewForceCloseTimeout"
|
||||
const val CTA_DATA = "CtaData"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2025 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.insurance.decentro
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.graphics.Bitmap
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.*
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Close
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import com.navi.insurance.analytics.InsuranceAnalyticsConstants
|
||||
|
||||
@SuppressLint("SetJavaScriptEnabled")
|
||||
@Composable
|
||||
fun WebViewScreen(
|
||||
url: String,
|
||||
exitUrl: String,
|
||||
nextScreen: () -> Unit = {},
|
||||
sendEvent: (String) -> Unit = {},
|
||||
) {
|
||||
|
||||
Surface(modifier = Modifier.fillMaxSize()) {
|
||||
Box(modifier = Modifier.fillMaxSize().padding(top = 32.dp)) {
|
||||
LaunchedEffect(Unit) {
|
||||
sendEvent(InsuranceAnalyticsConstants.HI_DECENTRO_KYC_WEBVIEW_INIT)
|
||||
}
|
||||
AndroidView(
|
||||
factory = { ctx ->
|
||||
WebView(ctx).apply {
|
||||
layoutParams =
|
||||
ViewGroup.LayoutParams(
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||
)
|
||||
|
||||
webViewClient =
|
||||
object : WebViewClient() {
|
||||
override fun onPageStarted(
|
||||
view: WebView?,
|
||||
url: String?,
|
||||
favicon: Bitmap?,
|
||||
) {
|
||||
sendEvent(
|
||||
InsuranceAnalyticsConstants
|
||||
.HI_DECENTRO_KYC_NAVIGATION_LISTENER
|
||||
)
|
||||
super.onPageStarted(view, url, favicon)
|
||||
url?.let { currentUrl ->
|
||||
if (shouldExitOnUrl(currentUrl, exitUrl)) {
|
||||
nextScreen()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun shouldOverrideUrlLoading(
|
||||
view: WebView?,
|
||||
request: WebResourceRequest?,
|
||||
): Boolean {
|
||||
request?.url?.let { uri ->
|
||||
val urlString = uri.toString()
|
||||
if (shouldExitOnUrl(urlString, exitUrl)) {
|
||||
nextScreen()
|
||||
}
|
||||
}
|
||||
return super.shouldOverrideUrlLoading(view, request)
|
||||
}
|
||||
}
|
||||
|
||||
webChromeClient =
|
||||
object : WebChromeClient() {
|
||||
override fun onReceivedTitle(view: WebView?, title: String?) {
|
||||
super.onReceivedTitle(view, title)
|
||||
title?.let { pageTitle ->
|
||||
sendEvent("HI_DECENTRO_" + pageTitle.take(30))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onConsoleMessage(
|
||||
consoleMessage: ConsoleMessage?
|
||||
): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
settings.apply {
|
||||
javaScriptEnabled = true
|
||||
domStorageEnabled = true
|
||||
loadWithOverviewMode = true
|
||||
useWideViewPort = true
|
||||
builtInZoomControls = true
|
||||
displayZoomControls = false
|
||||
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
|
||||
setSupportMultipleWindows(true)
|
||||
javaScriptCanOpenWindowsAutomatically = true
|
||||
loadsImagesAutomatically = true
|
||||
cacheMode = WebSettings.LOAD_DEFAULT
|
||||
}
|
||||
|
||||
loadUrl(url)
|
||||
}
|
||||
},
|
||||
update = { webView ->
|
||||
if (webView.url != url) {
|
||||
webView.loadUrl(url)
|
||||
}
|
||||
},
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
)
|
||||
IconButton(
|
||||
onClick = { nextScreen() },
|
||||
modifier = Modifier.align(Alignment.TopStart).padding(top = 16.dp),
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Close,
|
||||
contentDescription = "Close",
|
||||
tint = Color.Black,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldExitOnUrl(currentUrl: String, exitUrl: String): Boolean {
|
||||
if (exitUrl.isEmpty()) {
|
||||
return false
|
||||
}
|
||||
return currentUrl.contains(exitUrl)
|
||||
}
|
||||
@@ -119,6 +119,7 @@ import com.navi.insurance.common.util.NavigationHandler.Companion.URL_PAYMENT_ST
|
||||
import com.navi.insurance.common.util.NavigationHandler.Companion.URL_POP_UP_SCREEN
|
||||
import com.navi.insurance.common.util.NavigationHandler.Companion.URL_TELE_HRA_BOTTOM_SHEET
|
||||
import com.navi.insurance.common.util.NavigationHandler.Companion.URL_UPDATE_PREMIUM_BOTTOMSHEET
|
||||
import com.navi.insurance.decentro.GiWebViewActivity
|
||||
import com.navi.insurance.emi_date_change.EmiCalendarActivity
|
||||
import com.navi.insurance.endorsement.activity.EndorsementActivity
|
||||
import com.navi.insurance.engagement.health_risk_score.activity.HealthRiskScoreActivity
|
||||
@@ -657,6 +658,10 @@ object NaviInsuranceDeeplinkNavigator {
|
||||
intent = Intent(activity, InsuranceContainerActivity::class.java)
|
||||
bundle.putParcelable(KEY_CTA_DATA, ctaData)
|
||||
}
|
||||
NavigationHandler.URL_DECENTRO -> {
|
||||
intent = Intent(activity, GiWebViewActivity::class.java)
|
||||
bundle.putParcelable(KEY_CTA_DATA, ctaData)
|
||||
}
|
||||
NavigationHandler.URL_ABHA_CONTAINER -> {
|
||||
intent = Intent(activity, AbhaContainerActivity::class.java)
|
||||
bundle.putParcelable(KEY_CTA_DATA, ctaData)
|
||||
|
||||
@@ -218,6 +218,7 @@ object Constants {
|
||||
const val URL_TITLE_ICON_DESC_BOTTOM_SHEET = "gi/bottom_sheet/title_icon_desc_bottomsheet"
|
||||
const val screenName = "screenName"
|
||||
const val TELE_SALES_LANDING_PAGE = "TELE_SALES_LANDING_PAGE"
|
||||
const val DECENTRO_KYC_SCREEN = "DECENTRO_KYC_SCREEN"
|
||||
|
||||
const val KEY_NOTE_TEXT = "noteText"
|
||||
const val KEY_NOTE_BACKGROUND_COLOR = "noteBackgroundColor"
|
||||
|
||||
Reference in New Issue
Block a user