MineSec Pay 7
UI Customization
Screen Providers Reference

Screen Providers Reference

Every screen in msa-core is a ComposableScreen<State, Action>: your Composable receives an immutable State and a triggerAction callback.

fun interface ComposableScreen<S, A> {
    @Composable
    fun Content(state: S, triggerAction: (A) -> Unit)
}

You create one from a lambda:

ComposableScreen<LoginState, LoginAction> { state, triggerAction -> MyLoginScreen(state, triggerAction) }

How the screens are organised

ScreenProviders groups the screens by feature. Each group is an interface in com.theminesec.multiplatform.msa_core.app.contract.screens, and msa-uikit provides an open default class for each one:

interface ScreenProviders {
    val statusBarColor: @Composable (AppScreen) -> Color
    val themeWrapper: @Composable (content: @Composable () -> Unit) -> Unit
 
    val startup: StartupScreens
    val home: HomeScreens
    val payment: PaymentScreens
    val history: HistoryScreens
    val settlement: SettlementScreens
    val settings: SettingsScreens
    val idle: IdleScreens
 
    // App2App screens (see below)
}

To replace one screen, subclass DefaultScreenProviders, then override the group with a subclass of its default class, and override the one slot. Every other slot keeps tracking msa-uikit:

class MyScreenProviders : DefaultScreenProviders(MyBrandTheme) {
    override val history: HistoryScreens = object : DefaultHistoryScreens() {
        override val detail = ComposableScreen { state, triggerAction ->
            MyTransactionDetail(state, triggerAction)
        }
    }
}

Declare slots as stored properties (override val x = ...), never as getters. A getter creates a new screen on every read and forces recomposition.

Replacing a screen changes only how it looks. msa-core validates every operation, whatever the UI offers.


Startup: startup

Default class: DefaultStartupScreens

SlotStateActionDescription
loginLoginStateLoginActionPasscode login, with optional biometrics
landingLandingStateLandingActionSplash and activation screen

Home: home

Default class: DefaultHomeScreens

SlotStateActionDescription
homeHomeStateHomeActionMain dashboard with navigation to all features

Payment: payment

Default class: DefaultPaymentScreens. One payment, from the amount to the receipt.

SlotStateActionDescription
amountEntryAmountEntryStateAmountEntryActionAmount entry for sale, pre-auth and refund. The operation is part of the state.
methodSelectionPaymentSelectionStatePaymentSelectionActionPayment method selection: card, merchant QR or consumer QR
qrPresentPaymentQRSelectionStatePaymentQRSelectionActionThe merchant's QR code, shown for the customer to scan
qrScanConsumerQRScanStateConsumerQRScanActionThe camera, scanning the customer's QR code
cardPromptCardPromptStateCardPromptActionGet ready, tap card and processing, in one screen. Rendered in the card-reading activity.
processingProcessingInquiryStateProcessingInquiryActionWaiting for the acquirer's response
receiptReceiptStateReceiptActionThe full receipt

The result of a payment is shown by history.detail: a transaction that just ran is the same record as one looked up later.


History: history

Default class: DefaultHistoryScreens

SlotStateActionDescription
listHistoryStateHistoryActionTransaction history list
detailTransactionDetailStateTransactionDetailActionOne transaction in full, including the result of a payment that just ran

Settlement: settlement

Default class: DefaultSettlementScreens

SlotStateActionDescription
listSettlementStateSettlementActionBatch settlement overview
detailSettlementStateSettlementActionSettlement batch details

Settings: settings

Default class: DefaultSettingsScreens

SlotStateActionDescription
mainSettingsStateSettingsActionApplication settings
infoSettingsStateSettingsActionMerchant and terminal information

Idle: idle

Default class: DefaultIdleScreens. What an unattended (kiosk) terminal shows when nobody is using it.

SlotStateActionDescription
signageKioskIdleSignageStateKioskIdleSignageActionIdle signage in kiosk mode

App-to-App Screens

These screens are shown when a POS app on the same device calls MineSec Pay 7 through App2App. They are direct properties of ScreenProviders, not a group.

PropertyStateActionDescription
splashApp2AppScreenSplashApp2AppStateSplashApp2AppActionLoading screen while the request is read
activationApp2AppScreenActivationApp2AppStateActivationApp2AppActionActivation requested by the POS app
warmupApp2AppScreenWarmupApp2AppStateWarmupApp2AppActionWarm-up requested by the POS app
saleApp2AppScreenSaleApp2AppStateSaleApp2AppActionSale requested by the POS app
voidRefundApp2AppScreenVoidRefundApp2AppStateVoidRefundApp2AppActionVoid or refund requested by the POS app
queryApp2AppScreenQueryApp2AppStateQueryApp2AppActionTransaction query requested by the POS app
settlementApp2AppScreenSettlementApp2AppStateSettlementApp2AppActionSettlement requested by the POS app

Override them directly in your DefaultScreenProviders subclass:

override val saleApp2AppScreen = ComposableScreen { state, triggerAction ->
    MyApp2AppSaleScreen(state, triggerAction)
}

Where the classes live

ClassesPackage
ScreenProviders, ComposableScreen, ErrorStatecom.theminesec.multiplatform.msa_core.app.contract
Group interfaces (PaymentScreens, HistoryScreens, ...)com.theminesec.multiplatform.msa_core.app.contract.screens
AmountEntry*, CardPrompt*, TransactionDetail*com.theminesec.multiplatform.msa_core.app.contract.models
Other State and Action classesThe feature's presentation package in msa-core, for example ...msa_core.feature.login.presentation.LoginState
DefaultScreenProviders and the default group classescom.theminesec.multiplatform.msa.screens and its sub-packages (msa-uikit)

Your IDE's auto-import resolves them.


Status Bar Colour

statusBarColor picks the status bar colour for each screen. The stock implementation:

override val statusBarColor: @Composable (AppScreen) -> Color = { screen ->
    when (screen) {
        LandingScreen -> MsaTheme.colors.mutedForeground
        LoginScreen -> MsaTheme.colors.background
        HomeScreen -> MsaTheme.colors.surface
        AmountEntryScreen -> MsaTheme.colors.primary
        else -> MsaTheme.colors.background
    }
}

Override it in your DefaultScreenProviders subclass to change it.


Theme Wrapper

themeWrapper wraps the screens drawn outside the main activity: App2App and the card prompt. Override it with your theme so that those screens are branded too. See Applying your theme.