Files
thijooree/docs/thijooree/22-cards.md
T
shihaam a8cd22cbe1
Auto Tag on Version Change / check-version (push) Failing after 13m32s
update docs
2026-06-13 21:30:12 +05:00

4.3 KiB

Cards

Unified card management screen for both MIB and BML cards. Supports a horizontally-paged stack, freeze / unfreeze, default-card and hide-from-dashboard toggles, and launches the Tap to Pay NFC flow.


Fragment — CardsFragment

File: ui/home/PayWithCardFragment.kt. Bound to nav id R.id.nav_pay_with_card.

Opened via:

  • Navigation slot ("Cards")
  • OPEN_PAY_WITH_CARD intent
  • TAP_TO_PAY intent — auto-enters tap mode for the user's default BML card
  • Dashboard NFC button — auto-enters tap mode for the selected card

newInstanceWithAutoTapMode(accountNumber? = null) (PayWithCardFragment.kt:1203-1208) is the factory for the auto-tap entry points.


Card Stack

A horizontal RecyclerView driven by CardStackAdapter with a PagerSnapHelper. Off-centre cards are scaled to 82% and faded to 60% via applyCardScales(). Page dots beneath the stack are rebuilt on each scroll-idle.

Sources

rebuildCards() (PayWithCardFragment.kt:894-958) merges two lists:

  • BML: viewModel.accounts filtered to profileType in (BML_PREPAID, BML_CREDIT, BML_DEBIT)
  • MIB: viewModel.mibCards

The combined order is bmlActive + mibActive + bmlInactive + mibInactive. The user's default card (CredentialStore.getDefaultCardAccountNumber()) is moved to position 0. Initial data is seeded from CardsCache so the stack appears immediately; a background HomeActivity.triggerRefreshCards() refreshes it.

Card Art

Source Asset path
MIB cardType → asset CardsFragment.cardImageAsset(card)51cards/mib/faisa_card.png, 53visa_black_platinum.png, 57visa_blue_everyday.png, 70visa_business.png, 701/702visa_bingaa_mvr.png / visa_bingaa_usd.png
BML BmlCardParser.cardImageAsset(account)

Status chips use bindCardStatus(...). MIB statuses: CHST0 = active (no chip), CHST20 = "Temporary blocked by client", other values shown verbatim.


Pay Buttons

Button Behaviour
Scan to Pay (btnScanToPay) Launches QrScannerActivity. BML cards route the result to TransferFragment (BML QR mode or PayMV pre-fill). MIB cards show "not supported"
Tap to Pay (btnTapToPay) NfcPaymentUtil.checkAndProceed(...). If biometrics_transfer_confirm is on, shows a BIOMETRIC_STRONG prompt first, then enters tap mode. MIB cards show "not supported"

Manage Mode

Toggle: btnManageCard. Animates the focused card up into a single full-width "manage card" panel, hides the carousel, and exposes:

Control Effect
Default card switch CredentialStore.setDefaultCardAccountNumber() — BML only
Hide from dashboard switch CredentialStore.setCardHiddenFromDashboard(accountNumber, hidden)
Freeze / Unfreeze BML: BmlCardClient.setCardFreezeState(session, internalId, "freeze"/"unfreeze"). MIB: prompts for a comments string, then MibCardsClient().setCardFreezeState(session, cardId, action, comments) serialised through app.mibMutex with a profile switch first
Change PIN / Block Wired but currently shows a "work in progress" toast

Manage mode can be dismissed by tapping the button again or swipe-down on the manage card.


Tap Mode

Entered via setTapMode(true, item). Hides the carousel, animates the selected card to the top, draws an NfcTapAnimationView and a Cancel button.

fetchAndArmToken():

  1. Generates a TOTP from the BML OTP seed
  2. BmlTapToPayClient().fetchTokens(session, internalId, otp) returns a single-use BmlWalletToken
  3. BmlHostCardEmulatorService.setToken(token)
  4. Sets BmlHostCardEmulatorService.onTransactionComplete — on success shows a "Payment complete" toast and refreshes balances

Exiting tap mode clears the token and the callback. See Tap to Pay for the HCE protocol details.


Inactive Cards

Inactive cards remain in the stack at 45% alpha. Tap-to-pay and "default card" are disabled for them. Hide-from-dashboard is force-enabled and locked on for inactive cards (PayWithCardFragment.kt:522-530).


Back Handling

onBackPressed() returns true while in manage mode or tap mode so HomeActivity does not pop the back stack — instead the fragment exits the current mode.


 


← Dashboard     Next → Tap to Pay