NTP-60797 | Redirect user to home page when returning from background (#16426)

This commit is contained in:
shankar yadav
2025-06-04 15:47:42 +05:30
committed by GitHub
parent d69215c24a
commit 8a658a7e8c
4 changed files with 85 additions and 6 deletions

View File

@@ -148,6 +148,9 @@ object FirebaseRemoteConfigHelper {
"SHOULD_USE_GLOBAL_SCOPE_FOR_DASHBOARD_SYNC"
const val NAVI_PAY_DOWNLOAD_HISTORY_AS_PDF_ENABLED = "NAVI_PAY_DOWNLOAD_HISTORY_AS_PDF_ENABLED"
const val AUTO_REDIRECT_TO_HOME_PAGE_LIMIT_TIME_IN_MIN =
"AUTO_REDIRECT_TO_HOME_PAGE_LIMIT_TIME_IN_MIN"
// COMMON
const val LITMUS_EXPERIMENTS_CACHE_DURATION_IN_MILLIS =
"LITMUS_EXPERIMENTS_CACHE_DURATION_IN_MILLIS"

View File

@@ -20,6 +20,7 @@ import android.text.Spannable
import android.text.SpannableString
import android.text.Spanned
import android.text.TextPaint
import android.text.format.DateUtils
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.text.style.ForegroundColorSpan
@@ -62,6 +63,8 @@ import com.google.gson.JsonObject
import com.google.gson.reflect.TypeToken
import com.navi.analytics.utils.NaviTrackEvent
import com.navi.base.AppServiceManager
import com.navi.base.deeplink.DeepLinkManager
import com.navi.base.deeplink.util.DeeplinkConstants
import com.navi.base.model.ActionData
import com.navi.base.model.CtaData
import com.navi.base.model.LineItem
@@ -72,6 +75,7 @@ import com.navi.base.utils.orElse
import com.navi.common.CommonRetrofitProvider
import com.navi.common.R
import com.navi.common.customview.CustomTypefaceSpan
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
import com.navi.common.listeners.ClickableTextListener
import com.navi.common.network.models.RepoResult
import com.navi.common.network.retrofit.RetrofitService
@@ -90,6 +94,7 @@ import java.util.zip.GZIPOutputStream
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.cancellation.CancellationException
import kotlin.text.orEmpty
import kotlin.time.Duration
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
@@ -759,3 +764,55 @@ fun Activity.handleTouchEvent(event: MotionEvent?, shouldDismissKeyboardOnFocusC
}
}
}
/**
* Checks if the user has been inactive on a screen for longer than a specified threshold, and
* redirects to the Home screen if the limit is exceeded.
*
* This is useful for automatically navigating away from inactive screens to improve user experience
* and maintain app context.
*
* @param screenName The name of the screen for logging and analytics purposes.
* @param foregroundTime The timestamp (in milliseconds) when the screen came to the foreground.
* @param backgroundTime The timestamp (in milliseconds) when the screen went to the background.
*
* If either `foregroundTime` or `backgroundTime` is 0, the function exits early.
*
* The threshold for inactivity is fetched from Remote Config
* (`AUTO_REDIRECT_TO_HOME_PAGE_DEFAULT_TIME`), with a default value of 1 minute. If the calculated
* inactivity duration exceeds this threshold, the user is automatically redirected to the Home
* screen, and an event is logged.
*/
fun Activity.checkAndRedirectToHomeIfInactivityLimitCrossed(
screenName: String,
foregroundTime: Long,
backgroundTime: Long,
) {
if (foregroundTime == 0L || backgroundTime == 0L) return
val inactivityDurationInMinutes = (foregroundTime - backgroundTime) / DateUtils.MINUTE_IN_MILLIS
val thresholdInMinutes =
FirebaseRemoteConfigHelper.getLong(
FirebaseRemoteConfigHelper.AUTO_REDIRECT_TO_HOME_PAGE_LIMIT_TIME_IN_MIN,
120,
)
if (inactivityDurationInMinutes < thresholdInMinutes) return
NaviTrackEvent.trackEventOnClickStream(
eventName = "Dev_Auto_Redirect_To_HomePage",
eventValues =
mapOf(
"inactivityDurationInMinutes" to inactivityDurationInMinutes.toString(),
"thresholdInMinutes" to thresholdInMinutes.toString(),
"screenName" to screenName,
),
)
DeepLinkManager.getDeepLinkListener()
?.navigateTo(
activity = this,
ctaData = CtaData(url = DeeplinkConstants.HOME),
finish = true,
)
}

View File

@@ -50,15 +50,19 @@ import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.navi.analytics.utils.AlfredFacade
import com.navi.base.utils.TrustedTimeAccessor
import com.navi.common.lottie.LottieRepository
import com.navi.common.model.NaviLottieCompositionSpecType
import com.navi.common.utils.CommonUtils.getDisplayableAmount
import com.navi.common.utils.CommonUtils.initFraudCheckSDK
import com.navi.common.utils.checkAndRedirectToHomeIfInactivityLimitCrossed
import com.navi.common.utils.navigateUp
import com.navi.common.utils.setStatusBarColor
import com.navi.design.font.FontWeightEnum
import com.navi.pay.NavGraphs
import com.navi.pay.R
import com.navi.pay.analytics.NaviPayAnalytics
import com.navi.pay.analytics.NaviPayAnalytics.Companion.NAVI_PAY_SEND_MONEY
import com.navi.pay.common.model.view.NaviPayButtonAction
import com.navi.pay.common.model.view.NaviPayScreenType
import com.navi.pay.common.model.view.SetPinResult
@@ -176,13 +180,22 @@ fun SendMoneyScreen(
val observer = LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_RESUME,
Lifecycle.Event.ON_CREATE,
Lifecycle.Event.ON_PAUSE -> {
naviPayActivity.window.statusBarColor =
ContextCompat.getColor(naviPayActivity, colorResId)
Lifecycle.Event.ON_CREATE -> {
naviPayActivity.setStatusBarColor(color = colorResId)
sendMoneyViewModel.setBackgroundTime(0)
}
Lifecycle.Event.ON_RESUME -> {
naviPayActivity.setStatusBarColor(color = colorResId)
naviPayActivity.checkAndRedirectToHomeIfInactivityLimitCrossed(
screenName = NAVI_PAY_SEND_MONEY,
foregroundTime = TrustedTimeAccessor.getCurrentTimeMillis(),
backgroundTime = sendMoneyViewModel.screenBackgroundTimestamp,
)
sendMoneyViewModel.setBackgroundTime(0)
}
Lifecycle.Event.ON_STOP -> {
sendMoneyViewModel.setBackgroundTime(TrustedTimeAccessor.getCurrentTimeMillis())
}
else -> Unit
}
}

View File

@@ -835,6 +835,8 @@ constructor(
private var fetchOffersJob: Job? = null
var screenBackgroundTimestamp = 0L
val sortedOffersList =
combine(
paymentAmount.debounce(200.milliseconds).distinctUntilChanged(),
@@ -5082,6 +5084,10 @@ constructor(
}
}
fun setBackgroundTime(timestamp: Long) {
screenBackgroundTimestamp = timestamp
}
private fun transactionLedgerEnabled(): Boolean =
isTxnLedgerAvailable.value &&
(source is SendMoneyScreenSource.BankDetailInput ||