mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
fix: Database State
This commit is contained in:
@@ -5,7 +5,9 @@ import android.view.View
|
|||||||
import android.view.WindowManager.LayoutParams.FLAG_SECURE
|
import android.view.WindowManager.LayoutParams.FLAG_SECURE
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
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
|
||||||
@@ -18,26 +20,32 @@ import kotlinx.coroutines.launch
|
|||||||
abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
|
abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
|
||||||
|
|
||||||
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
||||||
|
private val mDatabase: ContextualDatabase?
|
||||||
|
get() = mDatabaseViewModel.database
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
// Initialize the parameters
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
mDatabaseViewModel.uiState.collect { uiState ->
|
mDatabaseViewModel.actionState.collect { uiState ->
|
||||||
when (uiState) {
|
when (uiState) {
|
||||||
is DatabaseViewModel.UIState.Loading -> {}
|
is DatabaseViewModel.ActionState.OnDatabaseActionFinished -> {
|
||||||
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
onDatabaseActionFinished(
|
||||||
resetAppTimeoutOnTouchOrFocus()
|
uiState.database,
|
||||||
onDatabaseRetrieved(uiState.database)
|
uiState.actionTask,
|
||||||
|
uiState.result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
|
}
|
||||||
onDatabaseActionFinished(
|
}
|
||||||
uiState.database,
|
}
|
||||||
uiState.actionTask,
|
lifecycleScope.launch {
|
||||||
uiState.result
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
)
|
mDatabaseViewModel.databaseState.collect { database ->
|
||||||
}
|
onDatabaseRetrieved(database)
|
||||||
else -> {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,7 +86,7 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
|
|||||||
fun resetAppTimeout() {
|
fun resetAppTimeout() {
|
||||||
context?.let {
|
context?.let {
|
||||||
TimeoutHelper.checkTimeAndLockIfTimeoutOrResetTimeout(it,
|
TimeoutHelper.checkTimeAndLockIfTimeoutOrResetTimeout(it,
|
||||||
mDatabaseViewModel.database?.loaded ?: false)
|
mDatabase?.loaded ?: false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,7 +99,7 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
|
|||||||
context?.let {
|
context?.let {
|
||||||
dialog?.window?.decorView?.resetAppTimeoutWhenViewTouchedOrFocused(
|
dialog?.window?.decorView?.resetAppTimeoutWhenViewTouchedOrFocused(
|
||||||
it,
|
it,
|
||||||
mDatabaseViewModel.database?.loaded
|
mDatabase?.loaded
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,45 +10,50 @@ 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
|
||||||
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
|
||||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||||
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
abstract class DatabaseFragment : Fragment(), DatabaseRetrieval {
|
abstract class DatabaseFragment : Fragment(), DatabaseRetrieval {
|
||||||
|
|
||||||
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
protected val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
||||||
|
protected val mDatabase: ContextualDatabase?
|
||||||
|
get() = mDatabaseViewModel.database
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
|
|
||||||
viewLifecycleOwner.lifecycleScope.launch {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
mDatabaseViewModel.uiState.collect { uiState ->
|
mDatabaseViewModel.actionState.collect { uiState ->
|
||||||
when (uiState) {
|
when (uiState) {
|
||||||
is DatabaseViewModel.UIState.Loading -> {}
|
is DatabaseViewModel.ActionState.OnDatabaseActionFinished -> {
|
||||||
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
|
||||||
onDatabaseRetrieved(uiState.database)
|
|
||||||
}
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
|
|
||||||
onDatabaseActionFinished(
|
onDatabaseActionFinished(
|
||||||
uiState.database,
|
uiState.database,
|
||||||
uiState.actionTask,
|
uiState.actionTask,
|
||||||
uiState.result
|
uiState.result
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
mDatabaseViewModel.databaseState.collect { database ->
|
||||||
|
onDatabaseRetrieved(database)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun resetAppTimeoutWhenViewFocusedOrChanged(view: View?) {
|
protected fun resetAppTimeoutWhenViewFocusedOrChanged(view: View?) {
|
||||||
context?.let {
|
context?.let {
|
||||||
view?.resetAppTimeoutWhenViewTouchedOrFocused(
|
view?.resetAppTimeoutWhenViewTouchedOrFocused(
|
||||||
context = it,
|
context = it,
|
||||||
databaseLoaded = mDatabaseViewModel.database?.loaded
|
databaseLoaded = mDatabase?.loaded
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -60,8 +65,4 @@ abstract class DatabaseFragment : Fragment(), DatabaseRetrieval {
|
|||||||
) {
|
) {
|
||||||
// Can be overridden by a subclass
|
// Can be overridden by a subclass
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun buildNewBinaryAttachment(): BinaryData? {
|
|
||||||
return mDatabaseViewModel.database?.buildNewBinaryAttachment()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -230,7 +230,7 @@ class EntryEditFragment: DatabaseFragment() {
|
|||||||
val attachmentToUploadUri = it.attachmentToUploadUri
|
val attachmentToUploadUri = it.attachmentToUploadUri
|
||||||
val fileName = it.fileName
|
val fileName = it.fileName
|
||||||
|
|
||||||
buildNewBinaryAttachment()?.let { binaryAttachment ->
|
mDatabaseViewModel.buildNewAttachment()?.let { binaryAttachment ->
|
||||||
val entryAttachment = Attachment(fileName, binaryAttachment)
|
val entryAttachment = Attachment(fileName, binaryAttachment)
|
||||||
// Ask to replace the current attachment
|
// Ask to replace the current attachment
|
||||||
if ((!mAllowMultipleAttachments
|
if ((!mAllowMultipleAttachments
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ import com.kunzisoft.keepass.database.element.node.Type
|
|||||||
import com.kunzisoft.keepass.settings.PreferencesUtil
|
import com.kunzisoft.keepass.settings.PreferencesUtil
|
||||||
import com.kunzisoft.keepass.tasks.ActionRunnable
|
import com.kunzisoft.keepass.tasks.ActionRunnable
|
||||||
import com.kunzisoft.keepass.utils.KeyboardUtil.hideKeyboard
|
import com.kunzisoft.keepass.utils.KeyboardUtil.hideKeyboard
|
||||||
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
|
||||||
import com.kunzisoft.keepass.viewmodels.GroupViewModel
|
import com.kunzisoft.keepass.viewmodels.GroupViewModel
|
||||||
import java.util.LinkedList
|
import java.util.LinkedList
|
||||||
|
|
||||||
@@ -61,7 +60,6 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
|||||||
private var mLayoutManager: LinearLayoutManager? = null
|
private var mLayoutManager: LinearLayoutManager? = null
|
||||||
private var mAdapter: NodesAdapter? = null
|
private var mAdapter: NodesAdapter? = null
|
||||||
|
|
||||||
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
|
||||||
private val mGroupViewModel: GroupViewModel by activityViewModels()
|
private val mGroupViewModel: GroupViewModel by activityViewModels()
|
||||||
|
|
||||||
private var mCurrentGroup: Group? = null
|
private var mCurrentGroup: Group? = null
|
||||||
@@ -105,7 +103,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
|||||||
PreferencesUtil.getListSort(context),
|
PreferencesUtil.getListSort(context),
|
||||||
PreferencesUtil.getAscendingSort(context),
|
PreferencesUtil.getAscendingSort(context),
|
||||||
PreferencesUtil.getGroupsBeforeSort(context),
|
PreferencesUtil.getGroupsBeforeSort(context),
|
||||||
if (mDatabaseViewModel.database?.isRecycleBinEnabled == true) {
|
if (mDatabase?.isRecycleBinEnabled == true) {
|
||||||
PreferencesUtil.getRecycleBinBottomSort(context)
|
PreferencesUtil.getRecycleBinBottomSort(context)
|
||||||
} else null
|
} else null
|
||||||
)
|
)
|
||||||
@@ -301,8 +299,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun containsRecycleBin(nodes: List<Node>): Boolean {
|
private fun containsRecycleBin(database: ContextualDatabase?, nodes: List<Node>): Boolean {
|
||||||
val database = mDatabaseViewModel.database
|
|
||||||
return database?.isRecycleBinEnabled == true
|
return database?.isRecycleBinEnabled == true
|
||||||
&& nodes.any { it == database.recycleBin }
|
&& nodes.any { it == database.recycleBin }
|
||||||
}
|
}
|
||||||
@@ -331,7 +328,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
|||||||
// Open and Edit for a single item
|
// Open and Edit for a single item
|
||||||
if (nodes.size == 1) {
|
if (nodes.size == 1) {
|
||||||
// Edition
|
// Edition
|
||||||
if (database.isReadOnly || containsRecycleBin(nodes)) {
|
if (database.isReadOnly || containsRecycleBin(database, nodes)) {
|
||||||
menu?.removeItem(R.id.menu_edit)
|
menu?.removeItem(R.id.menu_edit)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -351,7 +348,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deletion
|
// Deletion
|
||||||
if (database.isReadOnly || containsRecycleBin(nodes)) {
|
if (database.isReadOnly || containsRecycleBin(database, nodes)) {
|
||||||
menu?.removeItem(R.id.menu_delete)
|
menu?.removeItem(R.id.menu_delete)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,20 +57,16 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
mDatabaseViewModel.uiState.collect { uiState ->
|
mDatabaseViewModel.actionState.collect { uiState ->
|
||||||
when (uiState) {
|
when (uiState) {
|
||||||
is DatabaseViewModel.UIState.Loading -> {}
|
is DatabaseViewModel.ActionState.Loading -> {}
|
||||||
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
is DatabaseViewModel.ActionState.OnDatabaseReloaded -> {
|
||||||
onDatabaseRetrieved(uiState.database)
|
|
||||||
}
|
|
||||||
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseReloaded -> {
|
|
||||||
if (finishActivityIfReloadRequested()) {
|
if (finishActivityIfReloadRequested()) {
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseInfoChanged -> {
|
is DatabaseViewModel.ActionState.OnDatabaseInfoChanged -> {
|
||||||
showDatabaseChangedDialog(
|
showDatabaseChangedDialog(
|
||||||
uiState.previousDatabaseInfo,
|
uiState.previousDatabaseInfo,
|
||||||
uiState.newDatabaseInfo,
|
uiState.newDatabaseInfo,
|
||||||
@@ -78,29 +74,29 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseActionRequested -> {
|
is DatabaseViewModel.ActionState.OnDatabaseActionRequested -> {
|
||||||
startDatabasePermissionService(
|
startDatabasePermissionService(
|
||||||
uiState.bundle,
|
uiState.bundle,
|
||||||
uiState.actionTask
|
uiState.actionTask
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseActionStarted -> {
|
is DatabaseViewModel.ActionState.OnDatabaseActionStarted -> {
|
||||||
if (showDatabaseDialog())
|
if (showDatabaseDialog())
|
||||||
startDialog(uiState.progressMessage)
|
startDialog(uiState.progressMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseActionUpdated -> {
|
is DatabaseViewModel.ActionState.OnDatabaseActionUpdated -> {
|
||||||
if (showDatabaseDialog())
|
if (showDatabaseDialog())
|
||||||
updateDialog(uiState.progressMessage)
|
updateDialog(uiState.progressMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseActionStopped -> {
|
is DatabaseViewModel.ActionState.OnDatabaseActionStopped -> {
|
||||||
// Remove the progress task
|
// Remove the progress task
|
||||||
stopDialog()
|
stopDialog()
|
||||||
}
|
}
|
||||||
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
|
is DatabaseViewModel.ActionState.OnDatabaseActionFinished -> {
|
||||||
onDatabaseActionFinished(
|
onDatabaseActionFinished(
|
||||||
uiState.database,
|
uiState.database,
|
||||||
uiState.actionTask,
|
uiState.actionTask,
|
||||||
@@ -112,6 +108,13 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
mDatabaseViewModel.databaseState.collect { database ->
|
||||||
|
onDatabaseRetrieved(database)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
|
|||||||
|
|
||||||
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
|
||||||
// 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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,13 +21,15 @@ package com.kunzisoft.keepass.settings
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
|
||||||
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 androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceCategory
|
import androidx.preference.PreferenceCategory
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import com.kunzisoft.keepass.R
|
import com.kunzisoft.keepass.R
|
||||||
|
import com.kunzisoft.keepass.database.ContextualDatabase
|
||||||
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -36,6 +38,8 @@ class MainPreferenceFragment : PreferenceFragmentCompat() {
|
|||||||
private var mCallback: Callback? = null
|
private var mCallback: Callback? = null
|
||||||
|
|
||||||
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
||||||
|
private val mDatabase: ContextualDatabase?
|
||||||
|
get() = mDatabaseViewModel.database
|
||||||
|
|
||||||
override fun onAttach(context: Context) {
|
override fun onAttach(context: Context) {
|
||||||
super.onAttach(context)
|
super.onAttach(context)
|
||||||
@@ -51,20 +55,16 @@ class MainPreferenceFragment : PreferenceFragmentCompat() {
|
|||||||
mCallback = null
|
mCallback = null
|
||||||
super.onDetach()
|
super.onDetach()
|
||||||
}
|
}
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
// Initialize the parameters
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
mDatabaseViewModel.uiState.collect { uiState ->
|
mDatabaseViewModel.databaseState.collect { database ->
|
||||||
when (uiState) {
|
checkDatabaseLoaded(database?.loaded == true)
|
||||||
is DatabaseViewModel.UIState.Loading -> {}
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
|
||||||
checkDatabaseLoaded(uiState.database?.loaded == true)
|
|
||||||
}
|
|
||||||
else -> {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.onViewCreated(view, savedInstanceState)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkDatabaseLoaded(isDatabaseLoaded: Boolean) {
|
private fun checkDatabaseLoaded(isDatabaseLoaded: Boolean) {
|
||||||
@@ -128,7 +128,7 @@ class MainPreferenceFragment : PreferenceFragmentCompat() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDatabaseLoaded(mDatabaseViewModel.database?.loaded == true)
|
checkDatabaseLoaded(mDatabase?.loaded == true)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Callback {
|
interface Callback {
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ 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
|
||||||
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 androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceCategory
|
import androidx.preference.PreferenceCategory
|
||||||
import androidx.preference.TwoStatePreference
|
import androidx.preference.TwoStatePreference
|
||||||
@@ -77,6 +79,8 @@ import kotlinx.coroutines.launch
|
|||||||
class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetrieval {
|
class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetrieval {
|
||||||
|
|
||||||
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
||||||
|
private val mDatabase: ContextualDatabase?
|
||||||
|
get() = mDatabaseViewModel.database
|
||||||
private var mDatabaseReadOnly: Boolean = false
|
private var mDatabaseReadOnly: Boolean = false
|
||||||
private var mMergeDataAllowed: Boolean = false
|
private var mMergeDataAllowed: Boolean = false
|
||||||
private var mDatabaseAutoSaveEnabled: Boolean = true
|
private var mDatabaseAutoSaveEnabled: Boolean = true
|
||||||
@@ -139,38 +143,50 @@ class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetriev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
|
mDatabaseViewModel.actionState.collect { uiState ->
|
||||||
|
when (uiState) {
|
||||||
|
is DatabaseViewModel.ActionState.OnDatabaseActionFinished -> {
|
||||||
|
onDatabaseActionFinished(
|
||||||
|
uiState.database,
|
||||||
|
uiState.actionTask,
|
||||||
|
uiState.result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
mDatabaseViewModel.databaseState.collect { database ->
|
||||||
|
onDatabaseRetrieved(database)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
activity?.addMenuProvider(menuProvider, viewLifecycleOwner)
|
activity?.addMenuProvider(menuProvider, viewLifecycleOwner)
|
||||||
|
viewLifecycleOwner.lifecycleScope.launch {
|
||||||
lifecycleScope.launch {
|
mDatabaseViewModel.databaseState.collect { database ->
|
||||||
mDatabaseViewModel.uiState.collect { uiState ->
|
view.resetAppTimeoutWhenViewTouchedOrFocused(
|
||||||
when (uiState) {
|
context = requireContext(),
|
||||||
is DatabaseViewModel.UIState.Loading -> {}
|
databaseLoaded = database?.loaded
|
||||||
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
)
|
||||||
view.resetAppTimeoutWhenViewTouchedOrFocused(
|
|
||||||
context = requireContext(),
|
|
||||||
databaseLoaded = uiState.database?.loaded
|
|
||||||
)
|
|
||||||
onDatabaseRetrieved(uiState.database)
|
|
||||||
}
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
|
|
||||||
onDatabaseActionFinished(
|
|
||||||
uiState.database,
|
|
||||||
uiState.actionTask,
|
|
||||||
uiState.result
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateScreenPreference(screen: Screen, savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreateScreenPreference(screen: Screen, savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
mScreen = screen
|
mScreen = screen
|
||||||
val database = mDatabaseViewModel.database
|
val database = mDatabase
|
||||||
// Load the preferences from an XML resource
|
// Load the preferences from an XML resource
|
||||||
when (screen) {
|
when (screen) {
|
||||||
Screen.DATABASE -> {
|
Screen.DATABASE -> {
|
||||||
|
|||||||
@@ -42,6 +42,8 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat
|
|||||||
|
|
||||||
private var mDatabaseAutoSaveEnable = true
|
private var mDatabaseAutoSaveEnable = true
|
||||||
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
|
||||||
|
protected val mDatabase: ContextualDatabase?
|
||||||
|
get() = mDatabaseViewModel.database
|
||||||
|
|
||||||
override fun onAttach(context: Context) {
|
override fun onAttach(context: Context) {
|
||||||
super.onAttach(context)
|
super.onAttach(context)
|
||||||
@@ -50,27 +52,30 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat
|
|||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
mDatabaseViewModel.uiState.collect { uiState ->
|
mDatabaseViewModel.actionState.collect { uiState ->
|
||||||
when (uiState) {
|
when (uiState) {
|
||||||
is DatabaseViewModel.UIState.Loading -> {}
|
is DatabaseViewModel.ActionState.OnDatabaseActionFinished -> {
|
||||||
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
|
|
||||||
onDatabaseRetrieved(uiState.database)
|
|
||||||
}
|
|
||||||
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
|
|
||||||
onDatabaseActionFinished(
|
onDatabaseActionFinished(
|
||||||
uiState.database,
|
uiState.database,
|
||||||
uiState.actionTask,
|
uiState.actionTask,
|
||||||
uiState.result
|
uiState.result
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repeatOnLifecycle(Lifecycle.State.RESUMED) {
|
||||||
|
mDatabaseViewModel.databaseState.collect { database ->
|
||||||
|
onDatabaseRetrieved(database)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDatabaseActionFinished(
|
override fun onDatabaseActionFinished(
|
||||||
@@ -82,7 +87,7 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onDialogClosed(positiveResult: Boolean) {
|
override fun onDialogClosed(positiveResult: Boolean) {
|
||||||
onDialogClosed(mDatabaseViewModel.database, positiveResult)
|
onDialogClosed(mDatabase, positiveResult)
|
||||||
}
|
}
|
||||||
|
|
||||||
open fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
open fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ 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
|
||||||
import com.kunzisoft.keepass.database.element.Group
|
import com.kunzisoft.keepass.database.element.Group
|
||||||
|
import com.kunzisoft.keepass.database.element.binary.BinaryData
|
||||||
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.Node
|
||||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||||
@@ -26,11 +27,14 @@ import java.util.UUID
|
|||||||
|
|
||||||
class DatabaseViewModel(application: Application): AndroidViewModel(application) {
|
class DatabaseViewModel(application: Application): AndroidViewModel(application) {
|
||||||
|
|
||||||
var database: ContextualDatabase? = null
|
private val mDatabaseState = MutableStateFlow<ContextualDatabase?>(null)
|
||||||
private set
|
val databaseState: StateFlow<ContextualDatabase?> = mDatabaseState
|
||||||
|
|
||||||
private val mUiState = MutableStateFlow<UIState>(UIState.Loading)
|
val database: ContextualDatabase?
|
||||||
val uiState: StateFlow<UIState> = mUiState
|
get() = databaseState.value
|
||||||
|
|
||||||
|
private val mActionState = MutableStateFlow<ActionState>(ActionState.Loading)
|
||||||
|
val actionState: StateFlow<ActionState> = mActionState
|
||||||
|
|
||||||
private var mDatabaseTaskProvider: DatabaseTaskProvider = DatabaseTaskProvider(
|
private var mDatabaseTaskProvider: DatabaseTaskProvider = DatabaseTaskProvider(
|
||||||
context = application
|
context = application
|
||||||
@@ -40,15 +44,15 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
|
|||||||
mDatabaseTaskProvider.onDatabaseRetrieved = { databaseRetrieved ->
|
mDatabaseTaskProvider.onDatabaseRetrieved = { databaseRetrieved ->
|
||||||
val databaseWasReloaded = databaseRetrieved?.wasReloaded == true
|
val databaseWasReloaded = databaseRetrieved?.wasReloaded == true
|
||||||
if (databaseWasReloaded) {
|
if (databaseWasReloaded) {
|
||||||
mUiState.value = UIState.OnDatabaseReloaded
|
mActionState.value = ActionState.OnDatabaseReloaded
|
||||||
}
|
}
|
||||||
if (database == null || database != databaseRetrieved || databaseWasReloaded) {
|
if (database == null || database != databaseRetrieved || databaseWasReloaded) {
|
||||||
databaseRetrieved?.wasReloaded = false
|
databaseRetrieved?.wasReloaded = false
|
||||||
defineDatabase(databaseRetrieved)
|
mDatabaseState.value = databaseRetrieved
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mDatabaseTaskProvider.onStartActionRequested = { bundle, actionTask ->
|
mDatabaseTaskProvider.onStartActionRequested = { bundle, actionTask ->
|
||||||
mUiState.value = UIState.OnDatabaseActionRequested(bundle, actionTask)
|
mActionState.value = ActionState.OnDatabaseActionRequested(bundle, actionTask)
|
||||||
}
|
}
|
||||||
mDatabaseTaskProvider.databaseInfoListener = object : DatabaseTaskNotificationService.DatabaseInfoListener {
|
mDatabaseTaskProvider.databaseInfoListener = object : DatabaseTaskNotificationService.DatabaseInfoListener {
|
||||||
override fun onDatabaseInfoChanged(
|
override fun onDatabaseInfoChanged(
|
||||||
@@ -56,7 +60,7 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
|
|||||||
newDatabaseInfo: SnapFileDatabaseInfo,
|
newDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
readOnlyDatabase: Boolean
|
readOnlyDatabase: Boolean
|
||||||
) {
|
) {
|
||||||
mUiState.value = UIState.OnDatabaseInfoChanged(
|
mActionState.value = ActionState.OnDatabaseInfoChanged(
|
||||||
previousDatabaseInfo,
|
previousDatabaseInfo,
|
||||||
newDatabaseInfo,
|
newDatabaseInfo,
|
||||||
readOnlyDatabase
|
readOnlyDatabase
|
||||||
@@ -68,18 +72,18 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
|
|||||||
database: ContextualDatabase,
|
database: ContextualDatabase,
|
||||||
progressMessage: ProgressMessage
|
progressMessage: ProgressMessage
|
||||||
) {
|
) {
|
||||||
mUiState.value = UIState.OnDatabaseActionStarted(database, progressMessage)
|
mActionState.value = ActionState.OnDatabaseActionStarted(database, progressMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionUpdated(
|
override fun onActionUpdated(
|
||||||
database: ContextualDatabase,
|
database: ContextualDatabase,
|
||||||
progressMessage: ProgressMessage
|
progressMessage: ProgressMessage
|
||||||
) {
|
) {
|
||||||
mUiState.value = UIState.OnDatabaseActionUpdated(database, progressMessage)
|
mActionState.value = ActionState.OnDatabaseActionUpdated(database, progressMessage)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionStopped(database: ContextualDatabase?) {
|
override fun onActionStopped(database: ContextualDatabase?) {
|
||||||
mUiState.value = UIState.OnDatabaseActionStopped(database)
|
mActionState.value = ActionState.OnDatabaseActionStopped(database)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionFinished(
|
override fun onActionFinished(
|
||||||
@@ -87,7 +91,7 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
|
|||||||
actionTask: String,
|
actionTask: String,
|
||||||
result: ActionRunnable.Result
|
result: ActionRunnable.Result
|
||||||
) {
|
) {
|
||||||
mUiState.value = UIState.OnDatabaseActionFinished(database, actionTask, result)
|
mActionState.value = ActionState.OnDatabaseActionFinished(database, actionTask, result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,11 +102,6 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
|
|||||||
* Main database actions
|
* Main database actions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private fun defineDatabase(database: ContextualDatabase?) {
|
|
||||||
this.database = database
|
|
||||||
this.mUiState.value = UIState.OnDatabaseRetrieved(database)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadDatabase(
|
fun loadDatabase(
|
||||||
databaseUri: Uri,
|
databaseUri: Uri,
|
||||||
mainCredential: MainCredential,
|
mainCredential: MainCredential,
|
||||||
@@ -156,7 +155,9 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun closeDatabase() {
|
fun closeDatabase() {
|
||||||
database?.clearAndClose(getApplication<Application>().getBinaryDir())
|
database?.clearAndClose(
|
||||||
|
filesDirectory = getApplication<Application>().getBinaryDir()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDatabaseChangeValidated() {
|
fun onDatabaseChangeValidated() {
|
||||||
@@ -273,6 +274,14 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attributes
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun buildNewAttachment(): BinaryData? {
|
||||||
|
return database?.buildNewBinaryAttachment()
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Settings actions
|
* Settings actions
|
||||||
*/
|
*/
|
||||||
@@ -466,36 +475,33 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
|
|||||||
mDatabaseTaskProvider.destroy()
|
mDatabaseTaskProvider.destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed class UIState {
|
sealed class ActionState {
|
||||||
object Loading: UIState()
|
object Loading: ActionState()
|
||||||
data class OnDatabaseRetrieved(
|
object OnDatabaseReloaded: ActionState()
|
||||||
val database: ContextualDatabase?
|
|
||||||
): UIState()
|
|
||||||
object OnDatabaseReloaded: UIState()
|
|
||||||
data class OnDatabaseActionRequested(
|
data class OnDatabaseActionRequested(
|
||||||
val bundle: Bundle? = null,
|
val bundle: Bundle? = null,
|
||||||
val actionTask: String
|
val actionTask: String
|
||||||
): UIState()
|
): ActionState()
|
||||||
data class OnDatabaseInfoChanged(
|
data class OnDatabaseInfoChanged(
|
||||||
val previousDatabaseInfo: SnapFileDatabaseInfo,
|
val previousDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
val newDatabaseInfo: SnapFileDatabaseInfo,
|
val newDatabaseInfo: SnapFileDatabaseInfo,
|
||||||
val readOnlyDatabase: Boolean
|
val readOnlyDatabase: Boolean
|
||||||
): UIState()
|
): ActionState()
|
||||||
data class OnDatabaseActionStarted(
|
data class OnDatabaseActionStarted(
|
||||||
val database: ContextualDatabase,
|
var database: ContextualDatabase,
|
||||||
val progressMessage: ProgressMessage
|
val progressMessage: ProgressMessage
|
||||||
): UIState()
|
): ActionState()
|
||||||
data class OnDatabaseActionUpdated(
|
data class OnDatabaseActionUpdated(
|
||||||
val database: ContextualDatabase,
|
var database: ContextualDatabase,
|
||||||
val progressMessage: ProgressMessage
|
val progressMessage: ProgressMessage
|
||||||
): UIState()
|
): ActionState()
|
||||||
data class OnDatabaseActionStopped(
|
data class OnDatabaseActionStopped(
|
||||||
val database: ContextualDatabase?
|
var database: ContextualDatabase?
|
||||||
): UIState()
|
): ActionState()
|
||||||
data class OnDatabaseActionFinished(
|
data class OnDatabaseActionFinished(
|
||||||
val database: ContextualDatabase,
|
var database: ContextualDatabase,
|
||||||
val actionTask: String,
|
val actionTask: String,
|
||||||
val result: ActionRunnable.Result
|
val result: ActionRunnable.Result
|
||||||
): UIState()
|
): ActionState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user