From c1e09a181c914d48b965c6a43eecf1f312d71c2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juliano=20C=C3=A9zar=20Chagas=20Tavares?= Date: Thu, 14 Nov 2024 14:09:42 -0300 Subject: [PATCH] [Android][iOS] Improve home tabs (#45) This improves the SpruceKit Showcase apps' home page by: - Updating the switch tab component according to the Figma designs - Implement a way to redirect to a specific tab on the home page - Remove the QR Code instructions when the user doesn't have credentials - Update the Verifier upper right button icon according to the Figma designs --- .../com/spruceid/mobilesdkexample/HomeView.kt | 141 +++++++++++++----- .../mobilesdkexample/{verifier => }/Loader.kt | 2 +- .../mobilesdkexample/ScanningComponent.kt | 30 +--- .../mobilesdkexample/navigation/Screen.kt | 2 +- .../navigation/SetupNavGraph.kt | 11 +- .../mobilesdkexample/ui/theme/Color.kt | 3 + .../verifier/AddVerificationMethodView.kt | 8 +- .../verifier/VerifierBinarySuccessView.kt | 15 +- .../verifier/VerifierHomeView.kt | 4 +- .../verifier/VerifierMDocResultView.kt | 17 +-- .../mobilesdkexample/verifier/VerifyDLView.kt | 17 ++- .../verifier/VerifyDelegatedOid4vpView.kt | 6 +- .../mobilesdkexample/verifier/VerifyEAView.kt | 21 ++- .../verifier/VerifyMDocView.kt | 21 ++- .../mobilesdkexample/verifier/VerifyVCView.kt | 17 ++- .../VerifierSettingsHomeView.kt | 8 +- .../mobilesdkexample/wallet/DispatchQRView.kt | 5 +- .../mobilesdkexample/wallet/WalletHomeView.kt | 6 - .../walletsettings/WalletSettingsHomeView.kt | 15 +- .../main/res/drawable-hdpi/scan_qr_code.png | Bin 620 -> 0 bytes .../res/drawable-hdpi/scan_qr_code_white.png | Bin 892 -> 0 bytes .../main/res/drawable-mdpi/scan_qr_code.png | Bin 500 -> 0 bytes .../main/res/drawable-xhdpi/scan_qr_code.png | Bin 850 -> 0 bytes .../main/res/drawable-xxhdpi/scan_qr_code.png | Bin 1439 -> 0 bytes .../res/drawable-xxxhdpi/scan_qr_code.png | Bin 1637 -> 0 bytes .../res/drawable/add_first_credential.xml | 12 -- example/src/main/res/drawable/cog.xml | 9 ++ example/src/main/res/drawable/wallet.xml | 14 ++ example/src/main/res/values/colors.xml | 3 + example/src/main/res/values/strings.xml | 2 +- 30 files changed, 241 insertions(+), 148 deletions(-) rename example/src/main/java/com/spruceid/mobilesdkexample/{verifier => }/Loader.kt (98%) delete mode 100644 example/src/main/res/drawable-hdpi/scan_qr_code.png delete mode 100644 example/src/main/res/drawable-hdpi/scan_qr_code_white.png delete mode 100644 example/src/main/res/drawable-mdpi/scan_qr_code.png delete mode 100644 example/src/main/res/drawable-xhdpi/scan_qr_code.png delete mode 100644 example/src/main/res/drawable-xxhdpi/scan_qr_code.png delete mode 100644 example/src/main/res/drawable-xxxhdpi/scan_qr_code.png delete mode 100644 example/src/main/res/drawable/add_first_credential.xml create mode 100644 example/src/main/res/drawable/cog.xml create mode 100644 example/src/main/res/drawable/wallet.xml diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/HomeView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/HomeView.kt index 6a049db..d872ba6 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/HomeView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/HomeView.kt @@ -1,13 +1,18 @@ package com.spruceid.mobilesdkexample import android.annotation.SuppressLint +import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.BottomAppBar import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Scaffold @@ -17,14 +22,22 @@ 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.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController import com.spruceid.mobilesdkexample.ui.theme.Bg -import com.spruceid.mobilesdkexample.ui.theme.Inter +import com.spruceid.mobilesdkexample.ui.theme.ColorBlue300 +import com.spruceid.mobilesdkexample.ui.theme.ColorBlue500 +import com.spruceid.mobilesdkexample.ui.theme.ColorBlue900 +import com.spruceid.mobilesdkexample.ui.theme.Switzer import com.spruceid.mobilesdkexample.verifier.VerifierHomeView import com.spruceid.mobilesdkexample.viewmodels.CredentialPacksViewModel import com.spruceid.mobilesdkexample.viewmodels.VerificationMethodsViewModel @@ -38,57 +51,28 @@ enum class HomeTabs { @Composable fun HomeView( navController: NavController, + initialTab: String, verificationMethodsViewModel: VerificationMethodsViewModel, credentialPacksViewModel: CredentialPacksViewModel ) { var tab by remember { - mutableStateOf(HomeTabs.WALLET) + if (initialTab == "verifier") { + mutableStateOf(HomeTabs.VERIFIER) + } else { + mutableStateOf(HomeTabs.WALLET) + } } Scaffold( containerColor = Color.Transparent, bottomBar = { - Row( - modifier = Modifier - .fillMaxWidth() - .background(Bg), horizontalArrangement = Arrangement.SpaceEvenly - ) { - Button( - onClick = { tab = HomeTabs.WALLET }, - modifier = Modifier.weight(1f), - colors = ButtonDefaults.buttonColors( - containerColor = Color.Transparent, - contentColor = if (tab == HomeTabs.WALLET) Color.Blue else Color.Gray, - ) - ) { - Text( - text = "Wallet", - fontFamily = Inter, - fontWeight = FontWeight.Normal, - fontSize = 10.sp, - ) - } - - Button( - onClick = { tab = HomeTabs.VERIFIER }, - modifier = Modifier.weight(1f), - colors = ButtonDefaults.buttonColors( - containerColor = Color.Transparent, - contentColor = if (tab == HomeTabs.VERIFIER) Color.Blue else Color.Gray, - ) - ) { - Text( - text = "Verifier", - fontFamily = Inter, - fontWeight = FontWeight.Normal, - fontSize = 10.sp, - ) - } + HomeBottomTabs(tab) { newTab -> + tab = newTab } }, modifier = Modifier.navigationBarsPadding() ) { - Box(modifier = Modifier.padding(bottom = 30.dp)) { + Box(modifier = Modifier.padding(bottom = 60.dp)) { if (tab == HomeTabs.WALLET) { WalletHomeView( navController, @@ -103,3 +87,82 @@ fun HomeView( } } } + +@Composable +fun HomeBottomTabs( + tab: HomeTabs, + changeTabs: (HomeTabs) -> Unit +) { + BottomAppBar(containerColor = Bg) { + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center + ) { + Row( + modifier = Modifier + .clip(shape = RoundedCornerShape(14.dp)) + .background(ColorBlue900) + .padding(horizontal = 4.dp) + ) { + Button( + onClick = { changeTabs(HomeTabs.WALLET) }, + colors = ButtonDefaults.buttonColors( + containerColor = if (tab == HomeTabs.WALLET) ColorBlue500 else Color.Transparent, + contentColor = if (tab == HomeTabs.WALLET) Color.White else ColorBlue300, + ), + shape = RoundedCornerShape(10.dp) + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Image( + painter = painterResource(id = R.drawable.wallet), + contentDescription = stringResource(id = R.string.wallet), + colorFilter = ColorFilter.tint( + if (tab == HomeTabs.WALLET) Color.White else ColorBlue300, + ), + modifier = Modifier + .width(20.dp) + .height(20.dp) + .padding(end = 3.dp) + ) + Text( + text = "Wallet", + fontFamily = Switzer, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + ) + } + } + + Button( + onClick = { changeTabs(HomeTabs.VERIFIER) }, + colors = ButtonDefaults.buttonColors( + containerColor = if (tab == HomeTabs.VERIFIER) ColorBlue500 else Color.Transparent, + contentColor = if (tab == HomeTabs.VERIFIER) Color.White else ColorBlue300, + ), + shape = RoundedCornerShape(10.dp) + ) { + Row(verticalAlignment = Alignment.CenterVertically) { + Image( + painter = painterResource(id = R.drawable.qrcode_scanner), + contentDescription = stringResource(id = R.string.verifier), + colorFilter = ColorFilter.tint( + if (tab == HomeTabs.VERIFIER) Color.White else ColorBlue300, + ), + modifier = Modifier + .width(20.dp) + .height(20.dp) + .padding(end = 3.dp) + ) + Text( + text = "Verifier", + fontFamily = Switzer, + fontWeight = FontWeight.Normal, + fontSize = 14.sp, + ) + } + } + } + } + } + +} diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/Loader.kt b/example/src/main/java/com/spruceid/mobilesdkexample/Loader.kt similarity index 98% rename from example/src/main/java/com/spruceid/mobilesdkexample/verifier/Loader.kt rename to example/src/main/java/com/spruceid/mobilesdkexample/Loader.kt index 1b4e03f..4756f97 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/Loader.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/Loader.kt @@ -1,4 +1,4 @@ -package com.spruceid.mobilesdkexample.verifier +package com.spruceid.mobilesdkexample import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.VectorConverter diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/ScanningComponent.kt b/example/src/main/java/com/spruceid/mobilesdkexample/ScanningComponent.kt index 52edb8e..9557e5f 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/ScanningComponent.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/ScanningComponent.kt @@ -25,7 +25,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver -import androidx.navigation.NavController import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.isGranted import com.google.accompanist.permissions.rememberMultiplePermissionsState @@ -43,13 +42,12 @@ enum class ScanningType { @ExperimentalPermissionsApi @Composable fun ScanningComponent( - navController: NavController, scanningType: ScanningType, title: String = "Scan QR Code", subtitle: String = "Please align within the guides", onRead: (content: String) -> Unit, isMatch: (content: String) -> Boolean = { _ -> true }, - onCancel: (() -> Unit)? = null + onCancel: () -> Unit ) { val context = LocalContext.current @@ -79,18 +77,6 @@ fun ScanningComponent( }, ) - fun backHome() { - navController.popBackStack() - } - - fun internalOnCancel() { - if (onCancel != null) { - onCancel() - } else { - backHome() - } - } - Column( modifier = Modifier.fillMaxSize(), ) { @@ -104,7 +90,7 @@ fun ScanningComponent( cancelButtonLabel = "Cancel", onRead = onRead, isMatch = isMatch, - onCancel = ::internalOnCancel, + onCancel = onCancel, fontFamily = Inter, readerColor = Color.White, guidesColor = Color.White, @@ -118,7 +104,7 @@ fun ScanningComponent( cancelButtonLabel = "Cancel", onRead = onRead, isMatch = isMatch, - onCancel = ::internalOnCancel, + onCancel = onCancel, fontFamily = Inter, readerColor = Color.White, guidesColor = Color.White, @@ -132,7 +118,7 @@ fun ScanningComponent( cancelButtonLabel = "Cancel", onRead = onRead, isMatch = isMatch, - onCancel = ::internalOnCancel, + onCancel = onCancel, fontFamily = Inter, readerColor = Color.White, guidesColor = Color.White, @@ -144,9 +130,7 @@ fun ScanningComponent( AlertDialog( containerColor = Color.White, shape = RoundedCornerShape(8.dp), - onDismissRequest = { - backHome() - }, + onDismissRequest = onCancel, title = { Text( "Camera permission denied", @@ -189,9 +173,7 @@ fun ScanningComponent( }, dismissButton = { Button( - onClick = { - backHome() - }, + onClick = onCancel, colors = ButtonDefaults.buttonColors( containerColor = Color.Transparent, diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/navigation/Screen.kt b/example/src/main/java/com/spruceid/mobilesdkexample/navigation/Screen.kt index 986dcbe..19eb22a 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/navigation/Screen.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/navigation/Screen.kt @@ -1,6 +1,6 @@ package com.spruceid.mobilesdkexample.navigation -const val HOME_SCREEN_PATH = "home" +const val HOME_SCREEN_PATH = "home/{tab}" const val VERIFY_DL_PATH = "verify_dl" const val VERIFY_EA_PATH = "verify_ea" const val VERIFY_VC_PATH = "verify_vc" diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/navigation/SetupNavGraph.kt b/example/src/main/java/com/spruceid/mobilesdkexample/navigation/SetupNavGraph.kt index 69249d5..aabc737 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/navigation/SetupNavGraph.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/navigation/SetupNavGraph.kt @@ -2,8 +2,10 @@ package com.spruceid.mobilesdkexample.navigation import androidx.compose.runtime.Composable import androidx.navigation.NavHostController +import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable +import androidx.navigation.navArgument import androidx.navigation.navDeepLink import com.spruceid.mobilesdkexample.HomeView import com.spruceid.mobilesdkexample.credentials.AddToWalletView @@ -30,9 +32,16 @@ fun SetupNavGraph( NavHost(navController = navController, startDestination = Screen.HomeScreen.route) { composable( route = Screen.HomeScreen.route, - ) { + arguments = listOf( + navArgument("tab") { + type = NavType.StringType; defaultValue = "wallet" + } + ), + ) { backStackEntry -> + val tab = backStackEntry.arguments?.getString("tab")!! HomeView( navController, + initialTab = tab, verificationMethodsViewModel = verificationMethodsViewModel, credentialPacksViewModel = credentialPacksViewModel ) diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/ui/theme/Color.kt b/example/src/main/java/com/spruceid/mobilesdkexample/ui/theme/Color.kt index 0f6ecbd..6456e76 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/ui/theme/Color.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/ui/theme/Color.kt @@ -21,7 +21,10 @@ val VerifierCloseButton = Color(0xFF44403C) val ColorBase300 = Color(0xFFE6E1D6) val ColorBase800 = Color(0xFF75675C) val ColorBase900 = Color(0xFF584C43) +val ColorBlue300 = Color(0xFF98C7F8) +val ColorBlue500 = Color(0xFF4389F2) val ColorBlue600 = Color(0xFF2F6AE1) +val ColorBlue900 = Color(0xFF243F84) val ColorStone50 = Color(0xFFFAFAF9) val ColorStone200 = Color(0xFFE7E5E4) val ColorStone300 = Color(0xFFD6D3D1) diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/AddVerificationMethodView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/AddVerificationMethodView.kt index 89c9db6..dd7ad09 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/AddVerificationMethodView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/AddVerificationMethodView.kt @@ -30,7 +30,9 @@ fun AddVerificationMethodView( var qrcode by remember { mutableStateOf(null) } fun back() { - navController.navigate(Screen.HomeScreen.route) { + navController.navigate( + Screen.HomeScreen.route.replace("{tab}", "verifier") + ) { popUpTo(0) } } @@ -68,9 +70,9 @@ fun AddVerificationMethodView( } else if (qrcode == null) { ScanningComponent( subtitle = "Scan Verification QR Code", - navController = navController, scanningType = ScanningType.QRCODE, - onRead = ::onRead + onRead = ::onRead, + onCancel = ::back ) } else { LoadingView( diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierBinarySuccessView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierBinarySuccessView.kt index a3f311e..8636c9e 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierBinarySuccessView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierBinarySuccessView.kt @@ -26,9 +26,6 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.navigation.NavController -import androidx.navigation.NavHostController -import androidx.navigation.compose.rememberNavController import com.spruceid.mobilesdkexample.R import com.spruceid.mobilesdkexample.ui.theme.Inter import com.spruceid.mobilesdkexample.ui.theme.MobileSdkTheme @@ -39,9 +36,9 @@ import com.spruceid.mobilesdkexample.ui.theme.VerifierCloseButton @Composable fun VerifierBinarySuccessView( - navController: NavController, success: Boolean, - description: String + description: String, + onClose: () -> Unit ) { Column( modifier = Modifier @@ -124,9 +121,7 @@ fun VerifierBinarySuccessView( Spacer(modifier = Modifier.weight(1f)) Button( - onClick = { - navController.popBackStack() - }, + onClick = onClose, shape = RoundedCornerShape(5.dp), colors = ButtonDefaults.buttonColors( containerColor = VerifierCloseButton, @@ -148,12 +143,10 @@ fun VerifierBinarySuccessView( @Preview(showBackground = true) @Composable fun VerifierBinarySuccessViewPreview() { - val navController: NavHostController = rememberNavController() MobileSdkTheme { VerifierBinarySuccessView( - navController = navController, success = true, description = "Valid" - ) + ) {} } } \ No newline at end of file diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierHomeView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierHomeView.kt index a637266..f2af070 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierHomeView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierHomeView.kt @@ -84,8 +84,8 @@ fun VerifierHomeHeader( } ) { Image( - painter = painterResource(id = R.drawable.user), - contentDescription = stringResource(id = R.string.user), + painter = painterResource(id = R.drawable.cog), + contentDescription = stringResource(id = R.string.cog), modifier = Modifier .width(20.dp) .height(20.dp) diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierMDocResultView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierMDocResultView.kt index 4e31866..aa6f2f6 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierMDocResultView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifierMDocResultView.kt @@ -31,11 +31,8 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.navigation.NavController -import androidx.navigation.compose.rememberNavController import com.spruceid.mobile.sdk.rs.MDocItem import com.spruceid.mobilesdkexample.R -import com.spruceid.mobilesdkexample.navigation.Screen import com.spruceid.mobilesdkexample.ui.theme.BgSurfacePrimaryContrast import com.spruceid.mobilesdkexample.ui.theme.BgSurfacePureWhite import com.spruceid.mobilesdkexample.ui.theme.BorderSecondary @@ -77,8 +74,8 @@ fun mDocArrayToByteArray(repr: MDocItem.Array): ByteArray = @Composable fun VerifierMDocResultView( - navController: NavController, - result: Map> + result: Map>, + onClose: () -> Unit ) { val givenName = getDiscriminant(result["org.iso.18013.5.1"]?.get("given_name")!!) val familyName = getDiscriminant(result["org.iso.18013.5.1"]?.get("family_name")!!) @@ -262,7 +259,7 @@ fun VerifierMDocResultView( modifier = Modifier .fillMaxWidth(), shape = RoundedCornerShape(8.dp), - onClick = { navController.popBackStack() }, + onClick = onClose, colors = ButtonColors( containerColor = BgSurfacePrimaryContrast, contentColor = TextBase, disabledContainerColor = Color.Black, @@ -292,11 +289,7 @@ fun VerifierMDocResultView( .fillMaxWidth() .border(width = 1.dp, color = BorderSecondary), shape = RoundedCornerShape(8.dp), - onClick = { - navController.navigate(Screen.HomeScreen.route) { - popUpTo(0) - } - }, + onClick = onClose, colors = ButtonColors( containerColor = BgSurfacePureWhite, contentColor = TextPrimary, disabledContainerColor = BgSurfacePureWhite, @@ -344,5 +337,5 @@ fun MDocVerifyPreview() { "veteran" to MDocItem.Integer(1) ) ) - VerifierMDocResultView(rememberNavController(), example) + VerifierMDocResultView(example) {} } \ No newline at end of file diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyDLView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyDLView.kt index 5359408..0646abd 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyDLView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyDLView.kt @@ -11,6 +11,7 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.spruceid.mobile.sdk.rs.verifyPdf417Barcode import com.spruceid.mobilesdkexample.ScanningComponent import com.spruceid.mobilesdkexample.ScanningType +import com.spruceid.mobilesdkexample.navigation.Screen import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -35,18 +36,26 @@ fun VerifyDLView( } } + fun back() { + navController.navigate( + Screen.HomeScreen.route.replace("{tab}", "verifier") + ) { + popUpTo(0) + } + } + if (success == null) { ScanningComponent( subtitle = "Scan the\nback of your driver's license", - navController = navController, scanningType = ScanningType.PDF417, - onRead = ::onRead + onRead = ::onRead, + onCancel = ::back ) } else { VerifierBinarySuccessView( - navController = navController, success = success!!, - description = if (success!!) "Valid Driver's License" else "Invalid Driver's License" + description = if (success!!) "Valid Driver's License" else "Invalid Driver's License", + onClose = ::back ) } } \ No newline at end of file diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyDelegatedOid4vpView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyDelegatedOid4vpView.kt index 84e8e7e..d6cda9a 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyDelegatedOid4vpView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyDelegatedOid4vpView.kt @@ -104,7 +104,11 @@ fun VerifyDelegatedOid4vpView( } fun back() { - navController.navigate(Screen.HomeScreen.route) { popUpTo(0) } + navController.navigate( + Screen.HomeScreen.route.replace("{tab}", "verifier") + ) { + popUpTo(0) + } } LaunchedEffect(Unit) { diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyEAView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyEAView.kt index 6ab9b72..da35ae7 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyEAView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyEAView.kt @@ -13,6 +13,7 @@ import com.spruceid.mobile.sdk.rs.verifyVcbQrcodeAgainstMrz import com.spruceid.mobilesdkexample.LoadingView import com.spruceid.mobilesdkexample.ScanningComponent import com.spruceid.mobilesdkexample.ScanningType +import com.spruceid.mobilesdkexample.navigation.Screen import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -59,13 +60,21 @@ fun VerifyEAView( } } + fun back() { + navController.navigate( + Screen.HomeScreen.route.replace("{tab}", "verifier") + ) { + popUpTo(0) + } + } + when (step) { VerifyEASteps.STEP_ONE -> { ScanningComponent( subtitle = "Scan the front of your\nemployment authorization", - navController = navController, scanningType = ScanningType.QRCODE, - onRead = ::onReadStepOne + onRead = ::onReadStepOne, + onCancel = ::back ) } @@ -79,17 +88,17 @@ fun VerifyEAView( ScanningComponent( title = "Scan MRZ", subtitle = "Scan the back of your document", - navController = navController, scanningType = ScanningType.MRZ, - onRead = ::onReadStepTwo + onRead = ::onReadStepTwo, + onCancel = ::back ) } VerifyEASteps.SUCCESS -> { VerifierBinarySuccessView( - navController = navController, success = success!!, - description = if (success!!) "Valid Employment Authorization" else "Invalid Employment Authorization" + description = if (success!!) "Valid Employment Authorization" else "Invalid Employment Authorization", + onClose = ::back ) } } diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyMDocView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyMDocView.kt index 0fb1f2c..ead3dcf 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyMDocView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyMDocView.kt @@ -7,34 +7,30 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowColumn -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect 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.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.navigation.NavController -import androidx.navigation.compose.rememberNavController import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.spruceid.mobile.sdk.BLESessionStateDelegate import com.spruceid.mobile.sdk.IsoMdlReader import com.spruceid.mobile.sdk.getBluetoothManager import com.spruceid.mobile.sdk.getPermissions import com.spruceid.mobile.sdk.rs.MDocItem -import com.spruceid.mobile.sdk.ui.QRCodeScanner import com.spruceid.mobilesdkexample.LoadingView import com.spruceid.mobilesdkexample.ScanningComponent import com.spruceid.mobilesdkexample.ScanningType +import com.spruceid.mobilesdkexample.navigation.Screen import com.spruceid.mobilesdkexample.utils.checkAndRequestBluetoothPermissions import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -154,8 +150,12 @@ fun VerifyMDocView(navController: NavController) { } } - fun onCancel() { - navController.popBackStack() + fun back() { + navController.navigate( + Screen.HomeScreen.route.replace("{tab}", "verifier") + ) { + popUpTo(0) + } } val elementsList = elementMapToList(defaultElements) @@ -163,12 +163,11 @@ fun VerifyMDocView(navController: NavController) { when (scanProcessState) { State.SCANNING -> Column { ScanningComponent( - navController, ScanningType.QRCODE, title = "", subtitle = "", onRead = ::onRead, - onCancel = ::onCancel + onCancel = ::back ) HorizontalDivider(thickness = 1.dp) Text("Requesting the following:") @@ -187,10 +186,10 @@ fun VerifyMDocView(navController: NavController) { } } - State.TRANSMITTING -> LoadingView("Verifying...", "Cancel", ::onCancel) + State.TRANSMITTING -> LoadingView("Verifying...", "Cancel", ::back) State.DONE -> VerifierMDocResultView( - navController = navController, result = result!!, + onClose = ::back ) } } \ No newline at end of file diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyVCView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyVCView.kt index acb2afd..90b1700 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyVCView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/verifier/VerifyVCView.kt @@ -11,6 +11,7 @@ import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.spruceid.mobile.sdk.rs.verifyJwtVp import com.spruceid.mobilesdkexample.ScanningComponent import com.spruceid.mobilesdkexample.ScanningType +import com.spruceid.mobilesdkexample.navigation.Screen import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch @@ -35,17 +36,25 @@ fun VerifyVCView( } } + fun back() { + navController.navigate( + Screen.HomeScreen.route.replace("{tab}", "verifier") + ) { + popUpTo(0) + } + } + if (success == null) { ScanningComponent( - navController = navController, scanningType = ScanningType.QRCODE, - onRead = ::onRead + onRead = ::onRead, + onCancel = ::back ) } else { VerifierBinarySuccessView( - navController = navController, success = success!!, - description = if (success!!) "Valid Verifiable Credential" else "Invalid Verifiable Credential" + description = if (success!!) "Valid Verifiable Credential" else "Invalid Verifiable Credential", + onClose = ::back ) } } \ No newline at end of file diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/verifiersettings/VerifierSettingsHomeView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/verifiersettings/VerifierSettingsHomeView.kt index 8d3a442..0702f8c 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/verifiersettings/VerifierSettingsHomeView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/verifiersettings/VerifierSettingsHomeView.kt @@ -1,6 +1,5 @@ package com.spruceid.mobilesdkexample.verifiersettings -import android.widget.Space import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -34,6 +33,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController import com.spruceid.mobilesdkexample.R +import com.spruceid.mobilesdkexample.navigation.Screen import com.spruceid.mobilesdkexample.ui.theme.Inter import com.spruceid.mobilesdkexample.ui.theme.TextBody import com.spruceid.mobilesdkexample.ui.theme.TextHeader @@ -66,7 +66,11 @@ fun VerifierSettingsHomeView( if (subpage != null) { subpage = null } else { - navController.popBackStack() + navController.navigate( + Screen.HomeScreen.route.replace("{tab}", "verifier") + ) { + popUpTo(0) + } } } ) diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/wallet/DispatchQRView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/wallet/DispatchQRView.kt index 9c9bb6c..94205b1 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/wallet/DispatchQRView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/wallet/DispatchQRView.kt @@ -39,7 +39,9 @@ fun DispatchQRView( var loading by remember { mutableStateOf(false) } fun back() { - navController.navigate(Screen.HomeScreen.route) { + navController.navigate( + Screen.HomeScreen.route.replace("{tab}", "wallet") + ) { popUpTo(0) } } @@ -84,7 +86,6 @@ fun DispatchQRView( LoadingView(loadingText = "Loading...") } else { ScanningComponent( - navController = navController, scanningType = ScanningType.QRCODE, onRead = ::onRead, onCancel = ::back diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/wallet/WalletHomeView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/wallet/WalletHomeView.kt index 6c9084f..f593672 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/wallet/WalletHomeView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/wallet/WalletHomeView.kt @@ -139,12 +139,6 @@ fun WalletHomeBody(credentialPacksViewModel: CredentialPacksViewModel) { } } else { Box(Modifier.fillMaxSize()) { - Column(horizontalAlignment = Alignment.CenterHorizontally) { - Image( - painter = painterResource(id = R.drawable.add_first_credential), - contentDescription = stringResource(id = R.string.add_first_credential), - ) - } Column( Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, diff --git a/example/src/main/java/com/spruceid/mobilesdkexample/walletsettings/WalletSettingsHomeView.kt b/example/src/main/java/com/spruceid/mobilesdkexample/walletsettings/WalletSettingsHomeView.kt index 5f10f98..caf84f0 100644 --- a/example/src/main/java/com/spruceid/mobilesdkexample/walletsettings/WalletSettingsHomeView.kt +++ b/example/src/main/java/com/spruceid/mobilesdkexample/walletsettings/WalletSettingsHomeView.kt @@ -24,6 +24,7 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.navigation.NavController import com.spruceid.mobilesdkexample.R +import com.spruceid.mobilesdkexample.navigation.Screen import com.spruceid.mobilesdkexample.ui.theme.Inter import com.spruceid.mobilesdkexample.ui.theme.TextHeader import com.spruceid.mobilesdkexample.ui.theme.VerifiedRedInvalid @@ -34,16 +35,20 @@ fun WalletSettingsHomeView( navController: NavController, credentialPacksViewModel: CredentialPacksViewModel ) { + fun back() { + navController.navigate( + Screen.HomeScreen.route.replace("{tab}", "wallet") + ) { + popUpTo(0) + } + } + Column( Modifier .padding(all = 20.dp) .padding(top = 20.dp) ) { - WalletSettingsHomeHeader( - onBack = { - navController.popBackStack() - } - ) + WalletSettingsHomeHeader(onBack = ::back) WalletSettingsHomeBody(credentialPacksViewModel) } } diff --git a/example/src/main/res/drawable-hdpi/scan_qr_code.png b/example/src/main/res/drawable-hdpi/scan_qr_code.png deleted file mode 100644 index 87c85463c97059a56115c980686b9978af18e4e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 620 zcmV-y0+aoTP)CT58GK_4yt*e2ANnX00oqhAz zo!z!{#^dqha5!9!Mx#%Uq9|7McM@4tE*iemLI~bGaa#+CF}ao<@ASy?eBp`Pnk1Zi zeh)9`Rc7o-Aye4z^?FyHxUF@&-D}B_*&O5y3L?Oh{I!*$ss+i+JlJ1R1v`VZeSZk# zh!*67svyL-Du}l44%p}}DAf{&|kU#dUa4pvapgOO$Ou_1`v+nklAf|@=$ ztnG{8`m0CB(FH`heU|OaD~H+~I35rKyf#bzxnPMFNLGftZw2KIU-CKhm;rzwjYkANuKaL(a-TCse3^0~D(PpCwSCLV z)fctTwO0_!L^}qd;^dt1G3AG3j*lGpq6Gb?RSFupKO5ve({HsDRz9@*E=Ty!hJ9cM zc;dE3L3@4=|0(?go61jQTF@aB`YBDrcdD4p*^tO$a(w}ft8<0@V%M<%0000Px&Hc3Q5RCr$PTuXMO{mD1nvUg<5*K$$3YVfst6{> zb)Fz12YC-3BH{@5dj&ufed)oVR3z;H1?H1uVqu%R;XK5kYR~h?)gB|_4}n2^bO_nS zWAhx^!><0>u0hNomV;GIOm&&OXd>cs&!6B8=a|?LBB~n@nS6H>W3*pJ+cgOS2O$j^ z)EXe3pLczH4iWKEqmQ;8A(*_8G?3@1PMB#sCYa4?3@QLIfI-* z>oX{H^Va|%Cct-_#g_o#@nKG&$Zr3yvFRKZ9Haup9FvOMv^KGlHOvVV=Z~OZ)*)Q(+f4)G3U+;5v$*gL8>04 z=e1AFfUN>ldvT~`6y3x$?~|zR*u0x>szDBr;hrBoK*BMib@76xL2*Wr6vs08ZE#{= z5+Xkd1;%ipxOhQ0MrZ|8O--z|7wb`BwrT-Y0wB?2#`TA(IB4%`6t}>jRcjPm92LSb z)-thfWxyQ(TE0fH^-J^|uLpxn6YKdxt;cqN3`BbX zPfNo<5XE~C#ET+cy!0SML@YFI^QWOjf_M^dExpw5|2dpr*ol+r#-s-?4h-4O%)U4K zcC+bZu~@t=m&;?G=U+HuVv{qi7sm$Gvn<*&Ot<%qkZ? zpU+>U@ZbrEk<&Vrg)tJdk0*yk33zI(s;Vm*@C3xjX)HGP#9~E%Lcr3QjBmHw+dcwv zTF0Ex1VM8^8)vgTL5SI!!ythaOhb1u-)J4GF%wk1t z>?Q*){>dql`g>~RnRA-zy1uZO9UFU0>6|zuQvV*_l_%oqNxnwwx9=RO34LVErCkp qWov1%RM2|0pd$YN-{E=IOgWxRCz&=WrJDmU zJDv0SCYh7jOlLeEUyMehWtyhHj^Qnkl;UU z!n%bVHt#l2d&f?OAPx(gux^n&Gn+Sr0)gRh_$$k@uNvG|DL$Fc=g)1zx`iB4Lq<+p z2esLH3j{Eo*&QTCe z07nv78-zWHu?-TycH6!xC$jJnh?bUsl9s?Oa%u!tbPf`G@LoE@_o@W2#m5upBJWPC z+6mCRX@AUFP>|j!mJz@f9~&o+wbt*H+6cs;j6e*YJb@mGW5M%nV=-s#s(>17tX5iS zrJ^*oh>6?p_g^@jj9)4Lge|r9-C3Gyqr~N{>vV&`;6~{lgwPx9yR)1Wfql0UJT}f= zZ29{3*6n}9{?_S6|NhguR=RT=tFmYU>7JW8o_S|a@sLo2GNrqc-*@T)Z9c0+iy^Sr zc3Mlwo*d+II_$J>l(Ynt&?;H1K=ijfHrN62891H9`XF z1SCBu{j>;qt}GD!HLX(lCr(H45@Y0atQ8l7v96U1!Ie44$6YOt2OL_Yz;hFOWADz$ly3I}j$@OjL4aMQx_yse@o-xYam?E7cAwFe$Z6}) zJKn7XN-(nt>lVF$tDw+EL*NBs6V@%{uz9z^wbB31$U@NXh^8dEo-{ur3*CuaSAHf{ cgT&VJ7cd75Lu1pkF#rGn07*qoM6N<$g6OiC8vpO;Rk#iec&geVBao-p@V-^obHB zTZ)W~2RyJV9gojFqA8LgyO*ZvlgVWAeUc;>v)SzL`F#Fg9pEeYDCOS}V{gZ-wY>Dp zFM>ZM*uS$GT7g7nWe()>>XPsU`|rNT7eD{Ea2px4{W+ zmTz643EJ%08%-gBJ`1ia!M;s6{f0=EZ&S1(&?iy))DrC5gi|Jc$hGC$6r}>u#P}Ub zMSu99m7fVl=jZ2-EWy4_xF2L$_MLXN*Oq^dP$yn05Cx@z(ue7E`mNwux_ZU$ zTY`Pt?d|PX!gC-P!qxK6L5}2V^A8Gyx&*KlKQtppa<%zKfz(T-jx?{s8uzS!3t$@YBCn%0fkJ^cMb$Kgd)9wj zG|ejt6v(S|s=?TS*JIs4o1$-l$k8{Tyqjt;A@hv`7+^`DVIIgQkOcor{C?+m9RehL zL;t1%5km)lg*q(Y21mF2tSHd4`D(zsR*&F@7)ug}!G%;Oo)Dme96N6qpFj|h&$)aa zE*6W|RS=(q3N4YQ0%_ujjc)-bXfS9ZagLS_e4%2*VUj1` zGr4}iXfzMx6G+J(o}8R~jeiy7NxhQTA8f)+1tJEqYRJx{JBlIsX)Xq33?4qaH}CuI~D~BSQIE=QJ{cDfdUo<3Rn~< zU{Roe`2>;#u7ya#z>WJ=U};mzU)qE>5a_aMDL97?CKEXJCJ>`eo)Dv3o@@Y@w)}T8-ESTX*oNvKF{5a3Z2@n3>2A&`UZL;$XnM>|Hk!R9_mx; z+lfVi0u}`dSQIE=K7qPkFr!1Zaiq*#K7WLd3sw(ZKPmgOU`A(c{ML4uwPrqnCLJ%i zjy+rO5JyE?6Ylu<_$Sv-Tt?V~`BMS%hq z1qxUn0!f)6uWy5d4w-T;B-X_Ble#j&l#bf<>ug1_4}moCHGg9GS^%QBemgM^iUK+I zzZEETP6z7-#w#Ils%OCNjyaVHlybKX&J5^J1f_ zQ+|0$QS&OEdQMl{fT`ee2t z#kqd+?_ar>*P$(ped24p($J}A5@NFG1S$yB2C4+|S>3)&609{2B1dwy@z4ZqXvPK7 zzCaIEpio{>pg>-=1xkB3Q0Fsv&;f_y@V1gXM)Wzxx0?fXeH_X3S>AEih_lbzO0ExG zKXT~gNajPeC{VyQ7Km{`RX;bwG|OQ-O06Y%LJe2PS!z zVBeOkP7i*ze4C1?^sq$TB@xOUV>mSEr3 tT3)Gh>X{~G3zR{Bn$1rK-;=eK*B2)mHSk8Cg!upf002ovPDHLkV1luAtRnyb diff --git a/example/src/main/res/drawable-xxxhdpi/scan_qr_code.png b/example/src/main/res/drawable-xxxhdpi/scan_qr_code.png deleted file mode 100644 index 4d1d27b49953cf8a696d82f741e0fbf2ac334999..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1637 zcmV-r2AcVaP)-GA-LrCmwHv3~fpRbn7<+tR1 z3W%x?Kcs_WNxl{SDf~wV_9d~x_wxIKoD5vmQXHb|gBvW+jfau}v(@N=N<(yg*d?4R zwMIkeww4=RP-%#+5C4~j>{cPlmh-p#z10Pk25NA%)M^|;G)H?nsI44>W%rD8Ifd@Z%TrZ#sGRjXYS%^Gy9v6lfP z)Ppj#!@(?-X|CR*rmuw3id#Dfj!+rgOZ zb81T)9T%HJ^f3cQ;1GSxfDt%EA2VPC4$-G`I-2!Ob2@!H7?UL#fM#ve77x?W%-wKv zKsWGY{)0(>K}aYwAQ3`B znE{Cq63Prngpg2XKq7>MG6NDJB$OGD2qB@&fJ6uhWdw)PmeTgJj`i;Op11nBAJ2KPInM8V3GNyeQc#VZ)`T{BXzuX+SclT)JiP7ed~9!__wqv=(UwRI)VvJls+bs zXRZ77lvS^E3}iWC$?xBE43y;yJq|QOTU~>vi|zi780&FTcMvilCi@uBhC`1rEXM$6 zQZ0_0ItI3(bo8M#1KRm89nFCyG{-T7EB~FW z!Vz5`cXZ$C1|x9yovgwUT^~-dHkI#)4f%IOEL#f$Cg - - - diff --git a/example/src/main/res/drawable/cog.xml b/example/src/main/res/drawable/cog.xml new file mode 100644 index 0000000..23de2c0 --- /dev/null +++ b/example/src/main/res/drawable/cog.xml @@ -0,0 +1,9 @@ + + + diff --git a/example/src/main/res/drawable/wallet.xml b/example/src/main/res/drawable/wallet.xml new file mode 100644 index 0000000..80850e4 --- /dev/null +++ b/example/src/main/res/drawable/wallet.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/example/src/main/res/values/colors.xml b/example/src/main/res/values/colors.xml index 04f3b48..0e593cc 100644 --- a/example/src/main/res/values/colors.xml +++ b/example/src/main/res/values/colors.xml @@ -24,7 +24,10 @@ #FFE6E1D6 #FF75675C + #FF98C7F8 + #FF4389F2 #FF2F6AE1 + #FF243F84 #FFFAFAF9 #FFD6D3D1 #FFA8A29E diff --git a/example/src/main/res/values/strings.xml b/example/src/main/res/values/strings.xml index f76199e..a73d65b 100644 --- a/example/src/main/res/values/strings.xml +++ b/example/src/main/res/values/strings.xml @@ -18,8 +18,8 @@ Click to expand Click to collapse Error - Click on the button to add your first credential Read this QR Code to start the verification Start flow Restart + Settings \ No newline at end of file