NTP-9629 | Migrated few screens to M3 bottom sheet (#13449)

This commit is contained in:
Ujjwal Kumar
2024-11-04 16:15:55 +05:30
committed by GitHub
parent e00249c671
commit 0fd736a8ef
13 changed files with 559 additions and 597 deletions

View File

@@ -85,4 +85,5 @@ object NaviPayColor {
val rewardBottomBarGradientColor3 = Color(0xFF6C108B)
val scratchAndWinButtonColor = Color(0xFF743E87)
val rippleColor = Color.Black.copy(alpha = 0.3f)
val bottomSheetScrimColor = bgDarkPurple.copy(alpha = 0.64f)
}

View File

@@ -61,7 +61,6 @@ import androidx.compose.material.ModalBottomSheetState
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.ProgressIndicatorDefaults
import androidx.compose.material.TextFieldDefaults
import androidx.compose.material3.BottomSheetDefaults
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
@@ -2115,7 +2114,7 @@ fun NaviPayModalBottomSheet(
bottomSheetShape: Shape = RoundedCornerShape(topStart = 8.dp, topEnd = 8.dp),
onDismissRequest: () -> Unit,
shouldDismissOnBackPress: Boolean = false,
scrimColor: Color = BottomSheetDefaults.ScrimColor,
scrimColor: Color = NaviPayColor.bottomSheetScrimColor,
bottomSheetContent: @Composable ColumnScope.() -> Unit
) {
ModalBottomSheet(

View File

@@ -31,7 +31,6 @@ import com.navi.pay.NavGraphs
import com.navi.pay.common.model.view.ErrorVisibilityEvent
import com.navi.pay.common.model.view.NaviPayErrorButtonConfig
import com.navi.pay.common.model.view.NaviPayErrorConfig
import com.navi.pay.common.theme.color.NaviPayColor
import com.navi.pay.common.ui.NaviPayModalBottomSheet
import com.navi.pay.common.utils.ErrorEventHandler
import com.navi.pay.entry.NaviPayActivity
@@ -252,8 +251,7 @@ fun NaviPayMainScreen(
errorEvent = errorEvent,
onErrorCtaClick = onErrorCtaClick
)
},
scrimColor = NaviPayColor.bgDarkPurple.copy(alpha = 0.64f)
}
)
}
is ErrorVisibilityEvent.HideErrorSheet -> dismissErrorSheet()

View File

