From 7a1a4af6858e99d037a977fcc766ee68ae89bdb5 Mon Sep 17 00:00:00 2001 From: tomas-martins-crossmint <245057149+tomas-martins-crossmint@users.noreply.github.com> Date: Fri, 11 Sep 2026 13:37:01 +0000 Subject: [PATCH] sync demo app from SDK 1.2.0 --- .../playground/PasskeyCreation.android.kt | 129 +++++++ .../kotlin/AuthMethodSelectionScreen.kt | 61 ---- .../kotlin/com/crossmint/kotlin/DemoApp.kt | 46 ++- .../kotlin/com/crossmint/kotlin/Routes.kt | 3 - .../bringyourown/BringYourOwnAuthViewModel.kt | 2 - .../kotlin/checkout/CheckoutScreen.kt | 89 ----- .../kotlin/wallet/CreateWalletViewModel.kt | 17 + .../crossmint/kotlin/wallet/WalletEvents.kt | 23 ++ .../crossmint/kotlin/wallet/WalletScreen.kt | 25 -- .../kotlin/wallet/WalletViewModel.kt | 12 + .../wallet/createwallet/AdminSignerCard.kt | 30 ++ .../wallet/createwallet/CreateWalletScreen.kt | 7 +- .../wallet/createwallet/CreateWalletTypes.kt | 8 + checkout/.gitignore | 1 + checkout/build.gradle.kts | 124 +++++++ checkout/src/androidMain/AndroidManifest.xml | 32 ++ .../kotlin/checkoutdemo/MainActivity.kt | 18 + .../kotlin/checkoutdemo/ui/IdentityPreview.kt | 40 +++ .../kotlin/checkoutdemo/ui/PaneBackHandler.kt | 13 + .../kotlin/checkoutdemo/utility/Time.kt | 12 + .../drawable-v24/ic_launcher_foreground.xml | 17 + .../res/drawable/ic_launcher_background.xml | 10 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../mipmap-anydpi-v26/ic_launcher_round.xml | 5 + .../res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 4865 bytes .../res/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4865 bytes .../res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 3470 bytes .../res/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3470 bytes .../res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 6346 bytes .../res/mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 6346 bytes .../res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 9625 bytes .../res/mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 9625 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 13351 bytes .../res/mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 13351 bytes .../src/androidMain/res/values/strings.xml | 3 + .../res/xml/network_security_config.xml | 3 + .../drawable/crossmint_logo.png | Bin 0 -> 136690 bytes .../drawable/ic_crossmint.xml | 9 + .../crossmint/kotlin/checkoutdemo/AppRoot.kt | 22 ++ .../kotlin/checkoutdemo/PlaygroundUiState.kt | 29 ++ .../checkoutdemo/PlaygroundViewModel.kt | 113 +++++++ .../checkoutdemo/data/HttpClientFactory.kt | 21 ++ .../kotlin/checkoutdemo/data/OrderApiError.kt | 19 ++ .../kotlin/checkoutdemo/data/OrdersApi.kt | 139 ++++++++ .../kotlin/checkoutdemo/model/DemoEvent.kt | 6 + .../kotlin/checkoutdemo/model/OrderDraft.kt | 8 + .../kotlin/checkoutdemo/model/OrderSession.kt | 12 + .../checkoutdemo/model/PlaygroundOptions.kt | 136 ++++++++ .../checkoutdemo/model/PlaygroundSection.kt | 21 ++ .../kotlin/checkoutdemo/model/TokenPreset.kt | 105 ++++++ .../kotlin/checkoutdemo/ui/AboutSheet.kt | 75 +++++ .../kotlin/checkoutdemo/ui/AppTheme.kt | 61 ++++ .../kotlin/checkoutdemo/ui/CheckoutDemoApp.kt | 318 ++++++++++++++++++ .../checkoutdemo/ui/CheckoutPreviewHost.kt | 215 ++++++++++++ .../kotlin/checkoutdemo/ui/CopyableRow.kt | 30 ++ .../checkoutdemo/ui/EnvironmentBadge.kt | 12 + .../kotlin/checkoutdemo/ui/IdentityPreview.kt | 13 + .../kotlin/checkoutdemo/ui/PaneBackHandler.kt | 9 + .../kotlin/checkoutdemo/ui/SwitchRow.kt | 18 + .../ui/sections/AppearanceSectionView.kt | 98 ++++++ .../ui/sections/EventsSectionView.kt | 39 +++ .../ui/sections/FieldsSectionView.kt | 39 +++ .../ui/sections/IdentitySectionView.kt | 59 ++++ .../ui/sections/OrderSectionView.kt | 250 ++++++++++++++ .../ui/sections/PaymentSectionView.kt | 39 +++ .../kotlin/checkoutdemo/utility/Time.kt | 5 + gradle/libs.versions.toml | 10 +- settings.gradle.kts | 1 + 68 files changed, 2480 insertions(+), 186 deletions(-) delete mode 100644 app/src/commonMain/kotlin/com/crossmint/kotlin/checkout/CheckoutScreen.kt create mode 100644 checkout/.gitignore create mode 100644 checkout/build.gradle.kts create mode 100644 checkout/src/androidMain/AndroidManifest.xml create mode 100644 checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/MainActivity.kt create mode 100644 checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/IdentityPreview.kt create mode 100644 checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/PaneBackHandler.kt create mode 100644 checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/utility/Time.kt create mode 100644 checkout/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 checkout/src/androidMain/res/drawable/ic_launcher_background.xml create mode 100644 checkout/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 checkout/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 checkout/src/androidMain/res/mipmap-hdpi/ic_launcher.png create mode 100644 checkout/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png create mode 100644 checkout/src/androidMain/res/mipmap-mdpi/ic_launcher.png create mode 100644 checkout/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png create mode 100644 checkout/src/androidMain/res/mipmap-xhdpi/ic_launcher.png create mode 100644 checkout/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png create mode 100644 checkout/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 checkout/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 checkout/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 checkout/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 checkout/src/androidMain/res/values/strings.xml create mode 100644 checkout/src/androidMain/res/xml/network_security_config.xml create mode 100644 checkout/src/commonMain/composeResources/drawable/crossmint_logo.png create mode 100644 checkout/src/commonMain/composeResources/drawable/ic_crossmint.xml create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/AppRoot.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/PlaygroundUiState.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/PlaygroundViewModel.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/HttpClientFactory.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/OrderApiError.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/OrdersApi.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/DemoEvent.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/OrderDraft.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/OrderSession.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/PlaygroundOptions.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/PlaygroundSection.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/TokenPreset.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/AboutSheet.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/AppTheme.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CheckoutDemoApp.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CheckoutPreviewHost.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CopyableRow.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/EnvironmentBadge.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/IdentityPreview.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/PaneBackHandler.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/SwitchRow.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/AppearanceSectionView.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/EventsSectionView.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/FieldsSectionView.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/IdentitySectionView.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/OrderSectionView.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/PaymentSectionView.kt create mode 100644 checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/utility/Time.kt diff --git a/app/src/androidMain/kotlin/com/crossmint/kotlin/wallet/playground/PasskeyCreation.android.kt b/app/src/androidMain/kotlin/com/crossmint/kotlin/wallet/playground/PasskeyCreation.android.kt index ce085f8..6bce9ab 100644 --- a/app/src/androidMain/kotlin/com/crossmint/kotlin/wallet/playground/PasskeyCreation.android.kt +++ b/app/src/androidMain/kotlin/com/crossmint/kotlin/wallet/playground/PasskeyCreation.android.kt @@ -1,24 +1,153 @@ package com.crossmint.kotlin.wallet.playground +import android.app.Activity import android.content.Context +import android.content.ContextWrapper import android.util.Base64 +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.semantics.testTag import androidx.credentials.CreatePublicKeyCredentialRequest import androidx.credentials.CreatePublicKeyCredentialResponse import androidx.credentials.CredentialManager import androidx.credentials.exceptions.CreateCredentialCancellationException import com.crossmint.kotlin.signers.DelegatedSigner +import com.crossmint.kotlin.utility.exposeTestTags import java.math.BigInteger import java.security.SecureRandom +import kotlinx.coroutines.CompletableDeferred import org.json.JSONObject @Composable actual fun rememberPasskeyCreator(): (suspend (name: String) -> DelegatedSigner.Passkey?)? { val context = LocalContext.current + + // Mock mode is for CI e2e flows ONLY: GitHub Actions emulators cannot create real + // passkeys via CredentialManager (no signed-in Google account). The Maestro passkey + // flow launches the app with `arguments: { mockPasskey: true }`, which Android + // delivers as launcher-intent extras. Local/manual testing keeps the real path. + val mockMode = + remember(context) { + context + .findActivity() + ?.intent + ?.extras + ?.get("mockPasskey") + ?.toString() == "true" + } + + if (mockMode) { + return rememberMockPasskeyCreator() + } return { name -> createPasskeySigner(context, name) } } +private tailrec fun Context.findActivity(): Activity? = + when (this) { + is Activity -> this + is ContextWrapper -> baseContext.findActivity() + else -> null + } + +// --------------------------------------------------------------------------- +// Mock passkey creation (CI e2e only) — mirrors the Flutter playground dialog. +// --------------------------------------------------------------------------- + +@Composable +private fun rememberMockPasskeyCreator(): suspend (name: String) -> DelegatedSigner.Passkey? { + var pendingRequest by remember { mutableStateOf(null) } + + pendingRequest?.let { request -> + AlertDialog( + onDismissRequest = { + request.result.complete(null) + pendingRequest = null + }, + // AlertDialog hosts its own window: re-expose testTags for Maestro. + modifier = Modifier.exposeTestTags(), + title = { Text("Create Passkey (Mock)") }, + text = { + Text( + "Name: ${request.name}\n\n" + + "Playground-only simulation. On a real device this would trigger the " + + "Android Credential Manager passkey prompt. Tap Simulate to return " + + "mock credential data.", + ) + }, + confirmButton = { + Button( + onClick = { + request.result.complete(mockPasskeySigner(request.name)) + pendingRequest = null + }, + modifier = Modifier.semantics { testTag = "passkey-simulate-button" }, + ) { + Text("Simulate") + } + }, + dismissButton = { + TextButton( + onClick = { + request.result.complete(null) + pendingRequest = null + }, + ) { + Text("Cancel") + } + }, + ) + } + + return { name -> + val result = CompletableDeferred() + pendingRequest = PendingPasskeyRequest(name, result) + try { + result.await() + } finally { + pendingRequest = null + } + } +} + +private class PendingPasskeyRequest( + val name: String, + val result: CompletableDeferred, +) + +private fun mockPasskeySigner(name: String): DelegatedSigner.Passkey { + val random = SecureRandom() + + fun hex(byteCount: Int): String { + val bytes = ByteArray(byteCount).also { random.nextBytes(it) } + return bytes.joinToString("") { "%02x".format(it) } + } + + // The 0x prefix is required: the register-signer API validates publicKey.x/y as + // "a valid positive BigInt decimal or hex string" and rejects bare hex with HTTP 400. + // The server does not validate attestation/cryptography, so random values are + // accepted — mirrors the Flutter playground mock. + return DelegatedSigner.Passkey( + id = "mock-credential-${hex(8)}", + name = name, + publicKeyX = "0x${hex(32)}", + publicKeyY = "0x${hex(32)}", + ) +} + +// --------------------------------------------------------------------------- +// Real passkey creation via Android Credential Manager (default path). +// --------------------------------------------------------------------------- + private suspend fun createPasskeySigner( context: Context, name: String, diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/AuthMethodSelectionScreen.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/AuthMethodSelectionScreen.kt index 73de51c..2a66f35 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/AuthMethodSelectionScreen.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/AuthMethodSelectionScreen.kt @@ -14,9 +14,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButtonDefaults import androidx.compose.material3.Surface @@ -102,12 +100,6 @@ fun AuthMethodSelectionScreen( } }, ) - - OrDivider() - - CheckoutButton(onClick = { - navController.navigate(Routes.Checkout) - }) } Spacer(modifier = Modifier.weight(1f)) @@ -227,56 +219,3 @@ fun SignInButton( } } } - -@Composable -fun OrDivider() { - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - ) { - HorizontalDivider( - modifier = Modifier.weight(1f), - color = MaterialTheme.colorScheme.outlineVariant, - ) - Text( - text = "OR", - modifier = Modifier.padding(horizontal = 16.dp), - fontSize = 14.sp, - ) - HorizontalDivider( - modifier = Modifier.weight(1f), - color = MaterialTheme.colorScheme.outlineVariant, - ) - } -} - -@Composable -fun CheckoutButton(onClick: () -> Unit) { - OutlinedButton( - onClick = { onClick() }, - modifier = - Modifier - .fillMaxWidth() - .height(52.dp), - shape = RoundedCornerShape(12.dp), - colors = - ButtonDefaults.outlinedButtonColors( - contentColor = MaterialTheme.colorScheme.primary, - ), - ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - "Embedded Checkout", - fontSize = 16.sp, - fontWeight = FontWeight.Medium, - ) - Text( - "Payment Flow", - fontSize = 12.sp, - fontWeight = FontWeight.Normal, - ) - } - } -} diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/DemoApp.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/DemoApp.kt index 5e39bd0..72dac14 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/DemoApp.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/DemoApp.kt @@ -4,7 +4,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable @@ -15,12 +18,12 @@ import com.crossmint.kotlin.auth.bringyourown.BringYourOwnAuthScreen import com.crossmint.kotlin.auth.crossmint.CrossmintAuthViewModel import com.crossmint.kotlin.auth.crossmint.CrossmintOTPEmailScreen import com.crossmint.kotlin.auth.crossmint.CrossmintOTPVerificationScreen -import com.crossmint.kotlin.checkout.CheckoutScreen import com.crossmint.kotlin.compose.LocalCrossmintSDK import com.crossmint.kotlin.wallet.CreateWalletViewModel import com.crossmint.kotlin.wallet.WalletScreen import com.crossmint.kotlin.wallet.WalletViewModel import com.crossmint.kotlin.wallet.createwallet.CreateWalletScreen +import kotlinx.coroutines.launch // AuthMode is defined in androidMain, so we pass it as a parameter from AppRoot @Composable @@ -136,9 +139,44 @@ fun DemoApp( isStaging = isStaging, ) } + } - composable { - CheckoutScreen(navController = navController) - } + DeviceSignerOTPDialog( + walletViewModel = walletViewModel, + createWalletViewModel = createWalletViewModel, + ) +} + +@Composable +private fun DeviceSignerOTPDialog( + walletViewModel: WalletViewModel, + createWalletViewModel: CreateWalletViewModel, +) { + val sdk = LocalCrossmintSDK.current + val scope = rememberCoroutineScope() + var shouldShowOTP by remember { mutableStateOf(false) } + + LaunchedEffect(Unit) { + sdk.isOTPRequired.collect { shouldShowOTP = it } + } + + if (shouldShowOTP) { + val walletUiState by walletViewModel.uiState.collectAsState() + val createWalletUiState by createWalletViewModel.uiState.collectAsState() + val signerType = + createWalletUiState.pendingOTPSignerType + ?: when (walletUiState.selectedSigner?.type?.lowercase()) { + "phone" -> OTPSignerType.PHONE + else -> OTPSignerType.EMAIL + } + OTPDialog( + signerType = signerType, + onOTPSubmit = { scope.launch { sdk.submit(it) } }, + onDismiss = { + scope.launch { sdk.cancelTransaction() } + walletViewModel.clearTransaction() + shouldShowOTP = false + }, + ) } } diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/Routes.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/Routes.kt index 1c8af63..b157346 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/Routes.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/Routes.kt @@ -20,7 +20,4 @@ class Routes { @Serializable object CreateWallet - - @Serializable - object Checkout } diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/auth/bringyourown/BringYourOwnAuthViewModel.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/auth/bringyourown/BringYourOwnAuthViewModel.kt index 738e741..7c1c57b 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/auth/bringyourown/BringYourOwnAuthViewModel.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/auth/bringyourown/BringYourOwnAuthViewModel.kt @@ -49,8 +49,6 @@ class BringYourOwnAuthViewModel( return@launch } - // This function doesn't actually validate the JWT against the JWKS endpoint, but my presumption is that it - // would. Right now we are kind of implicitly relying on the first getWallet api call to validate our JWT token. authManager.setJWT(jwt) showToast("Authentication successful") diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/checkout/CheckoutScreen.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/checkout/CheckoutScreen.kt deleted file mode 100644 index 95e07d8..0000000 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/checkout/CheckoutScreen.kt +++ /dev/null @@ -1,89 +0,0 @@ -package com.crossmint.kotlin.checkout - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.automirrored.filled.ArrowBack -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBar -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.navigation.NavController -import com.crossmint.kotlin.checkout.models.CheckoutAllowedMethods -import com.crossmint.kotlin.checkout.models.CheckoutAppearance -import com.crossmint.kotlin.checkout.models.CheckoutAppearanceRules -import com.crossmint.kotlin.checkout.models.CheckoutCryptoPayment -import com.crossmint.kotlin.checkout.models.CheckoutDestinationInputRule -import com.crossmint.kotlin.checkout.models.CheckoutFiatPayment -import com.crossmint.kotlin.checkout.models.CheckoutPayment -import com.crossmint.kotlin.checkout.models.CheckoutReceiptEmailInputRule - -/** - * Demo screen showcasing the CrossmintEmbeddedCheckout component. - */ -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun CheckoutScreen(navController: NavController) { - Column( - modifier = - Modifier - .fillMaxSize() - .background(Color.White), - ) { - TopAppBar( - title = { Text("Checkout") }, - navigationIcon = { - IconButton(onClick = { navController.popBackStack() }) { - Icon( - imageVector = Icons.AutoMirrored.Filled.ArrowBack, - contentDescription = "Back", - ) - } - }, - ) - - Box( - modifier = - Modifier - .fillMaxWidth() - .weight(1f), - ) { - CrossmintEmbeddedCheckout( - orderId = "your-order-id", - clientSecret = "your-client-secret", - payment = - CheckoutPayment( - crypto = CheckoutCryptoPayment(enabled = false), - fiat = - CheckoutFiatPayment( - enabled = true, - allowedMethods = - CheckoutAllowedMethods( - googlePay = true, - applePay = true, - card = true, - ), - ), - receiptEmail = "robin+kotlin@crossmint.com", - ), - appearance = - CheckoutAppearance( - rules = - CheckoutAppearanceRules( - destinationInput = CheckoutDestinationInputRule(display = "hidden"), - receiptEmailInput = CheckoutReceiptEmailInputRule(display = "hidden"), - ), - ), - environment = CheckoutEnvironment.STAGING, - modifier = Modifier.fillMaxSize(), - ) - } - } -} diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/CreateWalletViewModel.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/CreateWalletViewModel.kt index eac4805..7e41d41 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/CreateWalletViewModel.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/CreateWalletViewModel.kt @@ -3,6 +3,7 @@ package com.crossmint.kotlin.wallet import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.navigation.NavController +import com.crossmint.kotlin.OTPSignerType import com.crossmint.kotlin.signers.DelegatedSigner import com.crossmint.kotlin.signers.SignerType import com.crossmint.kotlin.types.Chain @@ -18,6 +19,7 @@ data class CreateWalletUiState( val isCreating: Boolean = false, val errorMessage: String? = null, val createdWallet: Wallet? = null, + val pendingOTPSignerType: OTPSignerType? = null, ) { val hasError: Boolean get() = errorMessage != null @@ -44,6 +46,16 @@ class CreateWalletViewModel( _uiState.value.copy( isCreating = true, errorMessage = null, + pendingOTPSignerType = + if (deviceSigner) { + when (signer) { + is SignerType.Email -> OTPSignerType.EMAIL + is SignerType.Phone -> OTPSignerType.PHONE + SignerType.ApiKey, is SignerType.Passkey -> null + } + } else { + null + }, ) when ( @@ -56,11 +68,15 @@ class CreateWalletViewModel( ) ) { is Result.Success -> { + if (signer is SignerType.Phone) { + WalletEvents.rememberPhoneChannel(signer.phoneNumber, signer.channel) + } _uiState.value = _uiState.value.copy( createdWallet = result.value, isCreating = false, errorMessage = null, + pendingOTPSignerType = null, ) // Signal WalletViewModel to refresh WalletEvents.notifyWalletCreated() @@ -72,6 +88,7 @@ class CreateWalletViewModel( _uiState.value.copy( isCreating = false, errorMessage = "Failed to create wallet: ${result.error.message}", + pendingOTPSignerType = null, ) } } diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletEvents.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletEvents.kt index 72a2a28..dce8ce0 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletEvents.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletEvents.kt @@ -1,5 +1,6 @@ package com.crossmint.kotlin.wallet +import com.crossmint.kotlin.signers.OTPDeliveryChannel import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.asSharedFlow @@ -24,4 +25,26 @@ object WalletEvents { fun notifyWalletCreated() { _walletCreated.tryEmit(Unit) } + + /** + * The OTP delivery channel chosen for a phone signer, by phone number. + * + * The wallet API never returns this, so a wallet fetched with getWallet always falls back to + * SMS. The demo keeps the choice here and reapplies it with useSigner on every wallet load. + */ + private val phoneChannels = mutableMapOf() + + fun rememberPhoneChannel( + phoneNumber: String, + channel: OTPDeliveryChannel?, + ) { + if (channel != null) phoneChannels[phoneNumber] = channel + } + + fun phoneChannel(phoneNumber: String): OTPDeliveryChannel? = phoneChannels[phoneNumber] + + /** Called on sign out, so a channel never carries over to the next session. */ + fun clearPhoneChannels() { + phoneChannels.clear() + } } diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletScreen.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletScreen.kt index 52d10d9..5a54a66 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletScreen.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletScreen.kt @@ -65,10 +65,7 @@ import com.crossmint.crossmintdemoapp.generated.resources.ic_crossmint import com.crossmint.crossmintdemoapp.generated.resources.ic_eth import com.crossmint.crossmintdemoapp.generated.resources.ic_solana import com.crossmint.crossmintdemoapp.generated.resources.ic_stellar -import com.crossmint.kotlin.CrossmintSDK import com.crossmint.kotlin.Deps -import com.crossmint.kotlin.OTPDialog -import com.crossmint.kotlin.OTPSignerType import com.crossmint.kotlin.Routes import com.crossmint.kotlin.auth.AuthMethod import com.crossmint.kotlin.auth.crossmint.CrossmintAuthViewModel @@ -108,14 +105,9 @@ fun WalletScreen( var showSignersSheet by remember { mutableStateOf(false) } var showActivitySheet by remember { mutableStateOf(false) } var showSigningSheet by remember { mutableStateOf(false) } - val shouldShowOTP = remember { mutableStateOf(false) } var isRefreshing by remember { mutableStateOf(false) } val passkeyCreator = rememberPasskeyCreator() - LaunchedEffect(Unit) { - CrossmintSDK.shared.isOTPRequired.collect { shouldShowOTP.value = it } - } - LaunchedEffect(Unit) { walletViewModel.sessionExpired.collect { when (authMethod) { @@ -411,23 +403,6 @@ fun WalletScreen( onDismiss = { showSigningSheet = false }, ) } - - if (shouldShowOTP.value) { - val signerType = - when (uiState.selectedSigner?.type?.lowercase()) { - "phone" -> OTPSignerType.PHONE - else -> OTPSignerType.EMAIL - } - OTPDialog( - signerType = signerType, - onOTPSubmit = { scope.launch { CrossmintSDK.shared.submit(it) } }, - onDismiss = { - scope.launch { CrossmintSDK.shared.cancelTransaction() } - walletViewModel.clearTransaction() - shouldShowOTP.value = false - }, - ) - } } } diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletViewModel.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletViewModel.kt index 0e1ac6e..350e4da 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletViewModel.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/WalletViewModel.kt @@ -64,6 +64,12 @@ class WalletViewModel( @OptIn(ExperimentalUuidApi::class) private fun newIdempotencyKey(): String = Uuid.random().toString() + private suspend fun reapplyPhoneChannel(wallet: Wallet) { + val admin = wallet.config.adminSigner as? SignerData.Phone ?: return + val channel = WalletEvents.phoneChannel(admin.phone) ?: return + wallet.useSigner(DelegatedSigner.Phone(admin.phone, channel = channel)) + } + fun fetchWallet(chain: Chain) { val supportedChain = SupportedChain.entries.find { it.chain == chain } ?: return viewModelScope.launch { @@ -82,6 +88,7 @@ class WalletViewModel( ) { val signers = buildAvailableSigners(wallet) val securityLevel = crossmintWallets.getDeviceSignerSecurityLevel(wallet.address) + reapplyPhoneChannel(wallet) walletCache[supportedChain] = CachedWallet(wallet, securityLevel) notFoundChains.remove(supportedChain) activeFetches.remove(supportedChain) @@ -154,6 +161,7 @@ class WalletViewModel( is Result.Success -> { val wallet = result.value val securityLevel = crossmintWallets.getDeviceSignerSecurityLevel(wallet.address) + reapplyPhoneChannel(wallet) walletCache[chain] = CachedWallet(wallet, securityLevel) } is Result.Failure -> { @@ -205,6 +213,9 @@ class WalletViewModel( _uiState.value = _uiState.value.copy(isCreatingWallet = true, errorMessage = null) when (val result = crossmintWallets.createWallet(chain, signer, delegatedSigners)) { is Result.Success -> { + if (signer is SignerType.Phone) { + WalletEvents.rememberPhoneChannel(signer.phoneNumber, signer.channel) + } val wallet = result.value val signers = buildAvailableSigners(wallet) val supportedChain = SupportedChain.entries.find { it.chain == chain } @@ -315,6 +326,7 @@ class WalletViewModel( walletCache.clear() notFoundChains.clear() activeFetches.clear() + WalletEvents.clearPhoneChannels() _uiState.value = WalletUiState() } diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/AdminSignerCard.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/AdminSignerCard.kt index 3e0a972..5ea2ddc 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/AdminSignerCard.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/AdminSignerCard.kt @@ -17,10 +17,14 @@ import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextFieldDefaults +import androidx.compose.material3.SegmentedButton +import androidx.compose.material3.SegmentedButtonDefaults +import androidx.compose.material3.SingleChoiceSegmentedButtonRow import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -31,7 +35,9 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import com.crossmint.kotlin.signers.OTPDeliveryChannel +@OptIn(ExperimentalMaterial3Api::class) @Composable fun AdminSignerCard( selectedType: AdminSignerType, @@ -40,6 +46,8 @@ fun AdminSignerCard( onEmailChange: (String) -> Unit, phone: String, onPhoneChange: (String) -> Unit, + phoneChannel: OTPDeliveryChannel, + onPhoneChannelChange: (OTPDeliveryChannel) -> Unit, ) { var expanded by remember { mutableStateOf(false) } @@ -131,6 +139,28 @@ fun AdminSignerCard( ), singleLine = true, ) + + Spacer(modifier = Modifier.height(12.dp)) + + Text( + text = "OTP delivery", + fontSize = 12.sp, + ) + Spacer(modifier = Modifier.height(4.dp)) + + SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) { + OTPDeliveryChannel.entries.forEachIndexed { index, channel -> + SegmentedButton( + selected = phoneChannel == channel, + onClick = { onPhoneChannelChange(channel) }, + shape = + SegmentedButtonDefaults.itemShape( + index = index, + count = OTPDeliveryChannel.entries.size, + ), + ) { Text(channel.displayName) } + } + } } AdminSignerType.API_KEY -> { Text( diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/CreateWalletScreen.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/CreateWalletScreen.kt index 49afa6b..dd6c0df 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/CreateWalletScreen.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/CreateWalletScreen.kt @@ -36,6 +36,7 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import com.crossmint.kotlin.signers.DelegatedSigner +import com.crossmint.kotlin.signers.OTPDeliveryChannel import com.crossmint.kotlin.signers.SignerType import com.crossmint.kotlin.types.Chain import com.crossmint.kotlin.wallet.CreateWalletViewModel @@ -58,6 +59,7 @@ fun CreateWalletScreen( var selectedAdminSignerType by remember { mutableStateOf(AdminSignerType.EMAIL) } var adminEmail by remember { mutableStateOf(userEmail ?: "") } var adminPhone by remember { mutableStateOf("") } + var adminPhoneChannel by remember { mutableStateOf(OTPDeliveryChannel.SMS) } val delegatedSigners = remember { mutableStateListOf() } @@ -99,7 +101,8 @@ fun CreateWalletScreen( val adminSigner = when (selectedAdminSignerType) { AdminSignerType.EMAIL -> SignerType.Email(adminEmail) - AdminSignerType.PHONE -> SignerType.Phone(adminPhone) + AdminSignerType.PHONE -> + SignerType.Phone(adminPhone, channel = adminPhoneChannel) AdminSignerType.API_KEY -> SignerType.ApiKey } val deviceEntry = delegatedSigners.firstOrNull { it.type == DelegatedSignerType.DEVICE } @@ -182,6 +185,8 @@ fun CreateWalletScreen( onEmailChange = { adminEmail = it }, phone = adminPhone, onPhoneChange = { adminPhone = it }, + phoneChannel = adminPhoneChannel, + onPhoneChannelChange = { adminPhoneChannel = it }, ) Spacer(modifier = Modifier.height(32.dp)) diff --git a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/CreateWalletTypes.kt b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/CreateWalletTypes.kt index 4c39975..2e4af49 100644 --- a/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/CreateWalletTypes.kt +++ b/app/src/commonMain/kotlin/com/crossmint/kotlin/wallet/createwallet/CreateWalletTypes.kt @@ -7,6 +7,7 @@ import androidx.compose.material.icons.filled.Key import androidx.compose.material.icons.filled.Phone import androidx.compose.material.icons.filled.Smartphone import androidx.compose.ui.graphics.vector.ImageVector +import com.crossmint.kotlin.signers.OTPDeliveryChannel enum class AdminSignerType( val displayName: String, @@ -16,6 +17,13 @@ enum class AdminSignerType( API_KEY("API Key"), } +val OTPDeliveryChannel.displayName: String + get() = + when (this) { + OTPDeliveryChannel.SMS -> "SMS" + OTPDeliveryChannel.WHATSAPP -> "WhatsApp" + } + enum class DelegatedSignerType( val displayName: String, val icon: ImageVector, diff --git a/checkout/.gitignore b/checkout/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/checkout/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/checkout/build.gradle.kts b/checkout/build.gradle.kts new file mode 100644 index 0000000..de36285 --- /dev/null +++ b/checkout/build.gradle.kts @@ -0,0 +1,124 @@ +import java.util.Properties +import org.jetbrains.compose.resources.ResourcesExtension.ResourceClassGeneration +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + +plugins { + alias(libs.plugins.kotlinMultiplatform) + alias(libs.plugins.androidApplication) + alias(libs.plugins.buildkonfig) + alias(libs.plugins.composeMultiplatform) + alias(libs.plugins.composeCompiler) + alias(libs.plugins.kotlinSerialization) +} + +kotlin { + androidTarget { + @OptIn(ExperimentalKotlinGradlePluginApi::class) + compilerOptions { + jvmTarget.set(JvmTarget.JVM_11) + freeCompilerArgs.add("-Xexpect-actual-classes") + } + } + + sourceSets { + androidMain.dependencies { + implementation(compose.preview) + implementation(libs.androidx.activity.compose) + implementation(libs.androidx.appcompat) + implementation(libs.ktor.client.android) + implementation(libs.crossmint.identity) + } + + commonMain.dependencies { + implementation(compose.runtime) + implementation(compose.foundation) + implementation(compose.material3) + implementation(compose.ui) + implementation(compose.components.resources) + implementation(compose.components.uiToolingPreview) + implementation(compose.materialIconsExtended) + implementation(libs.androidx.lifecycle.viewmodelCompose) + implementation(libs.androidx.lifecycle.runtimeCompose) + + implementation(libs.crossmint.core) + implementation(libs.crossmint.checkout) + + implementation(libs.material3.adaptive) + implementation(libs.material3.adaptive.layout) + implementation(libs.material3.adaptive.navigation) + implementation(libs.material3.adaptive.navigation.suite) + + implementation(libs.ktor.client.core) + implementation(libs.ktor.client.content.negotiation) + implementation(libs.ktor.serialization.kotlinx.json) + implementation(libs.kotlinx.serialization.json) + + implementation(libs.navigation.compose) + } + } +} + +val localProperties = Properties() +val localPropertiesFile = rootProject.file("local.properties") +if (localPropertiesFile.exists()) { + localProperties.load(localPropertiesFile.inputStream()) +} + +android { + namespace = "com.crossmint.kotlin.checkoutdemo" + compileSdk = + libs.versions.android.compileSdk + .get() + .toInt() + + defaultConfig { + applicationId = "com.crossmint.checkoutdemo" + minSdk = + libs.versions.android.minSdk + .get() + .toInt() + targetSdk = + libs.versions.android.targetSdk + .get() + .toInt() + versionCode = 1 + versionName = "1.0" + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } + buildTypes { + getByName("release") { + isMinifyEnabled = false + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } +} + +buildkonfig { + packageName = "com.crossmint.checkoutdemo" + + defaultConfigs { + buildConfigField( + com.codingfeline.buildkonfig.compiler.FieldSpec.Type.STRING, + "CROSSMINT_API_KEY", + localProperties.getProperty("crossmint_api_key", ""), + ) + } +} + +dependencies { + debugImplementation(compose.uiTooling) +} + +compose.resources { + publicResClass = true + generateResClass = ResourceClassGeneration.Always + packageOfResClass = "com.crossmint.crossmintcheckoutdemoapp.generated.resources" +} diff --git a/checkout/src/androidMain/AndroidManifest.xml b/checkout/src/androidMain/AndroidManifest.xml new file mode 100644 index 0000000..1546d2a --- /dev/null +++ b/checkout/src/androidMain/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/MainActivity.kt b/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/MainActivity.kt new file mode 100644 index 0000000..d0a401d --- /dev/null +++ b/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/MainActivity.kt @@ -0,0 +1,18 @@ +package com.crossmint.kotlin.checkoutdemo + +import android.os.Bundle +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.appcompat.app.AppCompatActivity +import com.crossmint.checkoutdemo.BuildKonfig + +class MainActivity : AppCompatActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + enableEdgeToEdge() + super.onCreate(savedInstanceState) + + setContent { + AppRoot(apiKey = BuildKonfig.CROSSMINT_API_KEY) + } + } +} diff --git a/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/IdentityPreview.kt b/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/IdentityPreview.kt new file mode 100644 index 0000000..24a2bc9 --- /dev/null +++ b/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/IdentityPreview.kt @@ -0,0 +1,40 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.crossmint.kotlin.identity.CrossmintIdentityVerification +import com.crossmint.kotlin.identity.IdentityVerificationCredentials + +@Composable +actual fun IdentityPreview( + apiKey: String, + inquiryId: String, + sessionToken: String, + modifier: Modifier, + onEvent: (String) -> Unit, +) { + if (inquiryId.isBlank()) { + Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Text("Enter an inquiry ID to preview identity verification.") + } + return + } + + CrossmintIdentityVerification( + apiKey = apiKey, + credentials = + IdentityVerificationCredentials( + inquiryId = inquiryId, + sessionToken = sessionToken.ifBlank { null }, + ), + modifier = modifier, + onReady = { onEvent("Identity verification ready") }, + onComplete = { status -> onEvent("Identity verification completed: $status") }, + onCancel = { onEvent("Identity verification cancelled") }, + onError = { error -> onEvent("Identity verification error: ${error.message}") }, + ) +} diff --git a/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/PaneBackHandler.kt b/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/PaneBackHandler.kt new file mode 100644 index 0000000..d7bb47d --- /dev/null +++ b/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/PaneBackHandler.kt @@ -0,0 +1,13 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi +import androidx.compose.material3.adaptive.navigation.BackNavigationBehavior +import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator +import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldPredictiveBackHandler +import androidx.compose.runtime.Composable + +@OptIn(ExperimentalMaterial3AdaptiveApi::class) +@Composable +actual fun PaneBackHandler(navigator: ThreePaneScaffoldNavigator) { + ThreePaneScaffoldPredictiveBackHandler(navigator, BackNavigationBehavior.PopUntilScaffoldValueChange) +} diff --git a/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/utility/Time.kt b/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/utility/Time.kt new file mode 100644 index 0000000..efd292e --- /dev/null +++ b/checkout/src/androidMain/kotlin/com/crossmint/kotlin/checkoutdemo/utility/Time.kt @@ -0,0 +1,12 @@ +package com.crossmint.kotlin.checkoutdemo.utility + +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale + +actual fun currentTimeMillis(): Long = System.currentTimeMillis() + +actual fun formatTimestamp(timestamp: Long): String { + val formatter = SimpleDateFormat("HH:mm:ss", Locale.getDefault()) + return formatter.format(Date(timestamp)) +} diff --git a/checkout/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml b/checkout/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..8bf9ebf --- /dev/null +++ b/checkout/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/checkout/src/androidMain/res/drawable/ic_launcher_background.xml b/checkout/src/androidMain/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..05399f2 --- /dev/null +++ b/checkout/src/androidMain/res/drawable/ic_launcher_background.xml @@ -0,0 +1,10 @@ + + + + diff --git a/checkout/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml b/checkout/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/checkout/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/checkout/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml b/checkout/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..eca70cf --- /dev/null +++ b/checkout/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/checkout/src/androidMain/res/mipmap-hdpi/ic_launcher.png b/checkout/src/androidMain/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..84fa193249ef239a3e032b50915e8571edefeeb5 GIT binary patch literal 4865 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 v)dOFlZ_H=4ujqRp)6G^VI1^7Zt8(t literal 0 HcmV?d00001 diff --git a/checkout/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png b/checkout/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..217426ab86462b3d4471219281f1534db955484c GIT binary patch literal 9625 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 v)dOFlZ_H=4ujqRp)6G^VI1^7Zt8(t literal 0 HcmV?d00001 diff --git a/checkout/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png b/checkout/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..cc36b76af25cfe37c728f840fc30b1a04c6de9b7 GIT binary patch literal 13351 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�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�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 + Checkout Playground + diff --git a/checkout/src/androidMain/res/xml/network_security_config.xml b/checkout/src/androidMain/res/xml/network_security_config.xml new file mode 100644 index 0000000..1bd94b6 --- /dev/null +++ b/checkout/src/androidMain/res/xml/network_security_config.xml @@ -0,0 +1,3 @@ + + + diff --git a/checkout/src/commonMain/composeResources/drawable/crossmint_logo.png b/checkout/src/commonMain/composeResources/drawable/crossmint_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..d54fbfdb67d5a0e301cb15103be3cf17b198018c GIT binary patch literal 136690 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 Xt$0vxvea}C0ROqCp`%`@Y8Cl^($xp< literal 0 HcmV?d00001 diff --git a/checkout/src/commonMain/composeResources/drawable/ic_crossmint.xml b/checkout/src/commonMain/composeResources/drawable/ic_crossmint.xml new file mode 100644 index 0000000..4927ff5 --- /dev/null +++ b/checkout/src/commonMain/composeResources/drawable/ic_crossmint.xml @@ -0,0 +1,9 @@ + + + diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/AppRoot.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/AppRoot.kt new file mode 100644 index 0000000..51e4c3e --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/AppRoot.kt @@ -0,0 +1,22 @@ +package com.crossmint.kotlin.checkoutdemo + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import com.crossmint.kotlin.checkoutdemo.data.OrdersApi +import com.crossmint.kotlin.checkoutdemo.data.createHttpClient +import com.crossmint.kotlin.checkoutdemo.ui.CheckoutDemoApp +import com.crossmint.kotlin.checkoutdemo.ui.CheckoutDemoTheme + +@Composable +fun AppRoot(apiKey: String) { + CheckoutDemoTheme { + val viewModel = + remember { + PlaygroundViewModel( + ordersApi = OrdersApi(createHttpClient()), + apiKey = apiKey, + ) + } + CheckoutDemoApp(viewModel = viewModel, apiKey = apiKey) + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/PlaygroundUiState.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/PlaygroundUiState.kt new file mode 100644 index 0000000..d621647 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/PlaygroundUiState.kt @@ -0,0 +1,29 @@ +package com.crossmint.kotlin.checkoutdemo + +import com.crossmint.kotlin.checkoutdemo.model.DemoEvent +import com.crossmint.kotlin.checkoutdemo.model.OrderDraft +import com.crossmint.kotlin.checkoutdemo.model.OrderSession +import com.crossmint.kotlin.checkoutdemo.model.PlaygroundOptions +import com.crossmint.kotlin.checkoutdemo.model.PlaygroundSection + +data class PlaygroundUiState( + val section: PlaygroundSection = PlaygroundSection.ORDER, + val draft: OrderDraft = OrderDraft(), + val options: PlaygroundOptions = PlaygroundOptions(), + val existingOrderId: String = "", + val existingClientSecret: String = "", + val identityInquiryId: String = "", + val identitySessionToken: String = "", + val confirmedIdentityInquiryId: String = "", + val confirmedIdentitySessionToken: String = "", + val session: OrderSession? = null, + val isCreatingOrder: Boolean = false, + val orderErrorMessage: String? = null, + val events: List = emptyList(), +) { + val isPreviewingCheckout: Boolean + get() = session != null + + val isPreviewingIdentity: Boolean + get() = confirmedIdentityInquiryId.isNotBlank() +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/PlaygroundViewModel.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/PlaygroundViewModel.kt new file mode 100644 index 0000000..acec59e --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/PlaygroundViewModel.kt @@ -0,0 +1,113 @@ +package com.crossmint.kotlin.checkoutdemo + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.crossmint.kotlin.checkoutdemo.data.OrdersApi +import com.crossmint.kotlin.checkoutdemo.model.DemoEvent +import com.crossmint.kotlin.checkoutdemo.model.OrderDraft +import com.crossmint.kotlin.checkoutdemo.model.OrderSession +import com.crossmint.kotlin.checkoutdemo.model.PlaygroundOptions +import com.crossmint.kotlin.checkoutdemo.model.PlaygroundSection +import com.crossmint.kotlin.checkoutdemo.utility.currentTimeMillis +import com.crossmint.kotlin.types.Result +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.launch + +class PlaygroundViewModel( + private val ordersApi: OrdersApi, + private val apiKey: String, +) : ViewModel() { + private val _uiState = MutableStateFlow(PlaygroundUiState()) + val uiState: StateFlow = _uiState.asStateFlow() + + fun selectSection(section: PlaygroundSection) { + _uiState.value = _uiState.value.copy(section = section) + } + + fun updateDraft(draft: OrderDraft) { + _uiState.value = _uiState.value.copy(draft = draft) + } + + fun updateOptions(options: PlaygroundOptions) { + _uiState.value = _uiState.value.copy(options = options) + } + + fun updateExistingOrder( + orderId: String, + clientSecret: String, + ) { + _uiState.value = _uiState.value.copy(existingOrderId = orderId, existingClientSecret = clientSecret) + } + + fun updateIdentityCredentials( + inquiryId: String, + sessionToken: String, + ) { + _uiState.value = _uiState.value.copy(identityInquiryId = inquiryId, identitySessionToken = sessionToken) + } + + fun startIdentityPreview() { + val state = _uiState.value + _uiState.value = + state.copy( + confirmedIdentityInquiryId = state.identityInquiryId, + confirmedIdentitySessionToken = state.identitySessionToken, + ) + } + + fun useExistingOrder() { + val state = _uiState.value + val orderId = state.existingOrderId.trim() + val clientSecret = state.existingClientSecret.trim() + if (orderId.isEmpty() || clientSecret.isEmpty()) return + + setSession( + OrderSession(orderId = orderId, clientSecret = clientSecret, source = OrderSession.Source.EXISTING), + "Using existing order $orderId", + ) + } + + fun createOrder() { + val draft = _uiState.value.draft + _uiState.value = _uiState.value.copy(isCreatingOrder = true, orderErrorMessage = null) + + viewModelScope.launch { + when (val result = ordersApi.createOrder(apiKey, draft)) { + is Result.Success -> { + _uiState.value = _uiState.value.copy(isCreatingOrder = false) + setSession(result.value, "Order ${result.value.orderId} created") + } + + is Result.Failure -> { + _uiState.value = + _uiState.value.copy( + isCreatingOrder = false, + orderErrorMessage = result.error.message, + ) + logEvent("Order creation failed: ${result.error.message}") + } + } + } + } + + fun clearSession() { + _uiState.value = _uiState.value.copy(session = null) + } + + fun logExternalEvent(message: String) = logEvent(message) + + private fun setSession( + session: OrderSession, + eventMessage: String, + ) { + _uiState.value = _uiState.value.copy(session = session) + logEvent(eventMessage) + } + + private fun logEvent(message: String) { + val event = DemoEvent(timestamp = currentTimeMillis(), message = message) + _uiState.value = _uiState.value.copy(events = _uiState.value.events + event) + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/HttpClientFactory.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/HttpClientFactory.kt new file mode 100644 index 0000000..ac0c3c9 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/HttpClientFactory.kt @@ -0,0 +1,21 @@ +package com.crossmint.kotlin.checkoutdemo.data + +import io.ktor.client.HttpClient +import io.ktor.client.plugins.contentnegotiation.ContentNegotiation +import io.ktor.serialization.kotlinx.json.json +import kotlinx.serialization.json.Json + +val checkoutDemoJson = + Json { + ignoreUnknownKeys = true + isLenient = true + encodeDefaults = true + explicitNulls = false + } + +fun createHttpClient(): HttpClient = + HttpClient { + install(ContentNegotiation) { + json(checkoutDemoJson) + } + } diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/OrderApiError.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/OrderApiError.kt new file mode 100644 index 0000000..93c6a50 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/OrderApiError.kt @@ -0,0 +1,19 @@ +package com.crossmint.kotlin.checkoutdemo.data + +sealed interface OrderApiError { + val message: String + + data class Network( + val cause: Throwable, + ) : OrderApiError { + override val message: String = cause.message ?: "The Orders API request failed." + } + + data class Api( + override val message: String, + ) : OrderApiError + + data class UnexpectedResponse( + override val message: String = "The Orders API returned a response the demo could not read.", + ) : OrderApiError +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/OrdersApi.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/OrdersApi.kt new file mode 100644 index 0000000..7ed42c8 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/data/OrdersApi.kt @@ -0,0 +1,139 @@ +package com.crossmint.kotlin.checkoutdemo.data + +import com.crossmint.kotlin.checkout.CheckoutEnvironment +import com.crossmint.kotlin.checkoutdemo.model.OrderDraft +import com.crossmint.kotlin.checkoutdemo.model.OrderSession +import com.crossmint.kotlin.core.ApiKey +import com.crossmint.kotlin.core.Environment +import com.crossmint.kotlin.types.Result +import io.ktor.client.HttpClient +import io.ktor.client.request.header +import io.ktor.client.request.post +import io.ktor.client.request.setBody +import io.ktor.client.statement.bodyAsText +import io.ktor.http.ContentType +import io.ktor.http.contentType +import kotlin.coroutines.cancellation.CancellationException +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.SerializationException +import kotlinx.serialization.json.Json + +class OrdersApi( + private val httpClient: HttpClient, + private val json: Json = checkoutDemoJson, +) { + suspend fun createOrder( + apiKey: String, + draft: OrderDraft, + ): Result { + val parsedKey = + try { + ApiKey.fromString(apiKey) + } catch (e: Exception) { + return Result.Failure(OrderApiError.Api(e.message ?: "Invalid API key.")) + } + + val requestBody = + CreateOrderRequest( + payment = + OrderPayment( + receiptEmail = draft.receiptEmail.trim().ifEmpty { null }, + ), + lineItems = + OrderLineItems( + tokenLocator = draft.tokenLocator.trim(), + executionParameters = OrderExecutionParameters(amount = draft.amount.trim()), + ), + recipient = OrderRecipient(walletAddress = draft.recipientWalletAddress.trim()), + ) + + return try { + val response = + httpClient.post("https://${parsedKey.host}/api/2022-06-09/orders") { + header("X-API-KEY", apiKey) + contentType(ContentType.Application.Json) + setBody(requestBody) + } + val raw = response.bodyAsText() + val parsed = json.decodeFromString(CreateOrderResponse.serializer(), raw) + + val orderId = parsed.order?.orderId + val clientSecret = parsed.clientSecret + if (orderId != null && clientSecret != null) { + Result.Success( + OrderSession( + orderId = orderId, + clientSecret = clientSecret, + source = OrderSession.Source.CREATED_IN_APP, + ), + ) + } else if (parsed.error == true) { + Result.Failure(OrderApiError.Api(parsed.message ?: "The Orders API rejected the request.")) + } else { + Result.Failure(OrderApiError.UnexpectedResponse()) + } + } catch (e: CancellationException) { + throw e + } catch (e: SerializationException) { + Result.Failure(OrderApiError.UnexpectedResponse()) + } catch (e: Exception) { + Result.Failure(OrderApiError.Network(e)) + } + } +} + +internal val ApiKey.host: String + get() = "${apiEnvironmentPathComponent}crossmint.com" + +internal val ApiKey.checkoutEnvironment: CheckoutEnvironment + get() = + when (environment) { + Environment.PRODUCTION -> CheckoutEnvironment.PRODUCTION + Environment.STAGING, Environment.DEVELOPMENT -> CheckoutEnvironment.STAGING + } + +@Serializable +private data class CreateOrderRequest( + val payment: OrderPayment, + val lineItems: OrderLineItems, + val recipient: OrderRecipient, +) + +@Serializable +private data class OrderPayment( + val method: String = "card", + val currency: String = "usd", + val receiptEmail: String? = null, +) + +@Serializable +private data class OrderLineItems( + val tokenLocator: String, + val executionParameters: OrderExecutionParameters, +) + +@Serializable +private data class OrderExecutionParameters( + val mode: String = "exact-in", + val amount: String, +) + +@Serializable +private data class OrderRecipient( + val walletAddress: String, +) + +@Serializable +private data class CreateOrderResponse( + val error: Boolean? = null, + val message: String? = null, + val clientSecret: String? = null, + val order: CreateOrderResponseOrder? = null, +) + +@Serializable +private data class CreateOrderResponseOrder( + @SerialName("orderId") + val orderId: String? = null, +) diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/DemoEvent.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/DemoEvent.kt new file mode 100644 index 0000000..4fba725 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/DemoEvent.kt @@ -0,0 +1,6 @@ +package com.crossmint.kotlin.checkoutdemo.model + +data class DemoEvent( + val timestamp: Long, + val message: String, +) diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/OrderDraft.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/OrderDraft.kt new file mode 100644 index 0000000..5ba6158 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/OrderDraft.kt @@ -0,0 +1,8 @@ +package com.crossmint.kotlin.checkoutdemo.model + +data class OrderDraft( + val tokenLocator: String = "", + val amount: String = "1", + val recipientWalletAddress: String = "", + val receiptEmail: String = "", +) diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/OrderSession.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/OrderSession.kt new file mode 100644 index 0000000..22d0a89 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/OrderSession.kt @@ -0,0 +1,12 @@ +package com.crossmint.kotlin.checkoutdemo.model + +data class OrderSession( + val orderId: String, + val clientSecret: String, + val source: Source, +) { + enum class Source { + CREATED_IN_APP, + EXISTING, + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/PlaygroundOptions.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/PlaygroundOptions.kt new file mode 100644 index 0000000..d93135f --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/PlaygroundOptions.kt @@ -0,0 +1,136 @@ +package com.crossmint.kotlin.checkoutdemo.model + +import com.crossmint.kotlin.checkout.IdentityVerificationHandling +import com.crossmint.kotlin.checkout.models.CheckoutAllowedMethods +import com.crossmint.kotlin.checkout.models.CheckoutAppearance +import com.crossmint.kotlin.checkout.models.CheckoutAppearanceRules +import com.crossmint.kotlin.checkout.models.CheckoutAppearanceVariables +import com.crossmint.kotlin.checkout.models.CheckoutCryptoPayment +import com.crossmint.kotlin.checkout.models.CheckoutDestinationInputRule +import com.crossmint.kotlin.checkout.models.CheckoutFiatPayment +import com.crossmint.kotlin.checkout.models.CheckoutGlobalMessageRule +import com.crossmint.kotlin.checkout.models.CheckoutInputRule +import com.crossmint.kotlin.checkout.models.CheckoutPayment +import com.crossmint.kotlin.checkout.models.CheckoutPrimaryButtonRule +import com.crossmint.kotlin.checkout.models.CheckoutReceiptEmailInputRule +import com.crossmint.kotlin.checkout.models.CheckoutTabRule +import com.crossmint.kotlin.checkout.models.CheckoutVariablesColorStyle + +data class PlaygroundOptions( + val cryptoEnabled: Boolean = false, + val fiatEnabled: Boolean = true, + val allowCard: Boolean = true, + val allowGooglePay: Boolean = true, + val showsDestinationInput: Boolean = true, + val showsReceiptEmailInput: Boolean = true, + val showsStatusMessage: Boolean = true, + val textColor: String = "", + val backgroundColor: String = "", + val accentColor: String = "", + val dangerColor: String = "", + val inputRadius: Float = DEFAULT_BORDER_RADIUS, + val tabRadius: Float = DEFAULT_BORDER_RADIUS, + val buttonRadius: Float = DEFAULT_BORDER_RADIUS, + val externalIdentityVerification: Boolean = true, +) { + fun toCheckoutPayment(receiptEmail: String): CheckoutPayment = + CheckoutPayment( + crypto = CheckoutCryptoPayment(enabled = cryptoEnabled), + fiat = + CheckoutFiatPayment( + enabled = fiatEnabled, + allowedMethods = + CheckoutAllowedMethods( + googlePay = allowGooglePay, + applePay = false, + card = allowCard, + ), + ), + receiptEmail = receiptEmail.ifBlank { null }, + ) + + fun toCheckoutAppearance(): CheckoutAppearance? { + val colors = + if (textColor.isBlank() && backgroundColor.isBlank() && accentColor.isBlank() && dangerColor.isBlank()) { + null + } else { + CheckoutVariablesColorStyle( + textPrimary = textColor.ifBlank { null }, + backgroundPrimary = backgroundColor.ifBlank { null }, + accent = accentColor.ifBlank { null }, + danger = dangerColor.ifBlank { null }, + ) + } + + val variables = if (colors == null) null else CheckoutAppearanceVariables(colors = colors) + + val hidesElement = !showsDestinationInput || !showsReceiptEmailInput || !showsStatusMessage + val hasCustomInputRadius = inputRadius != DEFAULT_BORDER_RADIUS + val hasCustomTabRadius = tabRadius != DEFAULT_BORDER_RADIUS + val hasCustomButtonRadius = buttonRadius != DEFAULT_BORDER_RADIUS + + val rules = + if (hidesElement || hasCustomInputRadius || hasCustomTabRadius || hasCustomButtonRadius) { + CheckoutAppearanceRules( + destinationInput = + if (showsDestinationInput) { + null + } else { + CheckoutDestinationInputRule( + display = "hidden", + ) + }, + receiptEmailInput = + if (showsReceiptEmailInput) { + null + } else { + CheckoutReceiptEmailInputRule( + display = "hidden", + ) + }, + globalMessage = + if (showsStatusMessage) { + null + } else { + CheckoutGlobalMessageRule( + display = "hidden", + ) + }, + input = + if (hasCustomInputRadius) { + CheckoutInputRule( + borderRadius = "${inputRadius.toInt()}px", + ) + } else { + null + }, + tab = + if (hasCustomTabRadius) { + CheckoutTabRule( + borderRadius = "${tabRadius.toInt()}px", + ) + } else { + null + }, + primaryButton = + if (hasCustomButtonRadius) { + CheckoutPrimaryButtonRule(borderRadius = "${buttonRadius.toInt()}px") + } else { + null + }, + ) + } else { + null + } + + if (variables == null && rules == null) return null + return CheckoutAppearance(rules = rules, variables = variables) + } + + fun toIdentityVerificationHandling(): IdentityVerificationHandling? = + if (externalIdentityVerification) IdentityVerificationHandling.EXTERNAL else null + + companion object { + const val DEFAULT_BORDER_RADIUS = 8f + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/PlaygroundSection.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/PlaygroundSection.kt new file mode 100644 index 0000000..b7c78ce --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/PlaygroundSection.kt @@ -0,0 +1,21 @@ +package com.crossmint.kotlin.checkoutdemo.model + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.CreditCard +import androidx.compose.material.icons.filled.Palette +import androidx.compose.material.icons.filled.Person +import androidx.compose.material.icons.filled.ShoppingBag +import androidx.compose.material.icons.filled.TextFields +import androidx.compose.ui.graphics.vector.ImageVector + +enum class PlaygroundSection( + val title: String, + val navLabel: String, + val icon: ImageVector, +) { + ORDER("Order", "Order", Icons.Filled.ShoppingBag), + PAYMENT("Payment", "Payment", Icons.Filled.CreditCard), + APPEARANCE("Appearance", "Appearance", Icons.Filled.Palette), + FIELDS("Fields", "Fields", Icons.Filled.TextFields), + IDENTITY("Identity verification", "Identity", Icons.Filled.Person), +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/TokenPreset.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/TokenPreset.kt new file mode 100644 index 0000000..0dfe30c --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/model/TokenPreset.kt @@ -0,0 +1,105 @@ +package com.crossmint.kotlin.checkoutdemo.model + +import com.crossmint.kotlin.core.Environment + +data class TokenNetwork( + val chain: String, + val network: String, + val locator: String, +) { + val title: String get() = "$chain ($network)" +} + +data class TokenPreset( + val symbol: String, + val networks: List, +) { + companion object { + private val stagingPresets = + listOf( + TokenPreset( + symbol = "USDC", + networks = + listOf( + TokenNetwork("Solana", "Devnet", "solana:4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU"), + TokenNetwork("Base", "Sepolia", "base-sepolia:0x036CbD53842c5426634e7929541eC2318f3dCF7e"), + TokenNetwork( + "Stellar", + "Testnet", + "stellar:CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA", + ), + TokenNetwork("Polygon", "Amoy", "polygon-amoy:0x41E94Eb019C0762f9Bfcf9Fb1E58725BfB0e7582"), + ), + ), + TokenPreset( + symbol = "EURC", + networks = + listOf( + TokenNetwork("Solana", "Devnet", "solana:HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr"), + TokenNetwork("Base", "Sepolia", "base-sepolia:0x808456652fdb597867f38412077A9182bf77359F"), + TokenNetwork( + "Stellar", + "Testnet", + "stellar:CCUUDM434BMZMYWYDITHFXHDMIVTGGD6T2I5UKNX5BSLXLW7HVR4MCGZ", + ), + ), + ), + TokenPreset( + symbol = "Wirex USDC", + networks = + listOf( + TokenNetwork( + "WirexStellar", + "Stellar Testnet", + "stellar:CAUGJT4GREIY3WHOUUU5RIUDGSPVREF5CDCYJOWMHOVT2GWQT5JEETGJ", + ), + ), + ), + ) + + private val productionPresets = + listOf( + TokenPreset( + symbol = "USDC", + networks = + listOf( + TokenNetwork("Solana", "Mainnet", "solana:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"), + TokenNetwork("Base", "Mainnet", "base:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"), + TokenNetwork( + "Stellar", + "Mainnet", + "stellar:CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75", + ), + TokenNetwork("Polygon", "Mainnet", "polygon:0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359"), + ), + ), + TokenPreset( + symbol = "EURC", + networks = + listOf( + TokenNetwork("Solana", "Mainnet", "solana:HzwqbKZw8HxMN6bF2yFZNrht3c2iXXzpKcFu7uBEDKtr"), + TokenNetwork("Base", "Mainnet", "base:0x60a3E35Cc302bFA44Cb288Bc5a4F316Fdb1adb42"), + TokenNetwork( + "Stellar", + "Mainnet", + "stellar:CDTKPWPLOURQA2SGTKTUQOWRCBZEORB4BWBOMJ3D3ZTQQSGE5F6JBQLV", + ), + ), + ), + ) + + fun presets(environment: Environment): List = + if (environment == Environment.PRODUCTION) productionPresets else stagingPresets + + fun findByLocator( + environment: Environment, + locator: String, + ): Pair? { + for (preset in presets(environment)) { + val network = preset.networks.find { it.locator == locator } + if (network != null) return preset to network + } + return null + } + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/AboutSheet.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/AboutSheet.kt new file mode 100644 index 0000000..13a462d --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/AboutSheet.kt @@ -0,0 +1,75 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.OpenInNew +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.ListItem +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalUriHandler +import androidx.compose.ui.unit.dp +import com.crossmint.kotlin.core.ApiKey +import com.crossmint.kotlin.core.Environment + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun AboutSheet( + apiKey: String, + onDismissRequest: () -> Unit, +) { + val environment = runCatching { ApiKey.fromString(apiKey).environment }.getOrNull() + val uriHandler = LocalUriHandler.current + + ModalBottomSheet(onDismissRequest = onDismissRequest) { + Column(modifier = Modifier.padding(bottom = 16.dp)) { + Column(modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)) { + Text( + "Environment", + style = MaterialTheme.typography.labelMedium, + color = MaterialTheme.colorScheme.primary, + ) + Text( + environment?.value?.replaceFirstChar { it.uppercase() } ?: "Unknown", + style = MaterialTheme.typography.titleMedium, + ) + Text( + text = environmentNote(environment), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.padding(top = 4.dp, bottom = 16.dp), + ) + } + + HorizontalDivider() + + ListItem( + headlineContent = { Text("Documentation") }, + trailingContent = { Icon(Icons.AutoMirrored.Filled.OpenInNew, contentDescription = null) }, + modifier = Modifier.clickable { uriHandler.openUri("https://docs.crossmint.com") }, + ) + ListItem( + headlineContent = { Text("Crossmint Console") }, + trailingContent = { Icon(Icons.AutoMirrored.Filled.OpenInNew, contentDescription = null) }, + modifier = Modifier.clickable { uriHandler.openUri("https://console.crossmint.com") }, + ) + } + } +} + +private fun environmentNote(environment: Environment?): String = + when (environment) { + Environment.STAGING, Environment.DEVELOPMENT -> + "This build points at ${environment.value}. Orders use testnet tokens, so a checkout here cannot move real funds." + Environment.PRODUCTION -> "This build points at production. A checkout here moves real funds." + null -> + "The demo cannot tell which environment this key belongs to. Use a key that starts with ck_staging_ or ck_production_." + } diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/AppTheme.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/AppTheme.kt new file mode 100644 index 0000000..62544b3 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/AppTheme.kt @@ -0,0 +1,61 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.ui.graphics.Color + +private val CrossmintGreen = Color(0xFF00E6AC) + +private val LightColors = + lightColorScheme( + primary = Color(0xFF00997A), + onPrimary = Color.White, + primaryContainer = Color(0xFFB6FFEA), + onPrimaryContainer = Color(0xFF00201A), + secondary = Color(0xFF00997A), + onSecondary = Color.White, + secondaryContainer = Color(0xFFB6FFEA), + onSecondaryContainer = Color(0xFF00201A), + background = Color.White, + surface = Color.White, + surfaceVariant = Color(0xFFF5F5F5), + onSurface = Color(0xFF1C1C1E), + onSurfaceVariant = Color(0xFF6C6C70), + outlineVariant = Color(0xFFE5E5EA), + ) + +private val DarkColors = + darkColorScheme( + primary = CrossmintGreen, + onPrimary = Color(0xFF00382B), + primaryContainer = Color(0xFF00513E), + onPrimaryContainer = Color(0xFFB6FFEA), + secondary = CrossmintGreen, + onSecondary = Color(0xFF00382B), + secondaryContainer = Color(0xFF00513E), + onSecondaryContainer = Color(0xFFB6FFEA), + background = Color.Black, + surface = Color(0xFF1C1C1E), + surfaceVariant = Color(0xFF2C2C2E), + onSurface = Color(0xFFF2F2F7), + onSurfaceVariant = Color(0xFF8E8E93), + outlineVariant = Color(0xFF38383A), + ) + +@Composable +fun CheckoutDemoTheme(content: @Composable () -> Unit) { + MaterialTheme( + colorScheme = if (isSystemInDarkTheme()) DarkColors else LightColors, + content = content, + ) +} + +val ColorScheme.brandMark: Color + @Composable + @ReadOnlyComposable + get() = CrossmintGreen diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CheckoutDemoApp.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CheckoutDemoApp.kt new file mode 100644 index 0000000..fad85c0 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CheckoutDemoApp.kt @@ -0,0 +1,318 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.filled.List +import androidx.compose.material.icons.filled.Info +import androidx.compose.material3.BottomSheetScaffold +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi +import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo +import androidx.compose.material3.adaptive.layout.AnimatedPane +import androidx.compose.material3.adaptive.layout.SupportingPaneScaffold +import androidx.compose.material3.adaptive.layout.calculatePaneScaffoldDirective +import androidx.compose.material3.adaptive.navigation.rememberSupportingPaneScaffoldNavigator +import androidx.compose.material3.adaptive.navigationsuite.ExperimentalMaterial3AdaptiveNavigationSuiteApi +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold +import androidx.compose.material3.rememberBottomSheetScaffoldState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.crossmint.crossmintcheckoutdemoapp.generated.resources.Res +import com.crossmint.crossmintcheckoutdemoapp.generated.resources.ic_crossmint +import com.crossmint.kotlin.checkoutdemo.PlaygroundUiState +import com.crossmint.kotlin.checkoutdemo.PlaygroundViewModel +import com.crossmint.kotlin.checkoutdemo.model.PlaygroundSection +import com.crossmint.kotlin.checkoutdemo.ui.sections.AppearanceSectionView +import com.crossmint.kotlin.checkoutdemo.ui.sections.EventsSectionView +import com.crossmint.kotlin.checkoutdemo.ui.sections.FieldsSectionView +import com.crossmint.kotlin.checkoutdemo.ui.sections.IdentitySectionView +import com.crossmint.kotlin.checkoutdemo.ui.sections.OrderSectionView +import com.crossmint.kotlin.checkoutdemo.ui.sections.PaymentSectionView +import kotlinx.coroutines.launch +import org.jetbrains.compose.resources.painterResource + +@OptIn(ExperimentalMaterial3AdaptiveApi::class, ExperimentalMaterial3Api::class) +@Composable +fun CheckoutDemoApp( + viewModel: PlaygroundViewModel, + apiKey: String, +) { + val uiState by viewModel.uiState.collectAsState() + var showAbout by remember { mutableStateOf(false) } + var showEvents by remember { mutableStateOf(false) } + + val directive = calculatePaneScaffoldDirective(currentWindowAdaptiveInfo()) + if (directive.maxHorizontalPartitions >= 2) { + WideScaffold( + uiState = uiState, + viewModel = viewModel, + apiKey = apiKey, + onShowAbout = { showAbout = true }, + onShowEvents = { showEvents = true }, + ) + } else { + CompactScaffold( + uiState = uiState, + viewModel = viewModel, + apiKey = apiKey, + onShowAbout = { showAbout = true }, + onShowEvents = { showEvents = true }, + ) + } + + if (showAbout) { + AboutSheet(apiKey = apiKey, onDismissRequest = { showAbout = false }) + } + + if (showEvents) { + ModalBottomSheet(onDismissRequest = { showEvents = false }) { + EventsSectionView(events = uiState.events, modifier = Modifier.fillMaxWidth().heightIn(max = 480.dp)) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun PlaygroundTopBar( + apiKey: String, + onShowAbout: () -> Unit, + onShowEvents: () -> Unit, +) { + TopAppBar( + title = { + Row(verticalAlignment = Alignment.CenterVertically) { + Icon( + painter = painterResource(Res.drawable.ic_crossmint), + contentDescription = null, + tint = MaterialTheme.colorScheme.brandMark, + modifier = Modifier.size(24.dp), + ) + Text("Playground", modifier = Modifier.padding(start = 12.dp)) + } + }, + navigationIcon = { + IconButton(onClick = onShowAbout) { + Icon(Icons.Filled.Info, contentDescription = "About") + } + }, + actions = { + IconButton(onClick = onShowEvents) { + Icon(Icons.AutoMirrored.Filled.List, contentDescription = "Events") + } + EnvironmentBadge(apiKey) + }, + ) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun CompactScaffold( + uiState: PlaygroundUiState, + viewModel: PlaygroundViewModel, + apiKey: String, + onShowAbout: () -> Unit, + onShowEvents: () -> Unit, +) { + Scaffold( + topBar = { PlaygroundTopBar(apiKey = apiKey, onShowAbout = onShowAbout, onShowEvents = onShowEvents) }, + bottomBar = { + NavigationBar { + PlaygroundSection.entries.forEach { section -> + NavigationBarItem( + selected = uiState.section == section, + onClick = { viewModel.selectSection(section) }, + icon = { Icon(section.icon, contentDescription = null) }, + label = { Text(section.navLabel) }, + ) + } + } + }, + ) { padding -> + val isPreviewRunning = uiState.isPreviewingCheckout || uiState.isPreviewingIdentity + + if (isPreviewRunning) { + val scaffoldState = rememberBottomSheetScaffoldState() + val scope = rememberCoroutineScope() + + BottomSheetScaffold( + modifier = Modifier.padding(padding).fillMaxSize(), + scaffoldState = scaffoldState, + sheetPeekHeight = 112.dp, + sheetContent = { + PreviewSheetContent( + section = uiState.section, + uiState = uiState, + apiKey = apiKey, + onEvent = viewModel::logExternalEvent, + ) + }, + ) { sheetPadding -> + SectionConfigPane( + section = uiState.section, + uiState = uiState, + viewModel = viewModel, + apiKey = apiKey, + onOpenPreview = { scope.launch { scaffoldState.bottomSheetState.expand() } }, + modifier = Modifier.padding(sheetPadding).fillMaxSize(), + ) + } + } else { + SectionConfigPane( + section = uiState.section, + uiState = uiState, + viewModel = viewModel, + apiKey = apiKey, + onOpenPreview = {}, + modifier = Modifier.padding(padding).fillMaxSize(), + ) + } + } +} + +@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3AdaptiveNavigationSuiteApi::class) +@Composable +private fun WideScaffold( + uiState: PlaygroundUiState, + viewModel: PlaygroundViewModel, + apiKey: String, + onShowAbout: () -> Unit, + onShowEvents: () -> Unit, +) { + Scaffold( + topBar = { PlaygroundTopBar(apiKey = apiKey, onShowAbout = onShowAbout, onShowEvents = onShowEvents) }, + ) { padding -> + NavigationSuiteScaffold( + modifier = Modifier.padding(padding).fillMaxSize(), + navigationSuiteItems = { + PlaygroundSection.entries.forEach { section -> + item( + selected = uiState.section == section, + onClick = { viewModel.selectSection(section) }, + icon = { Icon(section.icon, contentDescription = null) }, + label = { Text(section.navLabel) }, + ) + } + }, + ) { + WidePlaygroundPanes(uiState = uiState, viewModel = viewModel, apiKey = apiKey) + } + } +} + +@OptIn(ExperimentalMaterial3AdaptiveApi::class) +@Composable +private fun WidePlaygroundPanes( + uiState: PlaygroundUiState, + viewModel: PlaygroundViewModel, + apiKey: String, +) { + val navigator = rememberSupportingPaneScaffoldNavigator() + + PaneBackHandler(navigator) + + SupportingPaneScaffold( + directive = navigator.scaffoldDirective, + value = navigator.scaffoldValue, + mainPane = { + AnimatedPane { + SectionConfigPane( + section = uiState.section, + uiState = uiState, + viewModel = viewModel, + apiKey = apiKey, + onOpenPreview = {}, + modifier = Modifier.fillMaxSize(), + ) + } + }, + supportingPane = { + AnimatedPane { + CheckoutPreviewHost( + section = uiState.section, + uiState = uiState, + apiKey = apiKey, + onEvent = viewModel::logExternalEvent, + modifier = Modifier.fillMaxSize(), + ) + } + }, + ) +} + +@Composable +private fun SectionConfigPane( + section: PlaygroundSection, + uiState: PlaygroundUiState, + viewModel: PlaygroundViewModel, + apiKey: String, + onOpenPreview: () -> Unit, + modifier: Modifier = Modifier, +) { + when (section) { + PlaygroundSection.ORDER -> + OrderSectionView( + uiState = uiState, + apiKey = apiKey, + onDraftChange = viewModel::updateDraft, + onCreateOrder = viewModel::createOrder, + onExistingOrderChange = viewModel::updateExistingOrder, + onUseExistingOrder = viewModel::useExistingOrder, + onOpenPreview = onOpenPreview, + modifier = modifier, + ) + + PlaygroundSection.PAYMENT -> + PaymentSectionView( + options = uiState.options, + onOptionsChange = viewModel::updateOptions, + modifier = modifier, + ) + + PlaygroundSection.APPEARANCE -> + AppearanceSectionView( + options = uiState.options, + onOptionsChange = viewModel::updateOptions, + modifier = modifier, + ) + + PlaygroundSection.FIELDS -> + FieldsSectionView( + options = uiState.options, + onOptionsChange = viewModel::updateOptions, + modifier = modifier, + ) + + PlaygroundSection.IDENTITY -> + IdentitySectionView( + uiState = uiState, + onCredentialsChange = viewModel::updateIdentityCredentials, + onOpenPreview = { + viewModel.startIdentityPreview() + onOpenPreview() + }, + modifier = modifier, + ) + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CheckoutPreviewHost.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CheckoutPreviewHost.kt new file mode 100644 index 0000000..ea7eead --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CheckoutPreviewHost.kt @@ -0,0 +1,215 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Info +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.ListItem +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.crossmint.crossmintcheckoutdemoapp.generated.resources.Res +import com.crossmint.crossmintcheckoutdemoapp.generated.resources.ic_crossmint +import com.crossmint.kotlin.checkout.CheckoutEnvironment +import com.crossmint.kotlin.checkout.CrossmintEmbeddedCheckout +import com.crossmint.kotlin.checkoutdemo.PlaygroundUiState +import com.crossmint.kotlin.checkoutdemo.data.checkoutEnvironment +import com.crossmint.kotlin.checkoutdemo.model.OrderSession +import com.crossmint.kotlin.checkoutdemo.model.PlaygroundSection +import com.crossmint.kotlin.checkoutdemo.utility.formatTimestamp +import com.crossmint.kotlin.core.ApiKey +import org.jetbrains.compose.resources.painterResource + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun CheckoutPreviewHost( + section: PlaygroundSection, + uiState: PlaygroundUiState, + apiKey: String, + onEvent: (String) -> Unit, + modifier: Modifier = Modifier, +) { + var showDetails by remember { mutableStateOf(false) } + val session = uiState.session + + Scaffold( + modifier = modifier, + topBar = { + TopAppBar( + title = { Text("Preview") }, + actions = { + if (section != PlaygroundSection.IDENTITY && session != null) { + IconButton(onClick = { showDetails = true }) { + Icon(Icons.Filled.Info, contentDescription = "Order details") + } + } + }, + ) + }, + ) { padding -> + PreviewBody( + section = section, + uiState = uiState, + apiKey = apiKey, + onEvent = onEvent, + modifier = Modifier.padding(padding).fillMaxSize(), + ) + } + + if (showDetails && session != null) { + OrderDetailsSheet(uiState = uiState, session = session, onDismissRequest = { showDetails = false }) + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun PreviewSheetContent( + section: PlaygroundSection, + uiState: PlaygroundUiState, + apiKey: String, + onEvent: (String) -> Unit, + modifier: Modifier = Modifier, +) { + var showDetails by remember { mutableStateOf(false) } + val session = uiState.session + + Column(modifier = modifier.fillMaxWidth()) { + Row( + modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Text("Preview", style = MaterialTheme.typography.titleMedium, modifier = Modifier.weight(1f)) + if (section != PlaygroundSection.IDENTITY && session != null) { + IconButton(onClick = { showDetails = true }) { + Icon(Icons.Filled.Info, contentDescription = "Order details") + } + } + } + HorizontalDivider() + PreviewBody( + section = section, + uiState = uiState, + apiKey = apiKey, + onEvent = onEvent, + modifier = Modifier.fillMaxWidth().height(640.dp), + ) + } + + if (showDetails && session != null) { + OrderDetailsSheet(uiState = uiState, session = session, onDismissRequest = { showDetails = false }) + } +} + +@Composable +private fun PreviewBody( + section: PlaygroundSection, + uiState: PlaygroundUiState, + apiKey: String, + onEvent: (String) -> Unit, + modifier: Modifier = Modifier, +) { + val session = uiState.session + + Box(modifier = modifier) { + when { + section == PlaygroundSection.IDENTITY && uiState.isPreviewingIdentity -> + IdentityPreview( + apiKey = apiKey, + inquiryId = uiState.confirmedIdentityInquiryId, + sessionToken = uiState.confirmedIdentitySessionToken, + modifier = Modifier.fillMaxSize(), + onEvent = onEvent, + ) + + section == PlaygroundSection.IDENTITY || session == null -> + EmptyPreviewState(modifier = Modifier.fillMaxSize()) + + else -> { + val environment = + runCatching { ApiKey.fromString(apiKey).checkoutEnvironment } + .getOrDefault(CheckoutEnvironment.STAGING) + + CrossmintEmbeddedCheckout( + orderId = session.orderId, + clientSecret = session.clientSecret, + payment = uiState.options.toCheckoutPayment(uiState.draft.receiptEmail), + appearance = uiState.options.toCheckoutAppearance(), + environment = environment, + identityVerificationHandling = uiState.options.toIdentityVerificationHandling(), + modifier = Modifier.fillMaxSize(), + ) + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun OrderDetailsSheet( + uiState: PlaygroundUiState, + session: OrderSession, + onDismissRequest: () -> Unit, +) { + ModalBottomSheet(onDismissRequest = onDismissRequest) { + Column(modifier = Modifier.padding(bottom = 16.dp)) { + CopyableRow(label = "Order ID", value = session.orderId) + CopyableRow(label = "Client secret", value = session.clientSecret) + + if (uiState.events.isNotEmpty()) { + HorizontalDivider() + Text( + "Events", + style = MaterialTheme.typography.titleSmall, + modifier = Modifier.padding(16.dp), + ) + for (event in uiState.events.asReversed()) { + ListItem( + headlineContent = { Text(event.message) }, + overlineContent = { Text(formatTimestamp(event.timestamp)) }, + ) + } + } + } + } +} + +@Composable +private fun EmptyPreviewState(modifier: Modifier = Modifier) { + Box(modifier = modifier.padding(24.dp), contentAlignment = Alignment.Center) { + Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(8.dp)) { + Icon( + painter = painterResource(Res.drawable.ic_crossmint), + contentDescription = null, + tint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f), + modifier = Modifier.size(72.dp), + ) + Text("No order yet", textAlign = TextAlign.Center) + Text( + "Create an order or use an existing one from the Order section.", + textAlign = TextAlign.Center, + ) + } + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CopyableRow.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CopyableRow.kt new file mode 100644 index 0000000..f14162c --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/CopyableRow.kt @@ -0,0 +1,30 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ContentCopy +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.ListItem +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.ClipboardManager +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.style.TextOverflow + +@Composable +fun CopyableRow( + label: String, + value: String, +) { + val clipboardManager: ClipboardManager = LocalClipboardManager.current + ListItem( + headlineContent = { Text(value, maxLines = 1, overflow = TextOverflow.Ellipsis) }, + overlineContent = { Text(label) }, + trailingContent = { + IconButton(onClick = { clipboardManager.setText(AnnotatedString(value)) }) { + Icon(Icons.Filled.ContentCopy, contentDescription = "Copy $label") + } + }, + ) +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/EnvironmentBadge.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/EnvironmentBadge.kt new file mode 100644 index 0000000..36028c4 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/EnvironmentBadge.kt @@ -0,0 +1,12 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.material3.AssistChip +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import com.crossmint.kotlin.core.ApiKey + +@Composable +fun EnvironmentBadge(apiKey: String) { + val environment = runCatching { ApiKey.fromString(apiKey).environment }.getOrNull() ?: return + AssistChip(onClick = {}, enabled = false, label = { Text(environment.value) }) +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/IdentityPreview.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/IdentityPreview.kt new file mode 100644 index 0000000..9eabb3f --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/IdentityPreview.kt @@ -0,0 +1,13 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +expect fun IdentityPreview( + apiKey: String, + inquiryId: String, + sessionToken: String, + modifier: Modifier, + onEvent: (String) -> Unit, +) diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/PaneBackHandler.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/PaneBackHandler.kt new file mode 100644 index 0000000..abe7031 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/PaneBackHandler.kt @@ -0,0 +1,9 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi +import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator +import androidx.compose.runtime.Composable + +@OptIn(ExperimentalMaterial3AdaptiveApi::class) +@Composable +expect fun PaneBackHandler(navigator: ThreePaneScaffoldNavigator) diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/SwitchRow.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/SwitchRow.kt new file mode 100644 index 0000000..d4372f0 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/SwitchRow.kt @@ -0,0 +1,18 @@ +package com.crossmint.kotlin.checkoutdemo.ui + +import androidx.compose.material3.ListItem +import androidx.compose.material3.Switch +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable + +@Composable +fun SwitchRow( + label: String, + checked: Boolean, + onCheckedChange: (Boolean) -> Unit, +) { + ListItem( + headlineContent = { Text(label) }, + trailingContent = { Switch(checked = checked, onCheckedChange = onCheckedChange) }, + ) +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/AppearanceSectionView.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/AppearanceSectionView.kt new file mode 100644 index 0000000..f0eaa8c --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/AppearanceSectionView.kt @@ -0,0 +1,98 @@ +package com.crossmint.kotlin.checkoutdemo.ui.sections + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Slider +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.crossmint.kotlin.checkoutdemo.model.PlaygroundOptions + +@Composable +fun AppearanceSectionView( + options: PlaygroundOptions, + onOptionsChange: (PlaygroundOptions) -> Unit, + modifier: Modifier = Modifier, +) { + Column(modifier = modifier.verticalScroll(rememberScrollState()).padding(16.dp)) { + Text( + "Colors (hex) are global appearance variables — they recolor every element at " + + "once. Corner radii below are per element.", + style = MaterialTheme.typography.bodyMedium, + ) + + OutlinedTextField( + value = options.textColor, + onValueChange = { onOptionsChange(options.copy(textColor = it)) }, + label = { Text("Text color") }, + placeholder = { Text("#1C1C1E") }, + singleLine = true, + modifier = Modifier.fillMaxWidth().padding(top = 12.dp), + ) + + OutlinedTextField( + value = options.backgroundColor, + onValueChange = { onOptionsChange(options.copy(backgroundColor = it)) }, + label = { Text("Background color") }, + placeholder = { Text("#FFFFFF") }, + singleLine = true, + modifier = Modifier.fillMaxWidth().padding(top = 12.dp), + ) + + OutlinedTextField( + value = options.accentColor, + onValueChange = { onOptionsChange(options.copy(accentColor = it)) }, + label = { Text("Accent color") }, + placeholder = { Text("#00C853") }, + singleLine = true, + modifier = Modifier.fillMaxWidth().padding(top = 12.dp), + ) + + OutlinedTextField( + value = options.dangerColor, + onValueChange = { onOptionsChange(options.copy(dangerColor = it)) }, + label = { Text("Danger color") }, + placeholder = { Text("#D32F2F") }, + singleLine = true, + modifier = Modifier.fillMaxWidth().padding(top = 12.dp), + ) + + RadiusSlider( + label = "Input corner radius", + value = options.inputRadius, + onValueChange = { onOptionsChange(options.copy(inputRadius = it)) }, + ) + + RadiusSlider( + label = "Tab corner radius", + value = options.tabRadius, + onValueChange = { onOptionsChange(options.copy(tabRadius = it)) }, + ) + + RadiusSlider( + label = "Button corner radius", + value = options.buttonRadius, + onValueChange = { onOptionsChange(options.copy(buttonRadius = it)) }, + ) + } +} + +@Composable +private fun RadiusSlider( + label: String, + value: Float, + onValueChange: (Float) -> Unit, +) { + Text( + "$label: ${value.toInt()}px", + style = MaterialTheme.typography.bodyMedium, + modifier = Modifier.padding(top = 20.dp), + ) + Slider(value = value, onValueChange = onValueChange, valueRange = 0f..24f) +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/EventsSectionView.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/EventsSectionView.kt new file mode 100644 index 0000000..fafbf70 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/EventsSectionView.kt @@ -0,0 +1,39 @@ +package com.crossmint.kotlin.checkoutdemo.ui.sections + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.ListItem +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.crossmint.kotlin.checkoutdemo.model.DemoEvent +import com.crossmint.kotlin.checkoutdemo.utility.formatTimestamp + +@Composable +fun EventsSectionView( + events: List, + modifier: Modifier = Modifier, +) { + if (events.isEmpty()) { + Box(modifier = modifier.fillMaxSize().padding(24.dp), contentAlignment = Alignment.Center) { + Text("No events yet. Create or use an order to get started.") + } + return + } + + LazyColumn(modifier = modifier) { + items(events.asReversed()) { event -> + ListItem( + headlineContent = { Text(event.message) }, + overlineContent = { Text(formatTimestamp(event.timestamp)) }, + ) + HorizontalDivider() + } + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/FieldsSectionView.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/FieldsSectionView.kt new file mode 100644 index 0000000..0a8d6a8 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/FieldsSectionView.kt @@ -0,0 +1,39 @@ +package com.crossmint.kotlin.checkoutdemo.ui.sections + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.crossmint.kotlin.checkoutdemo.model.PlaygroundOptions +import com.crossmint.kotlin.checkoutdemo.ui.SwitchRow + +@Composable +fun FieldsSectionView( + options: PlaygroundOptions, + onOptionsChange: (PlaygroundOptions) -> Unit, + modifier: Modifier = Modifier, +) { + Column(modifier = modifier.verticalScroll(rememberScrollState())) { + SwitchRow( + label = "Show destination input", + checked = options.showsDestinationInput, + onCheckedChange = { onOptionsChange(options.copy(showsDestinationInput = it)) }, + ) + SwitchRow( + label = "Show receipt email input", + checked = options.showsReceiptEmailInput, + onCheckedChange = { onOptionsChange(options.copy(showsReceiptEmailInput = it)) }, + ) + SwitchRow( + label = "Show status message", + checked = options.showsStatusMessage, + onCheckedChange = { onOptionsChange(options.copy(showsStatusMessage = it)) }, + ) + SwitchRow( + label = "Render identity verification externally", + checked = options.externalIdentityVerification, + onCheckedChange = { onOptionsChange(options.copy(externalIdentityVerification = it)) }, + ) + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/IdentitySectionView.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/IdentitySectionView.kt new file mode 100644 index 0000000..90eb92f --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/IdentitySectionView.kt @@ -0,0 +1,59 @@ +package com.crossmint.kotlin.checkoutdemo.ui.sections + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.FilledTonalButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.crossmint.kotlin.checkoutdemo.PlaygroundUiState + +@Composable +fun IdentitySectionView( + uiState: PlaygroundUiState, + onCredentialsChange: (inquiryId: String, sessionToken: String) -> Unit, + onOpenPreview: () -> Unit, + modifier: Modifier = Modifier, +) { + Column( + modifier = modifier.verticalScroll(rememberScrollState()).padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + Text( + "Paste the inquiry ID (and, if you have one, the session token) from an order's " + + "`payment.preparation.kyc` to preview the KYC step on its own.", + style = MaterialTheme.typography.bodyMedium, + ) + + OutlinedTextField( + value = uiState.identityInquiryId, + onValueChange = { onCredentialsChange(it, uiState.identitySessionToken) }, + label = { Text("Inquiry ID") }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + ) + + OutlinedTextField( + value = uiState.identitySessionToken, + onValueChange = { onCredentialsChange(uiState.identityInquiryId, it) }, + label = { Text("Session token (optional)") }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + ) + + FilledTonalButton( + onClick = onOpenPreview, + enabled = uiState.identityInquiryId.isNotBlank(), + modifier = Modifier.fillMaxWidth(), + ) { + Text("Open preview") + } + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/OrderSectionView.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/OrderSectionView.kt new file mode 100644 index 0000000..7922e39 --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/OrderSectionView.kt @@ -0,0 +1,250 @@ +package com.crossmint.kotlin.checkoutdemo.ui.sections + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.Button +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuAnchorType +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.FilledTonalButton +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.SegmentedButton +import androidx.compose.material3.SegmentedButtonDefaults +import androidx.compose.material3.SingleChoiceSegmentedButtonRow +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import com.crossmint.kotlin.checkoutdemo.PlaygroundUiState +import com.crossmint.kotlin.checkoutdemo.model.OrderDraft +import com.crossmint.kotlin.checkoutdemo.model.TokenPreset +import com.crossmint.kotlin.core.ApiKey +import com.crossmint.kotlin.core.Environment + +private enum class OrderMode( + val label: String, +) { + NEW("New order"), + EXISTING("Existing order"), +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun OrderSectionView( + uiState: PlaygroundUiState, + apiKey: String, + onDraftChange: (OrderDraft) -> Unit, + onCreateOrder: () -> Unit, + onExistingOrderChange: (orderId: String, clientSecret: String) -> Unit, + onUseExistingOrder: () -> Unit, + onOpenPreview: () -> Unit, + modifier: Modifier = Modifier, +) { + val draft = uiState.draft + var mode by remember { mutableStateOf(OrderMode.NEW) } + + Column( + modifier = modifier.verticalScroll(rememberScrollState()).padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) { + OrderMode.entries.forEachIndexed { index, entry -> + SegmentedButton( + selected = mode == entry, + onClick = { mode = entry }, + shape = SegmentedButtonDefaults.itemShape(index = index, count = OrderMode.entries.size), + ) { + Text(entry.label) + } + } + } + + if (mode == OrderMode.NEW) { + TokenPicker( + apiKey = apiKey, + tokenLocator = draft.tokenLocator, + onTokenLocatorChange = { onDraftChange(draft.copy(tokenLocator = it)) }, + ) + + OutlinedTextField( + value = draft.amount, + onValueChange = { onDraftChange(draft.copy(amount = it)) }, + label = { Text("Amount") }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + ) + + OutlinedTextField( + value = draft.recipientWalletAddress, + onValueChange = { onDraftChange(draft.copy(recipientWalletAddress = it)) }, + label = { Text("Recipient wallet address") }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + ) + + OutlinedTextField( + value = draft.receiptEmail, + onValueChange = { onDraftChange(draft.copy(receiptEmail = it)) }, + label = { Text("Receipt email") }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + ) + + uiState.orderErrorMessage?.let { message -> + Text(message, color = MaterialTheme.colorScheme.error) + } + + Button( + onClick = onCreateOrder, + enabled = + !uiState.isCreatingOrder && + draft.tokenLocator.isNotBlank() && + draft.amount.isNotBlank() && + draft.recipientWalletAddress.isNotBlank() && + draft.receiptEmail.isNotBlank(), + modifier = Modifier.fillMaxWidth(), + ) { + if (uiState.isCreatingOrder) { + CircularProgressIndicator(modifier = Modifier.size(18.dp), strokeWidth = 2.dp) + } else { + Text("Create order") + } + } + } else { + OutlinedTextField( + value = uiState.existingOrderId, + onValueChange = { onExistingOrderChange(it, uiState.existingClientSecret) }, + label = { Text("Order ID") }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + ) + + OutlinedTextField( + value = uiState.existingClientSecret, + onValueChange = { onExistingOrderChange(uiState.existingOrderId, it) }, + label = { Text("Client secret") }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + ) + + OutlinedButton( + onClick = onUseExistingOrder, + enabled = uiState.existingOrderId.isNotBlank() && uiState.existingClientSecret.isNotBlank(), + modifier = Modifier.fillMaxWidth(), + ) { + Text("Use this order") + } + } + + if (uiState.isPreviewingCheckout) { + HorizontalDivider(modifier = Modifier.padding(vertical = 8.dp)) + FilledTonalButton(onClick = onOpenPreview, modifier = Modifier.fillMaxWidth()) { + Text("Open preview") + } + } + } +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun TokenPicker( + apiKey: String, + tokenLocator: String, + onTokenLocatorChange: (String) -> Unit, +) { + val environment = + remember(apiKey) { runCatching { ApiKey.fromString(apiKey).environment }.getOrDefault(Environment.STAGING) } + val presets = remember(environment) { TokenPreset.presets(environment) } + val match = remember(presets, tokenLocator) { TokenPreset.findByLocator(environment, tokenLocator) } + val selectedPreset = match?.first + var isCustom by remember(presets) { mutableStateOf(tokenLocator.isNotBlank() && match == null) } + + var symbolExpanded by remember { mutableStateOf(false) } + ExposedDropdownMenuBox(expanded = symbolExpanded, onExpandedChange = { symbolExpanded = it }) { + OutlinedTextField( + value = + when { + selectedPreset != null -> selectedPreset.symbol + isCustom -> "Custom token" + else -> "" + }, + onValueChange = {}, + readOnly = true, + label = { Text("Token") }, + placeholder = { Text("Select a token") }, + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = symbolExpanded) }, + modifier = Modifier.fillMaxWidth().menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable), + ) + ExposedDropdownMenu(expanded = symbolExpanded, onDismissRequest = { symbolExpanded = false }) { + for (preset in presets) { + DropdownMenuItem( + text = { Text(preset.symbol) }, + onClick = { + isCustom = false + onTokenLocatorChange(preset.networks.first().locator) + symbolExpanded = false + }, + ) + } + DropdownMenuItem( + text = { Text("Custom token") }, + onClick = { + isCustom = true + onTokenLocatorChange("") + symbolExpanded = false + }, + ) + } + } + + if (selectedPreset != null) { + var networkExpanded by remember { mutableStateOf(false) } + ExposedDropdownMenuBox(expanded = networkExpanded, onExpandedChange = { networkExpanded = it }) { + OutlinedTextField( + value = match.second.title, + onValueChange = {}, + readOnly = true, + label = { Text("Chain") }, + trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = networkExpanded) }, + modifier = Modifier.fillMaxWidth().menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable), + ) + ExposedDropdownMenu(expanded = networkExpanded, onDismissRequest = { networkExpanded = false }) { + for (network in selectedPreset.networks) { + DropdownMenuItem( + text = { Text(network.title) }, + onClick = { + onTokenLocatorChange(network.locator) + networkExpanded = false + }, + ) + } + } + } + } + + if (isCustom) { + OutlinedTextField( + value = tokenLocator, + onValueChange = onTokenLocatorChange, + label = { Text("Token locator") }, + placeholder = { Text("chain:token-address") }, + singleLine = true, + modifier = Modifier.fillMaxWidth(), + ) + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/PaymentSectionView.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/PaymentSectionView.kt new file mode 100644 index 0000000..b4fe1fe --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/ui/sections/PaymentSectionView.kt @@ -0,0 +1,39 @@ +package com.crossmint.kotlin.checkoutdemo.ui.sections + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.crossmint.kotlin.checkoutdemo.model.PlaygroundOptions +import com.crossmint.kotlin.checkoutdemo.ui.SwitchRow + +@Composable +fun PaymentSectionView( + options: PlaygroundOptions, + onOptionsChange: (PlaygroundOptions) -> Unit, + modifier: Modifier = Modifier, +) { + Column(modifier = modifier.verticalScroll(rememberScrollState())) { + SwitchRow( + label = "Fiat payment", + checked = options.fiatEnabled, + onCheckedChange = { onOptionsChange(options.copy(fiatEnabled = it)) }, + ) + SwitchRow( + label = "Allow card", + checked = options.allowCard, + onCheckedChange = { onOptionsChange(options.copy(allowCard = it)) }, + ) + SwitchRow( + label = "Allow Google Pay", + checked = options.allowGooglePay, + onCheckedChange = { onOptionsChange(options.copy(allowGooglePay = it)) }, + ) + SwitchRow( + label = "Crypto payment", + checked = options.cryptoEnabled, + onCheckedChange = { onOptionsChange(options.copy(cryptoEnabled = it)) }, + ) + } +} diff --git a/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/utility/Time.kt b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/utility/Time.kt new file mode 100644 index 0000000..c723c2c --- /dev/null +++ b/checkout/src/commonMain/kotlin/com/crossmint/kotlin/checkoutdemo/utility/Time.kt @@ -0,0 +1,5 @@ +package com.crossmint.kotlin.checkoutdemo.utility + +expect fun currentTimeMillis(): Long + +expect fun formatTimestamp(timestamp: Long): String diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5f8908a..c45a721 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -crossmint = "1.1.0" +crossmint = "1.2.0" agp = "8.12.2" android-compileSdk = "35" @@ -16,6 +16,8 @@ kotlinx-serialization = "1.9.0" ktor = "3.3.1" navigationCompose = "2.9.1" processPhoenix = "3.0.0" +material3Adaptive = "1.2.0" +material3AdaptiveNavigationSuite = "1.9.0" [libraries] androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" } @@ -34,6 +36,12 @@ process-phoenix = { module = "com.jakewharton:process-phoenix", version.ref = "p crossmint-sdk = { module = "com.crossmint:crossmint-sdk", version.ref = "crossmint" } crossmint-compose = { module = "com.crossmint:crossmint-compose", version.ref = "crossmint" } crossmint-checkout = { module = "com.crossmint:sdk-checkout", version.ref = "crossmint" } +crossmint-core = { module = "com.crossmint:sdk-core", version.ref = "crossmint" } +crossmint-identity = { module = "com.crossmint:sdk-identity", version.ref = "crossmint" } +material3-adaptive = { module = "org.jetbrains.compose.material3.adaptive:adaptive", version.ref = "material3Adaptive" } +material3-adaptive-layout = { module = "org.jetbrains.compose.material3.adaptive:adaptive-layout", version.ref = "material3Adaptive" } +material3-adaptive-navigation = { module = "org.jetbrains.compose.material3.adaptive:adaptive-navigation", version.ref = "material3Adaptive" } +material3-adaptive-navigation-suite = { module = "org.jetbrains.compose.material3:material3-adaptive-navigation-suite", version.ref = "material3AdaptiveNavigationSuite" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } diff --git a/settings.gradle.kts b/settings.gradle.kts index b676d9a..fa76560 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -26,3 +26,4 @@ dependencyResolutionManagement { rootProject.name = "Crossmint Quickstart" include(":app") +include(":checkout")