feat: standardise flow for dialogs (#1061)

* feat: standardise flow for dialogs

* feat: minor change
This commit is contained in:
Yogesh Choudhary Paliyal
2025-01-26 11:54:52 +05:30
committed by GitHub
parent 76e3e7eb0a
commit 7831511ed6
20 changed files with 355 additions and 264 deletions

View File

@@ -1,8 +1,6 @@
package com.yogeshpaliyal.keypass.importer
import android.net.Uri
import androidx.compose.runtime.Composable
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
interface AccountsImporter {
@@ -12,6 +10,5 @@ interface AccountsImporter {
fun allowedMimeType(): String
@Composable
fun readFile(file: Uri, resolve: (List<AccountModel>) -> Unit, onCompleteOrCancel: (action: Action?) -> Unit)
fun readFileGetAction(file: Uri): Action
}

View File

@@ -1,32 +1,10 @@
package com.yogeshpaliyal.keypass.importer
import android.net.Uri
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.opencsv.CSVReader
import com.opencsv.exceptions.CsvMalformedLineException
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
import java.io.FileNotFoundException
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
import com.yogeshpaliyal.keypass.ui.redux.states.RestoreChromeBackupState
class ChromeAccountImporter : AccountsImporter {
override fun getImporterTitle(): Int = R.string.google_backup
@@ -36,67 +14,9 @@ class ChromeAccountImporter : AccountsImporter {
return "text/comma-separated-values"
}
@Composable
override fun readFile(file: Uri, resolve: (List<AccountModel>) -> Unit, onCompleteOrCancel: (action: Action?) -> Unit) {
val context = LocalContext.current
LaunchedEffect(key1 = file, block = {
try {
val inputStream = context.contentResolver.openInputStream(file)
val reader = CSVReader(inputStream?.reader())
val myEntries: List<Array<String>> = reader.readAll()
val headers = myEntries[0]
val result = myEntries.drop(1).map { data ->
headers.zip(data).toMap()
}
val listOfAccounts = ArrayList<AccountModel>()
result.forEach {
listOfAccounts.add(
AccountModel(
title = it["name"],
notes = it["note"],
password = it["password"],
username = it["username"],
site = it["url"]
)
)
}
resolve(listOfAccounts)
onCompleteOrCancel(ToastAction(R.string.backup_restored))
} catch (e: CsvMalformedLineException) {
onCompleteOrCancel(ToastAction(R.string.invalid_csv_file))
} catch (e: FileNotFoundException) {
onCompleteOrCancel(ToastAction(R.string.file_not_found))
}
})
LoadingDialog()
override fun readFileGetAction(
file: Uri
): Action {
return UpdateDialogAction(RestoreChromeBackupState(file))
}
}
@Composable
fun LoadingDialog() {
Dialog(onDismissRequest = {}) {
Column(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface, MaterialTheme.shapes.medium)
.fillMaxWidth(1f)
.padding(16.dp),
Arrangement.Center,
Alignment.CenterHorizontally
) {
Text(
text = stringResource(id = R.string.restore),
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.size(16.dp))
CircularProgressIndicator()
}
}
}
@Preview()
@Composable
fun DialogPreview() {
LoadingDialog()
}

View File

@@ -1,15 +1,10 @@
package com.yogeshpaliyal.keypass.importer
import android.net.Uri
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalContext
import com.opencsv.CSVReader
import com.opencsv.exceptions.CsvMalformedLineException
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
import com.yogeshpaliyal.keypass.ui.redux.states.RestoreKeePassBackupState
class KeePassAccountImporter : AccountsImporter {
override fun getImporterTitle(): Int = R.string.keepass_backup
@@ -19,40 +14,9 @@ class KeePassAccountImporter : AccountsImporter {
return "text/comma-separated-values"
}
@Composable
override fun readFile(file: Uri, resolve: (List<AccountModel>) -> Unit, onCompleteOrCancel: (action: Action?) -> Unit) {
val context = LocalContext.current
LaunchedEffect(key1 = file, block = {
try {
val inputStream = context.contentResolver.openInputStream(file)
val reader = CSVReader(inputStream?.reader())
val myEntries: List<Array<String>> = reader.readAll()
val headers = myEntries[0]
val result = myEntries.drop(1).map { data ->
headers.zip(data).toMap()
}
val listOfAccounts = ArrayList<AccountModel>()
result.forEach {
listOfAccounts.add(
AccountModel(
title = it["Title"],
notes = it["Notes"],
password = it["Password"],
username = it["Username"],
site = it["URL"],
tags = it["Group"],
secret = if (it["TOTP"].isNullOrBlank()) null else it["TOTP"]
)
)
}
resolve(listOfAccounts)
onCompleteOrCancel(ToastAction(R.string.backup_restored))
} catch (e: CsvMalformedLineException) {
onCompleteOrCancel(ToastAction(R.string.invalid_csv))
}
})
LoadingDialog()
override fun readFileGetAction(
file: Uri
): Action {
return UpdateDialogAction(RestoreKeePassBackupState(file))
}
}

View File

@@ -1,30 +1,9 @@
package com.yogeshpaliyal.keypass.importer
import android.net.Uri
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.common.dbhelper.restoreBackup
import com.yogeshpaliyal.common.utils.BACKUP_KEY_LENGTH
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
import kotlinx.coroutines.launch
import org.reduxkotlin.compose.rememberTypedDispatcher
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
class KeyPassAccountImporter : AccountsImporter {
override fun getImporterTitle(): Int {
@@ -37,86 +16,9 @@ class KeyPassAccountImporter : AccountsImporter {
return "*/*"
}
@Composable
override fun readFile(file: Uri, resolve: (List<AccountModel>) -> Unit, onCompleteOrCancel: (action: Action?) -> Unit) {
RestoreDialog(
selectedFile = file,
hideDialog = {
onCompleteOrCancel(null)
},
saveAccounts = resolve
)
override fun readFileGetAction(
file: Uri
): Action {
return UpdateDialogAction(com.yogeshpaliyal.keypass.ui.redux.states.RestoreKeyPassBackupState(file))
}
}
@Composable
fun RestoreDialog(
selectedFile: Uri,
hideDialog: () -> Unit,
saveAccounts: (list: List<AccountModel>) -> Unit
) {
val (keyphrase, setKeyPhrase) = remember {
mutableStateOf("")
}
val dispatchAction = rememberTypedDispatcher<Action>()
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
AlertDialog(
onDismissRequest = {
hideDialog()
},
title = {
Text(text = stringResource(id = R.string.restore))
},
confirmButton = {
TextButton(onClick = {
if (keyphrase.isEmpty()) {
dispatchAction(ToastAction(R.string.alert_blank_keyphrase))
return@TextButton
}
if (keyphrase.length != BACKUP_KEY_LENGTH) {
dispatchAction(ToastAction(R.string.alert_invalid_keyphrase))
return@TextButton
}
coroutineScope.launch {
val result =
restoreBackup(keyphrase, context.contentResolver, selectedFile)
if (result != null) {
saveAccounts(result)
hideDialog()
dispatchAction(ToastAction(R.string.backup_restored))
} else {
dispatchAction(ToastAction(R.string.invalid_keyphrase))
}
}
}) {
Text(text = stringResource(id = R.string.restore))
}
},
dismissButton = {
TextButton(onClick = hideDialog) {
Text(text = stringResource(id = R.string.cancel))
}
},
text = {
Column(modifier = Modifier.fillMaxWidth(1f)) {
Text(text = stringResource(id = R.string.keyphrase_restore_info))
Spacer(modifier = Modifier.size(8.dp))
OutlinedTextField(
modifier = Modifier.fillMaxWidth(1f),
value = keyphrase,
onValueChange = setKeyPhrase,
placeholder = {
Text(text = stringResource(id = R.string.enter_keyphrase))
}
)
}
}
)
}

View File

@@ -64,13 +64,7 @@ fun BackupImporter(state: BackupImporterState, mViewModel: DashboardViewModel =
})
result?.let {
state.selectedImported?.readFile(result, {
setResult(null)
setRestoredAccounts(it)
}) {
it?.let(dispatchAction)
dispatchAction(StateUpdateAction(state = state.copy(selectedImported = null)))
}
state.selectedImported?.readFileGetAction(result)?.let { it1 -> dispatchAction(it1) }
}
Scaffold(bottomBar = {

View File

@@ -0,0 +1,40 @@
package com.yogeshpaliyal.keypass.ui.commonComponents
import androidx.annotation.StringRes
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
@Composable
fun LoadingDialog(@StringRes id: Int) {
Dialog(onDismissRequest = {}) {
Column(
modifier = Modifier
.background(MaterialTheme.colorScheme.surface, MaterialTheme.shapes.medium)
.fillMaxWidth(1f)
.padding(16.dp),
Arrangement.Center,
Alignment.CenterHorizontally
) {
Text(
text = stringResource(id = id),
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.size(16.dp))
CircularProgressIndicator()
}
}
}

View File

@@ -0,0 +1,65 @@
package com.yogeshpaliyal.keypass.ui.dialogs
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalContext
import com.opencsv.CSVReader
import com.opencsv.exceptions.CsvMalformedLineException
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.ui.commonComponents.LoadingDialog
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
import com.yogeshpaliyal.keypass.ui.redux.actions.RestoreAccountsAction
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
import com.yogeshpaliyal.keypass.ui.redux.states.RestoreChromeBackupState
import org.reduxkotlin.compose.rememberTypedDispatcher
import java.io.FileNotFoundException
@Composable
fun RestoreChromeBackupDialog(
state: RestoreChromeBackupState
) {
val (selectedFile) = state
val dispatchAction = rememberTypedDispatcher<Action>()
val context = LocalContext.current
val onCompleteOrCancel: (ToastAction) -> Unit = {
dispatchAction(UpdateDialogAction(null))
dispatchAction(it)
}
LaunchedEffect(key1 = selectedFile, block = {
try {
val inputStream = context.contentResolver.openInputStream(selectedFile)
val reader = CSVReader(inputStream?.reader())
val myEntries: List<Array<String>> = reader.readAll()
val headers = myEntries[0]
val result = myEntries.drop(1).map { data ->
headers.zip(data).toMap()
}
val listOfAccounts = ArrayList<AccountModel>()
result.forEach {
listOfAccounts.add(
AccountModel(
title = it["name"],
notes = it["note"],
password = it["password"],
username = it["username"],
site = it["url"]
)
)
}
dispatchAction(RestoreAccountsAction(listOfAccounts))
onCompleteOrCancel(ToastAction(R.string.backup_restored))
} catch (e: CsvMalformedLineException) {
onCompleteOrCancel(ToastAction(R.string.invalid_csv_file))
} catch (e: FileNotFoundException) {
onCompleteOrCancel(ToastAction(R.string.file_not_found))
}
})
LoadingDialog(R.string.restore)
}

View File

@@ -0,0 +1,64 @@
package com.yogeshpaliyal.keypass.ui.dialogs
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.platform.LocalContext
import com.opencsv.CSVReader
import com.opencsv.exceptions.CsvMalformedLineException
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.ui.commonComponents.LoadingDialog
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
import com.yogeshpaliyal.keypass.ui.redux.actions.RestoreAccountsAction
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
import com.yogeshpaliyal.keypass.ui.redux.states.RestoreKeePassBackupState
import org.reduxkotlin.compose.rememberTypedDispatcher
@Composable
fun RestoreKeePassBackupDialog(
state: RestoreKeePassBackupState
) {
val (selectedFile) = state
val dispatchAction = rememberTypedDispatcher<Action>()
val context = LocalContext.current
val onCompleteOrCancel: (ToastAction) -> Unit = {
dispatchAction(UpdateDialogAction(null))
dispatchAction(it)
}
LaunchedEffect(key1 = selectedFile, block = {
try {
val inputStream = context.contentResolver.openInputStream(selectedFile)
val reader = CSVReader(inputStream?.reader())
val myEntries: List<Array<String>> = reader.readAll()
val headers = myEntries[0]
val result = myEntries.drop(1).map { data ->
headers.zip(data).toMap()
}
val listOfAccounts = ArrayList<AccountModel>()
result.forEach {
listOfAccounts.add(
AccountModel(
title = it["Title"],
notes = it["Notes"],
password = it["Password"],
username = it["Username"],
site = it["URL"],
tags = it["Group"],
secret = if (it["TOTP"].isNullOrBlank()) null else it["TOTP"]
)
)
}
dispatchAction(RestoreAccountsAction(listOfAccounts))
onCompleteOrCancel(ToastAction(R.string.backup_restored))
} catch (e: CsvMalformedLineException) {
onCompleteOrCancel(ToastAction(R.string.invalid_csv))
}
})
LoadingDialog(R.string.restore)
}

View File

@@ -0,0 +1,102 @@
package com.yogeshpaliyal.keypass.ui.dialogs
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.yogeshpaliyal.common.dbhelper.restoreBackup
import com.yogeshpaliyal.common.utils.BACKUP_KEY_LENGTH
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
import com.yogeshpaliyal.keypass.ui.redux.actions.RestoreAccountsAction
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
import com.yogeshpaliyal.keypass.ui.redux.states.RestoreKeyPassBackupState
import kotlinx.coroutines.launch
import org.reduxkotlin.compose.rememberTypedDispatcher
@Composable
fun RestoreKeyPassBackupDialog(
state: RestoreKeyPassBackupState
) {
val (keyphrase, setKeyPhrase) = remember {
mutableStateOf("")
}
val (selectedFile) = state
val dispatchAction = rememberTypedDispatcher<Action>()
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
val hideDialog: () -> Unit = {
dispatchAction(UpdateDialogAction(null))
}
AlertDialog(
onDismissRequest = hideDialog,
title = {
Text(text = stringResource(id = R.string.restore))
},
confirmButton = {
TextButton(onClick = {
if (keyphrase.isEmpty()) {
dispatchAction(ToastAction(R.string.alert_blank_keyphrase))
return@TextButton
}
if (keyphrase.length != BACKUP_KEY_LENGTH) {
dispatchAction(ToastAction(R.string.alert_invalid_keyphrase))
return@TextButton
}
coroutineScope.launch {
val result =
restoreBackup(keyphrase, context.contentResolver, selectedFile)
if (result != null) {
dispatchAction(RestoreAccountsAction(result))
dispatchAction(UpdateDialogAction(null))
dispatchAction(ToastAction(R.string.backup_restored))
} else {
dispatchAction(ToastAction(R.string.invalid_keyphrase))
}
}
}) {
Text(text = stringResource(id = R.string.restore))
}
},
dismissButton = {
TextButton(onClick = hideDialog) {
Text(text = stringResource(id = R.string.cancel))
}
},
text = {
Column(modifier = Modifier.fillMaxWidth(1f)) {
Text(text = stringResource(id = R.string.keyphrase_restore_info))
Spacer(modifier = Modifier.size(8.dp))
OutlinedTextField(
modifier = Modifier.fillMaxWidth(1f),
value = keyphrase,
onValueChange = setKeyPhrase,
placeholder = {
Text(text = stringResource(id = R.string.enter_keyphrase))
}
)
}
}
)
}

View File

@@ -1,4 +1,4 @@
package com.yogeshpaliyal.keypass.ui.home.components
package com.yogeshpaliyal.keypass.ui.dialogs
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
@@ -21,7 +21,7 @@ import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.ui.nav.LocalUserSettings
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogState
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
import com.yogeshpaliyal.keypass.ui.redux.states.ForgotKeyPhraseState
import kotlinx.coroutines.launch
import org.reduxkotlin.compose.rememberTypedDispatcher
@@ -40,7 +40,7 @@ fun ValidateKeyPhraseDialog() {
val coroutineScope = rememberCoroutineScope()
val hideDialog: () -> Unit = {
dispatchAction(UpdateDialogState(null))
dispatchAction(UpdateDialogAction(null))
}
AlertDialog(
@@ -92,7 +92,7 @@ fun ValidateKeyPhraseDialog() {
Spacer(modifier = Modifier.size(8.dp))
TextButton(onClick = {
dispatchAction(UpdateDialogState(ForgotKeyPhraseState))
dispatchAction(UpdateDialogAction(ForgotKeyPhraseState))
}) {
Text(text = stringResource(id = R.string.forgot_keyphrase_question))
}

View File

@@ -43,9 +43,11 @@ class DashboardViewModel @Inject constructor(
}
}
suspend fun restoreBackup(
fun restoreBackup(
list: List<AccountModel>
) {
return appDb.saveToDb(list)
viewModelScope.launch {
appDb.saveToDb(list)
}
}
}

View File

@@ -23,12 +23,15 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import com.yogeshpaliyal.keypass.ui.home.components.AccountsList
import com.yogeshpaliyal.keypass.ui.home.components.SearchBar
import com.yogeshpaliyal.keypass.ui.nav.LocalUserSettings
import com.yogeshpaliyal.keypass.ui.redux.KeyPassRedux
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction
import com.yogeshpaliyal.keypass.ui.redux.actions.StateUpdateAction
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogState
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateViewModalAction
import com.yogeshpaliyal.keypass.ui.redux.states.HomeState
import com.yogeshpaliyal.keypass.ui.redux.states.ValidateKeyPhrase
import org.reduxkotlin.compose.rememberDispatcher
import org.reduxkotlin.compose.rememberTypedDispatcher
import java.util.concurrent.TimeUnit
/*
@@ -52,12 +55,16 @@ fun Homepage(
val listOfAccountsLiveData by mViewModel.mediator.observeAsState()
val dispatchAction = rememberDispatcher()
val dispatchAction = rememberTypedDispatcher<Action>()
LaunchedEffect(tag, keyword, sortField, sortAscendingOrder, block = {
mViewModel.queryUpdated(keyword, tag, sortField, sortAscendingOrder)
})
LaunchedEffect(KeyPassRedux, mViewModel) {
dispatchAction(UpdateViewModalAction(mViewModel))
}
LaunchedEffect(Unit, {
if (userSettings.backupKey == null) {
return@LaunchedEffect
@@ -68,7 +75,7 @@ fun Homepage(
val diffInDays = TimeUnit.MILLISECONDS.toDays(diff)
if (diffInDays >= 7) {
// Show the modal
dispatchAction(UpdateDialogState(dialogState = ValidateKeyPhrase))
dispatchAction(UpdateDialogAction(dialogState = ValidateKeyPhrase))
}
})

View File

@@ -13,7 +13,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.yogeshpaliyal.keypass.R
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogState
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
import com.yogeshpaliyal.keypass.ui.redux.states.ValidateKeyPhrase
import org.reduxkotlin.compose.rememberTypedDispatcher
@@ -22,7 +22,7 @@ fun ForgotKeyPhraseDialog() {
val dispatchAction = rememberTypedDispatcher<Action>()
val hideDialog: () -> Unit = {
dispatchAction(UpdateDialogState(ValidateKeyPhrase))
dispatchAction(UpdateDialogAction(ValidateKeyPhrase))
}
AlertDialog(

View File

@@ -33,10 +33,13 @@ import com.yogeshpaliyal.keypass.ui.backupsImport.BackupImporter
import com.yogeshpaliyal.keypass.ui.changeDefaultPasswordLength.ChangeDefaultPasswordLengthScreen
import com.yogeshpaliyal.keypass.ui.changePassword.ChangePassword
import com.yogeshpaliyal.keypass.ui.detail.AccountDetailPage
import com.yogeshpaliyal.keypass.ui.dialogs.RestoreChromeBackupDialog
import com.yogeshpaliyal.keypass.ui.dialogs.RestoreKeePassBackupDialog
import com.yogeshpaliyal.keypass.ui.dialogs.RestoreKeyPassBackupDialog
import com.yogeshpaliyal.keypass.ui.dialogs.ValidateKeyPhraseDialog
import com.yogeshpaliyal.keypass.ui.generate.ui.GeneratePasswordScreen
import com.yogeshpaliyal.keypass.ui.home.Homepage
import com.yogeshpaliyal.keypass.ui.home.components.ForgotKeyPhraseDialog
import com.yogeshpaliyal.keypass.ui.home.components.ValidateKeyPhraseDialog
import com.yogeshpaliyal.keypass.ui.nav.components.DashboardBottomSheet
import com.yogeshpaliyal.keypass.ui.nav.components.KeyPassBottomBar
import com.yogeshpaliyal.keypass.ui.passwordHint.PasswordHintScreen
@@ -55,6 +58,9 @@ import com.yogeshpaliyal.keypass.ui.redux.states.ForgotKeyPhraseState
import com.yogeshpaliyal.keypass.ui.redux.states.HomeState
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
import com.yogeshpaliyal.keypass.ui.redux.states.PasswordGeneratorState
import com.yogeshpaliyal.keypass.ui.redux.states.RestoreChromeBackupState
import com.yogeshpaliyal.keypass.ui.redux.states.RestoreKeePassBackupState
import com.yogeshpaliyal.keypass.ui.redux.states.RestoreKeyPassBackupState
import com.yogeshpaliyal.keypass.ui.redux.states.SettingsState
import com.yogeshpaliyal.keypass.ui.redux.states.ValidateKeyPhrase
import com.yogeshpaliyal.keypass.ui.settings.MySettingCompose
@@ -132,7 +138,6 @@ fun Dashboard() {
DisposableEffect(KeyPassRedux, context) {
dispatch(UpdateContextAction(context))
onDispose {
dispatch(UpdateContextAction(null))
}
@@ -195,7 +200,10 @@ fun CurrentPage() {
currentScreen.dialog?.let {
when (it) {
is ValidateKeyPhrase -> ValidateKeyPhraseDialog()
ForgotKeyPhraseState -> ForgotKeyPhraseDialog()
is ForgotKeyPhraseState -> ForgotKeyPhraseDialog()
is RestoreKeyPassBackupState -> RestoreKeyPassBackupDialog(it)
is RestoreChromeBackupState -> RestoreChromeBackupDialog(it)
is RestoreKeePassBackupState -> RestoreKeePassBackupDialog(it)
}
}
}

View File

@@ -9,11 +9,13 @@ import com.yogeshpaliyal.keypass.ui.redux.actions.BottomSheetAction
import com.yogeshpaliyal.keypass.ui.redux.actions.CopyToClipboard
import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction
import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction
import com.yogeshpaliyal.keypass.ui.redux.actions.RestoreAccountsAction
import com.yogeshpaliyal.keypass.ui.redux.actions.StateUpdateAction
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastActionStr
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateContextAction
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogState
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateViewModalAction
import com.yogeshpaliyal.keypass.ui.redux.middlewares.intentNavigationMiddleware
import com.yogeshpaliyal.keypass.ui.redux.states.BottomSheetState
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
@@ -102,10 +104,19 @@ object KeyPassRedux {
)
)
}
is UpdateDialogState -> {
is UpdateDialogAction -> {
state.copy(dialog = action.dialogState)
}
is UpdateViewModalAction -> {
state.copy(viewModel = action.viewModal)
}
is RestoreAccountsAction -> {
state.viewModel?.restoreBackup(action.accounts)
state
}
else -> state
}
}

View File

@@ -1,13 +1,19 @@
package com.yogeshpaliyal.keypass.ui.redux.actions
import android.content.Context
import com.yogeshpaliyal.common.data.AccountModel
import com.yogeshpaliyal.keypass.ui.home.DashboardViewModel
import com.yogeshpaliyal.keypass.ui.redux.states.DialogState
import com.yogeshpaliyal.keypass.ui.redux.states.ScreenState
sealed interface Action
class UpdateContextAction(val context: Context?) : Action
class UpdateViewModalAction(val viewModal: DashboardViewModel?) : Action
data class NavigationAction(val state: ScreenState, val clearBackStack: Boolean = false) : Action
data class RestoreAccountsAction(val accounts: List<AccountModel>) : Action
data class StateUpdateAction(val state: ScreenState) : Action
data class UpdateDialogState(val dialogState: DialogState? = null) : Action
data class UpdateDialogAction(val dialogState: DialogState? = null) : Action

View File

@@ -1,6 +1,14 @@
package com.yogeshpaliyal.keypass.ui.redux.states
import android.net.Uri
sealed class DialogState()
object ValidateKeyPhrase : DialogState()
object ForgotKeyPhraseState : DialogState()
sealed class RestoreBackupState(val fileUri: Uri) : DialogState()
data class RestoreKeyPassBackupState(val fileUrii: Uri) : RestoreBackupState(fileUrii)
data class RestoreChromeBackupState(val fileUrii: Uri) : RestoreBackupState(fileUrii)
data class RestoreKeePassBackupState(val fileUrii: Uri) : RestoreBackupState(fileUrii)

View File

@@ -1,10 +1,12 @@
package com.yogeshpaliyal.keypass.ui.redux.states
import android.content.Context
import com.yogeshpaliyal.keypass.ui.home.DashboardViewModel
import com.yogeshpaliyal.keypass.ui.redux.BottomSheetRoutes
data class KeyPassState(
val context: Context? = null,
val viewModel: DashboardViewModel? = null,
val currentScreen: ScreenState,
val bottomSheet: BottomSheetState? = null,
val dialog: DialogState? = null,

View File

@@ -19,7 +19,6 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Info
import androidx.compose.material.icons.rounded.Feedback
import androidx.compose.material.icons.rounded.Fingerprint
import androidx.compose.material.icons.rounded.Info
import androidx.compose.material.icons.rounded.Password
import androidx.compose.material.icons.rounded.Share
import androidx.compose.material3.Divider
@@ -48,7 +47,7 @@ import com.yogeshpaliyal.keypass.ui.redux.actions.Action
import com.yogeshpaliyal.keypass.ui.redux.actions.IntentNavigation
import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogState
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateDialogAction
import com.yogeshpaliyal.keypass.ui.redux.states.AboutState
import com.yogeshpaliyal.keypass.ui.redux.states.BackupImporterState
import com.yogeshpaliyal.keypass.ui.redux.states.BackupScreenState
@@ -115,7 +114,7 @@ fun MySettingCompose() {
title = R.string.validate_keyphrase,
summary = R.string.validate_keyphrase
) {
dispatchAction(UpdateDialogState(ValidateKeyPhrase))
dispatchAction(UpdateDialogAction(ValidateKeyPhrase))
}
BiometricsOption()

View File

@@ -63,4 +63,4 @@ subprojects {
// commandLine = listOf("sh", "./githooks/git-init.sh")
//}
tasks.getByPath("app:assemble").dependsOn(installGitHook)
//tasks.getByPath("app:assemble").dependsOn(installGitHook)