mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
fix: Complete refactoring of database action
This commit is contained in:
@@ -217,7 +217,6 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||||
super.onDatabaseRetrieved(database)
|
|
||||||
if (database != null) {
|
if (database != null) {
|
||||||
launchGroupActivityIfLoaded(database)
|
launchGroupActivityIfLoaded(database)
|
||||||
}
|
}
|
||||||
@@ -228,8 +227,6 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
|||||||
actionTask: String,
|
actionTask: String,
|
||||||
result: ActionRunnable.Result
|
result: ActionRunnable.Result
|
||||||
) {
|
) {
|
||||||
super.onDatabaseActionFinished(database, actionTask, result)
|
|
||||||
|
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
// Update list
|
// Update list
|
||||||
when (actionTask) {
|
when (actionTask) {
|
||||||
@@ -392,7 +389,7 @@ class FileDatabaseSelectActivity : DatabaseModeActivity(),
|
|||||||
try {
|
try {
|
||||||
mDatabaseFileUri?.let { databaseUri ->
|
mDatabaseFileUri?.let { databaseUri ->
|
||||||
// Create the new database
|
// Create the new database
|
||||||
createDatabase(databaseUri, mainCredential)
|
mDatabaseViewModel.createDatabase(databaseUri, mainCredential)
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
val error = getString(R.string.error_create_database_file)
|
val error = getString(R.string.error_create_database_file)
|
||||||
|
|||||||
@@ -587,7 +587,7 @@ class MainCredentialActivity : DatabaseModeActivity() {
|
|||||||
readOnly: Boolean,
|
readOnly: Boolean,
|
||||||
cipherEncryptDatabase: CipherEncryptDatabase?,
|
cipherEncryptDatabase: CipherEncryptDatabase?,
|
||||||
fixDuplicateUUID: Boolean) {
|
fixDuplicateUUID: Boolean) {
|
||||||
loadDatabase(
|
mDatabaseViewModel.loadDatabase(
|
||||||
databaseUri,
|
databaseUri,
|
||||||
mainCredential,
|
mainCredential,
|
||||||
readOnly,
|
readOnly,
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ class DatabaseChangedDialogFragment : DatabaseDialogFragment() {
|
|||||||
}
|
}
|
||||||
builder.setMessage(stringBuilder)
|
builder.setMessage(stringBuilder)
|
||||||
builder.setPositiveButton(android.R.string.ok) { _, _ ->
|
builder.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
actionDatabaseListener?.validateDatabaseChanged()
|
actionDatabaseListener?.onDatabaseChangeValidated()
|
||||||
}
|
}
|
||||||
return builder.create()
|
return builder.create()
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ class DatabaseChangedDialogFragment : DatabaseDialogFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface ActionDatabaseChangedListener {
|
interface ActionDatabaseChangedListener {
|
||||||
fun validateDatabaseChanged()
|
fun onDatabaseChangeValidated()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -30,13 +30,17 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
|
|||||||
resetAppTimeoutOnTouchOrFocus()
|
resetAppTimeoutOnTouchOrFocus()
|
||||||
onDatabaseRetrieved(uiState.database)
|
onDatabaseRetrieved(uiState.database)
|
||||||
}
|
}
|
||||||
|
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
|
||||||
|
onDatabaseActionFinished(
|
||||||
|
uiState.database,
|
||||||
|
uiState.actionTask,
|
||||||
|
uiState.result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mDatabaseViewModel.actionFinished.observe(this) { result ->
|
|
||||||
onDatabaseActionFinished(result.database, result.actionTask, result.result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import android.os.Bundle
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval
|
import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval
|
||||||
import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused
|
import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused
|
||||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||||
@@ -20,21 +22,26 @@ abstract class DatabaseFragment : Fragment(), DatabaseRetrieval {
|
|||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
lifecycleScope.launch {
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
// Initialize the parameters
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
mDatabaseViewModel.uiState.collect { uiState ->
|
mDatabaseViewModel.uiState.collect { uiState ->
|
||||||
when (uiState) {
|
when (uiState) {
|
||||||
is DatabaseViewModel.UIState.Loading -> {}
|
is DatabaseViewModel.UIState.Loading -> {}
|
||||||
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
||||||
onDatabaseRetrieved(uiState.database)
|
onDatabaseRetrieved(uiState.database)
|
||||||
|
}
|
||||||
|
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
|
||||||
|
onDatabaseActionFinished(
|
||||||
|
uiState.database,
|
||||||
|
uiState.actionTask,
|
||||||
|
uiState.result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mDatabaseViewModel.actionFinished.observe(viewLifecycleOwner) { result ->
|
|
||||||
onDatabaseActionFinished(result.database, result.actionTask, result.result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun resetAppTimeoutWhenViewFocusedOrChanged(view: View?) {
|
protected fun resetAppTimeoutWhenViewFocusedOrChanged(view: View?) {
|
||||||
|
|||||||
@@ -1,58 +1,120 @@
|
|||||||
package com.kunzisoft.keepass.activities.legacy
|
package com.kunzisoft.keepass.activities.legacy
|
||||||
|
|
||||||
import android.net.Uri
|
import android.Manifest
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment
|
||||||
|
import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment.Companion.DATABASE_CHANGED_DIALOG_TAG
|
||||||
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
import com.kunzisoft.keepass.activities.stylish.StylishActivity
|
||||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||||
import com.kunzisoft.keepass.database.DatabaseTaskProvider
|
import com.kunzisoft.keepass.database.DatabaseTaskProvider.Companion.startDatabaseService
|
||||||
import com.kunzisoft.keepass.database.MainCredential
|
import com.kunzisoft.keepass.database.ProgressMessage
|
||||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
||||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||||
import com.kunzisoft.keepass.utils.getBinaryDir
|
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment
|
||||||
|
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.PROGRESS_TASK_DIALOG_TAG
|
||||||
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
||||||
|
|
||||||
protected val mDatabaseViewModel: DatabaseViewModel by viewModels()
|
protected val mDatabaseViewModel: DatabaseViewModel by viewModels()
|
||||||
protected var mDatabaseTaskProvider: DatabaseTaskProvider? = null
|
protected val mDatabase: ContextualDatabase?
|
||||||
protected var mDatabase: ContextualDatabase? = null
|
get() = mDatabaseViewModel.database
|
||||||
|
|
||||||
|
private var progressTaskDialogFragment: ProgressTaskDialogFragment? = null
|
||||||
|
private var databaseChangedDialogFragment: DatabaseChangedDialogFragment? = null
|
||||||
|
|
||||||
|
private val mActionDatabaseListener =
|
||||||
|
object : DatabaseChangedDialogFragment.ActionDatabaseChangedListener {
|
||||||
|
override fun onDatabaseChangeValidated() {
|
||||||
|
mDatabaseViewModel.onDatabaseChangeValidated()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val tempServiceParameters = mutableListOf<Pair<Bundle?, String>>()
|
||||||
|
private val requestPermissionLauncher = registerForActivityResult(
|
||||||
|
ActivityResultContracts.RequestPermission()
|
||||||
|
) { _ ->
|
||||||
|
// Whether or not the user has accepted, the service can be started,
|
||||||
|
// There just won't be any notification if it's not allowed.
|
||||||
|
tempServiceParameters.removeFirstOrNull()?.let {
|
||||||
|
startDatabaseService(it.first, it.second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
|
mDatabaseViewModel.uiState.collect { uiState ->
|
||||||
|
when (uiState) {
|
||||||
|
is DatabaseViewModel.UIState.Loading -> {}
|
||||||
|
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
||||||
|
onDatabaseRetrieved(uiState.database)
|
||||||
|
}
|
||||||
|
|
||||||
mDatabaseTaskProvider = DatabaseTaskProvider(this, showDatabaseDialog())
|
is DatabaseViewModel.UIState.OnDatabaseReloaded -> {
|
||||||
|
if (finishActivityIfReloadRequested()) {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mDatabaseTaskProvider?.onDatabaseRetrieved = { database ->
|
is DatabaseViewModel.UIState.OnDatabaseInfoChanged -> {
|
||||||
val databaseWasReloaded = database?.wasReloaded == true
|
showDatabaseChangedDialog(
|
||||||
if (databaseWasReloaded && finishActivityIfReloadRequested()) {
|
uiState.previousDatabaseInfo,
|
||||||
finish()
|
uiState.newDatabaseInfo,
|
||||||
} else if (mDatabase == null || mDatabase != database || databaseWasReloaded) {
|
uiState.readOnlyDatabase
|
||||||
database?.wasReloaded = false
|
)
|
||||||
onDatabaseRetrieved(database)
|
}
|
||||||
|
|
||||||
|
is DatabaseViewModel.UIState.OnDatabaseActionRequested -> {
|
||||||
|
startDatabasePermissionService(
|
||||||
|
uiState.bundle,
|
||||||
|
uiState.actionTask
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is DatabaseViewModel.UIState.OnDatabaseActionStarted -> {
|
||||||
|
if (showDatabaseDialog())
|
||||||
|
startDialog(uiState.progressMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
is DatabaseViewModel.UIState.OnDatabaseActionUpdated -> {
|
||||||
|
if (showDatabaseDialog())
|
||||||
|
updateDialog(uiState.progressMessage)
|
||||||
|
}
|
||||||
|
|
||||||
|
is DatabaseViewModel.UIState.OnDatabaseActionStopped -> {
|
||||||
|
// Remove the progress task
|
||||||
|
stopDialog()
|
||||||
|
}
|
||||||
|
|
||||||
|
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
|
||||||
|
onDatabaseActionFinished(
|
||||||
|
uiState.database,
|
||||||
|
uiState.actionTask,
|
||||||
|
uiState.result
|
||||||
|
)
|
||||||
|
stopDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mDatabaseTaskProvider?.onActionFinish = { database, actionTask, result ->
|
|
||||||
onDatabaseActionFinished(database, actionTask, result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected open fun showDatabaseDialog(): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
mDatabaseTaskProvider?.destroy()
|
|
||||||
mDatabaseTaskProvider = null
|
|
||||||
mDatabase = null
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||||
mDatabase = database
|
|
||||||
mDatabaseViewModel.defineDatabase(database)
|
|
||||||
// optional method implementation
|
// optional method implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,44 +123,100 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
|||||||
actionTask: String,
|
actionTask: String,
|
||||||
result: ActionRunnable.Result
|
result: ActionRunnable.Result
|
||||||
) {
|
) {
|
||||||
mDatabaseViewModel.onActionFinished(database, actionTask, result)
|
|
||||||
// optional method implementation
|
// optional method implementation
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createDatabase(
|
private fun startDatabasePermissionService(bundle: Bundle?, actionTask: String) {
|
||||||
databaseUri: Uri,
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
mainCredential: MainCredential
|
if (ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS)
|
||||||
|
== PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
startDatabaseService(bundle, actionTask)
|
||||||
|
} else if (ActivityCompat.shouldShowRequestPermissionRationale(
|
||||||
|
this,
|
||||||
|
Manifest.permission.POST_NOTIFICATIONS
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// it's not the first time, so the user deliberately chooses not to display the notification
|
||||||
|
startDatabaseService(bundle, actionTask)
|
||||||
|
} else {
|
||||||
|
AlertDialog.Builder(this)
|
||||||
|
.setMessage(R.string.warning_database_notification_permission)
|
||||||
|
.setNegativeButton(R.string.later) { _, _ ->
|
||||||
|
// Refuses the notification, so start the service
|
||||||
|
startDatabaseService(bundle, actionTask)
|
||||||
|
}
|
||||||
|
.setPositiveButton(R.string.ask) { _, _ ->
|
||||||
|
// Save the temp parameters to ask the permission
|
||||||
|
tempServiceParameters.add(Pair(bundle, actionTask))
|
||||||
|
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
||||||
|
}.create().show()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startDatabaseService(bundle, actionTask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showDatabaseChangedDialog(
|
||||||
|
previousDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
|
newDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
|
readOnlyDatabase: Boolean
|
||||||
) {
|
) {
|
||||||
mDatabaseTaskProvider?.startDatabaseCreate(databaseUri, mainCredential)
|
lifecycleScope.launch {
|
||||||
|
if (databaseChangedDialogFragment == null) {
|
||||||
|
databaseChangedDialogFragment = supportFragmentManager
|
||||||
|
.findFragmentByTag(DATABASE_CHANGED_DIALOG_TAG) as DatabaseChangedDialogFragment?
|
||||||
|
databaseChangedDialogFragment?.actionDatabaseListener =
|
||||||
|
mActionDatabaseListener
|
||||||
|
}
|
||||||
|
if (progressTaskDialogFragment == null) {
|
||||||
|
databaseChangedDialogFragment = DatabaseChangedDialogFragment.getInstance(
|
||||||
|
previousDatabaseInfo,
|
||||||
|
newDatabaseInfo,
|
||||||
|
readOnlyDatabase
|
||||||
|
)
|
||||||
|
databaseChangedDialogFragment?.actionDatabaseListener =
|
||||||
|
mActionDatabaseListener
|
||||||
|
databaseChangedDialogFragment?.show(
|
||||||
|
supportFragmentManager,
|
||||||
|
DATABASE_CHANGED_DIALOG_TAG
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadDatabase(
|
private fun startDialog(progressMessage: ProgressMessage) {
|
||||||
databaseUri: Uri,
|
lifecycleScope.launch {
|
||||||
mainCredential: MainCredential,
|
if (progressTaskDialogFragment == null) {
|
||||||
readOnly: Boolean,
|
progressTaskDialogFragment = supportFragmentManager
|
||||||
cipherEncryptDatabase: CipherEncryptDatabase?,
|
.findFragmentByTag(PROGRESS_TASK_DIALOG_TAG) as ProgressTaskDialogFragment?
|
||||||
fixDuplicateUuid: Boolean
|
}
|
||||||
) {
|
if (progressTaskDialogFragment == null) {
|
||||||
mDatabaseTaskProvider?.startDatabaseLoad(
|
progressTaskDialogFragment = ProgressTaskDialogFragment()
|
||||||
databaseUri,
|
progressTaskDialogFragment?.show(
|
||||||
mainCredential,
|
supportFragmentManager,
|
||||||
readOnly,
|
PROGRESS_TASK_DIALOG_TAG
|
||||||
cipherEncryptDatabase,
|
)
|
||||||
fixDuplicateUuid
|
}
|
||||||
)
|
updateDialog(progressMessage)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun closeDatabase() {
|
private fun updateDialog(progressMessage: ProgressMessage) {
|
||||||
mDatabase?.clearAndClose(this.getBinaryDir())
|
progressTaskDialogFragment?.apply {
|
||||||
|
updateTitle(progressMessage.titleId)
|
||||||
|
updateMessage(progressMessage.messageId)
|
||||||
|
updateWarning(progressMessage.warningId)
|
||||||
|
setCancellable(progressMessage.cancelable)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
private fun stopDialog() {
|
||||||
super.onResume()
|
progressTaskDialogFragment?.dismissAllowingStateLoss()
|
||||||
mDatabaseTaskProvider?.registerProgressTask()
|
progressTaskDialogFragment = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
protected open fun showDatabaseDialog(): Boolean {
|
||||||
mDatabaseTaskProvider?.unregisterProgressTask()
|
return true
|
||||||
super.onPause()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,80 +87,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
deleteDatabaseNodes(nodes)
|
deleteDatabaseNodes(nodes)
|
||||||
}
|
}
|
||||||
|
|
||||||
mDatabaseViewModel.saveDatabase.observe(this) { save ->
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSave(save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.mergeDatabase.observe(this) { save ->
|
|
||||||
mDatabaseTaskProvider?.startDatabaseMerge(save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.reloadDatabase.observe(this) { fixDuplicateUuid ->
|
|
||||||
mDatabaseTaskProvider?.askToStartDatabaseReload(mDatabase?.dataModifiedSinceLastLoading != false) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseReload(fixDuplicateUuid)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveName.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveName(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveDescription.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveDescription(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveDefaultUsername.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveDefaultUsername(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveColor.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveColor(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveCompression.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveCompression(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.removeUnlinkData.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseRemoveUnlinkedData(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveRecycleBin.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveRecycleBin(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveTemplatesGroup.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveTemplatesGroup(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveMaxHistoryItems.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveMaxHistoryItems(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveMaxHistorySize.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveMaxHistorySize(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveEncryption.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveEncryption(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveKeyDerivation.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveKeyDerivation(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveIterations.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveIterations(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveMemoryUsage.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveMemoryUsage(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mDatabaseViewModel.saveParallelism.observe(this) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseSaveParallelism(it.oldValue, it.newValue, it.save)
|
|
||||||
}
|
|
||||||
|
|
||||||
mExitLock = false
|
mExitLock = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,8 +95,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||||
super.onDatabaseRetrieved(database)
|
|
||||||
|
|
||||||
// End activity if database not loaded
|
// End activity if database not loaded
|
||||||
if (finishActivityIfDatabaseNotLoaded() && (database == null || !database.loaded)) {
|
if (finishActivityIfDatabaseNotLoaded() && (database == null || !database.loaded)) {
|
||||||
finish()
|
finish()
|
||||||
@@ -186,7 +110,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
if (mTimeoutEnable) {
|
if (mTimeoutEnable) {
|
||||||
if (mLockReceiver == null) {
|
if (mLockReceiver == null) {
|
||||||
mLockReceiver = LockReceiver {
|
mLockReceiver = LockReceiver {
|
||||||
mDatabase = null
|
|
||||||
closeDatabase(database)
|
closeDatabase(database)
|
||||||
mExitLock = true
|
mExitLock = true
|
||||||
closeOptionsMenu()
|
closeOptionsMenu()
|
||||||
@@ -227,7 +150,6 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
actionTask: String,
|
actionTask: String,
|
||||||
result: ActionRunnable.Result
|
result: ActionRunnable.Result
|
||||||
) {
|
) {
|
||||||
super.onDatabaseActionFinished(database, actionTask, result)
|
|
||||||
when (actionTask) {
|
when (actionTask) {
|
||||||
DatabaseTaskNotificationService.ACTION_DATABASE_MERGE_TASK,
|
DatabaseTaskNotificationService.ACTION_DATABASE_MERGE_TASK,
|
||||||
DatabaseTaskNotificationService.ACTION_DATABASE_RELOAD_TASK -> {
|
DatabaseTaskNotificationService.ACTION_DATABASE_RELOAD_TASK -> {
|
||||||
@@ -249,24 +171,15 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
databaseUri: Uri?,
|
databaseUri: Uri?,
|
||||||
mainCredential: MainCredential
|
mainCredential: MainCredential
|
||||||
) {
|
) {
|
||||||
assignDatabasePassword(databaseUri, mainCredential)
|
mDatabaseViewModel.assignMainCredential(databaseUri, mainCredential)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun assignDatabasePassword(
|
fun assignMainCredential(mainCredential: MainCredential) {
|
||||||
databaseUri: Uri?,
|
|
||||||
mainCredential: MainCredential
|
|
||||||
) {
|
|
||||||
if (databaseUri != null) {
|
|
||||||
mDatabaseTaskProvider?.startDatabaseAssignCredential(databaseUri, mainCredential)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun assignPassword(mainCredential: MainCredential) {
|
|
||||||
mDatabase?.let { database ->
|
mDatabase?.let { database ->
|
||||||
database.fileUri?.let { databaseUri ->
|
database.fileUri?.let { databaseUri ->
|
||||||
// Show the progress dialog now or after dialog confirmation
|
// Show the progress dialog now or after dialog confirmation
|
||||||
if (database.isValidCredential(mainCredential.toMasterCredential(contentResolver))) {
|
if (database.isValidCredential(mainCredential.toMasterCredential(contentResolver))) {
|
||||||
assignDatabasePassword(databaseUri, mainCredential)
|
mDatabaseViewModel.assignMainCredential(databaseUri, mainCredential)
|
||||||
} else {
|
} else {
|
||||||
PasswordEncodingDialogFragment.getInstance(databaseUri, mainCredential)
|
PasswordEncodingDialogFragment.getInstance(databaseUri, mainCredential)
|
||||||
.show(supportFragmentManager, "passwordEncodingTag")
|
.show(supportFragmentManager, "passwordEncodingTag")
|
||||||
@@ -276,45 +189,51 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun saveDatabase() {
|
fun saveDatabase() {
|
||||||
mDatabaseTaskProvider?.startDatabaseSave(true)
|
mDatabaseViewModel.saveDatabase(save = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveDatabaseTo(uri: Uri) {
|
fun saveDatabaseTo(uri: Uri) {
|
||||||
mDatabaseTaskProvider?.startDatabaseSave(true, uri)
|
mDatabaseViewModel.saveDatabase(save = true, saveToUri = uri)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mergeDatabase() {
|
fun mergeDatabase() {
|
||||||
mDatabaseTaskProvider?.startDatabaseMerge(mAutoSaveEnable)
|
mDatabaseViewModel.mergeDatabase(save = mAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mergeDatabaseFrom(uri: Uri, mainCredential: MainCredential) {
|
fun mergeDatabaseFrom(uri: Uri, mainCredential: MainCredential) {
|
||||||
mDatabaseTaskProvider?.startDatabaseMerge(mAutoSaveEnable, uri, mainCredential)
|
mDatabaseViewModel.mergeDatabase(mAutoSaveEnable, uri, mainCredential)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reloadDatabase() {
|
fun reloadDatabase() {
|
||||||
mDatabaseTaskProvider?.askToStartDatabaseReload(mDatabase?.dataModifiedSinceLastLoading != false) {
|
mDatabaseViewModel.reloadDatabase(fixDuplicateUuid = false)
|
||||||
mDatabaseTaskProvider?.startDatabaseReload(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createEntry(newEntry: Entry,
|
fun createEntry(
|
||||||
parent: Group) {
|
newEntry: Entry,
|
||||||
mDatabaseTaskProvider?.startDatabaseCreateEntry(newEntry, parent, mAutoSaveEnable)
|
parent: Group
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.createEntry(newEntry, parent, mAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateEntry(oldEntry: Entry,
|
fun updateEntry(
|
||||||
entryToUpdate: Entry) {
|
oldEntry: Entry,
|
||||||
mDatabaseTaskProvider?.startDatabaseUpdateEntry(oldEntry, entryToUpdate, mAutoSaveEnable)
|
entryToUpdate: Entry
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.updateEntry(oldEntry, entryToUpdate, mAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyNodes(nodesToCopy: List<Node>,
|
fun copyNodes(
|
||||||
newParent: Group) {
|
nodesToCopy: List<Node>,
|
||||||
mDatabaseTaskProvider?.startDatabaseCopyNodes(nodesToCopy, newParent, mAutoSaveEnable)
|
newParent: Group
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.copyNodes(nodesToCopy, newParent, mAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun moveNodes(nodesToMove: List<Node>,
|
fun moveNodes(
|
||||||
newParent: Group) {
|
nodesToMove: List<Node>,
|
||||||
mDatabaseTaskProvider?.startDatabaseMoveNodes(nodesToMove, newParent, mAutoSaveEnable)
|
newParent: Group
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.moveNodes(nodesToMove, newParent, mAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun eachNodeRecyclable(database: ContextualDatabase, nodes: List<Node>): Boolean {
|
private fun eachNodeRecyclable(database: ContextualDatabase, nodes: List<Node>): Boolean {
|
||||||
@@ -330,6 +249,7 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun deleteNodes(nodes: List<Node>, recycleBin: Boolean = false) {
|
fun deleteNodes(nodes: List<Node>, recycleBin: Boolean = false) {
|
||||||
|
// TODO Move in ViewModel
|
||||||
mDatabase?.let { database ->
|
mDatabase?.let { database ->
|
||||||
// If recycle bin enabled, ensure it exists
|
// If recycle bin enabled, ensure it exists
|
||||||
if (database.isRecycleBinEnabled) {
|
if (database.isRecycleBinEnabled) {
|
||||||
@@ -350,11 +270,14 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteDatabaseNodes(nodes: List<Node>) {
|
private fun deleteDatabaseNodes(nodes: List<Node>) {
|
||||||
mDatabaseTaskProvider?.startDatabaseDeleteNodes(nodes, mAutoSaveEnable)
|
mDatabaseViewModel.deleteNodes(nodes, mAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createGroup(parent: Group,
|
fun createGroup(
|
||||||
groupInfo: GroupInfo?) {
|
parent: Group,
|
||||||
|
groupInfo: GroupInfo?
|
||||||
|
) {
|
||||||
|
// TODO Move in ViewModel
|
||||||
// Build the group
|
// Build the group
|
||||||
mDatabase?.createGroup()?.let { newGroup ->
|
mDatabase?.createGroup()?.let { newGroup ->
|
||||||
groupInfo?.let { info ->
|
groupInfo?.let { info ->
|
||||||
@@ -362,12 +285,15 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
}
|
}
|
||||||
// Not really needed here because added in runnable but safe
|
// Not really needed here because added in runnable but safe
|
||||||
newGroup.parent = parent
|
newGroup.parent = parent
|
||||||
mDatabaseTaskProvider?.startDatabaseCreateGroup(newGroup, parent, mAutoSaveEnable)
|
mDatabaseViewModel.createGroup(newGroup, parent, mAutoSaveEnable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateGroup(oldGroup: Group,
|
fun updateGroup(
|
||||||
groupInfo: GroupInfo) {
|
oldGroup: Group,
|
||||||
|
groupInfo: GroupInfo
|
||||||
|
) {
|
||||||
|
// TODO Move in ViewModel
|
||||||
// If group updated save it in the database
|
// If group updated save it in the database
|
||||||
val updateGroup = Group(oldGroup).let { updateGroup ->
|
val updateGroup = Group(oldGroup).let { updateGroup ->
|
||||||
updateGroup.apply {
|
updateGroup.apply {
|
||||||
@@ -377,18 +303,21 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
this.setGroupInfo(groupInfo)
|
this.setGroupInfo(groupInfo)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mDatabaseTaskProvider?.startDatabaseUpdateGroup(oldGroup, updateGroup, mAutoSaveEnable)
|
mDatabaseViewModel.updateGroup(oldGroup, updateGroup, mAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun restoreEntryHistory(mainEntryId: NodeId<UUID>,
|
fun restoreEntryHistory(
|
||||||
entryHistoryPosition: Int) {
|
mainEntryId: NodeId<UUID>,
|
||||||
mDatabaseTaskProvider
|
entryHistoryPosition: Int
|
||||||
?.startDatabaseRestoreEntryHistory(mainEntryId, entryHistoryPosition, mAutoSaveEnable)
|
) {
|
||||||
|
mDatabaseViewModel.restoreEntryHistory(mainEntryId, entryHistoryPosition, mAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteEntryHistory(mainEntryId: NodeId<UUID>,
|
fun deleteEntryHistory(
|
||||||
entryHistoryPosition: Int) {
|
mainEntryId: NodeId<UUID>,
|
||||||
mDatabaseTaskProvider?.startDatabaseDeleteEntryHistory(mainEntryId, entryHistoryPosition, mAutoSaveEnable)
|
entryHistoryPosition: Int
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.deleteEntryHistory(mainEntryId, entryHistoryPosition, mAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkRegister() {
|
private fun checkRegister() {
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
*/
|
*/
|
||||||
package com.kunzisoft.keepass.database
|
package com.kunzisoft.keepass.database
|
||||||
|
|
||||||
import android.Manifest
|
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.ComponentName
|
import android.content.ComponentName
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
@@ -29,23 +28,16 @@ import android.content.Context.BIND_IMPORTANT
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.IntentFilter
|
import android.content.IntentFilter
|
||||||
import android.content.ServiceConnection
|
import android.content.ServiceConnection
|
||||||
import android.content.pm.PackageManager
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.IBinder
|
import android.os.IBinder
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.app.ActivityCompat.shouldShowRequestPermissionRationale
|
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED
|
import androidx.core.content.ContextCompat.RECEIVER_NOT_EXPORTED
|
||||||
import androidx.fragment.app.FragmentActivity
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment
|
import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment
|
||||||
import com.kunzisoft.keepass.activities.dialogs.DatabaseChangedDialogFragment.Companion.DATABASE_CHANGED_DIALOG_TAG
|
|
||||||
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
||||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
||||||
import com.kunzisoft.keepass.database.element.Entry
|
import com.kunzisoft.keepass.database.element.Entry
|
||||||
@@ -55,7 +47,6 @@ import com.kunzisoft.keepass.database.element.node.Node
|
|||||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||||
import com.kunzisoft.keepass.database.element.node.Type
|
import com.kunzisoft.keepass.database.element.node.Type
|
||||||
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||||
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_CHALLENGE_RESPONDED
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_CHALLENGE_RESPONDED
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_CREDENTIAL_TASK
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_ASSIGN_CREDENTIAL_TASK
|
||||||
@@ -89,13 +80,9 @@ import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.
|
|||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_RECYCLE_BIN_TASK
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_TEMPLATES_GROUP_TASK
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.getBundleFromListNodes
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService.Companion.getBundleFromListNodes
|
||||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment
|
|
||||||
import com.kunzisoft.keepass.tasks.ProgressTaskDialogFragment.Companion.PROGRESS_TASK_DIALOG_TAG
|
|
||||||
import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION
|
import com.kunzisoft.keepass.utils.DATABASE_START_TASK_ACTION
|
||||||
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
import com.kunzisoft.keepass.utils.DATABASE_STOP_TASK_ACTION
|
||||||
import com.kunzisoft.keepass.utils.putParcelableList
|
import com.kunzisoft.keepass.utils.putParcelableList
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -103,121 +90,41 @@ import java.util.UUID
|
|||||||
* Useful to retrieve a database instance and sending tasks commands
|
* Useful to retrieve a database instance and sending tasks commands
|
||||||
*/
|
*/
|
||||||
class DatabaseTaskProvider(
|
class DatabaseTaskProvider(
|
||||||
private var context: Context,
|
private var context: Context
|
||||||
private var showDialog: Boolean = true
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// To show dialog only if context is an activity
|
|
||||||
private var activity: FragmentActivity? = try {
|
|
||||||
context as? FragmentActivity?
|
|
||||||
} catch (_: Exception) {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
var onDatabaseRetrieved: ((database: ContextualDatabase?) -> Unit)? = null
|
var onDatabaseRetrieved: ((database: ContextualDatabase?) -> Unit)? = null
|
||||||
|
|
||||||
var onActionFinish: ((
|
var onStartActionRequested: ((bundle: Bundle?, actionTask: String) -> Unit)? = null
|
||||||
database: ContextualDatabase,
|
var actionTaskListener: DatabaseTaskNotificationService.ActionTaskListener? = null
|
||||||
actionTask: String,
|
var databaseInfoListener: DatabaseTaskNotificationService.DatabaseInfoListener? = null
|
||||||
result: ActionRunnable.Result
|
|
||||||
) -> Unit)? = null
|
|
||||||
|
|
||||||
private var intentDatabaseTask: Intent = Intent(
|
|
||||||
context.applicationContext,
|
|
||||||
DatabaseTaskNotificationService::class.java
|
|
||||||
)
|
|
||||||
|
|
||||||
private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null
|
private var databaseTaskBroadcastReceiver: BroadcastReceiver? = null
|
||||||
private var mBinder: DatabaseTaskNotificationService.ActionTaskBinder? = null
|
private var mBinder: DatabaseTaskNotificationService.ActionTaskBinder? = null
|
||||||
|
|
||||||
private var serviceConnection: ServiceConnection? = null
|
private var serviceConnection: ServiceConnection? = null
|
||||||
|
|
||||||
private var progressTaskDialogFragment: ProgressTaskDialogFragment? = null
|
private var intentDatabaseTask: Intent = Intent(
|
||||||
private var databaseChangedDialogFragment: DatabaseChangedDialogFragment? = null
|
context.applicationContext,
|
||||||
|
DatabaseTaskNotificationService::class.java
|
||||||
|
)
|
||||||
|
|
||||||
fun destroy() {
|
fun destroy() {
|
||||||
this.activity = null
|
|
||||||
this.onDatabaseRetrieved = null
|
this.onDatabaseRetrieved = null
|
||||||
this.onActionFinish = null
|
|
||||||
this.databaseTaskBroadcastReceiver = null
|
this.databaseTaskBroadcastReceiver = null
|
||||||
this.mBinder = null
|
this.mBinder = null
|
||||||
this.serviceConnection = null
|
this.serviceConnection = null
|
||||||
this.progressTaskDialogFragment = null
|
|
||||||
this.databaseChangedDialogFragment = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private val actionTaskListener = object : DatabaseTaskNotificationService.ActionTaskListener {
|
|
||||||
override fun onActionStarted(
|
|
||||||
database: ContextualDatabase,
|
|
||||||
progressMessage: ProgressMessage
|
|
||||||
) {
|
|
||||||
if (showDialog)
|
|
||||||
startDialog(progressMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActionUpdated(
|
|
||||||
database: ContextualDatabase,
|
|
||||||
progressMessage: ProgressMessage
|
|
||||||
) {
|
|
||||||
if (showDialog)
|
|
||||||
updateDialog(progressMessage)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActionStopped(
|
|
||||||
database: ContextualDatabase
|
|
||||||
) {
|
|
||||||
// Remove the progress task
|
|
||||||
stopDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onActionFinished(
|
|
||||||
database: ContextualDatabase,
|
|
||||||
actionTask: String,
|
|
||||||
result: ActionRunnable.Result
|
|
||||||
) {
|
|
||||||
onActionFinish?.invoke(database, actionTask, result)
|
|
||||||
onActionStopped(database)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val mActionDatabaseListener =
|
private val mActionDatabaseListener =
|
||||||
object : DatabaseChangedDialogFragment.ActionDatabaseChangedListener {
|
object : DatabaseChangedDialogFragment.ActionDatabaseChangedListener {
|
||||||
override fun validateDatabaseChanged() {
|
override fun onDatabaseChangeValidated() {
|
||||||
mBinder?.getService()?.saveDatabaseInfo()
|
mBinder?.getService()?.saveDatabaseInfo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var databaseInfoListener = object :
|
fun onDatabaseChangeValidated() {
|
||||||
DatabaseTaskNotificationService.DatabaseInfoListener {
|
mBinder?.getService()?.saveDatabaseInfo()
|
||||||
override fun onDatabaseInfoChanged(
|
|
||||||
previousDatabaseInfo: SnapFileDatabaseInfo,
|
|
||||||
newDatabaseInfo: SnapFileDatabaseInfo,
|
|
||||||
readOnlyDatabase: Boolean
|
|
||||||
) {
|
|
||||||
activity?.let { activity ->
|
|
||||||
activity.lifecycleScope.launch {
|
|
||||||
if (databaseChangedDialogFragment == null) {
|
|
||||||
databaseChangedDialogFragment = activity.supportFragmentManager
|
|
||||||
.findFragmentByTag(DATABASE_CHANGED_DIALOG_TAG) as DatabaseChangedDialogFragment?
|
|
||||||
databaseChangedDialogFragment?.actionDatabaseListener =
|
|
||||||
mActionDatabaseListener
|
|
||||||
}
|
|
||||||
if (progressTaskDialogFragment == null) {
|
|
||||||
databaseChangedDialogFragment = DatabaseChangedDialogFragment.getInstance(
|
|
||||||
previousDatabaseInfo,
|
|
||||||
newDatabaseInfo,
|
|
||||||
readOnlyDatabase
|
|
||||||
)
|
|
||||||
databaseChangedDialogFragment?.actionDatabaseListener =
|
|
||||||
mActionDatabaseListener
|
|
||||||
databaseChangedDialogFragment?.show(
|
|
||||||
activity.supportFragmentManager,
|
|
||||||
DATABASE_CHANGED_DIALOG_TAG
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private var databaseListener = object : DatabaseTaskNotificationService.DatabaseListener {
|
private var databaseListener = object : DatabaseTaskNotificationService.DatabaseListener {
|
||||||
@@ -226,49 +133,16 @@ class DatabaseTaskProvider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun startDialog(progressMessage: ProgressMessage) {
|
|
||||||
activity?.let { activity ->
|
|
||||||
activity.lifecycleScope.launch {
|
|
||||||
if (progressTaskDialogFragment == null) {
|
|
||||||
progressTaskDialogFragment = activity.supportFragmentManager
|
|
||||||
.findFragmentByTag(PROGRESS_TASK_DIALOG_TAG) as ProgressTaskDialogFragment?
|
|
||||||
}
|
|
||||||
if (progressTaskDialogFragment == null) {
|
|
||||||
progressTaskDialogFragment = ProgressTaskDialogFragment()
|
|
||||||
progressTaskDialogFragment?.show(
|
|
||||||
activity.supportFragmentManager,
|
|
||||||
PROGRESS_TASK_DIALOG_TAG
|
|
||||||
)
|
|
||||||
}
|
|
||||||
updateDialog(progressMessage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateDialog(progressMessage: ProgressMessage) {
|
|
||||||
progressTaskDialogFragment?.apply {
|
|
||||||
updateTitle(progressMessage.titleId)
|
|
||||||
updateMessage(progressMessage.messageId)
|
|
||||||
updateWarning(progressMessage.warningId)
|
|
||||||
setCancellable(progressMessage.cancelable)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun stopDialog() {
|
|
||||||
progressTaskDialogFragment?.dismissAllowingStateLoss()
|
|
||||||
progressTaskDialogFragment = null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initServiceConnection() {
|
private fun initServiceConnection() {
|
||||||
stopDialog()
|
actionTaskListener?.onActionStopped()
|
||||||
if (serviceConnection == null) {
|
if (serviceConnection == null) {
|
||||||
serviceConnection = object : ServiceConnection {
|
serviceConnection = object : ServiceConnection {
|
||||||
override fun onBindingDied(name: ComponentName?) {
|
override fun onBindingDied(name: ComponentName?) {
|
||||||
stopDialog()
|
actionTaskListener?.onActionStopped()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNullBinding(name: ComponentName?) {
|
override fun onNullBinding(name: ComponentName?) {
|
||||||
stopDialog()
|
actionTaskListener?.onActionStopped()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) {
|
override fun onServiceConnected(name: ComponentName?, serviceBinder: IBinder?) {
|
||||||
@@ -291,13 +165,21 @@ class DatabaseTaskProvider(
|
|||||||
|
|
||||||
private fun addServiceListeners(service: DatabaseTaskNotificationService.ActionTaskBinder?) {
|
private fun addServiceListeners(service: DatabaseTaskNotificationService.ActionTaskBinder?) {
|
||||||
service?.addDatabaseListener(databaseListener)
|
service?.addDatabaseListener(databaseListener)
|
||||||
service?.addDatabaseFileInfoListener(databaseInfoListener)
|
databaseInfoListener?.let { infoListener ->
|
||||||
service?.addActionTaskListener(actionTaskListener)
|
service?.addDatabaseFileInfoListener(infoListener)
|
||||||
|
}
|
||||||
|
actionTaskListener?.let { taskListener ->
|
||||||
|
service?.addActionTaskListener(taskListener)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeServiceListeners(service: DatabaseTaskNotificationService.ActionTaskBinder?) {
|
private fun removeServiceListeners(service: DatabaseTaskNotificationService.ActionTaskBinder?) {
|
||||||
service?.removeActionTaskListener(actionTaskListener)
|
actionTaskListener?.let { taskListener ->
|
||||||
service?.removeDatabaseFileInfoListener(databaseInfoListener)
|
service?.removeActionTaskListener(taskListener)
|
||||||
|
}
|
||||||
|
databaseInfoListener?.let { infoListener ->
|
||||||
|
service?.removeDatabaseFileInfoListener(infoListener)
|
||||||
|
}
|
||||||
service?.removeDatabaseListener(databaseListener)
|
service?.removeDatabaseListener(databaseListener)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,58 +251,9 @@ class DatabaseTaskProvider(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val tempServiceParameters = mutableListOf<Pair<Bundle?, String>>()
|
|
||||||
private val requestPermissionLauncher = activity?.registerForActivityResult(
|
|
||||||
ActivityResultContracts.RequestPermission()
|
|
||||||
) { _ ->
|
|
||||||
// Whether or not the user has accepted, the service can be started,
|
|
||||||
// There just won't be any notification if it's not allowed.
|
|
||||||
tempServiceParameters.removeFirstOrNull()?.let {
|
|
||||||
startService(it.first, it.second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun start(bundle: Bundle? = null, actionTask: String) {
|
private fun start(bundle: Bundle? = null, actionTask: String) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
onStartActionRequested?.invoke(bundle, actionTask) ?: run {
|
||||||
val contextActivity = activity
|
context.startDatabaseService(bundle, actionTask)
|
||||||
if (ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS)
|
|
||||||
== PackageManager.PERMISSION_GRANTED
|
|
||||||
) {
|
|
||||||
startService(bundle, actionTask)
|
|
||||||
} else if (contextActivity != null && shouldShowRequestPermissionRationale(
|
|
||||||
contextActivity,
|
|
||||||
Manifest.permission.POST_NOTIFICATIONS
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
// it's not the first time, so the user deliberately chooses not to display the notification
|
|
||||||
startService(bundle, actionTask)
|
|
||||||
} else {
|
|
||||||
AlertDialog.Builder(context)
|
|
||||||
.setMessage(R.string.warning_database_notification_permission)
|
|
||||||
.setNegativeButton(R.string.later) { _, _ ->
|
|
||||||
// Refuses the notification, so start the service
|
|
||||||
startService(bundle, actionTask)
|
|
||||||
}
|
|
||||||
.setPositiveButton(R.string.ask) { _, _ ->
|
|
||||||
// Save the temp parameters to ask the permission
|
|
||||||
tempServiceParameters.add(Pair(bundle, actionTask))
|
|
||||||
requestPermissionLauncher?.launch(Manifest.permission.POST_NOTIFICATIONS)
|
|
||||||
}.create().show()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
startService(bundle, actionTask)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startService(bundle: Bundle? = null, actionTask: String) {
|
|
||||||
try {
|
|
||||||
if (bundle != null)
|
|
||||||
intentDatabaseTask.putExtras(bundle)
|
|
||||||
intentDatabaseTask.action = actionTask
|
|
||||||
context.startService(intentDatabaseTask)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG, "Unable to perform database action", e)
|
|
||||||
Toast.makeText(context, R.string.error_start_database_action, Toast.LENGTH_LONG).show()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -843,5 +676,21 @@ class DatabaseTaskProvider(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = DatabaseTaskProvider::class.java.name
|
private val TAG = DatabaseTaskProvider::class.java.name
|
||||||
|
|
||||||
|
fun Context.startDatabaseService(bundle: Bundle? = null, actionTask: String) {
|
||||||
|
try {
|
||||||
|
val intentDatabaseTask = Intent(
|
||||||
|
applicationContext,
|
||||||
|
DatabaseTaskNotificationService::class.java
|
||||||
|
)
|
||||||
|
if (bundle != null)
|
||||||
|
intentDatabaseTask.putExtras(bundle)
|
||||||
|
intentDatabaseTask.action = actionTask
|
||||||
|
startService(intentDatabaseTask)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "Unable to perform database action", e)
|
||||||
|
Toast.makeText(this, R.string.error_start_database_action, Toast.LENGTH_LONG).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ class HardwareKeyActivity: DatabaseModeActivity(){
|
|||||||
if (result.resultCode == RESULT_OK) {
|
if (result.resultCode == RESULT_OK) {
|
||||||
val challengeResponse: ByteArray? = result.data?.getByteArrayExtra(HARDWARE_KEY_RESPONSE_KEY)
|
val challengeResponse: ByteArray? = result.data?.getByteArrayExtra(HARDWARE_KEY_RESPONSE_KEY)
|
||||||
Log.d(TAG, "Response form challenge")
|
Log.d(TAG, "Response form challenge")
|
||||||
mDatabaseTaskProvider?.startChallengeResponded(challengeResponse ?: ByteArray(0))
|
mDatabaseViewModel.onChallengeResponded(challengeResponse)
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG, "Response from challenge error")
|
Log.e(TAG, "Response from challenge error")
|
||||||
mDatabaseTaskProvider?.startChallengeResponded(ByteArray(0))
|
mDatabaseViewModel.onChallengeResponded(null)
|
||||||
}
|
}
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
@@ -49,13 +49,11 @@ class HardwareKeyActivity: DatabaseModeActivity(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||||
super.onDatabaseRetrieved(database)
|
|
||||||
|
|
||||||
val hardwareKey = HardwareKey.getHardwareKeyFromString(
|
val hardwareKey = HardwareKey.getHardwareKeyFromString(
|
||||||
intent.getStringExtra(DATA_HARDWARE_KEY)
|
intent.getStringExtra(DATA_HARDWARE_KEY)
|
||||||
)
|
)
|
||||||
if (isHardwareKeyAvailable(this, hardwareKey, true) {
|
if (isHardwareKeyAvailable(this, hardwareKey, true) {
|
||||||
mDatabaseTaskProvider?.startChallengeResponded(ByteArray(0))
|
mDatabaseViewModel.onChallengeResponded(null)
|
||||||
}) {
|
}) {
|
||||||
when (hardwareKey) {
|
when (hardwareKey) {
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ open class DatabaseTaskNotificationService : LockNotificationService(), Progress
|
|||||||
progressMessage: ProgressMessage
|
progressMessage: ProgressMessage
|
||||||
)
|
)
|
||||||
fun onActionStopped(
|
fun onActionStopped(
|
||||||
database: ContextualDatabase
|
database: ContextualDatabase? = null
|
||||||
)
|
)
|
||||||
fun onActionFinished(
|
fun onActionFinished(
|
||||||
database: ContextualDatabase,
|
database: ContextualDatabase,
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class MainPreferenceFragment : PreferenceFragmentCompat() {
|
|||||||
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
||||||
checkDatabaseLoaded(uiState.database?.loaded == true)
|
checkDatabaseLoaded(uiState.database?.loaded == true)
|
||||||
}
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,12 @@ package com.kunzisoft.keepass.settings
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.*
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
import androidx.core.view.MenuProvider
|
import androidx.core.view.MenuProvider
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
@@ -40,10 +45,29 @@ import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
|||||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
||||||
import com.kunzisoft.keepass.database.element.Group
|
import com.kunzisoft.keepass.database.element.Group
|
||||||
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
||||||
import com.kunzisoft.keepass.database.helper.*
|
import com.kunzisoft.keepass.database.helper.getLocalizedName
|
||||||
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
|
||||||
import com.kunzisoft.keepass.settings.preference.*
|
import com.kunzisoft.keepass.settings.preference.DialogColorPreference
|
||||||
import com.kunzisoft.keepass.settings.preferencedialogfragment.*
|
import com.kunzisoft.keepass.settings.preference.DialogListExplanationPreference
|
||||||
|
import com.kunzisoft.keepass.settings.preference.InputKdfNumberPreference
|
||||||
|
import com.kunzisoft.keepass.settings.preference.InputKdfSizePreference
|
||||||
|
import com.kunzisoft.keepass.settings.preference.InputNumberPreference
|
||||||
|
import com.kunzisoft.keepass.settings.preference.InputTextPreference
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseColorPreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseDataCompressionPreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseDefaultUsernamePreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseDescriptionPreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseEncryptionAlgorithmPreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseKeyDerivationPreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseMaxHistoryItemsPreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseMaxHistorySizePreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseMemoryUsagePreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseNamePreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseParallelismPreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseRecycleBinGroupPreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseRemoveUnlinkedDataPreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseRoundsPreferenceDialogFragmentCompat
|
||||||
|
import com.kunzisoft.keepass.settings.preferencedialogfragment.DatabaseTemplatesGroupPreferenceDialogFragmentCompat
|
||||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||||
import com.kunzisoft.keepass.utils.getParcelableCompat
|
import com.kunzisoft.keepass.utils.getParcelableCompat
|
||||||
import com.kunzisoft.keepass.utils.getSerializableCompat
|
import com.kunzisoft.keepass.utils.getSerializableCompat
|
||||||
@@ -131,13 +155,17 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
|||||||
)
|
)
|
||||||
onDatabaseRetrieved(uiState.database)
|
onDatabaseRetrieved(uiState.database)
|
||||||
}
|
}
|
||||||
|
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
|
||||||
|
onDatabaseActionFinished(
|
||||||
|
uiState.database,
|
||||||
|
uiState.actionTask,
|
||||||
|
uiState.result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mDatabaseViewModel.actionFinished.observe(viewLifecycleOwner) {
|
|
||||||
onDatabaseActionFinished(it.database, it.actionTask, it.result)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateScreenPreference(screen: Screen, savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreateScreenPreference(screen: Screen, savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
|
|||||||
@@ -192,7 +192,7 @@ open class SettingsActivity
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onAssignKeyDialogPositiveClick(mainCredential: MainCredential) {
|
override fun onAssignKeyDialogPositiveClick(mainCredential: MainCredential) {
|
||||||
assignPassword(mainCredential)
|
assignMainCredential(mainCredential)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAssignKeyDialogNegativeClick(mainCredential: MainCredential) {}
|
override fun onAssignKeyDialogNegativeClick(mainCredential: MainCredential) {}
|
||||||
|
|||||||
@@ -59,6 +59,14 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat
|
|||||||
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
||||||
onDatabaseRetrieved(uiState.database)
|
onDatabaseRetrieved(uiState.database)
|
||||||
}
|
}
|
||||||
|
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
|
||||||
|
onDatabaseActionFinished(
|
||||||
|
uiState.database,
|
||||||
|
uiState.actionTask,
|
||||||
|
uiState.result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,8 +89,10 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat
|
|||||||
// To inherit to save element in database
|
// To inherit to save element in database
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveColor(oldColor: Int?,
|
protected fun saveColor(
|
||||||
newColor: Int?) {
|
oldColor: Int?,
|
||||||
|
newColor: Int?
|
||||||
|
) {
|
||||||
val oldColorString = if (oldColor != null)
|
val oldColorString = if (oldColor != null)
|
||||||
ChromaUtil.getFormattedColorString(oldColor, false)
|
ChromaUtil.getFormattedColorString(oldColor, false)
|
||||||
else
|
else
|
||||||
@@ -91,77 +101,158 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat
|
|||||||
ChromaUtil.getFormattedColorString(newColor, false)
|
ChromaUtil.getFormattedColorString(newColor, false)
|
||||||
else
|
else
|
||||||
""
|
""
|
||||||
mDatabaseViewModel.saveColor(oldColorString, newColorString, mDatabaseAutoSaveEnable)
|
mDatabaseViewModel.saveColor(
|
||||||
|
oldColorString,
|
||||||
|
newColorString,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveCompression(oldCompression: CompressionAlgorithm,
|
protected fun saveCompression(
|
||||||
newCompression: CompressionAlgorithm
|
oldCompression: CompressionAlgorithm,
|
||||||
|
newCompression: CompressionAlgorithm
|
||||||
) {
|
) {
|
||||||
mDatabaseViewModel.saveCompression(oldCompression, newCompression, mDatabaseAutoSaveEnable)
|
mDatabaseViewModel.saveCompression(
|
||||||
|
oldCompression,
|
||||||
|
newCompression,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveDefaultUsername(oldUsername: String,
|
protected fun saveDefaultUsername(
|
||||||
newUsername: String) {
|
oldUsername: String,
|
||||||
mDatabaseViewModel.saveDefaultUsername(oldUsername, newUsername, mDatabaseAutoSaveEnable)
|
newUsername: String
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveDefaultUsername(
|
||||||
|
oldUsername,
|
||||||
|
newUsername,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveDescription(oldDescription: String,
|
protected fun saveDescription(
|
||||||
newDescription: String) {
|
oldDescription: String,
|
||||||
mDatabaseViewModel.saveDescription(oldDescription, newDescription, mDatabaseAutoSaveEnable)
|
newDescription: String
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveDescription(
|
||||||
|
oldDescription,
|
||||||
|
newDescription,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveEncryption(oldEncryption: EncryptionAlgorithm,
|
protected fun saveEncryption(
|
||||||
newEncryptionAlgorithm: EncryptionAlgorithm) {
|
oldEncryption: EncryptionAlgorithm,
|
||||||
mDatabaseViewModel.saveEncryption(oldEncryption, newEncryptionAlgorithm, mDatabaseAutoSaveEnable)
|
newEncryptionAlgorithm: EncryptionAlgorithm
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveEncryption(
|
||||||
|
oldEncryption,
|
||||||
|
newEncryptionAlgorithm,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveKeyDerivation(oldKeyDerivation: KdfEngine,
|
protected fun saveKeyDerivation(
|
||||||
newKeyDerivation: KdfEngine) {
|
oldKeyDerivation: KdfEngine,
|
||||||
mDatabaseViewModel.saveKeyDerivation(oldKeyDerivation, newKeyDerivation, mDatabaseAutoSaveEnable)
|
newKeyDerivation: KdfEngine
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveKeyDerivation(
|
||||||
|
oldKeyDerivation,
|
||||||
|
newKeyDerivation,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveName(oldName: String,
|
protected fun saveName(
|
||||||
newName: String) {
|
oldName: String,
|
||||||
mDatabaseViewModel.saveName(oldName, newName, mDatabaseAutoSaveEnable)
|
newName: String
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveName(
|
||||||
|
oldName,
|
||||||
|
newName,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveRecycleBin(oldGroup: Group?,
|
protected fun saveRecycleBin(
|
||||||
newGroup: Group?) {
|
oldGroup: Group?,
|
||||||
mDatabaseViewModel.saveRecycleBin(oldGroup, newGroup, mDatabaseAutoSaveEnable)
|
newGroup: Group?
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveRecycleBin(
|
||||||
|
oldGroup,
|
||||||
|
newGroup,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun removeUnlinkedData() {
|
protected fun removeUnlinkedData() {
|
||||||
mDatabaseViewModel.removeUnlinkedData(mDatabaseAutoSaveEnable)
|
mDatabaseViewModel.removeUnlinkedData(mDatabaseAutoSaveEnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveTemplatesGroup(oldGroup: Group?,
|
protected fun saveTemplatesGroup(
|
||||||
newGroup: Group?) {
|
oldGroup: Group?,
|
||||||
mDatabaseViewModel.saveTemplatesGroup(oldGroup, newGroup, mDatabaseAutoSaveEnable)
|
newGroup: Group?
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveTemplatesGroup(
|
||||||
|
oldGroup,
|
||||||
|
newGroup,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveMaxHistoryItems(oldNumber: Int,
|
protected fun saveMaxHistoryItems(
|
||||||
newNumber: Int) {
|
oldNumber: Int,
|
||||||
mDatabaseViewModel.saveMaxHistoryItems(oldNumber, newNumber, mDatabaseAutoSaveEnable)
|
newNumber: Int
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveMaxHistoryItems(
|
||||||
|
oldNumber,
|
||||||
|
newNumber,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveMaxHistorySize(oldNumber: Long,
|
protected fun saveMaxHistorySize(
|
||||||
newNumber: Long) {
|
oldNumber: Long,
|
||||||
mDatabaseViewModel.saveMaxHistorySize(oldNumber, newNumber, mDatabaseAutoSaveEnable)
|
newNumber: Long
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveMaxHistorySize(
|
||||||
|
oldNumber,
|
||||||
|
newNumber,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveMemoryUsage(oldNumber: Long,
|
protected fun saveMemoryUsage(
|
||||||
newNumber: Long) {
|
oldNumber: Long,
|
||||||
mDatabaseViewModel.saveMemoryUsage(oldNumber, newNumber, mDatabaseAutoSaveEnable)
|
newNumber: Long
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveMemoryUsage(
|
||||||
|
oldNumber,
|
||||||
|
newNumber,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveParallelism(oldNumber: Long,
|
protected fun saveParallelism(
|
||||||
newNumber: Long) {
|
oldNumber: Long,
|
||||||
mDatabaseViewModel.saveParallelism(oldNumber, newNumber, mDatabaseAutoSaveEnable)
|
newNumber: Long
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveParallelism(
|
||||||
|
oldNumber,
|
||||||
|
newNumber,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun saveIterations(oldNumber: Long,
|
protected fun saveIterations(
|
||||||
newNumber: Long) {
|
oldNumber: Long,
|
||||||
mDatabaseViewModel.saveIterations(oldNumber, newNumber, mDatabaseAutoSaveEnable)
|
newNumber: Long
|
||||||
|
) {
|
||||||
|
mDatabaseViewModel.saveIterations(
|
||||||
|
oldNumber,
|
||||||
|
newNumber,
|
||||||
|
mDatabaseAutoSaveEnable
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
@@ -1,17 +1,30 @@
|
|||||||
package com.kunzisoft.keepass.viewmodels
|
package com.kunzisoft.keepass.viewmodels
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData
|
import android.app.Application
|
||||||
import androidx.lifecycle.ViewModel
|
import android.net.Uri
|
||||||
|
import android.os.Bundle
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
import com.kunzisoft.keepass.database.ContextualDatabase
|
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||||
|
import com.kunzisoft.keepass.database.DatabaseTaskProvider
|
||||||
|
import com.kunzisoft.keepass.database.MainCredential
|
||||||
|
import com.kunzisoft.keepass.database.ProgressMessage
|
||||||
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
|
||||||
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
import com.kunzisoft.keepass.database.crypto.kdf.KdfEngine
|
||||||
|
import com.kunzisoft.keepass.database.element.Entry
|
||||||
import com.kunzisoft.keepass.database.element.Group
|
import com.kunzisoft.keepass.database.element.Group
|
||||||
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
|
||||||
|
import com.kunzisoft.keepass.database.element.node.Node
|
||||||
|
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||||
|
import com.kunzisoft.keepass.model.CipherEncryptDatabase
|
||||||
|
import com.kunzisoft.keepass.model.SnapFileDatabaseInfo
|
||||||
|
import com.kunzisoft.keepass.services.DatabaseTaskNotificationService
|
||||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||||
|
import com.kunzisoft.keepass.utils.getBinaryDir
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
class DatabaseViewModel: ViewModel() {
|
class DatabaseViewModel(application: Application): AndroidViewModel(application) {
|
||||||
|
|
||||||
var database: ContextualDatabase? = null
|
var database: ContextualDatabase? = null
|
||||||
private set
|
private set
|
||||||
@@ -19,174 +32,438 @@ class DatabaseViewModel: ViewModel() {
|
|||||||
private val mUiState = MutableStateFlow<UIState>(UIState.Loading)
|
private val mUiState = MutableStateFlow<UIState>(UIState.Loading)
|
||||||
val uiState: StateFlow<UIState> = mUiState
|
val uiState: StateFlow<UIState> = mUiState
|
||||||
|
|
||||||
val actionFinished : LiveData<ActionResult> get() = _actionFinished
|
private var mDatabaseTaskProvider: DatabaseTaskProvider = DatabaseTaskProvider(
|
||||||
private val _actionFinished = SingleLiveEvent<ActionResult>()
|
context = application
|
||||||
|
)
|
||||||
|
|
||||||
val saveDatabase : LiveData<Boolean> get() = _saveDatabase
|
init {
|
||||||
private val _saveDatabase = SingleLiveEvent<Boolean>()
|
mDatabaseTaskProvider.onDatabaseRetrieved = { databaseRetrieved ->
|
||||||
|
val databaseWasReloaded = databaseRetrieved?.wasReloaded == true
|
||||||
|
if (databaseWasReloaded) {
|
||||||
|
mUiState.value = UIState.OnDatabaseReloaded
|
||||||
|
}
|
||||||
|
if (database == null || database != databaseRetrieved || databaseWasReloaded) {
|
||||||
|
databaseRetrieved?.wasReloaded = false
|
||||||
|
defineDatabase(databaseRetrieved)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mDatabaseTaskProvider.onStartActionRequested = { bundle, actionTask ->
|
||||||
|
mUiState.value = UIState.OnDatabaseActionRequested(bundle, actionTask)
|
||||||
|
}
|
||||||
|
mDatabaseTaskProvider.databaseInfoListener = object : DatabaseTaskNotificationService.DatabaseInfoListener {
|
||||||
|
override fun onDatabaseInfoChanged(
|
||||||
|
previousDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
|
newDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
|
readOnlyDatabase: Boolean
|
||||||
|
) {
|
||||||
|
mUiState.value = UIState.OnDatabaseInfoChanged(
|
||||||
|
previousDatabaseInfo,
|
||||||
|
newDatabaseInfo,
|
||||||
|
readOnlyDatabase
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mDatabaseTaskProvider.actionTaskListener = object : DatabaseTaskNotificationService.ActionTaskListener {
|
||||||
|
override fun onActionStarted(
|
||||||
|
database: ContextualDatabase,
|
||||||
|
progressMessage: ProgressMessage
|
||||||
|
) {
|
||||||
|
mUiState.value = UIState.OnDatabaseActionStarted(database, progressMessage)
|
||||||
|
}
|
||||||
|
|
||||||
val mergeDatabase : LiveData<Boolean> get() = _mergeDatabase
|
override fun onActionUpdated(
|
||||||
private val _mergeDatabase = SingleLiveEvent<Boolean>()
|
database: ContextualDatabase,
|
||||||
|
progressMessage: ProgressMessage
|
||||||
|
) {
|
||||||
|
mUiState.value = UIState.OnDatabaseActionUpdated(database, progressMessage)
|
||||||
|
}
|
||||||
|
|
||||||
val reloadDatabase : LiveData<Boolean> get() = _reloadDatabase
|
override fun onActionStopped(database: ContextualDatabase?) {
|
||||||
private val _reloadDatabase = SingleLiveEvent<Boolean>()
|
mUiState.value = UIState.OnDatabaseActionStopped(database)
|
||||||
|
}
|
||||||
|
|
||||||
val saveName : LiveData<SuperString> get() = _saveName
|
override fun onActionFinished(
|
||||||
private val _saveName = SingleLiveEvent<SuperString>()
|
database: ContextualDatabase,
|
||||||
|
actionTask: String,
|
||||||
|
result: ActionRunnable.Result
|
||||||
|
) {
|
||||||
|
mUiState.value = UIState.OnDatabaseActionFinished(database, actionTask, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val saveDescription : LiveData<SuperString> get() = _saveDescription
|
mDatabaseTaskProvider.registerProgressTask()
|
||||||
private val _saveDescription = SingleLiveEvent<SuperString>()
|
}
|
||||||
|
|
||||||
val saveDefaultUsername : LiveData<SuperString> get() = _saveDefaultUsername
|
/*
|
||||||
private val _saveDefaultUsername = SingleLiveEvent<SuperString>()
|
* Main database actions
|
||||||
|
*/
|
||||||
|
|
||||||
val saveColor : LiveData<SuperString> get() = _saveColor
|
private fun defineDatabase(database: ContextualDatabase?) {
|
||||||
private val _saveColor = SingleLiveEvent<SuperString>()
|
|
||||||
|
|
||||||
val saveCompression : LiveData<SuperCompression> get() = _saveCompression
|
|
||||||
private val _saveCompression = SingleLiveEvent<SuperCompression>()
|
|
||||||
|
|
||||||
val removeUnlinkData : LiveData<Boolean> get() = _removeUnlinkData
|
|
||||||
private val _removeUnlinkData = SingleLiveEvent<Boolean>()
|
|
||||||
|
|
||||||
val saveRecycleBin : LiveData<SuperGroup> get() = _saveRecycleBin
|
|
||||||
private val _saveRecycleBin = SingleLiveEvent<SuperGroup>()
|
|
||||||
|
|
||||||
val saveTemplatesGroup : LiveData<SuperGroup> get() = _saveTemplatesGroup
|
|
||||||
private val _saveTemplatesGroup = SingleLiveEvent<SuperGroup>()
|
|
||||||
|
|
||||||
val saveMaxHistoryItems : LiveData<SuperInt> get() = _saveMaxHistoryItems
|
|
||||||
private val _saveMaxHistoryItems = SingleLiveEvent<SuperInt>()
|
|
||||||
|
|
||||||
val saveMaxHistorySize : LiveData<SuperLong> get() = _saveMaxHistorySize
|
|
||||||
private val _saveMaxHistorySize = SingleLiveEvent<SuperLong>()
|
|
||||||
|
|
||||||
val saveEncryption : LiveData<SuperEncryption> get() = _saveEncryption
|
|
||||||
private val _saveEncryption = SingleLiveEvent<SuperEncryption>()
|
|
||||||
|
|
||||||
val saveKeyDerivation : LiveData<SuperKeyDerivation> get() = _saveKeyDerivation
|
|
||||||
private val _saveKeyDerivation = SingleLiveEvent<SuperKeyDerivation>()
|
|
||||||
|
|
||||||
val saveIterations : LiveData<SuperLong> get() = _saveIterations
|
|
||||||
private val _saveIterations = SingleLiveEvent<SuperLong>()
|
|
||||||
|
|
||||||
val saveMemoryUsage : LiveData<SuperLong> get() = _saveMemoryUsage
|
|
||||||
private val _saveMemoryUsage = SingleLiveEvent<SuperLong>()
|
|
||||||
|
|
||||||
val saveParallelism : LiveData<SuperLong> get() = _saveParallelism
|
|
||||||
private val _saveParallelism = SingleLiveEvent<SuperLong>()
|
|
||||||
|
|
||||||
|
|
||||||
fun defineDatabase(database: ContextualDatabase?) {
|
|
||||||
this.database = database
|
this.database = database
|
||||||
this.mUiState.value = UIState.OnDatabaseRetrieved(database)
|
this.mUiState.value = UIState.OnDatabaseRetrieved(database)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onActionFinished(database: ContextualDatabase,
|
fun loadDatabase(
|
||||||
actionTask: String,
|
databaseUri: Uri,
|
||||||
result: ActionRunnable.Result) {
|
mainCredential: MainCredential,
|
||||||
this._actionFinished.value = ActionResult(database, actionTask, result)
|
readOnly: Boolean,
|
||||||
|
cipherEncryptDatabase: CipherEncryptDatabase?,
|
||||||
|
fixDuplicateUuid: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseLoad(
|
||||||
|
databaseUri,
|
||||||
|
mainCredential,
|
||||||
|
readOnly,
|
||||||
|
cipherEncryptDatabase,
|
||||||
|
fixDuplicateUuid
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveDatabase(save: Boolean) {
|
fun createDatabase(
|
||||||
_saveDatabase.value = save
|
databaseUri: Uri,
|
||||||
|
mainCredential: MainCredential
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseCreate(databaseUri, mainCredential)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mergeDatabase(save: Boolean) {
|
fun assignMainCredential(
|
||||||
_mergeDatabase.value = save
|
databaseUri: Uri?,
|
||||||
|
mainCredential: MainCredential
|
||||||
|
) {
|
||||||
|
if (databaseUri != null) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseAssignCredential(databaseUri, mainCredential)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveDatabase(save: Boolean, saveToUri: Uri? = null) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSave(save, saveToUri)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun mergeDatabase(
|
||||||
|
save: Boolean,
|
||||||
|
fromDatabaseUri: Uri? = null,
|
||||||
|
mainCredential: MainCredential? = null
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseMerge(save, fromDatabaseUri, mainCredential)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reloadDatabase(fixDuplicateUuid: Boolean) {
|
fun reloadDatabase(fixDuplicateUuid: Boolean) {
|
||||||
_reloadDatabase.value = fixDuplicateUuid
|
mDatabaseTaskProvider.askToStartDatabaseReload(
|
||||||
|
conditionToAsk = database?.dataModifiedSinceLastLoading != false
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseReload(fixDuplicateUuid)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveName(oldValue: String,
|
fun closeDatabase() {
|
||||||
newValue: String,
|
database?.clearAndClose(getApplication<Application>().getBinaryDir())
|
||||||
save: Boolean) {
|
|
||||||
_saveName.value = SuperString(oldValue, newValue, save)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveDescription(oldValue: String,
|
fun onDatabaseChangeValidated() {
|
||||||
newValue: String,
|
mDatabaseTaskProvider.onDatabaseChangeValidated()
|
||||||
save: Boolean) {
|
|
||||||
_saveDescription.value = SuperString(oldValue, newValue, save)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveDefaultUsername(oldValue: String,
|
/*
|
||||||
newValue: String,
|
* Nodes actions
|
||||||
save: Boolean) {
|
*/
|
||||||
_saveDefaultUsername.value = SuperString(oldValue, newValue, save)
|
|
||||||
|
fun createEntry(
|
||||||
|
newEntry: Entry,
|
||||||
|
parent: Group,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseCreateEntry(
|
||||||
|
newEntry,
|
||||||
|
parent,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveColor(oldValue: String,
|
fun updateEntry(
|
||||||
newValue: String,
|
oldEntry: Entry,
|
||||||
save: Boolean) {
|
entryToUpdate: Entry,
|
||||||
_saveColor.value = SuperString(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseUpdateEntry(
|
||||||
|
oldEntry,
|
||||||
|
entryToUpdate,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveCompression(oldValue: CompressionAlgorithm,
|
fun restoreEntryHistory(
|
||||||
newValue: CompressionAlgorithm,
|
mainEntryId: NodeId<UUID>,
|
||||||
save: Boolean) {
|
entryHistoryPosition: Int,
|
||||||
_saveCompression.value = SuperCompression(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseRestoreEntryHistory(
|
||||||
|
mainEntryId,
|
||||||
|
entryHistoryPosition,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteEntryHistory(
|
||||||
|
mainEntryId: NodeId<UUID>,
|
||||||
|
entryHistoryPosition: Int,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseDeleteEntryHistory(
|
||||||
|
mainEntryId,
|
||||||
|
entryHistoryPosition,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createGroup(
|
||||||
|
newGroup: Group,
|
||||||
|
parent: Group,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseCreateGroup(
|
||||||
|
newGroup,
|
||||||
|
parent,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateGroup(
|
||||||
|
oldGroup: Group,
|
||||||
|
groupToUpdate: Group,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseUpdateGroup(
|
||||||
|
oldGroup,
|
||||||
|
groupToUpdate,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun copyNodes(
|
||||||
|
nodesToCopy: List<Node>,
|
||||||
|
newParent: Group,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseCopyNodes(
|
||||||
|
nodesToCopy,
|
||||||
|
newParent,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun moveNodes(
|
||||||
|
nodesToMove: List<Node>,
|
||||||
|
newParent: Group,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseMoveNodes(
|
||||||
|
nodesToMove,
|
||||||
|
newParent,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteNodes(
|
||||||
|
nodes: List<Node>,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseDeleteNodes(
|
||||||
|
nodes,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Settings actions
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun saveName(
|
||||||
|
oldValue: String,
|
||||||
|
newValue: String,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveName(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveDescription(
|
||||||
|
oldValue: String,
|
||||||
|
newValue: String,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveDescription(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveDefaultUsername(
|
||||||
|
oldValue: String,
|
||||||
|
newValue: String,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveDefaultUsername(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveColor(
|
||||||
|
oldValue: String,
|
||||||
|
newValue: String,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveColor(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun saveCompression(
|
||||||
|
oldValue: CompressionAlgorithm,
|
||||||
|
newValue: CompressionAlgorithm,
|
||||||
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveCompression(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeUnlinkedData(save: Boolean) {
|
fun removeUnlinkedData(save: Boolean) {
|
||||||
_removeUnlinkData.value = save
|
mDatabaseTaskProvider.startDatabaseRemoveUnlinkedData(save)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveRecycleBin(oldValue: Group?,
|
fun saveRecycleBin(
|
||||||
newValue: Group?,
|
oldValue: Group?,
|
||||||
save: Boolean) {
|
newValue: Group?,
|
||||||
_saveRecycleBin.value = SuperGroup(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveRecycleBin(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveTemplatesGroup(oldValue: Group?,
|
fun saveTemplatesGroup(
|
||||||
newValue: Group?,
|
oldValue: Group?,
|
||||||
save: Boolean) {
|
newValue: Group?,
|
||||||
_saveTemplatesGroup.value = SuperGroup(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveTemplatesGroup(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveMaxHistoryItems(oldValue: Int,
|
fun saveMaxHistoryItems(
|
||||||
newValue: Int,
|
oldValue: Int,
|
||||||
save: Boolean) {
|
newValue: Int,
|
||||||
_saveMaxHistoryItems.value = SuperInt(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveMaxHistoryItems(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveMaxHistorySize(oldValue: Long,
|
fun saveMaxHistorySize(
|
||||||
newValue: Long,
|
oldValue: Long,
|
||||||
save: Boolean) {
|
newValue: Long,
|
||||||
_saveMaxHistorySize.value = SuperLong(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveMaxHistorySize(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun saveEncryption(oldValue: EncryptionAlgorithm,
|
fun saveEncryption(
|
||||||
newValue: EncryptionAlgorithm,
|
oldValue: EncryptionAlgorithm,
|
||||||
save: Boolean) {
|
newValue: EncryptionAlgorithm,
|
||||||
_saveEncryption.value = SuperEncryption(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveEncryption(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveKeyDerivation(oldValue: KdfEngine,
|
fun saveKeyDerivation(
|
||||||
newValue: KdfEngine,
|
oldValue: KdfEngine,
|
||||||
save: Boolean) {
|
newValue: KdfEngine,
|
||||||
_saveKeyDerivation.value = SuperKeyDerivation(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveKeyDerivation(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveIterations(oldValue: Long,
|
fun saveIterations(
|
||||||
newValue: Long,
|
oldValue: Long,
|
||||||
save: Boolean) {
|
newValue: Long,
|
||||||
_saveIterations.value = SuperLong(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveIterations(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveMemoryUsage(oldValue: Long,
|
fun saveMemoryUsage(
|
||||||
newValue: Long,
|
oldValue: Long,
|
||||||
save: Boolean) {
|
newValue: Long,
|
||||||
_saveMemoryUsage.value = SuperLong(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveMemoryUsage(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveParallelism(oldValue: Long,
|
fun saveParallelism(
|
||||||
newValue: Long,
|
oldValue: Long,
|
||||||
save: Boolean) {
|
newValue: Long,
|
||||||
_saveParallelism.value = SuperLong(oldValue, newValue, save)
|
save: Boolean
|
||||||
|
) {
|
||||||
|
mDatabaseTaskProvider.startDatabaseSaveParallelism(
|
||||||
|
oldValue,
|
||||||
|
newValue,
|
||||||
|
save
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hardware Key
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun onChallengeResponded(challengeResponse: ByteArray?) {
|
||||||
|
mDatabaseTaskProvider.startChallengeResponded(
|
||||||
|
challengeResponse ?: ByteArray(0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
mDatabaseTaskProvider.unregisterProgressTask()
|
||||||
|
mDatabaseTaskProvider.destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class UIState {
|
sealed class UIState {
|
||||||
@@ -194,33 +471,31 @@ class DatabaseViewModel: ViewModel() {
|
|||||||
data class OnDatabaseRetrieved(
|
data class OnDatabaseRetrieved(
|
||||||
val database: ContextualDatabase?
|
val database: ContextualDatabase?
|
||||||
): UIState()
|
): UIState()
|
||||||
|
object OnDatabaseReloaded: UIState()
|
||||||
|
data class OnDatabaseActionRequested(
|
||||||
|
val bundle: Bundle? = null,
|
||||||
|
val actionTask: String
|
||||||
|
): UIState()
|
||||||
|
data class OnDatabaseInfoChanged(
|
||||||
|
val previousDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
|
val newDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
|
val readOnlyDatabase: Boolean
|
||||||
|
): UIState()
|
||||||
|
data class OnDatabaseActionStarted(
|
||||||
|
val database: ContextualDatabase,
|
||||||
|
val progressMessage: ProgressMessage
|
||||||
|
): UIState()
|
||||||
|
data class OnDatabaseActionUpdated(
|
||||||
|
val database: ContextualDatabase,
|
||||||
|
val progressMessage: ProgressMessage
|
||||||
|
): UIState()
|
||||||
|
data class OnDatabaseActionStopped(
|
||||||
|
val database: ContextualDatabase?
|
||||||
|
): UIState()
|
||||||
|
data class OnDatabaseActionFinished(
|
||||||
|
val database: ContextualDatabase,
|
||||||
|
val actionTask: String,
|
||||||
|
val result: ActionRunnable.Result
|
||||||
|
): UIState()
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ActionResult(val database: ContextualDatabase,
|
|
||||||
val actionTask: String,
|
|
||||||
val result: ActionRunnable.Result)
|
|
||||||
data class SuperString(val oldValue: String,
|
|
||||||
val newValue: String,
|
|
||||||
val save: Boolean)
|
|
||||||
data class SuperInt(val oldValue: Int,
|
|
||||||
val newValue: Int,
|
|
||||||
val save: Boolean)
|
|
||||||
data class SuperLong(val oldValue: Long,
|
|
||||||
val newValue: Long,
|
|
||||||
val save: Boolean)
|
|
||||||
data class SuperMerge(val fixDuplicateUuid: Boolean,
|
|
||||||
val save: Boolean)
|
|
||||||
data class SuperCompression(val oldValue: CompressionAlgorithm,
|
|
||||||
val newValue: CompressionAlgorithm,
|
|
||||||
val save: Boolean)
|
|
||||||
data class SuperEncryption(val oldValue: EncryptionAlgorithm,
|
|
||||||
val newValue: EncryptionAlgorithm,
|
|
||||||
val save: Boolean)
|
|
||||||
data class SuperKeyDerivation(val oldValue: KdfEngine,
|
|
||||||
val newValue: KdfEngine,
|
|
||||||
val save: Boolean)
|
|
||||||
data class SuperGroup(val oldValue: Group?,
|
|
||||||
val newValue: Group?,
|
|
||||||
val save: Boolean)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user