NTP-17003 | Collect request notification handling (#15806)

This commit is contained in:
Aditya Narayan Malik
2025-04-15 17:54:02 +05:30
committed by GitHub
parent ff30fc459d
commit bbc1377461
14 changed files with 55 additions and 41 deletions

View File

@@ -85,6 +85,8 @@ class NaviFirebaseMessagingService : FirebaseMessagingService() {
@Inject lateinit var preferenceCleanerExecutor: Provider<NaviPreferenceCleanerExecutor>
@Inject lateinit var naviPayNotificationHandler: Provider<NaviPayNotificationHandler>
override fun onMessageReceived(remoteMessage: RemoteMessage) {
super.onMessageReceived(remoteMessage)
handleNotificationData(remoteMessage, applicationContext)
@@ -96,10 +98,7 @@ class NaviFirebaseMessagingService : FirebaseMessagingService() {
NaviTrackEvent.trackEventOnClickStream("push_notification_received")
when (remoteMessage.data[NotificationConstants.MODULE]) {
ModuleName.NAVIPAY.name ->
NaviPayNotificationHandler.handlePushNotification(
context = context,
data = remoteMessage.data,
)
naviPayNotificationHandler.get().handlePushNotification(data = remoteMessage.data)
else -> {
handleNotificationForSuperApp(remoteMessage, context)
Timber.d("Notification received: ${remoteMessage.data}")

View File

@@ -183,6 +183,7 @@ fun UPISettingSDK(
activity = activity,
qrDetails = action.qrDetails,
galleryLauncher = galleryLauncher,
naviPayNotificationHandler = settingSDKViewmodel.naviPayNotificationHandler,
)
naviSettingSDKAnalytics.onDownloadQRClicked()

View File

@@ -44,6 +44,7 @@ fun downloadQR(
activity: Activity,
qrDetails: QrDetails?,
galleryLauncher: ManagedActivityResultLauncher<Intent, ActivityResult>,
naviPayNotificationHandler: NaviPayNotificationHandler,
) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
launchFilePicker(qrDetails = qrDetails, galleryLauncher = galleryLauncher)
@@ -82,7 +83,10 @@ fun downloadQR(
}
outputStream.flush()
}
showDownloadNotification(activity = activity, uri = imageUri)
showDownloadNotification(
uri = imageUri,
naviPayNotificationHandler = naviPayNotificationHandler,
)
} catch (e: Exception) {
e.log()
showToast(context = activity, message = "Failed to save QR code")
@@ -118,9 +122,11 @@ private fun generateFileName(accountHolderName: String): String {
return "NaviQR_${accountHolderName}_$timestamp"
}
private fun showDownloadNotification(activity: Activity, uri: Uri) {
NaviPayNotificationHandler.showNotification(
context = activity.baseContext,
private fun showDownloadNotification(
uri: Uri,
naviPayNotificationHandler: NaviPayNotificationHandler,
) {
naviPayNotificationHandler.showNotification(
intent =
Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "image/png")

View File

@@ -26,6 +26,7 @@ import com.navi.pay.common.settingscreen.utils.WallpaperManager
import com.navi.pay.common.settingscreen.utils.isOnboardingRequired
import com.navi.pay.common.setup.NaviPayManager
import com.navi.pay.common.usecase.LinkedAccountsUseCase
import com.navi.pay.common.utils.NaviPayNotificationHandler
import com.navi.pay.common.utils.NaviPayOnboardingNavigator
import com.navi.pay.common.viewmodel.NaviPayBaseVM
import com.navi.pay.management.common.settings.util.SettingsCountManager
@@ -61,6 +62,7 @@ constructor(
private val linkedAccountsUseCase: LinkedAccountsUseCase,
private val naviPayPspManager: NaviPayPspManager,
val naviPayOnboardingNavigator: NaviPayOnboardingNavigator,
val naviPayNotificationHandler: NaviPayNotificationHandler,
private val wallpaperManager: WallpaperManager,
) : NaviPayBaseVM() {

View File

@@ -42,6 +42,7 @@ constructor(
private val naviCacheRepository: NaviCacheRepository,
private val upiLiteBalanceUseCase: UpiLiteBalanceUseCase,
private val dispatcherProvider: CoroutineDispatcherProvider,
private val naviPayNotificationHandler: NaviPayNotificationHandler,
@NaviPayGsonBuilder private val gson: Gson,
) {
private val naviPayAnalytics: NaviPayAnalytics.NaviPayUPILite =
@@ -111,15 +112,14 @@ constructor(
private suspend fun sendNotificationAndUpdateCache(upiLiteConfig: NaviPayUpiLiteConfig) {
val notificationData = upiLiteConfig.config.lowBalanceNotificationData
NaviPayNotificationHandler.handlePushNotification(
context = context,
naviPayNotificationHandler.handlePushNotification(
data =
mapOf(
NAVI_PAY_NOTIFICATION_DATA_CTA_KEY to notificationData.ctaUrl,
NAVI_PAY_NOTIFICATION_TITLE to notificationData.title,
NAVI_PAY_NOTIFICATION_BODY to notificationData.description,
NAVI_PAY_NOTIFICATION_ID to UPI_LITE_LOW_BALANCE_NOTIFICATION_ID.toString(),
),
)
)
// Update cache with current timestamp

View File

@@ -34,14 +34,18 @@ import com.navi.pay.utils.NAVI_PAY_NOTIFICATION_PENDING_INTENT_REQUEST_CODE
import com.navi.pay.utils.NAVI_PAY_NOTIFICATION_TITLE
import com.navi.pay.utils.PENDING_REQUEST_REFRESHED_REQUIRED
import com.navi.pay.utils.getBundle
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject
import kotlin.random.Random
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
object NaviPayNotificationHandler {
class NaviPayNotificationHandler
@Inject
constructor(@ApplicationContext private val context: Context) {
fun handlePushNotification(context: Context, data: Map<String, String>) {
fun handlePushNotification(data: Map<String, String>) {
val intent = Intent(context, NaviPayActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
@@ -66,7 +70,6 @@ object NaviPayNotificationHandler {
val notificationId = getNotificationIdAsInt(data = data[NAVI_PAY_NOTIFICATION_ID])
showNotification(
context = context,
intent = intent,
notificationContentTitle = notificationContentTitle,
notificationContentBody = notificationContentBody,
@@ -81,7 +84,6 @@ object NaviPayNotificationHandler {
}
fun showNotification(
context: Context,
intent: Intent,
notificationContentTitle: String,
notificationContentBody: String,
@@ -130,7 +132,7 @@ object NaviPayNotificationHandler {
notificationManager.notify(notificationId, notificationBuilder.build())
}
fun cancelNotification(context: Context, notificationId: String) {
fun cancelNotification(notificationId: String) {
val notificationIdAsInt = getNotificationIdAsInt(data = notificationId)
NotificationManagerCompat.from(context).cancel(notificationIdAsInt)
}

View File

@@ -52,7 +52,6 @@ import com.navi.pay.common.ui.NaviPayHeader
import com.navi.pay.common.ui.NaviPaySponsorView
import com.navi.pay.common.utils.ErrorEventHandler
import com.navi.pay.common.utils.NaviPayEventBus
import com.navi.pay.common.utils.NaviPayNotificationHandler
import com.navi.pay.common.utils.SnackBarPredefinedConfig
import com.navi.pay.common.viewmodel.NaviPayBaseVM.Companion.ERROR_NAVIGATE_BACK_TAG
import com.navi.pay.destinations.SendMoneyScreenDestination
@@ -87,18 +86,6 @@ fun CollectRequestsScreen(
collectRequestViewModel.clickedCollectRequestItemId.collectAsStateWithLifecycle()
val isRefreshing by collectRequestViewModel.isRefreshing.collectAsStateWithLifecycle()
val onProceedRequestClick = { collectRequest: CollectRequestEntity ->
NaviPayNotificationHandler.cancelNotification(
context = naviPayActivity.baseContext,
notificationId = collectRequest.transactionId,
)
collectRequestViewModel.onProceedButtonClicked(
collectRequestEntity = collectRequest,
sendMoneyAction = null,
)
}
val onBackClicked = { navigator.navigateUp(naviPayActivity) }
BackHandler { onBackClicked() }
@@ -157,7 +144,7 @@ fun CollectRequestsScreen(
CollectRequestsMainScreen(
collectRequestState = collectRequestState,
onProceedRequestClick = onProceedRequestClick,
onProceedRequestClick = collectRequestViewModel::onProceedButtonClicked,
onBackClicked = onBackClicked,
snackBarState = snackBarState,
showLoader = showLoader,

View File

@@ -22,6 +22,7 @@ import com.navi.pay.common.repository.CommonRepository
import com.navi.pay.common.repository.SharedPreferenceRepository
import com.navi.pay.common.usecase.LinkedAccountsUseCase
import com.navi.pay.common.utils.DeviceInfoProvider
import com.navi.pay.common.utils.NaviPayNotificationHandler
import com.navi.pay.common.utils.getMetricInfo
import com.navi.pay.common.viewmodel.NaviPayBaseVM
import com.navi.pay.entry.NaviPayActivityDataProvider
@@ -79,6 +80,7 @@ constructor(
private val naviPayOffersHelper: NaviPayOffersHelper,
private val linkedAccountsUseCase: LinkedAccountsUseCase,
private val litmusExperimentsUseCase: LitmusExperimentsUseCase,
val naviPayNotificationHandler: NaviPayNotificationHandler,
) : NaviPayBaseVM() {
private val naviPayAnalytics: NaviPayAnalytics.NaviPayCollectRequests =
@@ -258,6 +260,8 @@ constructor(
uiState = CollectRequestUIState.Loaded(collectRequests = collectRequests)
)
closePendingNotifications(collectRequests)
if (isOfferExperienceEnabled.value) {
fetchBestOfferForCollectRequests(collectRequests = collectRequests)
}
@@ -273,6 +277,14 @@ constructor(
}
}
private fun closePendingNotifications(collectRequests: List<CollectRequestEntity>) {
collectRequests.forEach { collectRequest ->
naviPayNotificationHandler.cancelNotification(
notificationId = collectRequest.transactionId
)
}
}
private fun updateIsRefreshing(isRefreshing: Boolean) {
_isRefreshing.update { isRefreshing }
}
@@ -381,7 +393,7 @@ constructor(
fun onProceedButtonClicked(
collectRequestEntity: CollectRequestEntity,
sendMoneyAction: SendMoneyAction?,
sendMoneyAction: SendMoneyAction? = null,
showButtonLoader: Boolean = true,
) {
viewModelScope.launch(Dispatchers.IO) {

View File

@@ -75,7 +75,6 @@ import com.navi.pay.common.ui.RenderBottomSheetMenuOptionItem
import com.navi.pay.common.ui.SecondaryRoundedButton
import com.navi.pay.common.ui.ShadowStrip
import com.navi.pay.common.ui.SuccessBottomSheetContent
import com.navi.pay.common.utils.NaviPayNotificationHandler
import com.navi.pay.common.utils.SnackBarPredefinedConfig
import com.navi.pay.destinations.MandateDetailScreenOfActiveOrCompletedCategoryDestination
import com.navi.pay.destinations.MandateDetailScreenOfPendingCategoryDestination
@@ -253,11 +252,11 @@ fun MandateDetailScreenOfPendingCategory(
naviPayAnalytics.onManageDetailsLoaded(
mandateDetailOfPendingCategoryViewModel.mandateEntity
)
NaviPayNotificationHandler.cancelNotification(
context = naviPayActivity.baseContext,
notificationId =
mandateDetailOfPendingCategoryViewModel.mandateEntity?.id.orEmpty(),
)
mandateDetailOfPendingCategoryViewModel.naviPayNotificationHandler
.cancelNotification(
notificationId =
mandateDetailOfPendingCategoryViewModel.mandateEntity?.id.orEmpty()
)
}
RenderMandateDetailScreenOfPendingCategory(
resultNavigator = resultNavigator,

View File

@@ -29,6 +29,7 @@ import com.navi.pay.common.usecase.UpiRequestIdUseCase
import com.navi.pay.common.usecase.ValidateVpaUseCase
import com.navi.pay.common.utils.DeviceInfoProvider
import com.navi.pay.common.utils.NaviPayCommonUtils
import com.navi.pay.common.utils.NaviPayNotificationHandler
import com.navi.pay.common.utils.getMetricInfo
import com.navi.pay.common.viewmodel.NaviPayBaseVM
import com.navi.pay.management.common.sendmoney.model.network.BlockSpamUserRequest
@@ -96,6 +97,7 @@ constructor(
private val accountEligibilityMerchantHelper: AccountEligibilityMerchantHelper,
private val naviPayPspManager: NaviPayPspManager,
private val createMandateUseCase: CreateMandateUseCase,
val naviPayNotificationHandler: NaviPayNotificationHandler,
) : NaviPayBaseVM() {
private val naviPayAnalytics: NaviPayAnalytics.NaviPayManageAutoPay =

View File

@@ -79,7 +79,6 @@ import com.navi.pay.common.ui.NaviPayModalBottomSheet
import com.navi.pay.common.ui.PrimaryAccountTypeTag
import com.navi.pay.common.ui.RenderUpiNumberLinkSuccessState
import com.navi.pay.common.ui.ThemedRoundedButton
import com.navi.pay.common.utils.NaviPayNotificationHandler
import com.navi.pay.common.utils.SnackBarPredefinedConfig
import com.navi.pay.common.utils.getAccountTypeFormattedValue
import com.navi.pay.destinations.AddNewUpiNumberScreenDestination
@@ -211,9 +210,8 @@ fun UpiNumberScreen(
upiNumberViewModel.upiNumberActionResult.collect { result ->
dismissBottomSheet()
if (result is UpiNumberActionResult.PhoneNumberLinkedAsUpiNumberResult) {
NaviPayNotificationHandler.cancelNotification(
context = naviPayActivity.baseContext,
notificationId = PORTED_OUT_PN_ID,
upiNumberViewModel.naviPayNotificationHandler.cancelNotification(
notificationId = PORTED_OUT_PN_ID
)
}
}

View File

@@ -22,6 +22,7 @@ import com.navi.pay.common.usecase.LinkedAccountsUseCase
import com.navi.pay.common.usecase.RefreshUpiNumbersUseCase
import com.navi.pay.common.utils.DeviceInfoProvider
import com.navi.pay.common.utils.NaviPayCommonUtils.getHelpCtaData
import com.navi.pay.common.utils.NaviPayNotificationHandler
import com.navi.pay.common.utils.fetchUserPhoneNumber
import com.navi.pay.common.utils.getMetricInfo
import com.navi.pay.common.viewmodel.NaviPayBaseVM
@@ -84,6 +85,7 @@ constructor(
private val naviPayActivityDataProvider: NaviPayActivityDataProvider,
private val upiNumbersHelper: UpiNumbersHelper,
private val naviPayPspManager: NaviPayPspManager,
val naviPayNotificationHandler: NaviPayNotificationHandler,
) : NaviPayBaseVM() {
private val naviPayAnalytics: NaviPayAnalytics.NaviPayUpiNumber =

View File

@@ -270,6 +270,8 @@ fun LinkedAccountDetailScreen(
activity = naviPayActivity,
qrDetails = qrDetails,
galleryLauncher = galleryLauncher,
naviPayNotificationHandler =
linkedAccountDetailViewModel.naviPayNotificationHandler,
)
},
onShareQRClicked = { qrDetails ->

View File

@@ -42,6 +42,7 @@ import com.navi.pay.common.usecase.UpiRequestIdUseCase
import com.navi.pay.common.utils.DeviceInfoProvider
import com.navi.pay.common.utils.NaviPayCommonUtils
import com.navi.pay.common.utils.NaviPayCommonUtils.getHelpCtaData
import com.navi.pay.common.utils.NaviPayNotificationHandler
import com.navi.pay.common.utils.VpaQRCodeManager
import com.navi.pay.common.utils.fetchUserPhoneNumber
import com.navi.pay.common.utils.getLinkedAccountQRDetails
@@ -152,6 +153,7 @@ constructor(
private val updateCustomerStatusOnAccountRemovalUseCase:
UpdateCustomerStatusOnAccountRemovalUseCase,
private val upiNumbersHelper: UpiNumbersHelper,
val naviPayNotificationHandler: NaviPayNotificationHandler,
naviPayActivityDataProvider: NaviPayActivityDataProvider,
savedStateHandle: SavedStateHandle,
@NaviPayGsonBuilder private val gson: Gson,