Skip to content

Commit

Permalink
[Android][iOS] Improve home tabs (#45)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Juliano1612 authored Nov 14, 2024
1 parent 2f23aaa commit c1e09a1
Show file tree
Hide file tree
Showing 30 changed files with 241 additions and 148 deletions.
141 changes: 102 additions & 39 deletions example/src/main/java/com/spruceid/mobilesdkexample/HomeView.kt
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -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,
Expand All @@ -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,
)
}
}
}
}
}

}
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down Expand Up @@ -79,18 +77,6 @@ fun ScanningComponent(
},
)

fun backHome() {
navController.popBackStack()
}

fun internalOnCancel() {
if (onCancel != null) {
onCancel()
} else {
backHome()
}
}

Column(
modifier = Modifier.fillMaxSize(),
) {
Expand All @@ -104,7 +90,7 @@ fun ScanningComponent(
cancelButtonLabel = "Cancel",
onRead = onRead,
isMatch = isMatch,
onCancel = ::internalOnCancel,
onCancel = onCancel,
fontFamily = Inter,
readerColor = Color.White,
guidesColor = Color.White,
Expand All @@ -118,7 +104,7 @@ fun ScanningComponent(
cancelButtonLabel = "Cancel",
onRead = onRead,
isMatch = isMatch,
onCancel = ::internalOnCancel,
onCancel = onCancel,
fontFamily = Inter,
readerColor = Color.White,
guidesColor = Color.White,
Expand All @@ -132,7 +118,7 @@ fun ScanningComponent(
cancelButtonLabel = "Cancel",
onRead = onRead,
isMatch = isMatch,
onCancel = ::internalOnCancel,
onCancel = onCancel,
fontFamily = Inter,
readerColor = Color.White,
guidesColor = Color.White,
Expand All @@ -144,9 +130,7 @@ fun ScanningComponent(
AlertDialog(
containerColor = Color.White,
shape = RoundedCornerShape(8.dp),
onDismissRequest = {
backHome()
},
onDismissRequest = onCancel,
title = {
Text(
"Camera permission denied",
Expand Down Expand Up @@ -189,9 +173,7 @@ fun ScanningComponent(
},
dismissButton = {
Button(
onClick = {
backHome()
},
onClick = onCancel,
colors =
ButtonDefaults.buttonColors(
containerColor = Color.Transparent,
Expand Down
Original file line number Diff line number Diff line change
@@ -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"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ fun AddVerificationMethodView(
var qrcode by remember { mutableStateOf<String?>(null) }

fun back() {
navController.navigate(Screen.HomeScreen.route) {
navController.navigate(
Screen.HomeScreen.route.replace("{tab}", "verifier")
) {
popUpTo(0)
}
}
Expand Down Expand Up @@ -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(
Expand Down
Loading

0 comments on commit c1e09a1

Please sign in to comment.