@@ -16,13 +16,14 @@ import androidx.compose.ui.unit.dp
import com.navi.pay.R
import com.navi.pay.common.ui.BottomSheetLoadingScreen
import com.navi.pay.common.ui.ConfirmationBottomSheetContent
import com.navi.pay.management.blockedusers.model.view.BlockedUserEntity
import com.navi.pay.management.blockedusers.model.view.BlockedUsersBottomSheetType
import com.navi.pay.management.blockedusers.viewmodel.BlockedUsersViewModel
@Composable
fun BlockedUsersBottomSheetContent(
blockedUsersBottomSheetType: BlockedUsersBottomSheetType?,
blockedUsersViewModel: BlockedUsersViewModel
onDismissBottomSheet: () -> Unit,
onUnblockUserClicked: (BlockedUserEntity) -> Unit
) {
when (blockedUsersBottomSheetType) {
is BlockedUsersBottomSheetType.Loading -> {
@@ -43,11 +44,9 @@ fun BlockedUsersBottomSheetContent(
),
secondaryButtonText = stringResource(id = R.string.cancel),
primaryButtonText = stringResource(id = R.string.yes_unblock),
onSecondaryButtonClicked = {
blockedUsersViewModel.updateBottomSheetUIState(showBottomSheet = false)
},
onSecondaryButtonClicked = onDismissBottomSheet,
onPrimaryButtonClicked = {
blockedUsersViewModel.unblockUser(blockedUsersBottomSheetType.blockedUserEntity)
onUnblockUserClicked(blockedUsersBottomSheetType.blockedUserEntity)
}
)
}

View File

@@ -5,6 +5,8 @@
*
*/
@file:OptIn(ExperimentalMaterial3Api::class)
package com.navi.pay.management.blockedusers.ui
import android.content.Context
@@ -19,13 +21,12 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.Divider
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.layoutId
@@ -52,7 +53,7 @@ import com.navi.pay.analytics.NaviPayAnalytics
import com.navi.pay.common.theme.color.NaviPayColor
import com.navi.pay.common.ui.EmptyDataScreen
import com.navi.pay.common.ui.NaviPayHeader
import com.navi.pay.common.ui.NaviPayModalBottomSheetLayout
import com.navi.pay.common.ui.NaviPayModalBottomSheet
import com.navi.pay.common.ui.TextImage
import com.navi.pay.common.utils.ErrorEventHandler
import com.navi.pay.common.utils.NaviPayEventBus
@@ -94,7 +95,7 @@ fun BlockedUsersScreen(
val bottomSheetState =
rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
skipPartiallyExpanded = true,
confirmValueChange = { bottomSheetStateHolder.bottomSheetStateChange }
)
@@ -105,15 +106,6 @@ fun BlockedUsersScreen(
}
}
LaunchedEffect(Unit) {
snapshotFlow { bottomSheetState.currentValue }
.collect {
if (it == ModalBottomSheetValue.Hidden) {
blockedUsersViewModel.updateBottomSheetUIState(showBottomSheet = false)
}
}
}
if (unblockAction is NotifyUnblockAction.ShowMessage) {
LaunchedEffect(Unit) {
naviPayAnalytics.onUnblockSuccess()
@@ -121,12 +113,22 @@ fun BlockedUsersScreen(
}
}
val onBackClicked = {
val onDismissBottomSheet: () -> Unit = {
scope
.launch { bottomSheetState.hide() }
.invokeOnCompletion {
if (!bottomSheetState.isVisible || !bottomSheetStateHolder.bottomSheetStateChange) {
blockedUsersViewModel.updateBottomSheetUIState(showBottomSheet = false)
}
}
}
val onBackClicked: () -> Unit = {
if (
bottomSheetState.isVisible &&
blockedUsersViewModel.bottomSheetStateHolder.value.showBottomSheet
) {
blockedUsersViewModel.updateBottomSheetUIState(showBottomSheet = false)
onDismissBottomSheet.invoke()
} else {
navigator.navigateUp(naviPayActivity)
}
@@ -134,35 +136,40 @@ fun BlockedUsersScreen(
BackHandler { onBackClicked() }
NaviPayModalBottomSheetLayout(
sheetState = bottomSheetState,
sheetContent = {
BlockedUsersBottomSheetContent(
blockedUsersBottomSheetType = bottomSheetStateHolder.bottomSheetUIState,
blockedUsersViewModel = blockedUsersViewModel
)
},
) {
Box {
BlockedUsersScreenContent(
blockedUsersPager = blockedUsersPager,
blockedUsersViewModel = blockedUsersViewModel,
naviPayAnalytics = naviPayAnalytics,
onBackClicked = onBackClicked
)
if (bottomSheetStateHolder.showBottomSheet) {
NaviPayModalBottomSheet(
modifier = Modifier.fillMaxWidth(),
bottomSheetState = bottomSheetState,
onDismissRequest = onDismissBottomSheet,
bottomSheetContent = {
BlockedUsersBottomSheetContent(
blockedUsersBottomSheetType = bottomSheetStateHolder.bottomSheetUIState,
onDismissBottomSheet = onDismissBottomSheet,
onUnblockUserClicked = blockedUsersViewModel::unblockUser
)
}
)
}
SuccessSnackBar(
modifier = Modifier.align(Alignment.BottomCenter).padding(horizontal = 16.dp),
show = unblockAction is NotifyUnblockAction.ShowMessage,
snackBarConfig =
getUnblockSnackBarConfig(
context = LocalContext.current,
showMessageAction = unblockAction
),
onDismissed = blockedUsersViewModel::resetUnblockMessage,
onTrailingIconClicked = blockedUsersViewModel::resetUnblockMessage
)
}
Box {
BlockedUsersScreenContent(
blockedUsersPager = blockedUsersPager,
blockedUsersViewModel = blockedUsersViewModel,
naviPayAnalytics = naviPayAnalytics,
onBackClicked = onBackClicked
)
SuccessSnackBar(
modifier = Modifier.align(Alignment.BottomCenter).padding(horizontal = 16.dp),
show = unblockAction is NotifyUnblockAction.ShowMessage,
snackBarConfig =
getUnblockSnackBarConfig(
context = LocalContext.current,
showMessageAction = unblockAction
),
onDismissed = blockedUsersViewModel::resetUnblockMessage,
onTrailingIconClicked = blockedUsersViewModel::resetUnblockMessage
)
}
}

View File

@@ -523,8 +523,7 @@ fun SendMoneyScreen(
onBackClick()
}
},
shouldDismissOnBackPress = true,
scrimColor = NaviPayColor.bgDarkPurple.copy(alpha = 0.64f)
shouldDismissOnBackPress = true
) {
SendMoneyBottomSheetContent(
bottomSheetType = bottomSheetStateHolder.bottomSheetUIState,

View File

@@ -5,6 +5,8 @@
*
*/
@file:OptIn(ExperimentalMaterial3Api::class)
package com.navi.pay.management.moneytransfer.scanpay.ui
import android.view.ScaleGestureDetector
@@ -47,10 +49,9 @@ import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Card
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.SnackbarDuration
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
@@ -61,7 +62,6 @@ import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
@@ -114,7 +114,7 @@ import com.navi.pay.common.ui.BottomSheetContentWithIconHeaderPrimarySecondaryBu
import com.navi.pay.common.ui.ContactIconView
import com.navi.pay.common.ui.IconWithTitleDescriptionButton
import com.navi.pay.common.ui.NaviPayLottieAnimation
import com.navi.pay.common.ui.NaviPayModalBottomSheetLayout
import com.navi.pay.common.ui.NaviPayModalBottomSheet
import com.navi.pay.common.ui.RewardsNudgeWithoutBg
import com.navi.pay.common.ui.StaticSearchBarView
import com.navi.pay.common.ui.contactTitle
@@ -154,7 +154,7 @@ import kotlinx.coroutines.launch
@androidx.annotation.OptIn(ExperimentalCameraProviderConfiguration::class)
@Destination
@OptIn(ExperimentalPermissionsApi::class, ExperimentalMaterialApi::class)
@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun QrScannerScreen(
naviPayActivity: NaviPayActivity,
@@ -244,11 +244,9 @@ fun QrScannerScreen(
val turnOffCamera by qrScannerViewModel.shouldTurnOffCamera.collectAsStateWithLifecycle()
val scope = rememberCoroutineScope()
val bottomSheetState =
rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
confirmValueChange = { false }
)
rememberModalBottomSheetState(skipPartiallyExpanded = true, confirmValueChange = { false })
DisposableEffect(key1 = lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
@@ -348,17 +346,16 @@ fun QrScannerScreen(
}
}
LaunchedEffect(Unit) {
snapshotFlow { bottomSheetState.currentValue }
.collect {
if (it == ModalBottomSheetValue.Hidden) {
val closeSheet: () -> Unit = {
scope
.launch { bottomSheetState.hide() }
.invokeOnCompletion {
if (!bottomSheetState.isVisible || !bottomSheetStateHolder.bottomSheetStateChange) {
qrScannerViewModel.updateBottomSheetUIState(showBottomSheet = false)
}
}
}
val closeSheet = { qrScannerViewModel.updateBottomSheetUIState(showBottomSheet = false) }
val navigateToPayToContactsScreen = {
navigator.navigate(PayToContactsScreenDestination(openSearchState = true))
}
@@ -430,165 +427,166 @@ fun QrScannerScreen(
}
}
NaviPayModalBottomSheetLayout(
sheetState = bottomSheetState,
sheetContent = {
QrScannerBottomSheetContent(
bottomSheetUIState = bottomSheetStateHolder.bottomSheetUIState,
onInvalidVpaBottomSheetCtaClicked = closeSheet,
onUrlRedirectionPrimaryCtaClicked = {
scope.launch {
try {
closeSheet()
delay(200.milliseconds)
// For closing bottom sheet before navigating
uriHandler.openUri(it)
} catch (e: Exception) {
e.log()
} finally {
qrScannerViewModel.isQrCodeProcessing.set(false)
if (bottomSheetStateHolder.showBottomSheet) {
NaviPayModalBottomSheet(
modifier = Modifier.fillMaxWidth(),
bottomSheetState = bottomSheetState,
onDismissRequest = closeSheet,
bottomSheetContent = {
QrScannerBottomSheetContent(
bottomSheetUIState = bottomSheetStateHolder.bottomSheetUIState,
onInvalidVpaBottomSheetCtaClicked = closeSheet,
onUrlRedirectionPrimaryCtaClicked = {
scope.launch {
try {
closeSheet()
delay(200.milliseconds)
// For closing bottom sheet before navigating
uriHandler.openUri(it)
} catch (e: Exception) {
e.log()
} finally {
qrScannerViewModel.isQrCodeProcessing.set(false)
}
}
},
onUrlRedirectionSecondaryCtaClicked = {
closeSheet()
qrScannerViewModel.isQrCodeProcessing.set(false)
}
)
},
)
}
Box(modifier = Modifier.fillMaxSize().background(color = colorAdjustedContent)) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
if (!turnOffCamera) {
if (cameraPermissionsState.allPermissionsGranted) {
QrCamera(
naviPayAnalytics = naviPayAnalytics,
isTorchEnabled = qrScannerViewModel.isTorchEnabled,
naviPayActivity = naviPayActivity,
onScanSuccess = qrScannerViewModel::processQrContent,
naviPaySessionAttributes = qrScannerViewModel.getNaviPaySessionAttributes()
)
}
}
Column(modifier = Modifier.fillMaxSize()) {
Spacer(
modifier =
Modifier.fillMaxWidth()
.height(144.dp)
.background(color = colorAdjustedContent)
)
if (cameraPermissionsState.allPermissionsGranted) {
rewardsNudgeDetailEntity?.let {
Box(
modifier =
Modifier.fillMaxWidth().background(color = colorAdjustedContent),
contentAlignment = Alignment.Center
) {
RewardsNudgeWithoutBg(
modifier = Modifier,
exchangeWidgetBgAlpha = 0.2f,
textColor = NaviPayColor.textWhite,
nudgeDetailEntity = it
)
}
}
},
onUrlRedirectionSecondaryCtaClicked = {
closeSheet()
qrScannerViewModel.isQrCodeProcessing.set(false)
}
)
},
) {
Box(modifier = Modifier.fillMaxSize().background(color = colorAdjustedContent)) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
if (!turnOffCamera) {
if (cameraPermissionsState.allPermissionsGranted) {
QrCamera(
naviPayAnalytics = naviPayAnalytics,
isTorchEnabled = qrScannerViewModel.isTorchEnabled,
naviPayActivity = naviPayActivity,
onScanSuccess = qrScannerViewModel::processQrContent,
naviPaySessionAttributes =
qrScannerViewModel.getNaviPaySessionAttributes()
)
}
}
Column(modifier = Modifier.fillMaxSize()) {
Spacer(
modifier =
Modifier.fillMaxWidth()
.height(144.dp)
.height(24.dp)
.background(color = colorAdjustedContent)
)
if (cameraPermissionsState.allPermissionsGranted) {
rewardsNudgeDetailEntity?.let {
Box(
Image(
modifier = Modifier.fillMaxWidth(),
painter = painterResource(id = R.drawable.bg_scanner_overlay),
contentDescription = stringResource(id = R.string.title_scan_and_pay),
contentScale = ContentScale.FillWidth
)
Column(
modifier = Modifier.fillMaxSize().background(color = colorAdjustedContent),
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(verticalAlignment = Alignment.CenterVertically) {
TorchButton(
isTorchEnabled = isTorchEnabled,
onTorchToggle = {
naviPayAnalytics.onTorchButtonClick(
isFlashOn = isTorchEnabled,
naviPaySessionAttributes =
qrScannerViewModel.getNaviPaySessionAttributes()
)
qrScannerViewModel.toggleTorchStatus()
}
)
Image(
modifier =
Modifier.fillMaxWidth()
.background(color = colorAdjustedContent),
contentAlignment = Alignment.Center
) {
RewardsNudgeWithoutBg(
modifier = Modifier,
exchangeWidgetBgAlpha = 0.2f,
textColor = NaviPayColor.textWhite,
nudgeDetailEntity = it
)
}
Modifier.clickableDebounce { onGalleryClick() }
.padding(start = 16.dp, end = 16.dp, top = 8.dp),
alignment = Alignment.Center,
painter = painterResource(id = R.drawable.camera_gallery_svg),
contentDescription = "gallery",
)
}
Spacer(
modifier =
Modifier.fillMaxWidth()
.height(24.dp)
.background(color = colorAdjustedContent)
)
Image(
modifier = Modifier.fillMaxWidth(),
painter = painterResource(id = R.drawable.bg_scanner_overlay),
contentDescription = stringResource(id = R.string.title_scan_and_pay),
contentScale = ContentScale.FillWidth
)
Column(
modifier =
Modifier.fillMaxSize().background(color = colorAdjustedContent),
horizontalAlignment = Alignment.CenterHorizontally
) {
Row(verticalAlignment = Alignment.CenterVertically) {
TorchButton(
isTorchEnabled = isTorchEnabled,
onTorchToggle = {
naviPayAnalytics.onTorchButtonClick(
isFlashOn = isTorchEnabled,
naviPaySessionAttributes =
qrScannerViewModel.getNaviPaySessionAttributes()
)
qrScannerViewModel.toggleTorchStatus()
}
)
Image(
modifier =
Modifier.clickableDebounce { onGalleryClick() }
.padding(start = 16.dp, end = 16.dp, top = 8.dp),
alignment = Alignment.Center,
painter = painterResource(id = R.drawable.camera_gallery_svg),
contentDescription = "gallery",
)
}
if (qrImageErrorViewEnable) {
Spacer(modifier = Modifier.height(8.dp))
QrScannerErrorView(
onTrailingIconClicked = {
qrScannerViewModel.isQrCodeProcessing.set(false)
qrScannerViewModel.setImageErrorView(
qrImageErrorViewEnable = false
)
}
)
}
if (qrImageErrorViewEnable) {
Spacer(modifier = Modifier.height(8.dp))
QrScannerErrorView(
onTrailingIconClicked = {
qrScannerViewModel.isQrCodeProcessing.set(false)
qrScannerViewModel.setImageErrorView(
qrImageErrorViewEnable = false
)
}
)
}
} else {
ScannerPermissionView(
modifier = Modifier.fillMaxWidth().padding(16.dp),
onAllowPermissionButtonClick = onAllowPermissionButtonClick
)
}
} else {
ScannerPermissionView(
modifier = Modifier.fillMaxWidth().padding(16.dp),
onAllowPermissionButtonClick = onAllowPermissionButtonClick
)
}
}
NavigationIconWithOtherAppsView(
modifier = Modifier.fillMaxWidth().padding(16.dp),
needsResult = naviPayActivity.needsResult,
onBackClick = onBackClick,
cameraPermissionsGranted = cameraPermissionsState.allPermissionsGranted
)
FrequentTransactionsListView(
modifier =
Modifier.fillMaxWidth().height(IntrinsicSize.Min).align(Alignment.BottomCenter),
frequentTransactions = frequentTransactions,
onFrequentTransactionSelected = { transactionEntity ->
naviPayActivity.naviPayActivityDataProvider.updateIntentData(
key = LINKED_ACCOUNT_SCREEN_SOURCE,
value = SELF_TRANSFER
)
qrScannerViewModel.initiatePayment(transactionEntity = transactionEntity)
naviPayAnalytics.onContactSelected(
source = NaviPayScreenType.NAVI_PAY_QR_SCANNER_SCREEN.name,
inContactList = false,
isFromFrequentTransactionList = true,
currentSearchQuery = "",
naviPaySessionAttributes = qrScannerViewModel.getNaviPaySessionAttributes(),
isPermissionGranted = cameraPermissionsState.allPermissionsGranted,
orderOfTransactionItem = frequentTransactions.indexOf(transactionEntity)
)
},
navigateToPayToContactsScreen = navigateToPayToContactsScreen,
showLoader = showLoader,
clickedContactPhoneNumber = clickedContactPhoneNumber,
frequentTransactionsHeading = frequentTransactionsHeading
)
}
NavigationIconWithOtherAppsView(
modifier = Modifier.fillMaxWidth().padding(16.dp),
needsResult = naviPayActivity.needsResult,
onBackClick = onBackClick,
cameraPermissionsGranted = cameraPermissionsState.allPermissionsGranted
)
FrequentTransactionsListView(
modifier =
Modifier.fillMaxWidth().height(IntrinsicSize.Min).align(Alignment.BottomCenter),
frequentTransactions = frequentTransactions,
onFrequentTransactionSelected = { transactionEntity ->
naviPayActivity.naviPayActivityDataProvider.updateIntentData(
key = LINKED_ACCOUNT_SCREEN_SOURCE,
value = SELF_TRANSFER
)
qrScannerViewModel.initiatePayment(transactionEntity = transactionEntity)
naviPayAnalytics.onContactSelected(
source = NaviPayScreenType.NAVI_PAY_QR_SCANNER_SCREEN.name,
inContactList = false,
isFromFrequentTransactionList = true,
currentSearchQuery = "",
naviPaySessionAttributes = qrScannerViewModel.getNaviPaySessionAttributes(),
isPermissionGranted = cameraPermissionsState.allPermissionsGranted,
orderOfTransactionItem = frequentTransactions.indexOf(transactionEntity)
)
},
navigateToPayToContactsScreen = navigateToPayToContactsScreen,
showLoader = showLoader,
clickedContactPhoneNumber = clickedContactPhoneNumber,
frequentTransactionsHeading = frequentTransactionsHeading
)
}
}

View File

@@ -5,6 +5,8 @@
*
*/
@file:OptIn(ExperimentalMaterial3Api::class)
package com.navi.pay.management.paytocontacts.ui
import androidx.activity.compose.BackHandler
@@ -27,18 +29,15 @@ import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ModalBottomSheetState
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.Scaffold
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Surface
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
@@ -82,7 +81,7 @@ import com.navi.pay.common.ui.InputTextFieldWithDescriptionHeader
import com.navi.pay.common.ui.LoadingScreen
import com.navi.pay.common.ui.NaviPayHeader
import com.navi.pay.common.ui.NaviPayLottieAnimation
import com.navi.pay.common.ui.NaviPayModalBottomSheetLayout
import com.navi.pay.common.ui.NaviPayModalBottomSheet
import com.navi.pay.common.ui.NaviPaySponsorView
import com.navi.pay.common.ui.RewardsNudgeWithBg
import com.navi.pay.common.ui.SelfTransferCtaView
@@ -111,7 +110,7 @@ import com.ramcosta.composedestinations.annotation.Destination
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import kotlinx.coroutines.launch
@OptIn(ExperimentalPermissionsApi::class, ExperimentalMaterialApi::class)
@OptIn(ExperimentalPermissionsApi::class)
@Destination
@Composable
fun PayToContactsScreen(
@@ -207,7 +206,7 @@ fun PayToContactsScreen(
val bottomSheetState =
rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
skipPartiallyExpanded = true,
confirmValueChange = { bottomSheetStateHolder.bottomSheetStateChange }
)
@@ -218,10 +217,11 @@ fun PayToContactsScreen(
}
}
LaunchedEffect(Unit) {
snapshotFlow { bottomSheetState.currentValue }
.collect {
if (it == ModalBottomSheetValue.Hidden) {
val onDismissBottomSheet: () -> Unit = {
scope
.launch { bottomSheetState.hide() }
.invokeOnCompletion {
if (!bottomSheetState.isVisible || !bottomSheetStateHolder.bottomSheetStateChange) {
payToContactsViewModel.updateBottomSheetUIState(showBottomSheet = false)
}
}
@@ -351,6 +351,21 @@ fun PayToContactsScreen(
}
}
if (bottomSheetStateHolder.showBottomSheet) {
NaviPayModalBottomSheet(
modifier = Modifier.fillMaxWidth(),
bottomSheetState = bottomSheetState,
onDismissRequest = onDismissBottomSheet,
shouldDismissOnBackPress = true,
bottomSheetContent = {
PayToContactsBottomSheetContent(
bottomSheetUIState = bottomSheetStateHolder.bottomSheetUIState,
onInvalidVpaBottomSheetCtaClicked = onDismissBottomSheet
)
}
)
}
when (uiState) {
PayToContactsUIState.Loading ->
LoadingScreen(lottieFileName = NAVI_PAY_LOADER, title = null)
@@ -361,17 +376,12 @@ fun PayToContactsScreen(
contactList = contactList,
onContactSelected = onContactSelected,
onNewContactSelected = onNewContactSelected,
bottomSheetState = bottomSheetState,
onBackClick = onBackClick,
onSearchBarClicked = {
if (!showLoader) {
payToContactsViewModel.updateUiState(uiState = PayToContactsUIState.Search)
}
},
bottomSheetUIState = bottomSheetStateHolder.bottomSheetUIState,
onInvalidVpaBottomSheetCtaClicked = {
payToContactsViewModel.updateBottomSheetUIState(showBottomSheet = false)
},
frequentTransactions = frequentTransactions,
frequentTransactionMaxColumns = payToContactsViewModel.getFrequentTxnsMaxColumns(),
frequentTransactionsHeading = frequentTransactionsHeading,
@@ -398,13 +408,8 @@ fun PayToContactsScreen(
contactList = contactList,
onContactSelected = onContactSelected,
onNewContactSelected = onNewContactSelected,
bottomSheetState = bottomSheetState,
isNewContactVisible = isNewContactVisible,
onPrimaryButtonClicked = onAllowPermissionButtonClicked,
bottomSheetUIState = bottomSheetStateHolder.bottomSheetUIState,
onInvalidVpaBottomSheetCtaClicked = {
payToContactsViewModel.updateBottomSheetUIState(showBottomSheet = false)
},
onFrequentTransactionSelected = onFrequentTransactionSelected,
frequentTransactionMaxColumns = payToContactsViewModel.getFrequentTxnsMaxColumns(),
frequentTransactionsHeading = frequentTransactionsHeading,
@@ -434,11 +439,8 @@ fun RenderPayToContactsSearchScreen(
contactList: List<PhoneContactEntity>,
onContactSelected: (PhoneContactEntity) -> Unit,
onNewContactSelected: (PhoneContactEntity) -> Unit,
bottomSheetState: ModalBottomSheetState,
isNewContactVisible: Boolean,
onPrimaryButtonClicked: () -> Unit,
bottomSheetUIState: PayToContactsBottomSheetUIState?,
onInvalidVpaBottomSheetCtaClicked: () -> Unit,
onFrequentTransactionSelected: (TransactionEntity) -> Unit,
frequentTransactionMaxColumns: Int,
frequentTransactionsHeading: String,
@@ -461,121 +463,111 @@ fun RenderPayToContactsSearchScreen(
val keyboardController = LocalSoftwareKeyboardController.current
val focusRequester = remember { FocusRequester() }
NaviPayModalBottomSheetLayout(
sheetContent = {
PayToContactsBottomSheetContent(
bottomSheetUIState = bottomSheetUIState,
onInvalidVpaBottomSheetCtaClicked = onInvalidVpaBottomSheetCtaClicked
)
Scaffold(
modifier =
Modifier.fillMaxSize()
.nestedScroll(
NaviPayCommonUtils.closeKeyboardOnScroll(
scope = scope,
context = context,
view = view,
keyboardController = keyboardController
)
),
topBar = {
Column(modifier = Modifier.fillMaxWidth()) {
Spacer(modifier = Modifier.height(16.dp))
InputTextFieldWithDescriptionHeader(
modifier =
Modifier.fillMaxWidth()
.padding(horizontal = 16.dp)
.focusRequester(focusRequester)
.clickable(!showLoader) {},
headerString = null,
placeHolderString = "",
leadingIconId = CommonR.drawable.ic_arrow_left_black_v2,
onLeadingIconClicked = onSearchBarBackClicked,
value = searchQuery,
onValueChangeListener = onSearchInputValueChange,
isTrailingIconEnabled = searchQuery.isNotEmpty(),
onTrailingIconClicked = onTrailingIconClicked,
isLeadingIconEnabled = true,
warningErrorInfoState = invalidState.isErrorState,
)
LaunchedEffect(Unit) {
focusRequester.requestFocus()
keyboardController?.show()
}
Spacer(modifier = Modifier.height(8.dp))
if (invalidState.isWarningState) {
NaviText(
text = invalidState.warningMessage.orEmpty(),
fontWeight = getFontWeight(FontWeightEnum.NAVI_BODY_REGULAR),
fontFamily = ttComposeFontFamily,
fontSize = 12.sp,
color = NaviPayColor.textPrimary,
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
)
}
if (invalidState.isErrorState) {
NaviText(
text = invalidState.errorMessage.orEmpty(),
fontWeight = getFontWeight(FontWeightEnum.NAVI_BODY_REGULAR),
fontFamily = ttComposeFontFamily,
fontSize = 12.sp,
color = NaviPayColor.inputFieldError,
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
)
}
}
},
sheetState = bottomSheetState
) {
Scaffold(
modifier =
Modifier.fillMaxSize()
.nestedScroll(
NaviPayCommonUtils.closeKeyboardOnScroll(
scope = scope,
context = context,
view = view,
keyboardController = keyboardController
)
),
topBar = {
Column(modifier = Modifier.fillMaxWidth()) {
Spacer(modifier = Modifier.height(16.dp))
InputTextFieldWithDescriptionHeader(
modifier =
Modifier.fillMaxWidth()
.padding(horizontal = 16.dp)
.focusRequester(focusRequester)
.clickable(!showLoader) {},
headerString = null,
placeHolderString = "",
leadingIconId = CommonR.drawable.ic_arrow_left_black_v2,
onLeadingIconClicked = onSearchBarBackClicked,
value = searchQuery,
onValueChangeListener = onSearchInputValueChange,
isTrailingIconEnabled = searchQuery.isNotEmpty(),
onTrailingIconClicked = onTrailingIconClicked,
isLeadingIconEnabled = true,
warningErrorInfoState = invalidState.isErrorState,
)
LaunchedEffect(Unit) {
focusRequester.requestFocus()
keyboardController?.show()
}
Spacer(modifier = Modifier.height(8.dp))
if (invalidState.isWarningState) {
NaviText(
text = invalidState.warningMessage.orEmpty(),
fontWeight = getFontWeight(FontWeightEnum.NAVI_BODY_REGULAR),
fontFamily = ttComposeFontFamily,
fontSize = 12.sp,
color = NaviPayColor.textPrimary,
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
)
}
if (invalidState.isErrorState) {
NaviText(
text = invalidState.errorMessage.orEmpty(),
fontWeight = getFontWeight(FontWeightEnum.NAVI_BODY_REGULAR),
fontFamily = ttComposeFontFamily,
fontSize = 12.sp,
color = NaviPayColor.inputFieldError,
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
)
}
}
},
content = {
if (isEmptyState) {
EmptyDataScreen(
iconResId = CommonR.drawable.ic_no_result_found,
title = stringResource(R.string.np_no_relevant_result_found),
description = stringResource(R.string.np_please_check_and_try_again),
titleFontSize = 16.sp,
titleFontWeight = FontWeightEnum.NAVI_BODY_DEMI_BOLD,
titleFontColor = NaviPayColor.textSecondary,
)
} else {
PayToContactScreenScaffoldContent(
modifier = Modifier.padding(it).fillMaxWidth(),
searchQuery = searchQuery,
frequentTransactions = frequentTransactions,
isNewContactVisible = isNewContactVisible,
contactList = contactList,
onContactSelected = onContactSelected,
onNewContactSelected = onNewContactSelected,
onFrequentTransactionSelected = onFrequentTransactionSelected,
frequentTransactionMaxColumns = frequentTransactionMaxColumns,
frequentTransactionsHeading = frequentTransactionsHeading,
areAllPermissionsGranted = areAllPermissionsGranted,
onPrimaryButtonClicked = onPrimaryButtonClicked,
isSearchState = true,
navigationIcon = 0,
onBackClick = {},
rewardsNudgeDetailEntity = null,
onSearchBarClicked = {},
hasNonZeroContacts = hasNonZeroContacts,
showLoader = showLoader,
clickedContactPhoneNumber = clickedContactPhoneNumber,
showShimmer = showShimmer,
newContact = newContact,
shouldShowYourContactsTitle = shouldShowYourContactsTitle,
userPhoneNumber = userPhoneNumber,
isSelfTransferCtaVisible = isSelfTransferCtaVisible,
onSelfTransferClicked = onSelfTransferClicked
)
}
},
)
}
content = {
if (isEmptyState) {
EmptyDataScreen(
iconResId = CommonR.drawable.ic_no_result_found,
title = stringResource(R.string.np_no_relevant_result_found),
description = stringResource(R.string.np_please_check_and_try_again),
titleFontSize = 16.sp,
titleFontWeight = FontWeightEnum.NAVI_BODY_DEMI_BOLD,
titleFontColor = NaviPayColor.textSecondary,
)
} else {
PayToContactScreenScaffoldContent(
modifier = Modifier.padding(it).fillMaxWidth(),
searchQuery = searchQuery,
frequentTransactions = frequentTransactions,
isNewContactVisible = isNewContactVisible,
contactList = contactList,
onContactSelected = onContactSelected,
onNewContactSelected = onNewContactSelected,
onFrequentTransactionSelected = onFrequentTransactionSelected,
frequentTransactionMaxColumns = frequentTransactionMaxColumns,
frequentTransactionsHeading = frequentTransactionsHeading,
areAllPermissionsGranted = areAllPermissionsGranted,
onPrimaryButtonClicked = onPrimaryButtonClicked,
isSearchState = true,
navigationIcon = 0,
onBackClick = {},
rewardsNudgeDetailEntity = null,
onSearchBarClicked = {},
hasNonZeroContacts = hasNonZeroContacts,
showLoader = showLoader,
clickedContactPhoneNumber = clickedContactPhoneNumber,
showShimmer = showShimmer,
newContact = newContact,
shouldShowYourContactsTitle = shouldShowYourContactsTitle,
userPhoneNumber = userPhoneNumber,
isSelfTransferCtaVisible = isSelfTransferCtaVisible,
onSelfTransferClicked = onSelfTransferClicked
)
}
},
)
}
@Composable
@@ -585,11 +577,8 @@ fun RenderPayToContactsScreen(
contactList: List<PhoneContactEntity>,
onContactSelected: (PhoneContactEntity) -> Unit,
onNewContactSelected: (PhoneContactEntity) -> Unit,
bottomSheetState: ModalBottomSheetState,
onBackClick: () -> Unit,
onSearchBarClicked: () -> Unit,
bottomSheetUIState: PayToContactsBottomSheetUIState?,
onInvalidVpaBottomSheetCtaClicked: () -> Unit,
frequentTransactions: List<TransactionEntity>,
frequentTransactionMaxColumns: Int,
frequentTransactionsHeading: String,
@@ -610,55 +599,45 @@ fun RenderPayToContactsScreen(
val view = LocalView.current
val keyboardController = LocalSoftwareKeyboardController.current
NaviPayModalBottomSheetLayout(
sheetContent = {
PayToContactsBottomSheetContent(
bottomSheetUIState = bottomSheetUIState,
onInvalidVpaBottomSheetCtaClicked = onInvalidVpaBottomSheetCtaClicked
Scaffold(
modifier =
Modifier.fillMaxSize()
.nestedScroll(
NaviPayCommonUtils.closeKeyboardOnScroll(
scope = scope,
context = context,
view = view,
keyboardController = keyboardController
)
),
content = {
PayToContactScreenScaffoldContent(
modifier = Modifier.padding(it).fillMaxWidth(),
searchQuery = searchQuery,
frequentTransactions = frequentTransactions,
isNewContactVisible = isNewContactVisible,
contactList = contactList,
onContactSelected = onContactSelected,
onNewContactSelected = onNewContactSelected,
onFrequentTransactionSelected = onFrequentTransactionSelected,
frequentTransactionMaxColumns = frequentTransactionMaxColumns,
frequentTransactionsHeading = frequentTransactionsHeading,
areAllPermissionsGranted = areAllPermissionsGranted,
onPrimaryButtonClicked = onPrimaryButtonClicked,
isSearchState = false,
navigationIcon = CommonR.drawable.ic_arrow_left_black_v2,
onBackClick = onBackClick,
rewardsNudgeDetailEntity = rewardsNudgeDetailEntity,
onSearchBarClicked = onSearchBarClicked,
hasNonZeroContacts = hasNonZeroContacts,
showLoader = showLoader,
clickedContactPhoneNumber = clickedContactPhoneNumber,
showShimmer = showShimmer,
newContact = newContact,
shouldShowYourContactsTitle = shouldShowYourContactsTitle
)
},
sheetState = bottomSheetState
) {
Scaffold(
modifier =
Modifier.fillMaxSize()
.nestedScroll(
NaviPayCommonUtils.closeKeyboardOnScroll(
scope = scope,
context = context,
view = view,
keyboardController = keyboardController
)
),
content = {
PayToContactScreenScaffoldContent(
modifier = Modifier.padding(it).fillMaxWidth(),
searchQuery = searchQuery,
frequentTransactions = frequentTransactions,
isNewContactVisible = isNewContactVisible,
contactList = contactList,
onContactSelected = onContactSelected,
onNewContactSelected = onNewContactSelected,
onFrequentTransactionSelected = onFrequentTransactionSelected,
frequentTransactionMaxColumns = frequentTransactionMaxColumns,
frequentTransactionsHeading = frequentTransactionsHeading,
areAllPermissionsGranted = areAllPermissionsGranted,
onPrimaryButtonClicked = onPrimaryButtonClicked,
isSearchState = false,
navigationIcon = CommonR.drawable.ic_arrow_left_black_v2,
onBackClick = onBackClick,
rewardsNudgeDetailEntity = rewardsNudgeDetailEntity,
onSearchBarClicked = onSearchBarClicked,
hasNonZeroContacts = hasNonZeroContacts,
showLoader = showLoader,
clickedContactPhoneNumber = clickedContactPhoneNumber,
showShimmer = showShimmer,
newContact = newContact,
shouldShowYourContactsTitle = shouldShowYourContactsTitle
)
},
)
}
)
}
@Composable

View File

@@ -5,6 +5,8 @@
*
*/
@file:OptIn(ExperimentalMaterial3Api::class)
package com.navi.pay.management.savedbeneficiary.ui
import androidx.activity.compose.BackHandler
@@ -27,17 +29,15 @@ import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ModalBottomSheetState
import androidx.compose.material.ModalBottomSheetValue
import androidx.compose.material.Scaffold
import androidx.compose.material.rememberModalBottomSheetState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Tab
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
@@ -78,7 +78,7 @@ import com.navi.pay.common.ui.ImageTitleDescriptionShimmerView
import com.navi.pay.common.ui.InputTextFieldWithDescriptionHeader
import com.navi.pay.common.ui.NaviPayHeader
import com.navi.pay.common.ui.NaviPayLottieAnimation
import com.navi.pay.common.ui.NaviPayModalBottomSheetLayout
import com.navi.pay.common.ui.NaviPayModalBottomSheet
import com.navi.pay.common.ui.NaviPayScrollableTabRow
import com.navi.pay.common.ui.NaviPaySponsorView
import com.navi.pay.common.ui.RewardsNudgeWithBg
@@ -152,7 +152,7 @@ fun SavedBeneficiaryScreen(
val bottomSheetState =
rememberModalBottomSheetState(
initialValue = ModalBottomSheetValue.Hidden,
skipPartiallyExpanded = true,
confirmValueChange = { bottomSheetStateHolder.bottomSheetStateChange }
)
@@ -163,6 +163,16 @@ fun SavedBeneficiaryScreen(
}
}
val onDismissBottomSheet: () -> Unit = {
scope
.launch { bottomSheetState.hide() }
.invokeOnCompletion {
if (!bottomSheetState.isVisible || !bottomSheetStateHolder.bottomSheetStateChange) {
savedBeneficiaryViewModel.updateBottomSheetUIState(showBottomSheet = false)
}
}
}
LaunchedEffect(key1 = hideKeyboard) {
if (hideKeyboard) {
keyboardController?.customHide(context = context, view = view)
@@ -171,15 +181,6 @@ fun SavedBeneficiaryScreen(
}
}
LaunchedEffect(Unit) {
snapshotFlow { bottomSheetState.currentValue }
.collect {
if (it == ModalBottomSheetValue.Hidden) {
savedBeneficiaryViewModel.updateBottomSheetUIState(showBottomSheet = false)
}
}
}
LaunchedEffect(Unit) {
savedBeneficiaryViewModel.navigateToNextScreen.collect { navigator.navigate(it) }
}
@@ -220,6 +221,19 @@ fun SavedBeneficiaryScreen(
)
}
if (bottomSheetStateHolder.showBottomSheet) {
NaviPayModalBottomSheet(
modifier = Modifier.fillMaxWidth(),
bottomSheetState = bottomSheetState,
onDismissRequest = onDismissBottomSheet,
bottomSheetContent = {
RenderSavedBeneficiaryBottomSheetUIState(
onInvalidVpaBottomSheetCtaClicked = onDismissBottomSheet
)
}
)
}
when (uiState) {
SavedBeneficiaryUIState.List ->
RenderSavedBeneficiaryListScreen(
@@ -265,10 +279,6 @@ fun SavedBeneficiaryScreen(
}
},
onSavedBeneficiaryItemClicked = onSavedBeneficiaryItemClicked,
bottomSheetState = bottomSheetState,
onInvalidVpaBottomSheetCtaClicked = {
savedBeneficiaryViewModel.updateBottomSheetUIState(showBottomSheet = false)
},
onBackClick = onBackClick,
rewardsNudgeDetailEntity = rewardsNudgeDetailEntity,
showLoader = showLoader,
@@ -292,17 +302,13 @@ fun SavedBeneficiaryScreen(
onSearchBarClearQueryClicked = {
savedBeneficiaryViewModel.updateSearchQuery(query = "")
},
searchDataItems = searchDataItems,
onSavedBeneficiaryItemClicked = onSavedBeneficiaryItemClicked,
onSearchItemClicked = {
keyboardController?.customHide(context = context, view = view)
focusManager.clearFocus()
savedBeneficiaryViewModel.onSearchItemClicked(it)
},
searchDataItems = searchDataItems,
onSavedBeneficiaryItemClicked = onSavedBeneficiaryItemClicked,
bottomSheetState = bottomSheetState,
onInvalidVpaBottomSheetCtaClicked = {
savedBeneficiaryViewModel.updateBottomSheetUIState(showBottomSheet = false)
},
searchDataSavedBeneficiaryEntity = searchDataSavedBeneficiaryEntity,
focusRequester = focusRequester,
showLoader = showLoader,
@@ -326,56 +332,45 @@ private fun RenderSavedBeneficiaryListScreen(
bankAccountTabItems: LazyPagingItems<SavedBeneficiaryEntity>,
onSavedBeneficiaryListBottomCtaClicked: () -> Unit,
onSavedBeneficiaryItemClicked: (SavedBeneficiaryEntity, Boolean) -> Unit,
bottomSheetState: ModalBottomSheetState,
onInvalidVpaBottomSheetCtaClicked: () -> Unit,
onBackClick: () -> Unit,
rewardsNudgeDetailEntity: NudgeDetailEntity?,
showLoader: Boolean,
activeQueryVpa: String = "",
) {
NaviPayModalBottomSheetLayout(
sheetContent = {
RenderSavedBeneficiaryBottomSheetUIState(
onInvalidVpaBottomSheetCtaClicked = onInvalidVpaBottomSheetCtaClicked
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
SavedBeneficiaryListTopBar(
onSearchBarClicked = onSearchBarClicked,
selectedTabIndex = selectedTabIndex,
tabData = tabData,
onTabClicked = onTabClicked,
onBackClick = onBackClick,
rewardsNudgeDetailEntity = rewardsNudgeDetailEntity,
showLoader = showLoader,
)
},
sheetState = bottomSheetState
) {
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
SavedBeneficiaryListTopBar(
onSearchBarClicked = onSearchBarClicked,
selectedTabIndex = selectedTabIndex,
tabData = tabData,
onTabClicked = onTabClicked,
onBackClick = onBackClick,
rewardsNudgeDetailEntity = rewardsNudgeDetailEntity,
showLoader = showLoader,
)
},
content = {
RenderSavedBeneficiaryListContent(
upiIdTabItems = upiIdTabItems,
bankAccountTabItems = bankAccountTabItems,
modifier = Modifier.padding(it),
onSavedBeneficiaryItemClicked = { onSavedBeneficiaryItemClicked(it, true) },
selectedTabIndex = selectedTabIndex,
onTabClicked = onTabClicked,
showLoader = showLoader,
activeQueryVpa = activeQueryVpa
)
},
bottomBar = {
SavedBeneficiaryListBottomBar(
selectedTabIndex = selectedTabIndex,
onSavedBeneficiaryListBottomCtaClicked = onSavedBeneficiaryListBottomCtaClicked,
showLoader = showLoader
)
}
)
}
content = {
RenderSavedBeneficiaryListContent(
upiIdTabItems = upiIdTabItems,
bankAccountTabItems = bankAccountTabItems,
modifier = Modifier.padding(it),
onSavedBeneficiaryItemClicked = { onSavedBeneficiaryItemClicked(it, true) },
selectedTabIndex = selectedTabIndex,
onTabClicked = onTabClicked,
showLoader = showLoader,
activeQueryVpa = activeQueryVpa
)
},
bottomBar = {
SavedBeneficiaryListBottomBar(
selectedTabIndex = selectedTabIndex,
onSavedBeneficiaryListBottomCtaClicked = onSavedBeneficiaryListBottomCtaClicked,
showLoader = showLoader
)
}
)
}
@Composable
@@ -585,8 +580,6 @@ private fun RenderSavedBeneficiarySearchScreen(
searchDataItems: LazyPagingItems<SavedBeneficiaryEntity>,
onSavedBeneficiaryItemClicked: (SavedBeneficiaryEntity, Boolean) -> Unit,
onSearchItemClicked: (SavedBeneficiaryEntity) -> Unit,
bottomSheetState: ModalBottomSheetState,
onInvalidVpaBottomSheetCtaClicked: () -> Unit,
searchDataSavedBeneficiaryEntity: SavedBeneficiaryEntity?,
focusRequester: FocusRequester,
showLoader: Boolean = false,
@@ -599,125 +592,116 @@ private fun RenderSavedBeneficiarySearchScreen(
val keyboardController = LocalSoftwareKeyboardController.current
NaviPayModalBottomSheetLayout(
sheetContent = {
RenderSavedBeneficiaryBottomSheetUIState(
onInvalidVpaBottomSheetCtaClicked = onInvalidVpaBottomSheetCtaClicked
)
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
Column(modifier = Modifier.fillMaxWidth()) {
Spacer(modifier = Modifier.height(16.dp))
InputTextFieldWithDescriptionHeader(
modifier =
Modifier.fillMaxWidth()
.padding(horizontal = 16.dp)
.focusRequester(focusRequester),
headerString = null,
placeHolderString = "",
value = searchQuery,
onValueChangeListener = onSearchQueryChanged,
isLeadingIconEnabled = true,
leadingIconId = CommonR.drawable.ic_arrow_left_black_v2,
onLeadingIconClicked = onSearchBarBackClicked,
isTrailingIconEnabled = searchQuery.isNotEmpty(),
onTrailingIconClicked = onSearchBarClearQueryClicked,
warningErrorInfoState = warningErrorInfoState.isErrorState,
trailingIconId = WidgetsR.drawable.small_cross_purple,
)
LaunchedEffect(Unit) {
focusRequester.requestFocus()
keyboardController?.show()
}
if (warningErrorInfoState.isWarningState) {
Spacer(modifier = Modifier.height(8.dp))
NaviText(
text = warningErrorInfoState.warningMessage.orEmpty(),
fontWeight = getFontWeight(FontWeightEnum.NAVI_BODY_REGULAR),
fontFamily = ttComposeFontFamily,
fontSize = 12.sp,
color = NaviPayColor.textPrimary,
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
)
}
if (warningErrorInfoState.isErrorState) {
Spacer(modifier = Modifier.height(8.dp))
NaviText(
text = warningErrorInfoState.errorMessage.orEmpty(),
fontWeight = getFontWeight(FontWeightEnum.NAVI_BODY_REGULAR),
fontFamily = ttComposeFontFamily,
fontSize = 12.sp,
color = NaviPayColor.inputFieldError,
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
)
}
}
},
sheetState = bottomSheetState
) {
Scaffold(
modifier = Modifier.fillMaxSize(),
topBar = {
Column(modifier = Modifier.fillMaxWidth()) {
Spacer(modifier = Modifier.height(16.dp))
InputTextFieldWithDescriptionHeader(
modifier =
Modifier.fillMaxWidth()
.padding(horizontal = 16.dp)
.focusRequester(focusRequester),
headerString = null,
placeHolderString = "",
value = searchQuery,
onValueChangeListener = onSearchQueryChanged,
isLeadingIconEnabled = true,
leadingIconId = CommonR.drawable.ic_arrow_left_black_v2,
onLeadingIconClicked = onSearchBarBackClicked,
isTrailingIconEnabled = searchQuery.isNotEmpty(),
onTrailingIconClicked = onSearchBarClearQueryClicked,
warningErrorInfoState = warningErrorInfoState.isErrorState,
trailingIconId = WidgetsR.drawable.small_cross_purple,
)
LaunchedEffect(Unit) {
focusRequester.requestFocus()
keyboardController?.show()
}
if (warningErrorInfoState.isWarningState) {
Spacer(modifier = Modifier.height(8.dp))
NaviText(
text = warningErrorInfoState.warningMessage.orEmpty(),
fontWeight = getFontWeight(FontWeightEnum.NAVI_BODY_REGULAR),
fontFamily = ttComposeFontFamily,
fontSize = 12.sp,
color = NaviPayColor.textPrimary,
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
)
}
if (warningErrorInfoState.isErrorState) {
Spacer(modifier = Modifier.height(8.dp))
NaviText(
text = warningErrorInfoState.errorMessage.orEmpty(),
fontWeight = getFontWeight(FontWeightEnum.NAVI_BODY_REGULAR),
fontFamily = ttComposeFontFamily,
fontSize = 12.sp,
color = NaviPayColor.inputFieldError,
modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)
)
}
}
},
content = {
if (showSelfTransferCta) {
SelfTransferCtaView(
description = searchQuery,
modifier =
Modifier.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 24.dp)
.clickable { onSelfTransferCtaClicked() }
)
}
LazyColumn(
modifier = Modifier.padding(it).fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
item { Spacer(modifier = Modifier.height(8.dp)) }
items(
count = searchDataItems.itemCount,
key = searchDataItems.itemKey { it.vpa }
) { index ->
searchDataItems[index]?.let { savedBeneficiaryEntity ->
SavedBeneficiaryItemView(
modifier = Modifier.padding(horizontal = 16.dp),
savedBeneficiaryEntity = savedBeneficiaryEntity,
onSavedBeneficiaryItemClicked = {
onSavedBeneficiaryItemClicked(it, true)
},
index = index,
showLoader = showLoader,
activeQueryVpa = activeQueryVpa
)
}
}
if (showShimmer) {
item { ImageTitleDescriptionShimmerView() }
}
if (searchDataSavedBeneficiaryEntity != null) {
item {
SavedBeneficiaryItemView(
modifier = Modifier.padding(horizontal = 16.dp),
savedBeneficiaryEntity = searchDataSavedBeneficiaryEntity,
onSavedBeneficiaryItemClicked = { onSearchItemClicked(it) },
index = 0,
showLoader = showLoader,
activeQueryVpa = activeQueryVpa
)
}
}
}
},
bottomBar = {
NaviPaySponsorView(
modifier = Modifier.fillMaxWidth().padding(top = 16.dp, bottom = 32.dp)
content = {
if (showSelfTransferCta) {
SelfTransferCtaView(
description = searchQuery,
modifier =
Modifier.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 24.dp)
.clickable { onSelfTransferCtaClicked() }
)
}
)
}
LazyColumn(
modifier = Modifier.padding(it).fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
item { Spacer(modifier = Modifier.height(8.dp)) }
items(
count = searchDataItems.itemCount,
key = searchDataItems.itemKey { it.vpa }
) { index ->
searchDataItems[index]?.let { savedBeneficiaryEntity ->
SavedBeneficiaryItemView(
modifier = Modifier.padding(horizontal = 16.dp),
savedBeneficiaryEntity = savedBeneficiaryEntity,
onSavedBeneficiaryItemClicked = {
onSavedBeneficiaryItemClicked(it, true)
},
index = index,
showLoader = showLoader,
activeQueryVpa = activeQueryVpa
)
}
}
if (showShimmer) {
item { ImageTitleDescriptionShimmerView() }
}
if (searchDataSavedBeneficiaryEntity != null) {
item {
SavedBeneficiaryItemView(
modifier = Modifier.padding(horizontal = 16.dp),
savedBeneficiaryEntity = searchDataSavedBeneficiaryEntity,
onSavedBeneficiaryItemClicked = { onSearchItemClicked(it) },
index = 0,
showLoader = showLoader,
activeQueryVpa = activeQueryVpa
)
}
}
}
},
bottomBar = {
NaviPaySponsorView(
modifier = Modifier.fillMaxWidth().padding(top = 16.dp, bottom = 32.dp)
)
}
)
}
@Composable

View File

@@ -490,8 +490,7 @@ fun UpiNumberMainScreen(
NaviPayModalBottomSheet(
bottomSheetState = bottomSheetState,
onDismissRequest = dismissBottomSheet,
shouldDismissOnBackPress = true,
scrimColor = NaviPayColor.bgDarkPurple.copy(alpha = 0.64f)
shouldDismissOnBackPress = true
) {
UpiNumberBottomSheetContent(
activateUpiNumber = upiNumberViewModel::activateUpiNumber,

View File

@@ -194,7 +194,7 @@ fun AccountAdditionBottomSheet(
onSearchQueryChanged = onSearchQueryChanged
)
},
scrimColor = NaviPayColor.bgDarkPurple.copy(alpha = 0.64f)
scrimColor = NaviPayColor.bottomSheetScrimColor
) {
Surface(modifier = Modifier.fillMaxSize(), color = NaviPayColor.transparent) {}
}

View File

@@ -525,8 +525,7 @@ fun RenderLinkedAccountDetailScreen(
NaviPayModalBottomSheet(
bottomSheetState = bottomSheetState,
onDismissRequest = dismissBottomSheet,
shouldDismissOnBackPress = true,
scrimColor = NaviPayColor.bgDarkPurple.copy(alpha = 0.64f)
shouldDismissOnBackPress = true
) {
RenderLinkedAccountDetailScreenBottomSheet(
bottomSheetType = bottomSheetStateHolder.bottomSheetType,

View File

@@ -555,7 +555,7 @@ fun GenericOnboardingBottomSheet(
shouldDismissOnBackPress = true
),
dragHandle = null,
scrimColor = NaviPayColor.bgDarkPurple.copy(alpha = 0.64f)
scrimColor = NaviPayColor.bottomSheetScrimColor
) {
NaviPayOnboardingBottomSheetContent(
naviPayAnalytics = naviPayAnalytics,