mirror of
https://github.com/yogeshpaliyal/KeyPass.git
synced 2026-01-19 10:43:39 -06:00
feat: standardise flow for dialogs (#1061)
* feat: standardise flow for dialogs * feat: minor change
This commit is contained in:
committed by
GitHub
parent
76e3e7eb0a
commit
7831511ed6
@@ -1,8 +1,6 @@
|
|||||||
package com.yogeshpaliyal.keypass.importer
|
package com.yogeshpaliyal.keypass.importer
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import com.yogeshpaliyal.common.data.AccountModel
|
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
||||||
|
|
||||||
interface AccountsImporter {
|
interface AccountsImporter {
|
||||||
@@ -12,6 +10,5 @@ interface AccountsImporter {
|
|||||||
|
|
||||||
fun allowedMimeType(): String
|
fun allowedMimeType(): String
|
||||||
|
|
||||||
@Composable
|
fun readFileGetAction(file: Uri): Action
|
||||||
fun readFile(file: Uri, resolve: (List<AccountModel>) -> Unit, onCompleteOrCancel: (action: Action?) -> Unit)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,10 @@
|
|||||||
package com.yogeshpaliyal.keypass.importer
|
package com.yogeshpaliyal.keypass.importer
|
||||||
|
|
||||||
import android.net.Uri
|
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.R
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
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 java.io.FileNotFoundException
|
import com.yogeshpaliyal.keypass.ui.redux.states.RestoreChromeBackupState
|
||||||
|
|
||||||
class ChromeAccountImporter : AccountsImporter {
|
class ChromeAccountImporter : AccountsImporter {
|
||||||
override fun getImporterTitle(): Int = R.string.google_backup
|
override fun getImporterTitle(): Int = R.string.google_backup
|
||||||
@@ -36,67 +14,9 @@ class ChromeAccountImporter : AccountsImporter {
|
|||||||
return "text/comma-separated-values"
|
return "text/comma-separated-values"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
override fun readFileGetAction(
|
||||||
override fun readFile(file: Uri, resolve: (List<AccountModel>) -> Unit, onCompleteOrCancel: (action: Action?) -> Unit) {
|
file: Uri
|
||||||
val context = LocalContext.current
|
): Action {
|
||||||
|
return UpdateDialogAction(RestoreChromeBackupState(file))
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
package com.yogeshpaliyal.keypass.importer
|
package com.yogeshpaliyal.keypass.importer
|
||||||
|
|
||||||
import android.net.Uri
|
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.R
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
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 {
|
class KeePassAccountImporter : AccountsImporter {
|
||||||
override fun getImporterTitle(): Int = R.string.keepass_backup
|
override fun getImporterTitle(): Int = R.string.keepass_backup
|
||||||
@@ -19,40 +14,9 @@ class KeePassAccountImporter : AccountsImporter {
|
|||||||
return "text/comma-separated-values"
|
return "text/comma-separated-values"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
override fun readFileGetAction(
|
||||||
override fun readFile(file: Uri, resolve: (List<AccountModel>) -> Unit, onCompleteOrCancel: (action: Action?) -> Unit) {
|
file: Uri
|
||||||
val context = LocalContext.current
|
): Action {
|
||||||
|
return UpdateDialogAction(RestoreKeePassBackupState(file))
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,9 @@
|
|||||||
package com.yogeshpaliyal.keypass.importer
|
package com.yogeshpaliyal.keypass.importer
|
||||||
|
|
||||||
import android.net.Uri
|
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.R
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
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 kotlinx.coroutines.launch
|
|
||||||
import org.reduxkotlin.compose.rememberTypedDispatcher
|
|
||||||
|
|
||||||
class KeyPassAccountImporter : AccountsImporter {
|
class KeyPassAccountImporter : AccountsImporter {
|
||||||
override fun getImporterTitle(): Int {
|
override fun getImporterTitle(): Int {
|
||||||
@@ -37,86 +16,9 @@ class KeyPassAccountImporter : AccountsImporter {
|
|||||||
return "*/*"
|
return "*/*"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
override fun readFileGetAction(
|
||||||
override fun readFile(file: Uri, resolve: (List<AccountModel>) -> Unit, onCompleteOrCancel: (action: Action?) -> Unit) {
|
file: Uri
|
||||||
RestoreDialog(
|
): Action {
|
||||||
selectedFile = file,
|
return UpdateDialogAction(com.yogeshpaliyal.keypass.ui.redux.states.RestoreKeyPassBackupState(file))
|
||||||
hideDialog = {
|
|
||||||
onCompleteOrCancel(null)
|
|
||||||
},
|
|
||||||
saveAccounts = resolve
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@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))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -64,13 +64,7 @@ fun BackupImporter(state: BackupImporterState, mViewModel: DashboardViewModel =
|
|||||||
})
|
})
|
||||||
|
|
||||||
result?.let {
|
result?.let {
|
||||||
state.selectedImported?.readFile(result, {
|
state.selectedImported?.readFileGetAction(result)?.let { it1 -> dispatchAction(it1) }
|
||||||
setResult(null)
|
|
||||||
setRestoredAccounts(it)
|
|
||||||
}) {
|
|
||||||
it?.let(dispatchAction)
|
|
||||||
dispatchAction(StateUpdateAction(state = state.copy(selectedImported = null)))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Scaffold(bottomBar = {
|
Scaffold(bottomBar = {
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
@@ -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))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -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.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
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.nav.LocalUserSettings
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
|
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 com.yogeshpaliyal.keypass.ui.redux.states.ForgotKeyPhraseState
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.reduxkotlin.compose.rememberTypedDispatcher
|
import org.reduxkotlin.compose.rememberTypedDispatcher
|
||||||
@@ -40,7 +40,7 @@ fun ValidateKeyPhraseDialog() {
|
|||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
val hideDialog: () -> Unit = {
|
val hideDialog: () -> Unit = {
|
||||||
dispatchAction(UpdateDialogState(null))
|
dispatchAction(UpdateDialogAction(null))
|
||||||
}
|
}
|
||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
@@ -92,7 +92,7 @@ fun ValidateKeyPhraseDialog() {
|
|||||||
Spacer(modifier = Modifier.size(8.dp))
|
Spacer(modifier = Modifier.size(8.dp))
|
||||||
|
|
||||||
TextButton(onClick = {
|
TextButton(onClick = {
|
||||||
dispatchAction(UpdateDialogState(ForgotKeyPhraseState))
|
dispatchAction(UpdateDialogAction(ForgotKeyPhraseState))
|
||||||
}) {
|
}) {
|
||||||
Text(text = stringResource(id = R.string.forgot_keyphrase_question))
|
Text(text = stringResource(id = R.string.forgot_keyphrase_question))
|
||||||
}
|
}
|
||||||
@@ -43,9 +43,11 @@ class DashboardViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun restoreBackup(
|
fun restoreBackup(
|
||||||
list: List<AccountModel>
|
list: List<AccountModel>
|
||||||
) {
|
) {
|
||||||
return appDb.saveToDb(list)
|
viewModelScope.launch {
|
||||||
|
appDb.saveToDb(list)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.AccountsList
|
||||||
import com.yogeshpaliyal.keypass.ui.home.components.SearchBar
|
import com.yogeshpaliyal.keypass.ui.home.components.SearchBar
|
||||||
import com.yogeshpaliyal.keypass.ui.nav.LocalUserSettings
|
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.NavigationAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.StateUpdateAction
|
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.HomeState
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.ValidateKeyPhrase
|
import com.yogeshpaliyal.keypass.ui.redux.states.ValidateKeyPhrase
|
||||||
import org.reduxkotlin.compose.rememberDispatcher
|
import org.reduxkotlin.compose.rememberTypedDispatcher
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -52,12 +55,16 @@ fun Homepage(
|
|||||||
|
|
||||||
val listOfAccountsLiveData by mViewModel.mediator.observeAsState()
|
val listOfAccountsLiveData by mViewModel.mediator.observeAsState()
|
||||||
|
|
||||||
val dispatchAction = rememberDispatcher()
|
val dispatchAction = rememberTypedDispatcher<Action>()
|
||||||
|
|
||||||
LaunchedEffect(tag, keyword, sortField, sortAscendingOrder, block = {
|
LaunchedEffect(tag, keyword, sortField, sortAscendingOrder, block = {
|
||||||
mViewModel.queryUpdated(keyword, tag, sortField, sortAscendingOrder)
|
mViewModel.queryUpdated(keyword, tag, sortField, sortAscendingOrder)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
LaunchedEffect(KeyPassRedux, mViewModel) {
|
||||||
|
dispatchAction(UpdateViewModalAction(mViewModel))
|
||||||
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit, {
|
LaunchedEffect(Unit, {
|
||||||
if (userSettings.backupKey == null) {
|
if (userSettings.backupKey == null) {
|
||||||
return@LaunchedEffect
|
return@LaunchedEffect
|
||||||
@@ -68,7 +75,7 @@ fun Homepage(
|
|||||||
val diffInDays = TimeUnit.MILLISECONDS.toDays(diff)
|
val diffInDays = TimeUnit.MILLISECONDS.toDays(diff)
|
||||||
if (diffInDays >= 7) {
|
if (diffInDays >= 7) {
|
||||||
// Show the modal
|
// Show the modal
|
||||||
dispatchAction(UpdateDialogState(dialogState = ValidateKeyPhrase))
|
dispatchAction(UpdateDialogAction(dialogState = ValidateKeyPhrase))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.yogeshpaliyal.keypass.R
|
import com.yogeshpaliyal.keypass.R
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.Action
|
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 com.yogeshpaliyal.keypass.ui.redux.states.ValidateKeyPhrase
|
||||||
import org.reduxkotlin.compose.rememberTypedDispatcher
|
import org.reduxkotlin.compose.rememberTypedDispatcher
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ fun ForgotKeyPhraseDialog() {
|
|||||||
val dispatchAction = rememberTypedDispatcher<Action>()
|
val dispatchAction = rememberTypedDispatcher<Action>()
|
||||||
|
|
||||||
val hideDialog: () -> Unit = {
|
val hideDialog: () -> Unit = {
|
||||||
dispatchAction(UpdateDialogState(ValidateKeyPhrase))
|
dispatchAction(UpdateDialogAction(ValidateKeyPhrase))
|
||||||
}
|
}
|
||||||
|
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
|
|||||||
@@ -33,10 +33,13 @@ import com.yogeshpaliyal.keypass.ui.backupsImport.BackupImporter
|
|||||||
import com.yogeshpaliyal.keypass.ui.changeDefaultPasswordLength.ChangeDefaultPasswordLengthScreen
|
import com.yogeshpaliyal.keypass.ui.changeDefaultPasswordLength.ChangeDefaultPasswordLengthScreen
|
||||||
import com.yogeshpaliyal.keypass.ui.changePassword.ChangePassword
|
import com.yogeshpaliyal.keypass.ui.changePassword.ChangePassword
|
||||||
import com.yogeshpaliyal.keypass.ui.detail.AccountDetailPage
|
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.generate.ui.GeneratePasswordScreen
|
||||||
import com.yogeshpaliyal.keypass.ui.home.Homepage
|
import com.yogeshpaliyal.keypass.ui.home.Homepage
|
||||||
import com.yogeshpaliyal.keypass.ui.home.components.ForgotKeyPhraseDialog
|
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.DashboardBottomSheet
|
||||||
import com.yogeshpaliyal.keypass.ui.nav.components.KeyPassBottomBar
|
import com.yogeshpaliyal.keypass.ui.nav.components.KeyPassBottomBar
|
||||||
import com.yogeshpaliyal.keypass.ui.passwordHint.PasswordHintScreen
|
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.HomeState
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
|
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.PasswordGeneratorState
|
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.SettingsState
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.ValidateKeyPhrase
|
import com.yogeshpaliyal.keypass.ui.redux.states.ValidateKeyPhrase
|
||||||
import com.yogeshpaliyal.keypass.ui.settings.MySettingCompose
|
import com.yogeshpaliyal.keypass.ui.settings.MySettingCompose
|
||||||
@@ -132,7 +138,6 @@ fun Dashboard() {
|
|||||||
|
|
||||||
DisposableEffect(KeyPassRedux, context) {
|
DisposableEffect(KeyPassRedux, context) {
|
||||||
dispatch(UpdateContextAction(context))
|
dispatch(UpdateContextAction(context))
|
||||||
|
|
||||||
onDispose {
|
onDispose {
|
||||||
dispatch(UpdateContextAction(null))
|
dispatch(UpdateContextAction(null))
|
||||||
}
|
}
|
||||||
@@ -195,7 +200,10 @@ fun CurrentPage() {
|
|||||||
currentScreen.dialog?.let {
|
currentScreen.dialog?.let {
|
||||||
when (it) {
|
when (it) {
|
||||||
is ValidateKeyPhrase -> ValidateKeyPhraseDialog()
|
is ValidateKeyPhrase -> ValidateKeyPhraseDialog()
|
||||||
ForgotKeyPhraseState -> ForgotKeyPhraseDialog()
|
is ForgotKeyPhraseState -> ForgotKeyPhraseDialog()
|
||||||
|
is RestoreKeyPassBackupState -> RestoreKeyPassBackupDialog(it)
|
||||||
|
is RestoreChromeBackupState -> RestoreChromeBackupDialog(it)
|
||||||
|
is RestoreKeePassBackupState -> RestoreKeePassBackupDialog(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.CopyToClipboard
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction
|
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.StateUpdateAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastActionStr
|
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastActionStr
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.UpdateContextAction
|
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.middlewares.intentNavigationMiddleware
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.BottomSheetState
|
import com.yogeshpaliyal.keypass.ui.redux.states.BottomSheetState
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
|
import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState
|
||||||
@@ -102,10 +104,19 @@ object KeyPassRedux {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is UpdateDialogState -> {
|
is UpdateDialogAction -> {
|
||||||
state.copy(dialog = action.dialogState)
|
state.copy(dialog = action.dialogState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is UpdateViewModalAction -> {
|
||||||
|
state.copy(viewModel = action.viewModal)
|
||||||
|
}
|
||||||
|
|
||||||
|
is RestoreAccountsAction -> {
|
||||||
|
state.viewModel?.restoreBackup(action.accounts)
|
||||||
|
state
|
||||||
|
}
|
||||||
|
|
||||||
else -> state
|
else -> state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
package com.yogeshpaliyal.keypass.ui.redux.actions
|
package com.yogeshpaliyal.keypass.ui.redux.actions
|
||||||
|
|
||||||
import android.content.Context
|
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.DialogState
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.ScreenState
|
import com.yogeshpaliyal.keypass.ui.redux.states.ScreenState
|
||||||
|
|
||||||
sealed interface Action
|
sealed interface Action
|
||||||
|
|
||||||
class UpdateContextAction(val context: Context?) : 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 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 StateUpdateAction(val state: ScreenState) : Action
|
||||||
data class UpdateDialogState(val dialogState: DialogState? = null) : Action
|
data class UpdateDialogAction(val dialogState: DialogState? = null) : Action
|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
package com.yogeshpaliyal.keypass.ui.redux.states
|
package com.yogeshpaliyal.keypass.ui.redux.states
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
|
||||||
sealed class DialogState()
|
sealed class DialogState()
|
||||||
|
|
||||||
object ValidateKeyPhrase : DialogState()
|
object ValidateKeyPhrase : DialogState()
|
||||||
object ForgotKeyPhraseState : 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)
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
package com.yogeshpaliyal.keypass.ui.redux.states
|
package com.yogeshpaliyal.keypass.ui.redux.states
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.yogeshpaliyal.keypass.ui.home.DashboardViewModel
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.BottomSheetRoutes
|
import com.yogeshpaliyal.keypass.ui.redux.BottomSheetRoutes
|
||||||
|
|
||||||
data class KeyPassState(
|
data class KeyPassState(
|
||||||
val context: Context? = null,
|
val context: Context? = null,
|
||||||
|
val viewModel: DashboardViewModel? = null,
|
||||||
val currentScreen: ScreenState,
|
val currentScreen: ScreenState,
|
||||||
val bottomSheet: BottomSheetState? = null,
|
val bottomSheet: BottomSheetState? = null,
|
||||||
val dialog: DialogState? = null,
|
val dialog: DialogState? = null,
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.outlined.Info
|
import androidx.compose.material.icons.outlined.Info
|
||||||
import androidx.compose.material.icons.rounded.Feedback
|
import androidx.compose.material.icons.rounded.Feedback
|
||||||
import androidx.compose.material.icons.rounded.Fingerprint
|
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.Password
|
||||||
import androidx.compose.material.icons.rounded.Share
|
import androidx.compose.material.icons.rounded.Share
|
||||||
import androidx.compose.material3.Divider
|
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.IntentNavigation
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction
|
import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction
|
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.AboutState
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.BackupImporterState
|
import com.yogeshpaliyal.keypass.ui.redux.states.BackupImporterState
|
||||||
import com.yogeshpaliyal.keypass.ui.redux.states.BackupScreenState
|
import com.yogeshpaliyal.keypass.ui.redux.states.BackupScreenState
|
||||||
@@ -115,7 +114,7 @@ fun MySettingCompose() {
|
|||||||
title = R.string.validate_keyphrase,
|
title = R.string.validate_keyphrase,
|
||||||
summary = R.string.validate_keyphrase
|
summary = R.string.validate_keyphrase
|
||||||
) {
|
) {
|
||||||
dispatchAction(UpdateDialogState(ValidateKeyPhrase))
|
dispatchAction(UpdateDialogAction(ValidateKeyPhrase))
|
||||||
}
|
}
|
||||||
|
|
||||||
BiometricsOption()
|
BiometricsOption()
|
||||||
|
|||||||
@@ -63,4 +63,4 @@ subprojects {
|
|||||||
// commandLine = listOf("sh", "./githooks/git-init.sh")
|
// commandLine = listOf("sh", "./githooks/git-init.sh")
|
||||||
//}
|
//}
|
||||||
|
|
||||||
tasks.getByPath("app:assemble").dependsOn(installGitHook)
|
//tasks.getByPath("app:assemble").dependsOn(installGitHook)
|
||||||
|
|||||||
Reference in New Issue
Block a user