mirror of
https://github.com/yogeshpaliyal/KeyPass.git
synced 2025-12-31 00:59:51 -06:00
improve bottom nav bar on home
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<Action>()
|
||||
|
||||
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()) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
) {
|
||||
|
||||
@@ -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<Action>,
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class QRScanner : ActivityResultContract<Int, QRScannerResult>() {
|
||||
} else {
|
||||
null
|
||||
}
|
||||
(context.applicationContext as? MyApplication)?.activityLaunchTriggered()
|
||||
(context.applicationContext as? MyApplication)?.knownActivityLaunchTriggered()
|
||||
return intentIntegration?.setPrompt("")?.createScanIntent() ?: Intent()
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ class BottomNavViewModel @Inject constructor(
|
||||
|
||||
private fun postListUpdate() {
|
||||
val newList = if (tagsList.isNullOrEmpty().not()) {
|
||||
NavigationModel.navigationMenuItems + NavigationModelItem.NavDivider("Tags") + (
|
||||
mutableListOf<NavigationModelItem>() + NavigationModelItem.NavDivider("Tags", true) + (
|
||||
tagsList?.filter { it != null }
|
||||
?.map { NavigationModelItem.NavTagItem(it) } ?: listOf()
|
||||
)
|
||||
|
||||
@@ -112,7 +112,7 @@ class DashboardComposeActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Dashboard() {
|
||||
fun Dashboard(viewModel: BottomNavViewModel = androidx.lifecycle.viewmodel.compose.viewModel()) {
|
||||
val systemBackPress by selectState<KeyPassState, Boolean> { 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<NavMenuItem>(
|
||||
// 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
|
||||
// )
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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<KeyPassState, BottomSheetState?> { 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()
|
||||
|
||||
|
||||
@@ -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<KeyPassState, ScreenState> { 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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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<KeyPassState> { store, next, action
|
||||
private fun Store<KeyPassState>.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(
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -18,7 +18,7 @@ class OpenKeyPassBackup<T : AccountsImporter>(val importer: T?) : ActivityResult
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
)
|
||||
|
||||
(context.applicationContext as? MyApplication)?.activityLaunchTriggered()
|
||||
(context.applicationContext as? MyApplication)?.knownActivityLaunchTriggered()
|
||||
|
||||
return intent
|
||||
}
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
<string name="backup_desc">Backups are encrypted with a passphrase and stored on your device</string>
|
||||
<string name="yes">Yes</string>
|
||||
<string name="create_backup">Create Backup</string>
|
||||
<string name="create_account">Create Account</string>
|
||||
<string name="edit_account">Edit Account</string>
|
||||
<string name="alert">Alert</string>
|
||||
<string name="copy_keypharse_msg">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?</string>
|
||||
<string name="help">Help</string>
|
||||
@@ -94,6 +96,7 @@
|
||||
<string name="change_app_hint">Change Hint</string>
|
||||
<string name="remove_app_hint">Remove Hint</string>
|
||||
<string name="app_password_hint">App Password Hint</string>
|
||||
<string name="app_password_hint_desc">A password hint helps you remember your password if you forget it. Make sure it\'s a hint only you would understand.</string>
|
||||
<string name="set_app_password_hint">Set App Password Hint</string>
|
||||
<string name="change_app_password_hint">Change App Password Hint</string>
|
||||
<string name="old_password">Old Password</string>
|
||||
@@ -144,6 +147,7 @@
|
||||
<string name="contact_developer">Contact Developer</string>
|
||||
<string name="contact_via_email">Send an email for support, feedback, or suggestions</string>
|
||||
<string name="choose_default_password_length">Choose Default Password Length</string>
|
||||
<string name="choose_default_password_length_desc">This length will be used as default when generating new passwords. Longer passwords provide better security.</string>
|
||||
|
||||
</resources>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user