White-label App SDK
UI Customization
Compose (Screen)

Custom UI Guide - Compose Screen

This guide provides an example of how to customize the screens using the MineSec Headless SDK with Jetpack Compose. The example demonstrates how to override the default screens provided by the SDK.

🧑🏽‍💻

You can find the example code for screen provider here via github (opens in a new tab)

UI States

Throughout the lifecycle of a PoiRequest, the Headless SDK shows the Screen differently. Here're all the UI State:

ScreenDescription
PreparationScreenPreparing for the profile & reader.
AwaitingCardScreenAwaiting card tapping.
ProcessingScreenOnline processing PoiRequest.
SchemeSensoryBrandingScreenUpon a transaction approval, show per card scheme sensory animation.
SignatureScreenSignature on screen.

The default UI as following

AwaitingCardScreen

ProcessingScreen

SignatureScreen

Walkthrough

To customize the screen with the SDK,

Create a custom HeadlessActivity

class HeadlessImplWithScreenProvider : HeadlessActivity()

Remember to register the new activity in the app's AndroidManifest.xml

Override the flag and ScreenProvider

From this activity, override both the experimentalScreenProvider = true and wire up a ScreenProvider

class HeadlessImplWithScreenProvider : HeadlessActivity() {
    override val experimentalScreenProvider = true
    override val screenProvider = object : ScreenProvider() {}
}

Customize your screen

From the ScreenProvider, you can find different screens (as a composable function) to override.

For example, if you want to have a custom await card screen:

@Composable
override fun AwaitingCardScreen(
    poiRequest: PoiRequest.ActionNew,
    awaitingFlow: Flow<UiState.Awaiting>,
    supportedMethods: List<PaymentMethod>,
    countdownFlow: StateFlow<Int>,
    onAbort: () -> Unit
) {
    val countdownSec by countdownFlow.collectAsStateWithLifecycle()
    val uiState by awaitingFlow.collectAsStateWithLifecycle(UiState.Preparing.Idle)
    Shell {
        Title(text = "Await Card Screen")
        Desc(text = "-> awaiting card tapping")
        Text(text = "countdown: $countdownSec")
        Text(text = "uiState: $uiState")
        AmountText(poiRequest.amount)
        PoiRequestText(poiRequest)
        Text(text = "supportedMethods: $supportedMethods")
        FlowRow(
            modifier = Modifier.fillMaxWidth(),
            verticalArrangement = Arrangement.spacedBy(HeadlessTheme.spacing.xs2),
            horizontalArrangement = Arrangement.spacedBy(
                HeadlessTheme.spacing.xs,
                Alignment.CenterHorizontally
            )
        ) {
            supportedMethods.forEach { it.Icon() }
        }
        Button(onClick = onAbort) {
            Text(text = "Abort")
        }
    }
}

Then the UI would look like: