From 7ae95ac8b9f4b9ba4d410ef2d7091c4a99c19f01 Mon Sep 17 00:00:00 2001 From: Yogesh Choudhary Paliyal Date: Sun, 18 May 2025 15:34:54 +0530 Subject: [PATCH] improve bottom nav bar on home --- .../yogeshpaliyal/keypass/MyApplication.kt | 4 +- .../keypass/ui/about/AboutScreen.kt | 42 ++++--- .../ui/backup/KeyPassBackupDirectoryPick.kt | 2 +- .../ui/backupsImport/BackupImporter.kt | 6 +- .../ChangeDefaultPasswordLengthScreen.kt | 115 +++++------------- .../ui/changePassword/ChangePassword.kt | 7 +- .../ui/commonComponents/DefaultTopAppBar.kt | 7 +- .../keypass/ui/detail/AccountDetailPage.kt | 8 +- .../keypass/ui/detail/QRScanner.kt | 2 +- .../keypass/ui/detail/components/BottomBar.kt | 37 ++++-- .../keypass/ui/nav/BottomNavViewModel.kt | 2 +- .../ui/nav/DashboardComposeActivity.kt | 8 +- .../keypass/ui/nav/NavigationModel.kt | 31 ++--- .../keypass/ui/nav/NavigationModelItem.kt | 2 +- .../ui/nav/components/DashboardBottomSheet.kt | 6 +- .../ui/nav/components/KeyPassBottomBar.kt | 28 +++-- .../ui/nav/components/NavItemSection.kt | 9 +- .../ui/passwordHint/PasswordHintScreen.kt | 28 ++--- .../middlewares/IntentNavigationMiddleware.kt | 3 + .../keypass/ui/settings/MySettingsFragment.kt | 4 +- .../keypass/ui/settings/OpenKeyPassBackup.kt | 2 +- app/src/main/res/values/strings.xml | 4 + 22 files changed, 168 insertions(+), 189 deletions(-) diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/MyApplication.kt b/app/src/main/java/com/yogeshpaliyal/keypass/MyApplication.kt index 7841ba75..b4011874 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/MyApplication.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/MyApplication.kt @@ -17,11 +17,11 @@ class MyApplication : CommonMyApplication() { private var timeToLaunchActivity : Long? = null - fun activityLaunchTriggered() { + fun knownActivityLaunchTriggered() { timeToLaunchActivity = SystemClock.uptimeMillis() } - fun isActivityLaunchTriggered() : Boolean { + fun isKnownActivityLaunchTriggered() : Boolean { val mTimeToLaunchActivity = timeToLaunchActivity ?: return false timeToLaunchActivity = null return SystemClock.uptimeMillis() - mTimeToLaunchActivity < 1000 diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/about/AboutScreen.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/about/AboutScreen.kt index 52b1cf68..65f828b7 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/about/AboutScreen.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/about/AboutScreen.kt @@ -30,11 +30,13 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -47,6 +49,7 @@ import com.yogeshpaliyal.common.utils.openLink import com.yogeshpaliyal.keypass.BuildConfig import com.yogeshpaliyal.keypass.R import com.yogeshpaliyal.keypass.ui.commonComponents.DefaultBottomAppBar +import com.yogeshpaliyal.keypass.ui.commonComponents.DefaultTopAppBar import com.yogeshpaliyal.keypass.ui.commonComponents.PreferenceItem import com.yogeshpaliyal.keypass.ui.redux.actions.Action import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction @@ -54,15 +57,12 @@ import org.reduxkotlin.compose.rememberTypedDispatcher @Composable fun AboutScreen() { - val dispatchAction = rememberTypedDispatcher() - + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() Scaffold( - bottomBar = { - // Add back button to bottom bar - DefaultBottomAppBar( - showBackButton = true - ) - } + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + topBar = { + DefaultTopAppBar(title = R.string.app_name, scrollBehavior = scrollBehavior) + }, ) { contentPadding -> Surface( modifier = Modifier @@ -98,9 +98,11 @@ private fun MainContent() { horizontalAlignment = Alignment.CenterHorizontally ) { // App Info Card - ElevatedCard( + Card( modifier = Modifier.fillMaxWidth(), - elevation = CardDefaults.elevatedCardElevation(defaultElevation = 2.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainerLow + ), shape = RoundedCornerShape(16.dp) ) { Column( @@ -124,13 +126,13 @@ private fun MainContent() { Spacer(modifier = Modifier.height(16.dp)) - // App Name - Text( - text = stringResource(id = R.string.app_name), - style = MaterialTheme.typography.headlineMedium, - fontWeight = FontWeight.Bold, - color = MaterialTheme.colorScheme.primary - ) +// // App Name +// Text( +// text = stringResource(id = R.string.app_name), +// style = MaterialTheme.typography.headlineMedium, +// fontWeight = FontWeight.Bold, +// color = MaterialTheme.colorScheme.primary +// ) Spacer(modifier = Modifier.height(4.dp)) @@ -203,9 +205,11 @@ private fun MainContent() { textAlign = TextAlign.Start ) - ElevatedCard( + Card( modifier = Modifier.fillMaxWidth(), - elevation = CardDefaults.elevatedCardElevation(defaultElevation = 2.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainerLow + ), shape = RoundedCornerShape(16.dp) ) { Column(modifier = Modifier.fillMaxWidth()) { diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/backup/KeyPassBackupDirectoryPick.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/backup/KeyPassBackupDirectoryPick.kt index 710f0198..e80e7ec1 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/backup/KeyPassBackupDirectoryPick.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/backup/KeyPassBackupDirectoryPick.kt @@ -15,7 +15,7 @@ class KeyPassBackupDirectoryPick : ActivityResultContracts.OpenDocument() { Intent.FLAG_GRANT_WRITE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION ) - (context.applicationContext as? MyApplication)?.activityLaunchTriggered() + (context.applicationContext as? MyApplication)?.knownActivityLaunchTriggered() return intent } diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/backupsImport/BackupImporter.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/backupsImport/BackupImporter.kt index 724ab38b..a0e5d518 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/backupsImport/BackupImporter.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/backupsImport/BackupImporter.kt @@ -197,11 +197,13 @@ fun BackupImporter(state: BackupImporterState, mViewModel: DashboardViewModel = @Composable private fun ImportOptionCard(option: ImportOption, onClick: () -> Unit) { val desc = option.importer.getImporterDesc() - ElevatedCard( + Card( modifier = Modifier .fillMaxWidth() .padding(vertical = 8.dp), - elevation = CardDefaults.elevatedCardElevation(defaultElevation = 1.dp), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainerLow + ), onClick = onClick, shape = RoundedCornerShape(12.dp) ) { diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/changeDefaultPasswordLength/ChangeDefaultPasswordLengthScreen.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/changeDefaultPasswordLength/ChangeDefaultPasswordLengthScreen.kt index e439d5f3..5c54cdc6 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/changeDefaultPasswordLength/ChangeDefaultPasswordLengthScreen.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/changeDefaultPasswordLength/ChangeDefaultPasswordLengthScreen.kt @@ -1,10 +1,6 @@ package com.yogeshpaliyal.keypass.ui.changeDefaultPasswordLength -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut 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.Spacer @@ -12,25 +8,17 @@ 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.rounded.ArrowBackIosNew import androidx.compose.material.icons.rounded.Done -import androidx.compose.material.icons.rounded.Info -import androidx.compose.material3.BottomAppBar import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults -import androidx.compose.material3.ElevatedCard import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.LinearProgressIndicator import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf @@ -50,6 +38,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.yogeshpaliyal.keypass.R +import com.yogeshpaliyal.keypass.ui.commonComponents.DefaultTopAppBar import com.yogeshpaliyal.keypass.ui.generate.ui.components.PasswordLengthInput import com.yogeshpaliyal.keypass.ui.redux.actions.Action import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction @@ -66,7 +55,13 @@ fun ChangeDefaultPasswordLengthScreen( val state by viewModel.viewState.collectAsState() Scaffold( - bottomBar = { BottomBar(dispatchAction, viewModel) } + topBar = { + DefaultTopAppBar( + title = R.string.choose_default_password_length, + subtitle = R.string.choose_default_password_length_desc + ) + }, + floatingActionButton = { FloatingActionButton(dispatchAction, viewModel) } ) { contentPadding -> Surface( modifier = Modifier @@ -97,16 +92,11 @@ private fun ChangeDefaultPasswordLengthContent( ) { // Password length input with improved UI - Text( - text = stringResource(R.string.choose_default_password_length), - style = MaterialTheme.typography.headlineSmall, - fontWeight = FontWeight.SemiBold, - textAlign = TextAlign.Start - ) - - ElevatedCard( + Card( modifier = Modifier.fillMaxWidth(), - elevation = CardDefaults.elevatedCardElevation(defaultElevation = 1.dp) + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainerLow + ) ) { Column( modifier = Modifier.padding(16.dp), @@ -130,38 +120,6 @@ private fun ChangeDefaultPasswordLengthContent( } Spacer(modifier = Modifier.height(8.dp)) - - // Information card - InfoCard() - } -} - -@Composable -private fun InfoCard() { - Card( - modifier = Modifier.fillMaxWidth(), - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.secondaryContainer.copy(alpha = 0.7f) - ) - ) { - Row( - modifier = Modifier.padding(16.dp), - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - imageVector = Icons.Rounded.Info, - contentDescription = null, - tint = MaterialTheme.colorScheme.onSecondaryContainer, - modifier = Modifier.size(24.dp) - ) - Text( - text = "This length will be used as default when generating new passwords. " + - "Longer passwords provide better security.", - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.onSecondaryContainer, - modifier = Modifier.padding(start = 12.dp) - ) - } } } @@ -231,44 +189,29 @@ private fun PasswordStrengthIndicator(strength: PasswordStrength) { } @Composable -private fun BottomBar( +private fun FloatingActionButton( dispatchAction: TypedDispatcher, viewModel: ChangeDefaultPasswordLengthViewModel ) { val context = LocalContext.current - BottomAppBar( - actions = { - // Add back button on the left side - IconButton( - onClick = { dispatchAction(GoBackAction) } - ) { - Icon( - painter = rememberVectorPainter(image = Icons.Rounded.ArrowBackIosNew), - contentDescription = "Cancel", - tint = MaterialTheme.colorScheme.onSurfaceVariant - ) + + FloatingActionButton( + modifier = Modifier.testTag("save"), + onClick = { + // Save new password length + viewModel.updatePasswordLength(context) { + // Close screen + dispatchAction(GoBackAction) } }, - floatingActionButton = { - FloatingActionButton( - modifier = Modifier.testTag("save"), - onClick = { - // Save new password length - viewModel.updatePasswordLength(context) { - // Close screen - dispatchAction(GoBackAction) - } - }, - containerColor = MaterialTheme.colorScheme.primaryContainer - ) { - Icon( - painter = rememberVectorPainter(image = Icons.Rounded.Done), - contentDescription = "Save Changes", - tint = MaterialTheme.colorScheme.onPrimaryContainer - ) - } - } - ) + containerColor = MaterialTheme.colorScheme.primaryContainer + ) { + Icon( + painter = rememberVectorPainter(image = Icons.Rounded.Done), + contentDescription = "Save Changes", + tint = MaterialTheme.colorScheme.onPrimaryContainer + ) + } } @Preview(name = "ChangeDefaultPasswordLength", showBackground = true, showSystemUi = true) diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/changePassword/ChangePassword.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/changePassword/ChangePassword.kt index 2afe7f9c..ec6c510a 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/changePassword/ChangePassword.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/changePassword/ChangePassword.kt @@ -149,7 +149,7 @@ fun ChangePassword(state: ChangeAppPasswordState) { Card( modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors( - containerColor = MaterialTheme.colorScheme.secondaryContainer + containerColor = MaterialTheme.colorScheme.surfaceContainerLow ) ) { Column( @@ -176,7 +176,10 @@ fun ChangePassword(state: ChangeAppPasswordState) { // Password input fields in a card Card( - modifier = Modifier.fillMaxWidth() + modifier = Modifier.fillMaxWidth(), + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainerLow + ) ) { Column( modifier = Modifier diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/commonComponents/DefaultTopAppBar.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/commonComponents/DefaultTopAppBar.kt index f732f758..8d918c56 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/commonComponents/DefaultTopAppBar.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/commonComponents/DefaultTopAppBar.kt @@ -9,9 +9,11 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.LargeFlexibleTopAppBar import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarScrollBehavior import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.res.stringResource import com.yogeshpaliyal.keypass.ui.redux.actions.Action @@ -36,12 +38,11 @@ fun DefaultTopAppBar( text = stringResource(id = subtitle), ) } - }, title = { + }, colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Unspecified, scrolledContainerColor = MaterialTheme.colorScheme.surface), + title = { Text( text = stringResource(id = title), ) - - }, actions = { extraAction?.invoke(this) }, navigationIcon = { diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/AccountDetailPage.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/AccountDetailPage.kt index a7c2f55a..93b4f842 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/AccountDetailPage.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/AccountDetailPage.kt @@ -33,6 +33,7 @@ import com.yogeshpaliyal.common.constants.ScannerType import com.yogeshpaliyal.common.utils.TOTPHelper import com.yogeshpaliyal.keypass.R import com.yogeshpaliyal.keypass.ui.detail.components.BottomBar +import com.yogeshpaliyal.keypass.ui.detail.components.FABAddAccount import com.yogeshpaliyal.keypass.ui.detail.components.Fields import com.yogeshpaliyal.keypass.ui.redux.actions.CopyToClipboard import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction @@ -104,7 +105,7 @@ fun AccountDetailPage( } } Scaffold( - bottomBar = { + topBar = { BottomBar( accountModel, backPressed = goBack, @@ -120,7 +121,10 @@ fun AccountDetailPage( openPasswordConfiguration = { dispatchAction(NavigationAction(PasswordGeneratorState())) } - ) { + ) + }, + floatingActionButton = { + FABAddAccount{ viewModel.insertOrUpdate(accountModel, goBack) } } diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/QRScanner.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/QRScanner.kt index e05a3308..cb6b5d85 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/QRScanner.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/QRScanner.kt @@ -20,7 +20,7 @@ class QRScanner : ActivityResultContract() { } else { null } - (context.applicationContext as? MyApplication)?.activityLaunchTriggered() + (context.applicationContext as? MyApplication)?.knownActivityLaunchTriggered() return intentIntegration?.setPrompt("")?.createScanIntent() ?: Intent() } diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/components/BottomBar.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/components/BottomBar.kt index 09ce4d6a..9d03167f 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/components/BottomBar.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/detail/components/BottomBar.kt @@ -7,18 +7,24 @@ import androidx.compose.material.icons.rounded.ArrowBackIosNew import androidx.compose.material.icons.rounded.Delete import androidx.compose.material.icons.rounded.Done import androidx.compose.material3.BottomAppBar +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.LargeFlexibleTopAppBar import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.platform.testTag +import androidx.compose.ui.res.stringResource import com.yogeshpaliyal.common.data.AccountModel +import com.yogeshpaliyal.keypass.R +@OptIn(ExperimentalMaterial3ExpressiveApi::class) @Composable fun BottomBar( accountModel: AccountModel, @@ -26,12 +32,17 @@ fun BottomBar( onDeleteAccount: () -> Unit, generateQrCodeClicked: () -> Unit, openPasswordConfiguration: () -> Unit, - onSaveClicked: () -> Unit ) { val openDialog = remember { mutableStateOf(false) } - BottomAppBar( - actions = { + LargeFlexibleTopAppBar( + title = { + Text( + text = stringResource(if (accountModel.id == null) R.string.create_account else R.string.edit_account), + color = MaterialTheme.colorScheme.onSurface + ) + }, + navigationIcon = { IconButton(onClick = backPressed) { Icon( painter = rememberVectorPainter(image = Icons.Rounded.ArrowBackIosNew), @@ -39,6 +50,8 @@ fun BottomBar( tint = MaterialTheme.colorScheme.onSurface ) } + }, + actions = { IconButton( modifier = Modifier.testTag("action_configure_password"), @@ -73,14 +86,6 @@ fun BottomBar( ) } } - }, - floatingActionButton = { - FloatingActionButton(modifier = Modifier.testTag("save"), onClick = onSaveClicked) { - Icon( - painter = rememberVectorPainter(image = Icons.Rounded.Done), - contentDescription = "Save Changes" - ) - } } ) @@ -92,3 +97,13 @@ fun BottomBar( onDeleteAccount ) } + +@Composable +fun FABAddAccount(onSaveClicked: () -> Unit) { + FloatingActionButton(modifier = Modifier.testTag("save"), onClick = onSaveClicked) { + Icon( + painter = rememberVectorPainter(image = Icons.Rounded.Done), + contentDescription = "Save Changes" + ) + } +} diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/BottomNavViewModel.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/BottomNavViewModel.kt index 8c142b2e..d03418b8 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/BottomNavViewModel.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/BottomNavViewModel.kt @@ -41,7 +41,7 @@ class BottomNavViewModel @Inject constructor( private fun postListUpdate() { val newList = if (tagsList.isNullOrEmpty().not()) { - NavigationModel.navigationMenuItems + NavigationModelItem.NavDivider("Tags") + ( + mutableListOf() + NavigationModelItem.NavDivider("Tags", true) + ( tagsList?.filter { it != null } ?.map { NavigationModelItem.NavTagItem(it) } ?: listOf() ) diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/DashboardComposeActivity.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/DashboardComposeActivity.kt index 23cebfd5..4a7ae70e 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/DashboardComposeActivity.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/DashboardComposeActivity.kt @@ -112,7 +112,7 @@ class DashboardComposeActivity : AppCompatActivity() { } @Composable -fun Dashboard() { +fun Dashboard(viewModel: BottomNavViewModel = androidx.lifecycle.viewmodel.compose.viewModel()) { val systemBackPress by selectState { this.systemBackPress } val context = LocalContext.current @@ -124,7 +124,7 @@ fun Dashboard() { // Call this like any other SideEffect in your composable LifecycleEventEffect(Lifecycle.Event.ON_PAUSE) { if (userSettings.autoLockEnabled == true && - (context.applicationContext as? MyApplication)?.isActivityLaunchTriggered() == false) { + (context.applicationContext as? MyApplication)?.isKnownActivityLaunchTriggered() == false) { dispatch(NavigationAction(AuthState.Login)) } } @@ -142,12 +142,12 @@ fun Dashboard() { onDispose { dispatch(UpdateContextAction(null)) } } - Scaffold(bottomBar = { KeyPassBottomBar() }, modifier = Modifier.safeDrawingPadding()) { + Scaffold(bottomBar = { KeyPassBottomBar(viewModel) }, modifier = Modifier.safeDrawingPadding()) { paddingValues -> Surface(modifier = Modifier.padding(paddingValues)) { CurrentPage() - DashboardBottomSheet() + DashboardBottomSheet(viewModel) } } } diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/NavigationModel.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/NavigationModel.kt index f3e30f01..c53c8a37 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/NavigationModel.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/NavigationModel.kt @@ -1,6 +1,7 @@ package com.yogeshpaliyal.keypass.ui.nav import com.yogeshpaliyal.keypass.R +import com.yogeshpaliyal.keypass.ui.nav.NavigationModelItem.NavMenuItem import com.yogeshpaliyal.keypass.ui.redux.actions.IntentNavigation import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction import com.yogeshpaliyal.keypass.ui.redux.states.HomeState @@ -11,20 +12,20 @@ object NavigationModel { const val GENERATE_PASSWORD = 1 const val ADD_TOPT = 2 - var navigationMenuItems = mutableListOf( - NavigationModelItem.NavMenuItem( - id = HOME, - icon = R.drawable.ic_twotone_home_24, - titleRes = R.string.home, - checked = false, - action = NavigationAction(HomeState(), true) - ), - NavigationModelItem.NavMenuItem( - id = GENERATE_PASSWORD, - icon = R.drawable.ic_twotone_vpn_key_24, - titleRes = R.string.generate_password, - checked = false, - action = IntentNavigation.GeneratePassword - ) + var navigationMenuItems = mutableListOf( +// NavigationModelItem.NavMenuItem( +// id = HOME, +// icon = R.drawable.ic_twotone_home_24, +// titleRes = R.string.home, +// checked = false, +// action = NavigationAction(HomeState(), true) +// ), +// NavigationModelItem.NavMenuItem( +// id = GENERATE_PASSWORD, +// icon = R.drawable.ic_twotone_vpn_key_24, +// titleRes = R.string.generate_password, +// checked = false, +// action = IntentNavigation.GeneratePassword +// ) ) } diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/NavigationModelItem.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/NavigationModelItem.kt index 0840910f..f1c9f789 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/NavigationModelItem.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/NavigationModelItem.kt @@ -18,7 +18,7 @@ sealed class NavigationModelItem { * A class which is used to show a section divider (a subtitle and underline) between * sections of different NavigationModelItem types. */ - data class NavDivider(val title: String) : NavigationModelItem() + data class NavDivider(val title: String, val hideDivider: Boolean = false) : NavigationModelItem() data class NavTagItem(val tag: String) : NavigationModelItem() } diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/DashboardBottomSheet.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/DashboardBottomSheet.kt index a4e0d08b..156b52bb 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/DashboardBottomSheet.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/DashboardBottomSheet.kt @@ -21,19 +21,19 @@ import org.reduxkotlin.compose.rememberDispatcher import org.reduxkotlin.compose.selectState @Composable -fun DashboardBottomSheet() { +fun DashboardBottomSheet(viewModel: BottomNavViewModel) { val bottomSheetState by selectState { this.bottomSheet } if (bottomSheetState?.isBottomSheetOpen != true) { return } - OptionBottomBar() + OptionBottomBar(viewModel) } @Composable fun OptionBottomBar( - viewModel: BottomNavViewModel = androidx.lifecycle.viewmodel.compose.viewModel() + viewModel: BottomNavViewModel ) { val dispatchAction = rememberDispatcher() diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/KeyPassBottomBar.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/KeyPassBottomBar.kt index 5a505372..f55475a3 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/KeyPassBottomBar.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/KeyPassBottomBar.kt @@ -1,13 +1,11 @@ package com.yogeshpaliyal.keypass.ui.nav.components -import androidx.compose.foundation.selection.selectable import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Home import androidx.compose.material.icons.outlined.Menu import androidx.compose.material.icons.outlined.Settings +import androidx.compose.material.icons.outlined.VpnKey import androidx.compose.material.icons.rounded.Add -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -16,11 +14,14 @@ import androidx.compose.material3.IconToggleButton import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.rememberVectorPainter import androidx.compose.ui.platform.testTag import com.yogeshpaliyal.keypass.ui.commonComponents.DefaultBottomAppBar +import com.yogeshpaliyal.keypass.ui.nav.BottomNavViewModel import com.yogeshpaliyal.keypass.ui.redux.actions.BottomSheetAction +import com.yogeshpaliyal.keypass.ui.redux.actions.IntentNavigation import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction import com.yogeshpaliyal.keypass.ui.redux.states.AccountDetailState import com.yogeshpaliyal.keypass.ui.redux.states.HomeState @@ -34,10 +35,11 @@ import org.reduxkotlin.compose.selectState @Composable -fun KeyPassBottomBar() { +fun KeyPassBottomBar(viewModel: BottomNavViewModel) { val currentScreen: ScreenState by selectState { this.currentScreen } val showMainBottomAppBar = currentScreen.showMainBottomAppBar val dispatchAction = rememberDispatcher() + val navigationItems by viewModel.navigationList.observeAsState() if (!showMainBottomAppBar) { return @@ -59,15 +61,27 @@ fun KeyPassBottomBar() { } IconButton(onClick = { - dispatchAction(BottomSheetAction.HomeNavigationMenu(true)) + dispatchAction(IntentNavigation.GeneratePassword) }) { Icon( - painter = rememberVectorPainter(image = Icons.Outlined.Menu), - contentDescription = "Menu", + painter = rememberVectorPainter(image = Icons.Outlined.VpnKey), + contentDescription = "Generate Password", tint = MaterialTheme.colorScheme.onSurface ) } + if (navigationItems?.isNotEmpty() == true) { + IconButton(onClick = { + dispatchAction(BottomSheetAction.HomeNavigationMenu(true)) + }) { + Icon( + painter = rememberVectorPainter(image = Icons.Outlined.Menu), + contentDescription = "Menu", + tint = MaterialTheme.colorScheme.onSurface + ) + } + } + IconToggleButton(colors = IconButtonDefaults.iconToggleButtonColors( checkedContainerColor = MaterialTheme.colorScheme.primaryContainer, checkedContentColor = MaterialTheme.colorScheme.onPrimaryContainer diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/NavItemSection.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/NavItemSection.kt index b35d00fd..18bfa2e8 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/NavItemSection.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/components/NavItemSection.kt @@ -18,12 +18,13 @@ import java.util.Locale @Composable fun NavItemSection(divider: NavigationModelItem.NavDivider) { Column(modifier = Modifier.padding(16.dp)) { - Divider() - Spacer(modifier = Modifier.height(32.dp)) + if (!divider.hideDivider) { + Divider() + Spacer(modifier = Modifier.height(32.dp)) + } Text( text = divider.title.uppercase(Locale.getDefault()), - style = MaterialTheme.typography.labelMedium, - fontSize = TextUnit(12f, TextUnitType.Sp) + style = MaterialTheme.typography.titleLarge ) } } diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/passwordHint/PasswordHintScreen.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/passwordHint/PasswordHintScreen.kt index 828391e9..27441697 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/passwordHint/PasswordHintScreen.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/passwordHint/PasswordHintScreen.kt @@ -40,6 +40,7 @@ import androidx.compose.ui.unit.dp import com.yogeshpaliyal.common.utils.setPasswordHint import com.yogeshpaliyal.keypass.R import com.yogeshpaliyal.keypass.ui.commonComponents.DefaultBottomAppBar +import com.yogeshpaliyal.keypass.ui.commonComponents.DefaultTopAppBar import com.yogeshpaliyal.keypass.ui.commonComponents.KeyPassInputField import com.yogeshpaliyal.keypass.ui.nav.LocalUserSettings import com.yogeshpaliyal.keypass.ui.redux.actions.Action @@ -61,10 +62,8 @@ fun PasswordHintScreen() { var showInfoDialog by remember { mutableStateOf(false) } Scaffold( - bottomBar = { - DefaultBottomAppBar( - showBackButton = true - ) + topBar = { + DefaultTopAppBar(title = R.string.app_password_hint, subtitle = R.string.app_password_hint_desc) } ) { contentPadding -> Surface( @@ -78,26 +77,13 @@ fun PasswordHintScreen() { .padding(16.dp), verticalArrangement = Arrangement.spacedBy(16.dp) ) { - // Title and Description - Text( - text = stringResource(id = R.string.app_password_hint), - style = MaterialTheme.typography.headlineMedium, - fontWeight = FontWeight.Bold - ) - - Text( - text = "A password hint helps you remember your password if you forget it. " + - "Make sure it's a hint only you would understand.", - style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.onSurfaceVariant - ) - - Spacer(modifier = Modifier.height(8.dp)) // Input Card - ElevatedCard( + Card( modifier = Modifier.fillMaxWidth(), - elevation = CardDefaults.elevatedCardElevation(defaultElevation = 2.dp) + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.colorScheme.surfaceContainerLow + ) ) { Column( modifier = Modifier.padding(16.dp), diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/redux/middlewares/IntentNavigationMiddleware.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/redux/middlewares/IntentNavigationMiddleware.kt index 9ca00385..50981f8d 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/redux/middlewares/IntentNavigationMiddleware.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/redux/middlewares/IntentNavigationMiddleware.kt @@ -2,6 +2,7 @@ package com.yogeshpaliyal.keypass.ui.redux.middlewares import android.content.Intent import com.yogeshpaliyal.keypass.BuildConfig +import com.yogeshpaliyal.keypass.MyApplication import com.yogeshpaliyal.keypass.R import com.yogeshpaliyal.keypass.ui.generate.GeneratePasswordActivity import com.yogeshpaliyal.keypass.ui.redux.actions.BatchActions @@ -29,11 +30,13 @@ val intentNavigationMiddleware = middleware { store, next, action private fun Store.handleAction(action: Any, state: KeyPassState) { when (action) { is IntentNavigation.GeneratePassword -> { + (state.context?.applicationContext as? MyApplication)?.knownActivityLaunchTriggered() val intent = Intent(state.context, GeneratePasswordActivity::class.java) state.context?.startActivity(intent) } is IntentNavigation.ShareApp -> { + (state.context?.applicationContext as? MyApplication)?.knownActivityLaunchTriggered() val sendIntent = Intent() sendIntent.action = Intent.ACTION_SEND sendIntent.putExtra( diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/MySettingsFragment.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/MySettingsFragment.kt index aab6f8ad..5553aa50 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/MySettingsFragment.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/MySettingsFragment.kt @@ -11,7 +11,6 @@ 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.rememberScrollState import androidx.compose.foundation.verticalScroll @@ -25,7 +24,6 @@ import androidx.compose.material.icons.rounded.Share import androidx.compose.material.icons.filled.Search import androidx.compose.material.icons.filled.KeyboardArrowDown import androidx.compose.material.icons.filled.KeyboardArrowUp -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.OutlinedTextField @@ -339,7 +337,7 @@ fun MySettingCompose() { PreferenceType.AUTO_FILL -> { val autoFillClick = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { { - (context.applicationContext as? MyApplication)?.activityLaunchTriggered() + (context.applicationContext as? MyApplication)?.knownActivityLaunchTriggered() context.enableAutoFillService() } } else null diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/OpenKeyPassBackup.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/OpenKeyPassBackup.kt index b2ce18bd..05b6f9bc 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/OpenKeyPassBackup.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/OpenKeyPassBackup.kt @@ -18,7 +18,7 @@ class OpenKeyPassBackup(val importer: T?) : ActivityResult Intent.FLAG_GRANT_READ_URI_PERMISSION ) - (context.applicationContext as? MyApplication)?.activityLaunchTriggered() + (context.applicationContext as? MyApplication)?.knownActivityLaunchTriggered() return intent } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8f01cf6f..5faddd54 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -50,6 +50,8 @@ Backups are encrypted with a passphrase and stored on your device Yes Create Backup + Create Account + Edit Account Alert Copy This Key Phrase this will be used to recover this backup, this will not be provided by KeyPass Again, have you copied or written down? Help @@ -94,6 +96,7 @@ Change Hint Remove Hint App Password Hint + A password hint helps you remember your password if you forget it. Make sure it\'s a hint only you would understand. Set App Password Hint Change App Password Hint Old Password @@ -144,6 +147,7 @@ Contact Developer Send an email for support, feedback, or suggestions Choose Default Password Length + This length will be used as default when generating new passwords. Longer passwords provide better security.