TP-64883 | Pinned widget feature (#10673)
Co-authored-by: Shaurya Rehan <shaurya.rehan@navi.com>
This commit is contained in:
@@ -117,6 +117,11 @@ object FirebaseRemoteConfigHelper {
|
||||
const val NAVI_PAY_ENABLE_VALIDATE_VPA_CACHING = "NAVI_PAY_ENABLE_VALIDATE_VPA_CACHING"
|
||||
const val NAVI_PAY_VALIDATE_VPA_CACHING_TTL_IN_HOURS =
|
||||
"NAVI_PAY_VALIDATE_VPA_CACHING_TTL_IN_HOURS"
|
||||
const val NAVI_PAY_ENABLE_SCAN_PAY_PINNED_WIDGET = "NAVI_PAY_ENABLE_SCAN_PAY_PINNED_WIDGET"
|
||||
const val NAVI_PAY_SCAN_AND_PAY_PINNED_WIDGET_REQUEST_MIN_DAYS =
|
||||
"NAVI_PAY_SCAN_AND_PAY_PINNED_WIDGET_REQUEST_MIN_DAYS"
|
||||
const val NAVI_PAY_SCAN_AND_PAY_PINNED_WIDGET_INITIAL_DELAY_IN_SECS =
|
||||
"NAVI_PAY_SCAN_AND_PAY_PINNED_WIDGET_INITIAL_DELAY_IN_SECS"
|
||||
|
||||
// BBPS
|
||||
const val NAVI_BBPS_CATEGORIES_CACHE_MILLIS = "NAVI_BBPS_CATEGORIES_CACHE_MILLIS"
|
||||
|
||||
@@ -497,4 +497,12 @@
|
||||
<key>NAVI_PAY_VALIDATE_VPA_CACHING_TTL_IN_HOURS</key>
|
||||
<value>48</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>NAVI_PAY_SCAN_AND_PAY_PINNED_WIDGET_REQUEST_MIN_DAYS</key>
|
||||
<value>7</value>
|
||||
</entry>
|
||||
<entry>
|
||||
<key>NAVI_PAY_SCAN_AND_PAY_PINNED_WIDGET_INITIAL_DELAY_IN_SECS</key>
|
||||
<value>5</value>
|
||||
</entry>
|
||||
</defaultsMap>
|
||||
@@ -2892,6 +2892,58 @@ class NaviPayAnalytics private constructor() {
|
||||
}
|
||||
}
|
||||
|
||||
inner class NaviPayWidgetManager {
|
||||
|
||||
fun onScanAndPayPinnedWidgetDisabled() {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
"NaviPay_Dev_WidgetManager_ScanAndPayPinnedWidgetDisabled"
|
||||
)
|
||||
}
|
||||
|
||||
fun onScanAndPayPinnedWidgetTimeThresholdNotPassed(
|
||||
lastRequestIntervalInDays: String,
|
||||
minRequestIntervalInDays: String
|
||||
) {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
"NaviPay_Dev_WidgetManager_ScanAndPayPinnedWidgetTimeThresholdNotPassed",
|
||||
mapOf(
|
||||
"lastRequestIntervalInDays" to lastRequestIntervalInDays,
|
||||
"minRequestIntervalInDays" to minRequestIntervalInDays
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun onScanAndPayPinnedWidgetBelowAndroid8() {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
"NaviPay_Dev_WidgetManager_ScanAndPayPinnedWidgetBelowAndroid8"
|
||||
)
|
||||
}
|
||||
|
||||
fun onScanAndPayPinnedWidgetPinningNotSupported() {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
"NaviPay_Dev_WidgetManager_ScanAndPayPinnedWidgetPinningNotSupported"
|
||||
)
|
||||
}
|
||||
|
||||
fun onScanAndPayPinnedWidgetAlreadyPinned() {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
"NaviPay_Dev_WidgetManager_ScanAndPayPinnedWidgetAlreadyPinned"
|
||||
)
|
||||
}
|
||||
|
||||
fun onScanAndPayPinnedWidgetNotPinned() {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
"NaviPay_Dev_WidgetManager_ScanAndPayPinnedWidgetNotPinned"
|
||||
)
|
||||
}
|
||||
|
||||
fun onScanAndPayPinnedWidgetRequested() {
|
||||
NaviTrackEvent.trackEventOnClickStream(
|
||||
"NaviPay_Dev_WidgetManager_ScanAndPayPinnedWidgetRequested"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val INSTANCE = NaviPayAnalytics()
|
||||
const val NAVI_HOME_SCREEN = "navi_home"
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.navi.pay.common.usecase.LinkedAccountsUseCase
|
||||
import com.navi.pay.common.utils.DeviceInfoProvider
|
||||
import com.navi.pay.common.utils.NaviPayCommonUtils
|
||||
import com.navi.pay.common.utils.NaviPaySdkUtils
|
||||
import com.navi.pay.common.widget.NaviPayWidgetManager
|
||||
import com.navi.pay.db.NaviPayAppDatabase
|
||||
import com.navi.pay.db.NaviPayAppEncryptedDatabase
|
||||
import com.navi.pay.utils.KEY_UPI_LITE_ACTIVE_ACCOUNT_INFO
|
||||
@@ -60,7 +61,8 @@ constructor(
|
||||
private val naviPayAppEncryptedDatabase: Provider<NaviPayAppEncryptedDatabase>,
|
||||
private val deviceInfoProvider: Provider<DeviceInfoProvider>,
|
||||
private val linkedAccountsUseCase: Provider<LinkedAccountsUseCase>,
|
||||
private val sharedPreferenceRepository: SharedPreferenceRepository
|
||||
private val sharedPreferenceRepository: SharedPreferenceRepository,
|
||||
private val naviPayWidgetManager: Provider<NaviPayWidgetManager>
|
||||
) {
|
||||
companion object {
|
||||
lateinit var baseUrl: String
|
||||
@@ -184,7 +186,7 @@ constructor(
|
||||
logoutTasks.add(async { naviCacheRepository.get().clearOnLogout() })
|
||||
logoutTasks.awaitAll()
|
||||
}
|
||||
NaviPayCommonUtils.removeScanAndPayShortcut(context = context)
|
||||
naviPayWidgetManager.get().removeScanAndPayLauncherWidget()
|
||||
}
|
||||
|
||||
fun isUserOnboarded(): Boolean {
|
||||
|
||||
@@ -12,7 +12,6 @@ import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.VibrationEffect
|
||||
import android.os.Vibrator
|
||||
@@ -20,7 +19,6 @@ import android.provider.Settings
|
||||
import android.telephony.SmsManager
|
||||
import android.telephony.SubscriptionManager
|
||||
import android.view.View
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
@@ -28,9 +26,6 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||
import androidx.compose.ui.platform.SoftwareKeyboardController
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import com.navi.analytics.utils.NaviTrackEvent
|
||||
import com.navi.base.deeplink.util.DeeplinkConstants
|
||||
import com.navi.base.model.CtaData
|
||||
@@ -48,11 +43,9 @@ import com.navi.common.utils.log
|
||||
import com.navi.pay.R
|
||||
import com.navi.pay.common.model.view.NaviPayAccessEligibility
|
||||
import com.navi.pay.common.model.view.NaviPayErrorConfig
|
||||
import com.navi.pay.common.model.view.NaviPayScreenType
|
||||
import com.navi.pay.common.model.view.SimInfo
|
||||
import com.navi.pay.common.theme.color.NaviPayColor
|
||||
import com.navi.pay.common.viewmodel.NaviPayBaseVM
|
||||
import com.navi.pay.entry.NaviPayActivity
|
||||
import com.navi.pay.management.common.sendmoney.model.network.TransactionInitiationType
|
||||
import com.navi.pay.management.common.transaction.model.view.TransactionCategoryTags
|
||||
import com.navi.pay.management.common.transaction.model.view.TransactionStatusOfView
|
||||
@@ -72,14 +65,9 @@ import com.navi.pay.utils.DOT_IFSC_DOT_NPCI
|
||||
import com.navi.pay.utils.INTENT_ACTION_SMS_DELIVERED
|
||||
import com.navi.pay.utils.INTENT_ACTION_SMS_SENT
|
||||
import com.navi.pay.utils.NAVI_PAY_FAIL_LOTTIE
|
||||
import com.navi.pay.utils.NAVI_PAY_LOCAL_URI_SCHEME
|
||||
import com.navi.pay.utils.NAVI_PAY_PAYMENT_STATUS_SUCCESS_LOTTIE
|
||||
import com.navi.pay.utils.NAVI_PAY_PENDING_LOTTIE
|
||||
import com.navi.pay.utils.NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_CLICKED
|
||||
import com.navi.pay.utils.NAVI_PAY_SCAN_AND_PAY_SHORTCUT_ID
|
||||
import com.navi.pay.utils.NAVI_PAY_SCAN_AND_PAY_WIDGET_ANALYTICS_EVENT_KEY
|
||||
import com.navi.pay.utils.NAVI_PAY_TRANSACTION_HISTORY_TAG_SEPARATOR
|
||||
import com.navi.pay.utils.NEEDS_RESULT
|
||||
import com.navi.pay.utils.ONE_HOUR_IN_MILLIS
|
||||
import com.navi.pay.utils.ONE_MINUTE_IN_MILLIS
|
||||
import com.navi.pay.utils.PHONE_NUMBER_LENGTH
|
||||
@@ -267,66 +255,6 @@ object NaviPayCommonUtils {
|
||||
}
|
||||
}
|
||||
|
||||
fun addScanAndPayShortcut(context: Context) {
|
||||
|
||||
if (
|
||||
ShortcutManagerCompat.getDynamicShortcuts(context).any {
|
||||
it.id == NAVI_PAY_SCAN_AND_PAY_SHORTCUT_ID
|
||||
}
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
val uri =
|
||||
Uri.Builder()
|
||||
.scheme(NAVI_PAY_LOCAL_URI_SCHEME)
|
||||
.authority(NaviPayScreenType.NAVI_PAY_QR_SCANNER_SCREEN.name)
|
||||
.build()
|
||||
|
||||
val scanAndPayShortcut =
|
||||
getShortcutObject(
|
||||
id = NAVI_PAY_SCAN_AND_PAY_SHORTCUT_ID,
|
||||
shortLabel = context.getString(R.string.title_scan_and_pay),
|
||||
longLabel = context.getString(R.string.title_scan_and_pay),
|
||||
icon = R.drawable.ic_ps_scan_pay,
|
||||
intent =
|
||||
Intent(Intent.ACTION_VIEW, uri, context, NaviPayActivity::class.java).apply {
|
||||
putExtra(NEEDS_RESULT, true)
|
||||
putExtra(
|
||||
NAVI_PAY_SCAN_AND_PAY_WIDGET_ANALYTICS_EVENT_KEY,
|
||||
NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_CLICKED
|
||||
)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
},
|
||||
context = context
|
||||
)
|
||||
|
||||
ShortcutManagerCompat.pushDynamicShortcut(context, scanAndPayShortcut)
|
||||
}
|
||||
|
||||
fun removeScanAndPayShortcut(context: Context) {
|
||||
ShortcutManagerCompat.removeDynamicShortcuts(
|
||||
context,
|
||||
listOf(NAVI_PAY_SCAN_AND_PAY_SHORTCUT_ID)
|
||||
)
|
||||
}
|
||||
|
||||
private fun getShortcutObject(
|
||||
id: String,
|
||||
shortLabel: String,
|
||||
longLabel: String,
|
||||
@DrawableRes icon: Int,
|
||||
intent: Intent,
|
||||
context: Context
|
||||
): ShortcutInfoCompat {
|
||||
return ShortcutInfoCompat.Builder(context, id)
|
||||
.setShortLabel(shortLabel)
|
||||
.setLongLabel(longLabel)
|
||||
.setIcon(IconCompat.createWithResource(context, icon))
|
||||
.setIntent(intent)
|
||||
.build()
|
||||
}
|
||||
|
||||
fun getDateTimeObjectFromDateTimeString(
|
||||
dateTime: String?,
|
||||
timeZone: DateTimeZone = DateTimeZone.getDefault()
|
||||
|
||||
@@ -17,6 +17,6 @@ import com.navi.pay.utils.NAVI_PAY_DATABASE_VALIDATE_VPA_CACHE_TABLE_NAME
|
||||
data class ValidateVpaEntity(
|
||||
@ColumnInfo(name = "vpa") @PrimaryKey val vpa: String,
|
||||
@ColumnInfo(name = "response") val response: String,
|
||||
@ColumnInfo(name = "updated_at") val updatedAt: Long = System.currentTimeMillis(),
|
||||
@ColumnInfo(name = "updatedAt") val updatedAt: Long = System.currentTimeMillis(),
|
||||
@ColumnInfo(name = "ttl") val ttl: Long
|
||||
)
|
||||
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright © 2024 by Navi Technologies Limited
|
||||
* * All rights reserved. Strictly confidential
|
||||
*
|
||||
*/
|
||||
|
||||
package com.navi.pay.common.widget
|
||||
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.ShortcutInfo
|
||||
import android.content.pm.ShortcutManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.core.content.pm.ShortcutInfoCompat
|
||||
import androidx.core.content.pm.ShortcutManagerCompat
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NAVI_PAY_ENABLE_SCAN_PAY_PINNED_WIDGET
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NAVI_PAY_SCAN_AND_PAY_PINNED_WIDGET_REQUEST_MIN_DAYS
|
||||
import com.navi.pay.R
|
||||
import com.navi.pay.analytics.NaviPayAnalytics
|
||||
import com.navi.pay.common.model.view.NaviPayScreenType
|
||||
import com.navi.pay.common.sync.model.view.SyncEntity
|
||||
import com.navi.pay.common.sync.repository.SyncRepository
|
||||
import com.navi.pay.entry.NaviPayActivity
|
||||
import com.navi.pay.utils.NAVI_PAY_LOCAL_URI_SCHEME
|
||||
import com.navi.pay.utils.NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_CLICKED
|
||||
import com.navi.pay.utils.NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_SHORTCUT_ID
|
||||
import com.navi.pay.utils.NAVI_PAY_SCAN_AND_PAY_WIDGET_ANALYTICS_EVENT_KEY
|
||||
import com.navi.pay.utils.NAVI_PAY_SYNC_TABLE_SCAN_PAY_PINNED_WIDGET_KEY
|
||||
import com.navi.pay.utils.NEEDS_RESULT
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.absoluteValue
|
||||
import org.joda.time.DateTime
|
||||
import org.joda.time.Days
|
||||
|
||||
/**
|
||||
* LauncherWidget - When you long press on app icon & option is shown
|
||||
*
|
||||
* StaticWidget - When you long press on home screen & select widgets & then select app
|
||||
*
|
||||
* PinnedWidget - Adding launcher widget to home screen
|
||||
*
|
||||
* TileWidget - Widget appearing in notification panel
|
||||
*/
|
||||
interface NaviPayWidgetManager {
|
||||
|
||||
fun addScanAndPayLauncherWidget()
|
||||
|
||||
fun removeScanAndPayLauncherWidget()
|
||||
|
||||
suspend fun requestScanAndPayPinnedWidget()
|
||||
}
|
||||
|
||||
class NaviPayWidgetManagerImpl
|
||||
@Inject
|
||||
constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val syncRepository: SyncRepository
|
||||
) : NaviPayWidgetManager {
|
||||
|
||||
private val qrScannerUri by lazy {
|
||||
Uri.Builder()
|
||||
.scheme(NAVI_PAY_LOCAL_URI_SCHEME)
|
||||
.authority(NaviPayScreenType.NAVI_PAY_QR_SCANNER_SCREEN.name)
|
||||
.build()
|
||||
}
|
||||
|
||||
private val qrScannerIntent by lazy {
|
||||
Intent(Intent.ACTION_VIEW, qrScannerUri, context, NaviPayActivity::class.java).apply {
|
||||
putExtra(NEEDS_RESULT, true)
|
||||
putExtra(
|
||||
NAVI_PAY_SCAN_AND_PAY_WIDGET_ANALYTICS_EVENT_KEY,
|
||||
NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_CLICKED
|
||||
)
|
||||
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
}
|
||||
}
|
||||
|
||||
private val naviPayAnalytics by lazy { NaviPayAnalytics.INSTANCE.NaviPayWidgetManager() }
|
||||
|
||||
private val shortcutManager by lazy {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1) {
|
||||
context.getSystemService(ShortcutManager::class.java)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun addScanAndPayLauncherWidget() {
|
||||
if (
|
||||
ShortcutManagerCompat.getDynamicShortcuts(context).any {
|
||||
it.id == NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_SHORTCUT_ID
|
||||
}
|
||||
) { // Already added
|
||||
return
|
||||
}
|
||||
|
||||
val scanAndPayShortcut =
|
||||
getShortcutObject(
|
||||
id = NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_SHORTCUT_ID,
|
||||
shortLabel = context.getString(R.string.title_scan_and_pay),
|
||||
longLabel = context.getString(R.string.title_scan_and_pay),
|
||||
icon = R.drawable.ic_ps_scan_pay,
|
||||
intent = qrScannerIntent,
|
||||
context = context
|
||||
)
|
||||
|
||||
ShortcutManagerCompat.pushDynamicShortcut(context, scanAndPayShortcut)
|
||||
}
|
||||
|
||||
override fun removeScanAndPayLauncherWidget() {
|
||||
ShortcutManagerCompat.removeDynamicShortcuts(
|
||||
context,
|
||||
listOf(NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_SHORTCUT_ID)
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun requestScanAndPayPinnedWidget() {
|
||||
|
||||
if (!FirebaseRemoteConfigHelper.getBoolean(NAVI_PAY_ENABLE_SCAN_PAY_PINNED_WIDGET)) {
|
||||
naviPayAnalytics.onScanAndPayPinnedWidgetDisabled()
|
||||
return
|
||||
}
|
||||
|
||||
val shortCutManager = shortcutManager ?: return
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
|
||||
naviPayAnalytics.onScanAndPayPinnedWidgetBelowAndroid8()
|
||||
return
|
||||
}
|
||||
|
||||
if (!shortCutManager.isRequestPinShortcutSupported) {
|
||||
naviPayAnalytics.onScanAndPayPinnedWidgetPinningNotSupported()
|
||||
return
|
||||
}
|
||||
|
||||
if (
|
||||
shortCutManager.pinnedShortcuts.firstOrNull {
|
||||
it.id == NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_SHORTCUT_ID && it.isPinned
|
||||
} != null
|
||||
) {
|
||||
naviPayAnalytics.onScanAndPayPinnedWidgetAlreadyPinned()
|
||||
return
|
||||
} else {
|
||||
naviPayAnalytics.onScanAndPayPinnedWidgetNotPinned()
|
||||
}
|
||||
|
||||
val lastSyncedTimestamp =
|
||||
syncRepository
|
||||
.get(NAVI_PAY_SYNC_TABLE_SCAN_PAY_PINNED_WIDGET_KEY)
|
||||
?.lastSyncedTimestamp
|
||||
?.toLongOrNull() ?: 0L
|
||||
|
||||
val lastRequestIntervalInDays =
|
||||
Days.daysBetween(DateTime(System.currentTimeMillis()), DateTime(lastSyncedTimestamp))
|
||||
.days
|
||||
.absoluteValue
|
||||
|
||||
val minRequestIntervalInDays =
|
||||
FirebaseRemoteConfigHelper.getLong(NAVI_PAY_SCAN_AND_PAY_PINNED_WIDGET_REQUEST_MIN_DAYS)
|
||||
|
||||
if (lastRequestIntervalInDays < minRequestIntervalInDays) {
|
||||
naviPayAnalytics.onScanAndPayPinnedWidgetTimeThresholdNotPassed(
|
||||
lastRequestIntervalInDays = lastRequestIntervalInDays.toString(),
|
||||
minRequestIntervalInDays = minRequestIntervalInDays.toString()
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val scanAndPayShortcut =
|
||||
ShortcutInfo.Builder(context, NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_SHORTCUT_ID).build()
|
||||
|
||||
val pinnedShortcutCallbackIntent =
|
||||
shortCutManager.createShortcutResultIntent(scanAndPayShortcut)
|
||||
|
||||
val successCallback =
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
pinnedShortcutCallbackIntent,
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
} else {
|
||||
PendingIntent.getBroadcast(
|
||||
context,
|
||||
0,
|
||||
pinnedShortcutCallbackIntent,
|
||||
PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
}
|
||||
|
||||
shortCutManager.requestPinShortcut(scanAndPayShortcut, successCallback.intentSender)
|
||||
|
||||
syncRepository.insert(
|
||||
syncEntity =
|
||||
SyncEntity(
|
||||
key = NAVI_PAY_SYNC_TABLE_SCAN_PAY_PINNED_WIDGET_KEY,
|
||||
lastSyncedTimestamp = System.currentTimeMillis().toString()
|
||||
)
|
||||
)
|
||||
|
||||
naviPayAnalytics.onScanAndPayPinnedWidgetRequested()
|
||||
}
|
||||
|
||||
private fun getShortcutObject(
|
||||
id: String,
|
||||
shortLabel: String,
|
||||
longLabel: String,
|
||||
@DrawableRes icon: Int,
|
||||
intent: Intent,
|
||||
context: Context
|
||||
): ShortcutInfoCompat {
|
||||
return ShortcutInfoCompat.Builder(context, id)
|
||||
.setShortLabel(shortLabel)
|
||||
.setLongLabel(longLabel)
|
||||
.setIcon(IconCompat.createWithResource(context, icon))
|
||||
.setIntent(intent)
|
||||
.build()
|
||||
}
|
||||
}
|
||||
@@ -135,7 +135,7 @@ class NaviPayActivity : BaseActivity() {
|
||||
val isOnboarded = viewModel.isUserOnboarded()
|
||||
if (isOnboarded) {
|
||||
checkOnboardedUserMandatoryPermissions()
|
||||
NaviPayCommonUtils.addScanAndPayShortcut(context = baseContext)
|
||||
viewModel.addScanAndPayLauncherWidget()
|
||||
} else {
|
||||
onboardingResultLauncher.launch(
|
||||
Intent(this, NaviPayOnboardingActivity::class.java).apply { data = intent?.data }
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.navi.pay.common.usecase.RefreshLinkedAccountsUseCase
|
||||
import com.navi.pay.common.usecase.RefreshUiTronScreenResponseUseCase
|
||||
import com.navi.pay.common.usecase.SyncLitmusExperimentsUseCase
|
||||
import com.navi.pay.common.viewmodel.NaviPayBaseVM
|
||||
import com.navi.pay.common.widget.NaviPayWidgetManager
|
||||
import com.navi.pay.management.common.model.view.NudgeDetailEntity
|
||||
import com.navi.pay.network.di.NaviPayGsonBuilder
|
||||
import com.navi.pay.utils.FIRESTORE_BANK_UPTIME_COLLECTION_PATH
|
||||
@@ -78,7 +79,8 @@ constructor(
|
||||
private val scratchCardNudgeHelper: ScratchCardNudgeHelper,
|
||||
private val naviCacheRepository: NaviCacheRepository,
|
||||
private val syncLitmusExperimentsUseCase: SyncLitmusExperimentsUseCase,
|
||||
@NaviPayGsonBuilder private val gson: Gson
|
||||
@NaviPayGsonBuilder private val gson: Gson,
|
||||
private val naviPayWidgetManager: NaviPayWidgetManager
|
||||
) : NaviPayBaseVM(naviPayVmData = NaviPayVmData(screenName = NaviPayAnalytics.NAVI_PAY_ACTIVITY)) {
|
||||
|
||||
val BANK_UPTIME_POLLING_INTERVAL = 15.seconds
|
||||
@@ -333,4 +335,6 @@ constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun addScanAndPayLauncherWidget() = naviPayWidgetManager.addScanAndPayLauncherWidget()
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import com.navi.base.utils.DateUtils
|
||||
import com.navi.base.utils.orFalse
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NAVI_PAY_REWARDS_GRATIFICATION_ENABLED
|
||||
import com.navi.common.firebaseremoteconfig.FirebaseRemoteConfigHelper.NAVI_PAY_SCAN_AND_PAY_PINNED_WIDGET_INITIAL_DELAY_IN_SECS
|
||||
import com.navi.common.network.models.RepoResult
|
||||
import com.navi.common.network.models.isSuccess
|
||||
import com.navi.common.network.models.isSuccessWithData
|
||||
@@ -33,6 +34,7 @@ import com.navi.pay.common.utils.NaviPayCommonUtils.checkForDynamicQR
|
||||
import com.navi.pay.common.utils.NaviPayCommonUtils.getPayeeVpaToDisplay
|
||||
import com.navi.pay.common.utils.getTransactionDetailItemProperty
|
||||
import com.navi.pay.common.viewmodel.NaviPayBaseVM
|
||||
import com.navi.pay.common.widget.NaviPayWidgetManager
|
||||
import com.navi.pay.destinations.SendMoneyScreenDestination
|
||||
import com.navi.pay.management.common.model.view.NudgeDetailEntity
|
||||
import com.navi.pay.management.common.paymentsummary.model.network.TransactionStatusRequest
|
||||
@@ -68,6 +70,7 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import javax.inject.Inject
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
@@ -94,7 +97,8 @@ constructor(
|
||||
private val liteAccountSyncUseCase: LiteAccountSyncUseCase,
|
||||
private val scratchCardNudgeHelper: ScratchCardNudgeHelper,
|
||||
private val naviPaySessionHelper: NaviPaySessionHelper,
|
||||
private val rewardsNudgeEntityFetchUseCase: RewardsNudgeEntityFetchUseCase
|
||||
private val rewardsNudgeEntityFetchUseCase: RewardsNudgeEntityFetchUseCase,
|
||||
private val naviPayWidgetManager: NaviPayWidgetManager
|
||||
) : NaviPayBaseVM(NaviPayVmData(screenName = NaviPayAnalytics.NAVI_PAY_PAYMENT_STATUS)) {
|
||||
|
||||
companion object {
|
||||
@@ -269,6 +273,7 @@ constructor(
|
||||
updateRewardsNudgeEntity()
|
||||
pollForRewardsGratification()
|
||||
startStatusPolling()
|
||||
checkAndUpdateWidgets()
|
||||
}
|
||||
|
||||
private suspend fun updateNavigateToNextScreenOnHelpCta(ctaData: CtaData?) {
|
||||
@@ -737,6 +742,24 @@ constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAndUpdateWidgets() {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
// Request for pinned widget only in case of successful transaction
|
||||
// For 1st successful transaction, don't request pinned widget
|
||||
if (
|
||||
transactionStatus == TransactionStatus.SUCCESS && !isTransactionEligibleForNpsComms
|
||||
) {
|
||||
delay(
|
||||
FirebaseRemoteConfigHelper.getDouble(
|
||||
NAVI_PAY_SCAN_AND_PAY_PINNED_WIDGET_INITIAL_DELAY_IN_SECS
|
||||
)
|
||||
.seconds
|
||||
)
|
||||
naviPayWidgetManager.requestScanAndPayPinnedWidget()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealed interface PaymentSummaryBottomSheetUIState {
|
||||
|
||||
@@ -29,6 +29,8 @@ import com.navi.pay.common.utils.DeviceInfoImpl
|
||||
import com.navi.pay.common.utils.DeviceInfoProvider
|
||||
import com.navi.pay.common.utils.NaviPayCommonUtils
|
||||
import com.navi.pay.common.utils.naviPayGsonBuilder
|
||||
import com.navi.pay.common.widget.NaviPayWidgetManager
|
||||
import com.navi.pay.common.widget.NaviPayWidgetManagerImpl
|
||||
import com.navi.pay.db.NAVI_PAY_APP_DATABASE_MIGRATION_1_2
|
||||
import com.navi.pay.db.NAVI_PAY_APP_DATABASE_MIGRATION_2_3
|
||||
import com.navi.pay.db.NAVI_PAY_APP_DATABASE_MIGRATION_3_4
|
||||
@@ -266,6 +268,12 @@ abstract class NaviPayDeviceModule {
|
||||
@Singleton @Binds abstract fun bindImageCache(imageCacheImpl: ImageCacheImpl): ImageCache
|
||||
|
||||
@Singleton @Binds abstract fun bindSmsManager(smsManagerImpl: SmsManagerImpl): SmsManager
|
||||
|
||||
@Singleton
|
||||
@Binds
|
||||
abstract fun bindNaviPayWidgetManager(
|
||||
naviPayWidgetManagerImpl: NaviPayWidgetManagerImpl
|
||||
): NaviPayWidgetManager
|
||||
}
|
||||
|
||||
@Qualifier @Retention(AnnotationRetention.BINARY) annotation class NaviPayRetrofit
|
||||
|
||||
@@ -385,9 +385,7 @@ private fun ObserverSmsVerificationState(
|
||||
SmsVerificationState.Success -> {
|
||||
LaunchedEffect(Unit) {
|
||||
naviPayAnalytics.simBindingSuccess()
|
||||
NaviPayCommonUtils.addScanAndPayShortcut(
|
||||
context = naviPayOnboardingActivity.baseContext
|
||||
)
|
||||
naviPayOnboardingViewModel.addScanAndPayLauncherWidget()
|
||||
naviPayOnboardingViewModel.handleNavigationOnCustomerStatus()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ import com.navi.pay.common.usecase.SyncTransactionHistoryUseCase
|
||||
import com.navi.pay.common.utils.DeviceInfoProvider
|
||||
import com.navi.pay.common.utils.NaviPayCommonUtils
|
||||
import com.navi.pay.common.viewmodel.NaviPayBaseVM
|
||||
import com.navi.pay.common.widget.NaviPayWidgetManager
|
||||
import com.navi.pay.onboarding.binding.model.network.BindDeviceRequest
|
||||
import com.navi.pay.onboarding.binding.model.network.BindDeviceResponse
|
||||
import com.navi.pay.onboarding.binding.model.network.BindDeviceStatusRequest
|
||||
@@ -116,7 +117,8 @@ constructor(
|
||||
private val syncFrequentTransactionsUseCase: SyncFrequentTransactionsUseCase,
|
||||
private val syncSavedBeneficiariesUseCase: SyncSavedBeneficiariesUseCase,
|
||||
private val resourceProvider: ResourceProvider,
|
||||
savedStateHandle: SavedStateHandle
|
||||
savedStateHandle: SavedStateHandle,
|
||||
private val naviPayWidgetManager: NaviPayWidgetManager
|
||||
) : NaviPayBaseVM(NaviPayVmData(screenName = NAVI_PAY_SETUP)) {
|
||||
|
||||
private val naviPayAnalytics: NaviPayAnalytics.NaviPaySetup =
|
||||
@@ -941,6 +943,8 @@ constructor(
|
||||
_onboardingAction.emit(NaviPayOnboardingAction.StartOnboarding)
|
||||
}
|
||||
|
||||
fun addScanAndPayLauncherWidget() = naviPayWidgetManager.addScanAndPayLauncherWidget()
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
fun clearReplayCacheForHardUpdateParam() {
|
||||
_isHardUpdateRequired.resetReplayCache()
|
||||
|
||||
@@ -166,6 +166,7 @@ const val NAVI_PAY_SYNC_TABLE_SAVED_BENEFICIARY_KEY = "savedBeneficiaryKey"
|
||||
const val NAVI_PAY_SYNC_TABLE_FREQUENT_TRANSACTIONS_KEY = "frequentTransactionsKey"
|
||||
const val NAVI_PAY_LITMUS_EXPERIMENTS_LAST_REFRESHED_TIMESTAMP =
|
||||
"litmusExperimentsLastRefreshedTimestamp"
|
||||
const val NAVI_PAY_SYNC_TABLE_SCAN_PAY_PINNED_WIDGET_KEY = "scanPayPinnedWidgetKey"
|
||||
|
||||
// Generic
|
||||
const val NAVIPAY_NETWORK_INFO_TIMEOUT = 65L
|
||||
@@ -262,7 +263,7 @@ const val NAVI_PAY_DATABASE_BANK_UPTIME_TABLE = "bankUptime"
|
||||
const val NAVI_PAY_DATABASE_VALIDATE_VPA_CACHE_TABLE_NAME = "validateVpaCache"
|
||||
|
||||
// Dynamic Shortcut
|
||||
const val NAVI_PAY_SCAN_AND_PAY_SHORTCUT_ID = "scanAndPayShortcutId"
|
||||
const val NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_SHORTCUT_ID = "scanAndPayShortcutId"
|
||||
const val NAVI_PAY_SCAN_AND_PAY_WIDGET_ANALYTICS_EVENT_KEY =
|
||||
"NaviPay_ScanAndPay_Widget_Clicked_Event_Key"
|
||||
const val NAVI_PAY_SCAN_AND_PAY_LAUNCHER_WIDGET_CLICKED =
|
||||
|
||||
Reference in New Issue
Block a user