diff --git a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ConfigurationActivity.kt b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ConfigurationActivity.kt
index bba1f063eb..cd78ff0ecc 100644
--- a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ConfigurationActivity.kt
+++ b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ConfigurationActivity.kt
@@ -139,6 +139,9 @@ class ConfigurationActivity : AppCompatActivity() {
binding.switchReviewScreenCustomBottomNavbar.isChecked =
configuration.isReviewScreenCustomBottomNavBarEnabled
+ binding.switchSkontoCustomBottomNavbar.isChecked =
+ configuration.isSkontoCustomNavBarEnabled
+
// 12 enable image picker screens custom bottom navigation bar -> was implemented on iOS, not needed for Android
// 13 enable onboarding screens at first launch
@@ -369,6 +372,14 @@ class ConfigurationActivity : AppCompatActivity() {
)
}
+ binding.switchSkontoCustomBottomNavbar.setOnCheckedChangeListener { _, isChecked ->
+ configurationViewModel.setConfiguration(
+ configurationViewModel.configurationFlow.value.copy(
+ isSkontoCustomNavBarEnabled = isChecked
+ )
+ )
+ }
+
// 12 enable image picker screens custom bottom navigation bar -> was implemented on iOS, not needed for Android
// 13 enable onboarding screens at first launch
@@ -421,6 +432,7 @@ class ConfigurationActivity : AppCompatActivity() {
)
)
}
+
// 19 enable multi page in custom onboarding pages
binding.switchCustomOnboardingMultiPage.setOnCheckedChangeListener { _, isChecked ->
configurationViewModel.setConfiguration(
diff --git a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ConfigurationViewModel.kt b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ConfigurationViewModel.kt
index e2abeb843b..cc9dea3200 100644
--- a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ConfigurationViewModel.kt
+++ b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/ConfigurationViewModel.kt
@@ -26,6 +26,7 @@ import net.gini.android.bank.sdk.exampleapp.ui.adapters.CustomOnButtonLoadingInd
import net.gini.android.bank.sdk.exampleapp.ui.adapters.CustomOnboardingIllustrationAdapter
import net.gini.android.bank.sdk.exampleapp.ui.adapters.CustomOnboardingNavigationBarBottomAdapter
import net.gini.android.bank.sdk.exampleapp.ui.adapters.CustomReviewNavigationBarBottomAdapter
+import net.gini.android.bank.sdk.exampleapp.ui.adapters.CustomSkontoNavigationBarBottomAdapter
import net.gini.android.bank.sdk.exampleapp.ui.data.Configuration
import net.gini.android.capture.GiniCaptureDebug
import net.gini.android.capture.help.HelpItem
@@ -275,6 +276,12 @@ class ConfigurationViewModel @Inject constructor(
CustomDigitalInvoiceHelpNavigationBarBottomAdapter()
}
+ if (configuration.isSkontoCustomNavBarEnabled) {
+ GiniBank.skontoNavigationBarBottomAdapter = CustomSkontoNavigationBarBottomAdapter()
+ } else {
+ GiniBank.skontoNavigationBarBottomAdapter = null
+ }
+
// 35 Digital invoice onboarding bottom navigation bar
if (configuration.isDigitalInvoiceOnboardingBottomNavigationBarEnabled) {
GiniBank.digitalInvoiceOnboardingNavigationBarBottomAdapter =
diff --git a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/adapters/CustomSkontoNavigationBarBottomAdapter.kt b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/adapters/CustomSkontoNavigationBarBottomAdapter.kt
new file mode 100644
index 0000000000..0cba099059
--- /dev/null
+++ b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/adapters/CustomSkontoNavigationBarBottomAdapter.kt
@@ -0,0 +1,54 @@
+package net.gini.android.bank.sdk.exampleapp.ui.adapters
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.core.view.isVisible
+import net.gini.android.bank.sdk.capture.skonto.SkontoNavigationBarBottomAdapter
+import net.gini.android.bank.sdk.exampleapp.databinding.CustomSkontoNavigationBarBinding
+
+class CustomSkontoNavigationBarBottomAdapter : SkontoNavigationBarBottomAdapter {
+
+ private var binding: CustomSkontoNavigationBarBinding? = null
+
+ override fun setOnHelpClickListener(onClick: () -> Unit) {
+ binding?.gbsHelpBtn?.setOnClickListener { onClick() }
+ }
+
+ override fun setOnBackClickListener(onClick: () -> Unit) {
+ binding?.gbsBackBtn?.setOnClickListener { onClick() }
+ }
+
+ override fun setOnProceedClickListener(onClick: () -> Unit) {
+ binding?.gbsPay?.setOnClickListener { onClick() }
+ }
+
+ override fun setProceedButtonEnabled(enabled: Boolean) {
+ binding?.gbsPay?.isEnabled = enabled
+ }
+
+ override fun setTotalPriceText(text: String) {
+ binding?.priceTotal?.text = text
+ }
+
+ override fun setDiscountLabelText(text: String) {
+ binding?.discountInfo?.text = text
+ }
+
+ override fun onCreateView(container: ViewGroup): View {
+ binding = CustomSkontoNavigationBarBinding.inflate(
+ LayoutInflater.from(container.context),
+ container,
+ false
+ )
+ return binding!!.root
+ }
+
+ override fun setDiscountLabelVisible(visible: Boolean) {
+ binding?.discountInfo?.isVisible = visible
+ }
+
+ override fun onDestroy() {
+ binding = null
+ }
+}
\ No newline at end of file
diff --git a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/data/Configuration.kt b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/data/Configuration.kt
index cc40c366fa..64c04492db 100644
--- a/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/data/Configuration.kt
+++ b/bank-sdk/example-app/src/main/java/net/gini/android/bank/sdk/exampleapp/ui/data/Configuration.kt
@@ -154,8 +154,12 @@ data class Configuration(
// 37 Debug mode
val isDebugModeEnabled: Boolean = true,
+ // 38 Is Allow Screenshots
val isAllowScreenshotsEnabled: Boolean = true,
+ // 39 Skonto Custom bottom navigation
+ val isSkontoCustomNavBarEnabled: Boolean = false,
+
) : Parcelable {
companion object {
diff --git a/bank-sdk/example-app/src/main/res/layout/activity_configuration.xml b/bank-sdk/example-app/src/main/res/layout/activity_configuration.xml
index 845396ef52..b26e83aa42 100644
--- a/bank-sdk/example-app/src/main/res/layout/activity_configuration.xml
+++ b/bank-sdk/example-app/src/main/res/layout/activity_configuration.xml
@@ -208,13 +208,27 @@
android:text="@string/review_screen_custom_bottom_navbar_switch_label" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bank-sdk/example-app/src/main/res/values/strings.xml b/bank-sdk/example-app/src/main/res/values/strings.xml
index 5ed91dbac2..1b59b68ffa 100644
--- a/bank-sdk/example-app/src/main/res/values/strings.xml
+++ b/bank-sdk/example-app/src/main/res/values/strings.xml
@@ -67,6 +67,7 @@
The custom bottom navigation bar is shown if \'Bottom navigation bar\' is also enabled.
Camera screen custom bottom navigation bar
Review screen custom bottom navigation bar
+ Skonto screen custom bottom navigation bar
Onboarding screens at every launch
Onboarding screens at first launch
Overwrites \'Onboarding screens at first launch\'.
diff --git a/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/GiniBank.kt b/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/GiniBank.kt
index d86a1a582f..4b158e9a23 100644
--- a/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/GiniBank.kt
+++ b/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/GiniBank.kt
@@ -24,6 +24,7 @@ import net.gini.android.bank.sdk.capture.digitalinvoice.view.DefaultDigitalInvoi
import net.gini.android.bank.sdk.capture.digitalinvoice.view.DefaultDigitalInvoiceOnboardingNavigationBarBottomAdapter
import net.gini.android.bank.sdk.capture.digitalinvoice.view.DigitalInvoiceNavigationBarBottomAdapter
import net.gini.android.bank.sdk.capture.digitalinvoice.view.DigitalInvoiceOnboardingNavigationBarBottomAdapter
+import net.gini.android.bank.sdk.capture.skonto.SkontoNavigationBarBottomAdapter
import net.gini.android.bank.sdk.error.AmountParsingException
import net.gini.android.bank.sdk.pay.getBusinessIntent
import net.gini.android.bank.sdk.pay.getRequestId
@@ -101,6 +102,18 @@ object GiniBank {
}
get() = digitalInvoiceNavigationBarBottomAdapterInstance.viewAdapter
+
+ internal var skontoNavigationBarBottomAdapterInstance: InjectedViewAdapterInstance? =
+ null
+
+ var skontoNavigationBarBottomAdapter: SkontoNavigationBarBottomAdapter?
+ set(value) {
+ skontoNavigationBarBottomAdapterInstance =
+ value?.let { InjectedViewAdapterInstance(it) }
+ }
+ get() = skontoNavigationBarBottomAdapterInstance?.viewAdapter
+
+
internal fun getCaptureConfiguration() = captureConfiguration
/**
@@ -316,18 +329,26 @@ object GiniBank {
): CancellationToken {
giniCapture.let { capture ->
check(capture != null) { "Capture feature is not configured. Call setCaptureConfiguration before starting the flow." }
- return capture.createDocumentForImportedFiles(intent, context, object : AsyncCallback {
- override fun onSuccess(result: Document) {
- resultLauncher.launch(CaptureImportInput.Forward(result))
- }
-
- override fun onError(exception: ImportedFileValidationException?) {
- resultLauncher.launch(CaptureImportInput.Error(exception?.validationError, exception?.message))
- }
+ return capture.createDocumentForImportedFiles(
+ intent,
+ context,
+ object : AsyncCallback {
+ override fun onSuccess(result: Document) {
+ resultLauncher.launch(CaptureImportInput.Forward(result))
+ }
+
+ override fun onError(exception: ImportedFileValidationException?) {
+ resultLauncher.launch(
+ CaptureImportInput.Error(
+ exception?.validationError,
+ exception?.message
+ )
+ )
+ }
- override fun onCancelled() {
- }
- })
+ override fun onCancelled() {
+ }
+ })
}
}
@@ -413,17 +434,18 @@ object GiniBank {
/**
* The document was processed successfully.
*/
- data class Success(val document: Document?): CreateDocumentFromImportedFileResult()
+ data class Success(val document: Document?) : CreateDocumentFromImportedFileResult()
/**
* Document processing returned an error.
*/
- data class Error(val error: ImportedFileValidationException?): CreateDocumentFromImportedFileResult()
+ data class Error(val error: ImportedFileValidationException?) :
+ CreateDocumentFromImportedFileResult()
/**
* Document processing was cancelled.
*/
- object Cancelled: CreateDocumentFromImportedFileResult()
+ object Cancelled : CreateDocumentFromImportedFileResult()
}
/**
@@ -442,7 +464,7 @@ object GiniBank {
return giniCapture?.createDocumentForImportedFiles(
intent,
context,
- object: AsyncCallback {
+ object : AsyncCallback {
override fun onSuccess(result: Document?) {
callback(CreateDocumentFromImportedFileResult.Success(result))
}
diff --git a/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/Configuration.kt b/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/Configuration.kt
index f5f3821e12..1d921d7287 100644
--- a/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/Configuration.kt
+++ b/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/Configuration.kt
@@ -1,5 +1,6 @@
package net.gini.android.bank.sdk.capture
+import net.gini.android.bank.sdk.capture.skonto.SkontoNavigationBarBottomAdapter
import net.gini.android.capture.DocumentImportEnabledFileTypes
import net.gini.android.capture.EntryPoint
import net.gini.android.capture.GiniCapture
@@ -181,6 +182,11 @@ data class CaptureConfiguration(
*/
val reviewNavigationBarBottomAdapter: ReviewNavigationBarBottomAdapter? = null,
+ /**
+ * Set an adapter implementation to show a custom bottom navigation bar on the Skonto screen.
+ */
+ val skontoNavigationBarBottomAdapter: SkontoNavigationBarBottomAdapter? = null,
+
/**
* Set an adapter implementation to show a custom bottom navigation bar on the help screen.
*/
@@ -200,7 +206,7 @@ data class CaptureConfiguration(
*
* IMPORTANT: If you disallow screenshots and use the [CaptureFlowFragment] for launching the SDK in your activity, please clear the [android.view.WindowManager.LayoutParams.FLAG_SECURE]
* on your activity's window after the SDK has finished to allow users to take screenshots of your app again.
- */
+ */
val allowScreenshots: Boolean = true,
/**
@@ -236,15 +242,47 @@ internal fun GiniCapture.Builder.applyConfiguration(configuration: CaptureConfig
})
}
configuration.navigationBarTopAdapter?.let { setNavigationBarTopAdapter(it) }
- configuration.onboardingAlignCornersIllustrationAdapter?.let { setOnboardingAlignCornersIllustrationAdapter(it) }
- configuration.onboardingLightingIllustrationAdapter?.let { setOnboardingLightingIllustrationAdapter(it) }
- configuration.onboardingMultiPageIllustrationAdapter?.let { setOnboardingMultiPageIllustrationAdapter(it) }
- configuration.onboardingQRCodeIllustrationAdapter?.let { setOnboardingQRCodeIllustrationAdapter(it) }
+ configuration.onboardingAlignCornersIllustrationAdapter?.let {
+ setOnboardingAlignCornersIllustrationAdapter(
+ it
+ )
+ }
+ configuration.onboardingLightingIllustrationAdapter?.let {
+ setOnboardingLightingIllustrationAdapter(
+ it
+ )
+ }
+ configuration.onboardingMultiPageIllustrationAdapter?.let {
+ setOnboardingMultiPageIllustrationAdapter(
+ it
+ )
+ }
+ configuration.onboardingQRCodeIllustrationAdapter?.let {
+ setOnboardingQRCodeIllustrationAdapter(
+ it
+ )
+ }
configuration.customLoadingIndicatorAdapter?.let { setLoadingIndicatorAdapter(it) }
- configuration.onButtonLoadingIndicatorAdapter?.let { setOnButtonLoadingIndicatorAdapter(it) }
- configuration.onboardingNavigationBarBottomAdapter?.let { setOnboardingNavigationBarBottomAdapter(it) }
- configuration.cameraNavigationBarBottomAdapter?.let { setCameraNavigationBarBottomAdapter(it) }
- configuration.reviewNavigationBarBottomAdapter?.let { setReviewBottomBarNavigationAdapter(it) }
+ configuration.onButtonLoadingIndicatorAdapter?.let {
+ setOnButtonLoadingIndicatorAdapter(
+ it
+ )
+ }
+ configuration.onboardingNavigationBarBottomAdapter?.let {
+ setOnboardingNavigationBarBottomAdapter(
+ it
+ )
+ }
+ configuration.cameraNavigationBarBottomAdapter?.let {
+ setCameraNavigationBarBottomAdapter(
+ it
+ )
+ }
+ configuration.reviewNavigationBarBottomAdapter?.let {
+ setReviewBottomBarNavigationAdapter(
+ it
+ )
+ }
configuration.helpNavigationBarBottomAdapter?.let { setHelpNavigationBarBottomAdapter(it) }
}
}
diff --git a/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/skonto/SkontoFragment.kt b/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/skonto/SkontoFragment.kt
index df86a072a6..bf5a7fefe7 100644
--- a/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/skonto/SkontoFragment.kt
+++ b/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/skonto/SkontoFragment.kt
@@ -2,10 +2,10 @@ package net.gini.android.bank.sdk.capture.skonto
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import android.os.Bundle
-import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import android.widget.FrameLayout
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
@@ -28,6 +28,7 @@ import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -44,6 +45,7 @@ import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.platform.ComposeView
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.res.painterResource
@@ -52,8 +54,10 @@ import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
+import net.gini.android.bank.sdk.GiniBank
import net.gini.android.bank.sdk.R
import net.gini.android.bank.sdk.capture.skonto.colors.SkontoScreenColors
import net.gini.android.bank.sdk.capture.skonto.colors.section.SkontoFooterSectionColors
@@ -70,19 +74,27 @@ import net.gini.android.capture.ui.components.textinput.amount.GiniAmountTextInp
import net.gini.android.capture.ui.components.topbar.GiniTopBar
import net.gini.android.capture.ui.components.topbar.GiniTopBarColors
import net.gini.android.capture.ui.theme.GiniTheme
+import net.gini.android.capture.view.InjectedViewAdapterInstance
import java.math.BigDecimal
import java.math.RoundingMode
-import java.text.DecimalFormat
import java.time.LocalDate
import java.time.format.DateTimeFormatter
class SkontoFragment : Fragment() {
- val bottomNavBar = GiniCapture.getInstance().internal().navigationBarTopAdapterInstance
+ private val isBottomNavigationBarEnabled =
+ GiniCapture.getInstance().isBottomNavigationBarEnabled
+
+ private val customBottomNavBarAdapter: InjectedViewAdapterInstance? =
+ GiniBank.skontoNavigationBarBottomAdapterInstance
+ private var customBottomNavigationBarView: View? = null
+
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
+ customBottomNavigationBarView =
+ container?.let { customBottomNavBarAdapter?.viewAdapter?.onCreateView(it) }
val viewModel = ViewModelProvider(requireActivity())[SkontoFragmentViewModel::class.java]
@@ -92,6 +104,8 @@ class SkontoFragment : Fragment() {
GiniTheme {
ScreenContent(
viewModel = viewModel,
+ isBottomNavigationBarEnabled = isBottomNavigationBarEnabled,
+ customBottomNavBarAdapter = customBottomNavBarAdapter,
)
}
}
@@ -103,7 +117,9 @@ class SkontoFragment : Fragment() {
private fun ScreenContent(
viewModel: SkontoFragmentViewModel,
modifier: Modifier = Modifier,
- screenColorScheme: SkontoScreenColors = SkontoScreenColors.colors()
+ screenColorScheme: SkontoScreenColors = SkontoScreenColors.colors(),
+ isBottomNavigationBarEnabled: Boolean,
+ customBottomNavBarAdapter: InjectedViewAdapterInstance?,
) {
val state by viewModel.stateFlow.collectAsState()
ScreenStateContent(
@@ -113,7 +129,12 @@ private fun ScreenContent(
onDiscountSectionActiveChange = viewModel::onSkontoActiveChanged,
onSkontoAmountChange = viewModel::onSkontoAmountFieldChanged,
onDueDateChanged = viewModel::onSkontoDueDateChanged,
- onFullAmountChange = viewModel::onFullAmountFieldChanged
+ onFullAmountChange = viewModel::onFullAmountFieldChanged,
+ isBottomNavigationBarEnabled = isBottomNavigationBarEnabled,
+ onBackClicked = {},
+ onHelpClicked = {},
+ customBottomNavBarAdapter = customBottomNavBarAdapter,
+ onProceedClicked = {}
)
}
@@ -124,6 +145,11 @@ private fun ScreenStateContent(
onSkontoAmountChange: (BigDecimal) -> Unit,
onFullAmountChange: (BigDecimal) -> Unit,
onDueDateChanged: (LocalDate) -> Unit,
+ onBackClicked: () -> Unit,
+ onHelpClicked: () -> Unit,
+ onProceedClicked: () -> Unit,
+ isBottomNavigationBarEnabled: Boolean,
+ customBottomNavBarAdapter: InjectedViewAdapterInstance?,
modifier: Modifier = Modifier,
screenColorScheme: SkontoScreenColors = SkontoScreenColors.colors()
) {
@@ -136,7 +162,12 @@ private fun ScreenStateContent(
onDiscountSectionActiveChange = onDiscountSectionActiveChange,
onDiscountAmountChange = onSkontoAmountChange,
onDueDateChanged = onDueDateChanged,
- onFullAmountChange = onFullAmountChange
+ onFullAmountChange = onFullAmountChange,
+ onBackClicked = onBackClicked,
+ onHelpClicked = onHelpClicked,
+ isBottomNavigationBarEnabled = isBottomNavigationBarEnabled,
+ customBottomNavBarAdapter = customBottomNavBarAdapter,
+ onProceedClicked = onProceedClicked,
)
}
@@ -144,11 +175,16 @@ private fun ScreenStateContent(
@Composable
private fun ScreenReadyState(
+ onBackClicked: () -> Unit,
+ onHelpClicked: () -> Unit,
+ onProceedClicked: () -> Unit,
state: SkontoFragmentContract.State.Ready,
onDiscountSectionActiveChange: (Boolean) -> Unit,
onDiscountAmountChange: (BigDecimal) -> Unit,
onDueDateChanged: (LocalDate) -> Unit,
onFullAmountChange: (BigDecimal) -> Unit,
+ isBottomNavigationBarEnabled: Boolean,
+ customBottomNavBarAdapter: InjectedViewAdapterInstance?,
modifier: Modifier = Modifier,
screenColorScheme: SkontoScreenColors = SkontoScreenColors.colors(),
) {
@@ -156,13 +192,26 @@ private fun ScreenReadyState(
val scrollState = rememberScrollState()
Scaffold(modifier = modifier,
containerColor = screenColorScheme.backgroundColor,
- topBar = { TopAppBar(colors = screenColorScheme.topAppBarColors) },
+ topBar = {
+ TopAppBar(
+ isBottomNavigationBarEnabled = isBottomNavigationBarEnabled,
+ colors = screenColorScheme.topAppBarColors,
+ onBackClicked = onBackClicked,
+ onHelpClicked = onHelpClicked,
+ )
+ },
bottomBar = {
FooterSection(
colors = screenColorScheme.footerSectionColors,
discountValue = state.discountValue,
totalAmount = state.totalAmount,
- currency = state.currency
+ currency = state.currency,
+ isBottomNavigationBarEnabled = isBottomNavigationBarEnabled,
+ onBackClicked = onBackClicked,
+ onHelpClicked = onHelpClicked,
+ customBottomNavBarAdapter = customBottomNavBarAdapter,
+ onProceedClicked = onProceedClicked,
+ isSkontoSectionActive = state.isSkontoSectionActive
)
}) {
Column(
@@ -200,7 +249,10 @@ private fun ScreenReadyState(
@Composable
private fun TopAppBar(
+ onBackClicked: () -> Unit,
+ onHelpClicked: () -> Unit,
modifier: Modifier = Modifier,
+ isBottomNavigationBarEnabled: Boolean,
colors: GiniTopBarColors,
) {
GiniTopBar(
@@ -208,21 +260,50 @@ private fun TopAppBar(
colors = colors,
title = stringResource(id = R.string.gbs_skonto_screen_title),
navigationIcon = {
- Icon(
- modifier = Modifier.padding(16.dp),
- painter = rememberVectorPainter(image = Icons.AutoMirrored.Default.ArrowBack),
- contentDescription = null,
- )
+ AnimatedVisibility(visible = !isBottomNavigationBarEnabled) {
+ NavigationActionBack(onClick = onBackClicked)
+ }
},
actions = {
- Icon(
- modifier = Modifier.padding(16.dp),
- painter = painterResource(net.gini.android.capture.R.drawable.gc_help_icon),
- contentDescription = null,
- )
+ AnimatedVisibility(visible = !isBottomNavigationBarEnabled) {
+ NavigationActionHelp(onClick = onHelpClicked)
+ }
})
}
+@Composable
+private fun NavigationActionBack(
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ IconButton(
+ modifier = modifier,
+ onClick = onClick
+ ) {
+ Icon(
+ painter = rememberVectorPainter(image = Icons.AutoMirrored.Default.ArrowBack),
+ contentDescription = null,
+ )
+ }
+}
+
+@Composable
+private fun NavigationActionHelp(
+ onClick: () -> Unit,
+ modifier: Modifier = Modifier,
+) {
+ IconButton(
+ modifier = modifier,
+ onClick = onClick
+ ) {
+ Icon(
+ modifier = Modifier,
+ painter = painterResource(net.gini.android.capture.R.drawable.gc_help_icon),
+ contentDescription = null,
+ )
+ }
+}
+
@Composable
private fun YourInvoiceScanSection(
modifier: Modifier = Modifier,
@@ -390,10 +471,12 @@ private fun SkontoSection(
}
if (isDatePickerVisible) {
- GiniDatePickerDialog(onDismissRequest = { isDatePickerVisible = false }, onSaved = {
- isDatePickerVisible = false
- onDueDateChanged(it)
- })
+ GiniDatePickerDialog(
+ onDismissRequest = { isDatePickerVisible = false },
+ onSaved = {
+ isDatePickerVisible = false
+ onDueDateChanged(it)
+ })
}
}
@@ -496,66 +579,117 @@ private fun FooterSection(
discountValue: BigDecimal,
currency: String,
colors: SkontoFooterSectionColors,
+ isBottomNavigationBarEnabled: Boolean,
+ isSkontoSectionActive: Boolean,
+ onBackClicked: () -> Unit,
+ onHelpClicked: () -> Unit,
+ onProceedClicked: () -> Unit,
modifier: Modifier = Modifier,
+ customBottomNavBarAdapter: InjectedViewAdapterInstance?,
) {
- Card(
- modifier = modifier.fillMaxWidth(),
- shape = RectangleShape,
- colors = CardDefaults.cardColors(containerColor = colors.cardBackgroundColor)
- ) {
- Column(
- modifier = Modifier.padding(16.dp)
+ val animatedTotalAmount by animateFloatAsState(
+ targetValue = totalAmount.toFloat(), label = "totalAmount"
+ )
+ val animatedDiscountAmount by animateFloatAsState(
+ targetValue = discountValue.toFloat(), label = "discountAmount"
+ )
+ val totalPriceText = "${currencyFormatterWithoutSymbol().format(animatedTotalAmount)} $currency"
+ val discountLabelText = stringResource(
+ id = R.string.gbs_skonto_section_footer_label_discount,
+ animatedDiscountAmount.formatAsDiscountPercentage()
+ )
+ val proceedEnabled by remember { mutableStateOf(true) }
+
+ if (customBottomNavBarAdapter != null) {
+ val ctx = LocalContext.current
+ AndroidView(factory = {
+ customBottomNavBarAdapter.viewAdapter.onCreateView(FrameLayout(ctx))
+ }, update = {
+ with(customBottomNavBarAdapter.viewAdapter) {
+ setTotalPriceText(totalPriceText)
+ setProceedButtonEnabled(proceedEnabled) // TODO Integrate validation
+ setOnHelpClickListener(onHelpClicked)
+ setOnBackClickListener(onBackClicked)
+ setDiscountLabelText(discountLabelText)
+ setDiscountLabelVisible(isSkontoSectionActive)
+ setOnProceedClickListener(onProceedClicked)
+ }
+ })
+ } else {
+ Card(
+ modifier = modifier.fillMaxWidth(),
+ shape = RectangleShape,
+ colors = CardDefaults.cardColors(containerColor = colors.cardBackgroundColor)
) {
- Text(
- text = stringResource(id = R.string.gbs_skonto_section_footer_title),
- style = GiniTheme.typography.body1,
- color = colors.titleTextColor,
- )
- Row(
- modifier = Modifier
- .fillMaxWidth()
- .padding(top = 4.dp),
- horizontalArrangement = Arrangement.Start,
- verticalAlignment = Alignment.CenterVertically,
- ) {
- val animatedTotalAmount by animateFloatAsState(
- targetValue = totalAmount.toFloat(), label = "totalAmount"
- )
- Text(
- text = "${currencyFormatterWithoutSymbol().format(animatedTotalAmount)} $currency",
- style = GiniTheme.typography.headline5,
- color = colors.amountTextColor,
- )
- Box(
- modifier = Modifier
- .height(IntrinsicSize.Min)
- .padding(horizontal = 12.dp)
- .background(
- colors.discountLabelColorScheme.backgroundColor,
- RoundedCornerShape(4.dp)
- ),
+ Column {
+ Column(
+ modifier = Modifier.padding(start = 20.dp, end = 20.dp, top = 20.dp)
) {
- val animatedDiscountAmount by animateFloatAsState(
- targetValue = discountValue.toFloat(), label = "discountAmount"
- )
-
Text(
- modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp),
- text = stringResource(
- id = R.string.gbs_skonto_section_footer_label_discount,
- animatedDiscountAmount.formatAsDiscountPercentage()
- ),
- style = GiniTheme.typography.caption1,
- color = colors.discountLabelColorScheme.textColor,
+ text = stringResource(id = R.string.gbs_skonto_section_footer_title),
+ style = GiniTheme.typography.body1,
+ color = colors.titleTextColor,
+ )
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(top = 4.dp),
+ horizontalArrangement = Arrangement.Start,
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ Text(
+ text = totalPriceText,
+ style = GiniTheme.typography.headline5,
+ color = colors.amountTextColor,
+ )
+ AnimatedVisibility(visible = isSkontoSectionActive) {
+ Box(
+ modifier = Modifier
+ .height(IntrinsicSize.Min)
+ .padding(horizontal = 12.dp)
+ .background(
+ colors.discountLabelColorScheme.backgroundColor,
+ RoundedCornerShape(4.dp)
+ ),
+ ) {
+ Text(
+ modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp),
+ text = discountLabelText,
+ style = GiniTheme.typography.caption1,
+ color = colors.discountLabelColorScheme.textColor,
+ )
+ }
+ }
+ }
+ }
+ val buttonPaddingHorizontal = if (isBottomNavigationBarEnabled) 0.dp else 20.dp
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ verticalAlignment = Alignment.CenterVertically,
+ horizontalArrangement = Arrangement.SpaceEvenly
+ ) {
+ AnimatedVisibility(visible = isBottomNavigationBarEnabled) {
+ NavigationActionBack(
+ modifier = Modifier.padding(horizontal = 4.dp),
+ onClick = onBackClicked
+ )
+ }
+ GiniButton(
+ modifier = Modifier
+ .weight(0.1f)
+ .padding(horizontal = buttonPaddingHorizontal),
+ text = stringResource(id = R.string.gbs_skonto_section_footer_continue_button_text),
+ onClick = onProceedClicked,
+ giniButtonColors = colors.continueButtonColors
)
+ AnimatedVisibility(visible = isBottomNavigationBarEnabled) {
+ NavigationActionHelp(
+ modifier = Modifier.padding(horizontal = 4.dp),
+ onClick = onHelpClicked
+ )
+ }
}
}
- GiniButton(
- modifier = Modifier.fillMaxWidth(),
- text = stringResource(id = R.string.gbs_skonto_section_footer_continue_button_text),
- onClick = { /*TODO*/ },
- giniButtonColors = colors.continueButtonColors
- )
}
}
}
@@ -585,6 +719,11 @@ private fun ScreenReadyStatePreview() {
onDiscountAmountChange = {},
onDueDateChanged = {},
onFullAmountChange = {},
+ onHelpClicked = {},
+ onBackClicked = {},
+ isBottomNavigationBarEnabled = false,
+ onProceedClicked = {},
+ customBottomNavBarAdapter = null
)
}
}
diff --git a/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/skonto/SkontoNavigationBarBottomAdapter.kt b/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/skonto/SkontoNavigationBarBottomAdapter.kt
new file mode 100644
index 0000000000..52a95e7b3c
--- /dev/null
+++ b/bank-sdk/sdk/src/main/java/net/gini/android/bank/sdk/capture/skonto/SkontoNavigationBarBottomAdapter.kt
@@ -0,0 +1,45 @@
+package net.gini.android.bank.sdk.capture.skonto
+
+import net.gini.android.capture.view.InjectedViewAdapter
+
+interface SkontoNavigationBarBottomAdapter : InjectedViewAdapter {
+
+ /**
+ * Set the click listener for the help button.
+ *
+ * @param onClick the click function for the help button
+ */
+ fun setOnHelpClickListener(onClick: () -> Unit)
+
+ /**
+ * Set the click listener for the back button.
+ *
+ * @param onClick the click function for the back button
+ */
+ fun setOnBackClickListener(onClick: () -> Unit)
+
+ /**
+ * Set the click listener for the proceed button.
+ *
+ * @param listener the click listener for the button
+ */
+ fun setOnProceedClickListener(onClick: () -> Unit)
+
+ /**
+ * Enable or disable the proceed button.
+ *
+ * @param enabled for enabling or disabling the button
+ */
+ fun setProceedButtonEnabled(enabled: Boolean)
+
+ /**
+ * Set the total price.
+ *
+ * @param text price string with currency symbol
+ */
+ fun setTotalPriceText(text: String)
+
+ fun setDiscountLabelVisible(visible: Boolean)
+
+ fun setDiscountLabelText(text: String)
+}
\ No newline at end of file
diff --git a/capture-sdk/sdk/src/main/java/net/gini/android/capture/ui/components/topbar/GiniTopBar.kt b/capture-sdk/sdk/src/main/java/net/gini/android/capture/ui/components/topbar/GiniTopBar.kt
index 1b3bdc2fda..5ec05f9af2 100644
--- a/capture-sdk/sdk/src/main/java/net/gini/android/capture/ui/components/topbar/GiniTopBar.kt
+++ b/capture-sdk/sdk/src/main/java/net/gini/android/capture/ui/components/topbar/GiniTopBar.kt
@@ -31,7 +31,6 @@ fun GiniTopBar(
GiniTopBar(
modifier = modifier, colors = colors, title = {
Text(
- modifier = Modifier.padding(16.dp),
text = title,
style = GiniTheme.typography.headline6,
)