fix: Database State

This commit is contained in:
J-Jamet
2025-10-09 14:31:03 +02:00
parent 50b1ac388e
commit 755e0ea9a5
10 changed files with 170 additions and 134 deletions

View File

@@ -5,7 +5,9 @@ import android.view.View
import android.view.WindowManager.LayoutParams.FLAG_SECURE
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval
import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused
import com.kunzisoft.keepass.database.ContextualDatabase
@@ -18,26 +20,32 @@ import kotlinx.coroutines.launch
abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
private val mDatabase: ContextualDatabase?
get() = mDatabaseViewModel.database
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
// Initialize the parameters
mDatabaseViewModel.uiState.collect { uiState ->
when (uiState) {
is DatabaseViewModel.UIState.Loading -> {}
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
resetAppTimeoutOnTouchOrFocus()
onDatabaseRetrieved(uiState.database)
repeatOnLifecycle(Lifecycle.State.STARTED) {
mDatabaseViewModel.actionState.collect { uiState ->
when (uiState) {
is DatabaseViewModel.ActionState.OnDatabaseActionFinished -> {
onDatabaseActionFinished(
uiState.database,
uiState.actionTask,
uiState.result
)
}
else -> {}
}
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
onDatabaseActionFinished(
uiState.database,
uiState.actionTask,
uiState.result
)
}
else -> {}
}
}
}
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
mDatabaseViewModel.databaseState.collect { database ->
onDatabaseRetrieved(database)
}
}
}
@@ -78,7 +86,7 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
fun resetAppTimeout() {
context?.let {
TimeoutHelper.checkTimeAndLockIfTimeoutOrResetTimeout(it,
mDatabaseViewModel.database?.loaded ?: false)
mDatabase?.loaded ?: false)
}
}
@@ -91,7 +99,7 @@ abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval {
context?.let {
dialog?.window?.decorView?.resetAppTimeoutWhenViewTouchedOrFocused(
it,
mDatabaseViewModel.database?.loaded
mDatabase?.loaded
)
}
}

View File

@@ -10,45 +10,50 @@ import androidx.lifecycle.repeatOnLifecycle
import com.kunzisoft.keepass.activities.legacy.DatabaseRetrieval
import com.kunzisoft.keepass.activities.legacy.resetAppTimeoutWhenViewTouchedOrFocused
import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.database.element.binary.BinaryData
import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
import kotlinx.coroutines.launch
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) {
mDatabaseViewModel.uiState.collect { uiState ->
mDatabaseViewModel.actionState.collect { uiState ->
when (uiState) {
is DatabaseViewModel.UIState.Loading -> {}
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
onDatabaseRetrieved(uiState.database)
}
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
is DatabaseViewModel.ActionState.OnDatabaseActionFinished -> {
onDatabaseActionFinished(
uiState.database,
uiState.actionTask,
uiState.result
)
}
else -> {}
}
}
}
}
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
mDatabaseViewModel.databaseState.collect { database ->
onDatabaseRetrieved(database)
}
}
}
}
protected fun resetAppTimeoutWhenViewFocusedOrChanged(view: View?) {
context?.let {
view?.resetAppTimeoutWhenViewTouchedOrFocused(
context = it,
databaseLoaded = mDatabaseViewModel.database?.loaded
databaseLoaded = mDatabase?.loaded
)
}
}
@@ -60,8 +65,4 @@ abstract class DatabaseFragment : Fragment(), DatabaseRetrieval {
) {
// Can be overridden by a subclass
}
protected fun buildNewBinaryAttachment(): BinaryData? {
return mDatabaseViewModel.database?.buildNewBinaryAttachment()
}
}

View File

@@ -230,7 +230,7 @@ class EntryEditFragment: DatabaseFragment() {
val attachmentToUploadUri = it.attachmentToUploadUri
val fileName = it.fileName
buildNewBinaryAttachment()?.let { binaryAttachment ->
mDatabaseViewModel.buildNewAttachment()?.let { binaryAttachment ->
val entryAttachment = Attachment(fileName, binaryAttachment)
// Ask to replace the current attachment
if ((!mAllowMultipleAttachments

View File

@@ -47,7 +47,6 @@ import com.kunzisoft.keepass.database.element.node.Type
import com.kunzisoft.keepass.settings.PreferencesUtil
import com.kunzisoft.keepass.tasks.ActionRunnable
import com.kunzisoft.keepass.utils.KeyboardUtil.hideKeyboard
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
import com.kunzisoft.keepass.viewmodels.GroupViewModel
import java.util.LinkedList
@@ -61,7 +60,6 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
private var mLayoutManager: LinearLayoutManager? = null
private var mAdapter: NodesAdapter? = null
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
private val mGroupViewModel: GroupViewModel by activityViewModels()
private var mCurrentGroup: Group? = null
@@ -105,7 +103,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
PreferencesUtil.getListSort(context),
PreferencesUtil.getAscendingSort(context),
PreferencesUtil.getGroupsBeforeSort(context),
if (mDatabaseViewModel.database?.isRecycleBinEnabled == true) {
if (mDatabase?.isRecycleBinEnabled == true) {
PreferencesUtil.getRecycleBinBottomSort(context)
} else null
)
@@ -301,8 +299,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
}
}
private fun containsRecycleBin(nodes: List<Node>): Boolean {
val database = mDatabaseViewModel.database
private fun containsRecycleBin(database: ContextualDatabase?, nodes: List<Node>): Boolean {
return database?.isRecycleBinEnabled == true
&& nodes.any { it == database.recycleBin }
}
@@ -331,7 +328,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
// Open and Edit for a single item
if (nodes.size == 1) {
// Edition
if (database.isReadOnly || containsRecycleBin(nodes)) {
if (database.isReadOnly || containsRecycleBin(database, nodes)) {
menu?.removeItem(R.id.menu_edit)
}
} else {
@@ -351,7 +348,7 @@ class GroupFragment : DatabaseFragment(), SortDialogFragment.SortSelectionListen
}
// Deletion
if (database.isReadOnly || containsRecycleBin(nodes)) {
if (database.isReadOnly || containsRecycleBin(database, nodes)) {
menu?.removeItem(R.id.menu_delete)
}
}

View File

@@ -57,20 +57,16 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
mDatabaseViewModel.uiState.collect { uiState ->
mDatabaseViewModel.actionState.collect { uiState ->
when (uiState) {
is DatabaseViewModel.UIState.Loading -> {}
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
onDatabaseRetrieved(uiState.database)
}
is DatabaseViewModel.UIState.OnDatabaseReloaded -> {
is DatabaseViewModel.ActionState.Loading -> {}
is DatabaseViewModel.ActionState.OnDatabaseReloaded -> {
if (finishActivityIfReloadRequested()) {
finish()
}
}
is DatabaseViewModel.UIState.OnDatabaseInfoChanged -> {
is DatabaseViewModel.ActionState.OnDatabaseInfoChanged -> {
showDatabaseChangedDialog(
uiState.previousDatabaseInfo,
uiState.newDatabaseInfo,
@@ -78,29 +74,29 @@ abstract class DatabaseActivity : StylishActivity(), DatabaseRetrieval {
)
}
is DatabaseViewModel.UIState.OnDatabaseActionRequested -> {
is DatabaseViewModel.ActionState.OnDatabaseActionRequested -> {
startDatabasePermissionService(
uiState.bundle,
uiState.actionTask
)
}
is DatabaseViewModel.UIState.OnDatabaseActionStarted -> {
is DatabaseViewModel.ActionState.OnDatabaseActionStarted -> {
if (showDatabaseDialog())
startDialog(uiState.progressMessage)
}
is DatabaseViewModel.UIState.OnDatabaseActionUpdated -> {
is DatabaseViewModel.ActionState.OnDatabaseActionUpdated -> {
if (showDatabaseDialog())
updateDialog(uiState.progressMessage)
}
is DatabaseViewModel.UIState.OnDatabaseActionStopped -> {
is DatabaseViewModel.ActionState.OnDatabaseActionStopped -> {
// Remove the progress task
stopDialog()
}
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
is DatabaseViewModel.ActionState.OnDatabaseActionFinished -> {
onDatabaseActionFinished(
uiState.database,
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?) {

View File

@@ -96,7 +96,7 @@ abstract class DatabaseLockActivity : DatabaseModeActivity(),
override fun onDatabaseRetrieved(database: ContextualDatabase?) {
// End activity if database not loaded
if (finishActivityIfDatabaseNotLoaded() && (database == null || !database.loaded)) {
if (finishActivityIfDatabaseNotLoaded() && (database != null && !database.loaded)) {
finish()
}

View File

@@ -21,13 +21,15 @@ package com.kunzisoft.keepass.settings
import android.content.Context
import android.os.Bundle
import android.view.View
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import com.kunzisoft.keepass.R
import com.kunzisoft.keepass.database.ContextualDatabase
import com.kunzisoft.keepass.viewmodels.DatabaseViewModel
import kotlinx.coroutines.launch
@@ -36,6 +38,8 @@ class MainPreferenceFragment : PreferenceFragmentCompat() {
private var mCallback: Callback? = null
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
private val mDatabase: ContextualDatabase?
get() = mDatabaseViewModel.database
override fun onAttach(context: Context) {
super.onAttach(context)
@@ -51,20 +55,16 @@ class MainPreferenceFragment : PreferenceFragmentCompat() {
mCallback = null
super.onDetach()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
// Initialize the parameters
mDatabaseViewModel.uiState.collect { uiState ->
when (uiState) {
is DatabaseViewModel.UIState.Loading -> {}
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
checkDatabaseLoaded(uiState.database?.loaded == true)
}
else -> {}
repeatOnLifecycle(Lifecycle.State.RESUMED) {
mDatabaseViewModel.databaseState.collect { database ->
checkDatabaseLoaded(database?.loaded == true)
}
}
}
super.onViewCreated(view, savedInstanceState)
}
private fun checkDatabaseLoaded(isDatabaseLoaded: Boolean) {
@@ -128,7 +128,7 @@ class MainPreferenceFragment : PreferenceFragmentCompat() {
}
}
checkDatabaseLoaded(mDatabaseViewModel.database?.loaded == true)
checkDatabaseLoaded(mDatabase?.loaded == true)
}
interface Callback {

View File

@@ -31,7 +31,9 @@ import androidx.core.graphics.toColorInt
import androidx.core.view.MenuProvider
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.activityViewModels
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.preference.Preference
import androidx.preference.PreferenceCategory
import androidx.preference.TwoStatePreference
@@ -77,6 +79,8 @@ import kotlinx.coroutines.launch
class NestedDatabaseSettingsFragment : NestedSettingsFragment(), DatabaseRetrieval {
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
private val mDatabase: ContextualDatabase?
get() = mDatabaseViewModel.database
private var mDatabaseReadOnly: Boolean = false
private var mMergeDataAllowed: Boolean = false
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?) {
super.onViewCreated(view, savedInstanceState)
activity?.addMenuProvider(menuProvider, viewLifecycleOwner)
lifecycleScope.launch {
mDatabaseViewModel.uiState.collect { uiState ->
when (uiState) {
is DatabaseViewModel.UIState.Loading -> {}
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 -> {}
}
viewLifecycleOwner.lifecycleScope.launch {
mDatabaseViewModel.databaseState.collect { database ->
view.resetAppTimeoutWhenViewTouchedOrFocused(
context = requireContext(),
databaseLoaded = database?.loaded
)
}
}
}
override fun onCreateScreenPreference(screen: Screen, savedInstanceState: Bundle?, rootKey: String?) {
mScreen = screen
val database = mDatabaseViewModel.database
val database = mDatabase
// Load the preferences from an XML resource
when (screen) {
Screen.DATABASE -> {

View File

@@ -42,6 +42,8 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat
private var mDatabaseAutoSaveEnable = true
private val mDatabaseViewModel: DatabaseViewModel by activityViewModels()
protected val mDatabase: ContextualDatabase?
get() = mDatabaseViewModel.database
override fun onAttach(context: Context) {
super.onAttach(context)
@@ -50,27 +52,30 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
mDatabaseViewModel.uiState.collect { uiState ->
repeatOnLifecycle(Lifecycle.State.STARTED) {
mDatabaseViewModel.actionState.collect { uiState ->
when (uiState) {
is DatabaseViewModel.UIState.Loading -> {}
is DatabaseViewModel.UIState.OnDatabaseRetrieved -> {
onDatabaseRetrieved(uiState.database)
}
is DatabaseViewModel.UIState.OnDatabaseActionFinished -> {
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 onDatabaseActionFinished(
@@ -82,7 +87,7 @@ abstract class DatabaseSavePreferenceDialogFragmentCompat
}
override fun onDialogClosed(positiveResult: Boolean) {
onDialogClosed(mDatabaseViewModel.database, positiveResult)
onDialogClosed(mDatabase, positiveResult)
}
open fun onDialogClosed(database: ContextualDatabase?, positiveResult: Boolean) {

View File

@@ -12,6 +12,7 @@ import com.kunzisoft.keepass.database.crypto.EncryptionAlgorithm
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.binary.BinaryData
import com.kunzisoft.keepass.database.element.database.CompressionAlgorithm
import com.kunzisoft.keepass.database.element.node.Node
import com.kunzisoft.keepass.database.element.node.NodeId
@@ -26,11 +27,14 @@ import java.util.UUID
class DatabaseViewModel(application: Application): AndroidViewModel(application) {
var database: ContextualDatabase? = null
private set
private val mDatabaseState = MutableStateFlow<ContextualDatabase?>(null)
val databaseState: StateFlow<ContextualDatabase?> = mDatabaseState
private val mUiState = MutableStateFlow<UIState>(UIState.Loading)
val uiState: StateFlow<UIState> = mUiState
val database: ContextualDatabase?
get() = databaseState.value
private val mActionState = MutableStateFlow<ActionState>(ActionState.Loading)
val actionState: StateFlow<ActionState> = mActionState
private var mDatabaseTaskProvider: DatabaseTaskProvider = DatabaseTaskProvider(
context = application
@@ -40,15 +44,15 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
mDatabaseTaskProvider.onDatabaseRetrieved = { databaseRetrieved ->
val databaseWasReloaded = databaseRetrieved?.wasReloaded == true
if (databaseWasReloaded) {
mUiState.value = UIState.OnDatabaseReloaded
mActionState.value = ActionState.OnDatabaseReloaded
}
if (database == null || database != databaseRetrieved || databaseWasReloaded) {
databaseRetrieved?.wasReloaded = false
defineDatabase(databaseRetrieved)
mDatabaseState.value = databaseRetrieved
}
}
mDatabaseTaskProvider.onStartActionRequested = { bundle, actionTask ->
mUiState.value = UIState.OnDatabaseActionRequested(bundle, actionTask)
mActionState.value = ActionState.OnDatabaseActionRequested(bundle, actionTask)
}
mDatabaseTaskProvider.databaseInfoListener = object : DatabaseTaskNotificationService.DatabaseInfoListener {
override fun onDatabaseInfoChanged(
@@ -56,7 +60,7 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
newDatabaseInfo: SnapFileDatabaseInfo,
readOnlyDatabase: Boolean
) {
mUiState.value = UIState.OnDatabaseInfoChanged(
mActionState.value = ActionState.OnDatabaseInfoChanged(
previousDatabaseInfo,
newDatabaseInfo,
readOnlyDatabase
@@ -68,18 +72,18 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
database: ContextualDatabase,
progressMessage: ProgressMessage
) {
mUiState.value = UIState.OnDatabaseActionStarted(database, progressMessage)
mActionState.value = ActionState.OnDatabaseActionStarted(database, progressMessage)
}
override fun onActionUpdated(
database: ContextualDatabase,
progressMessage: ProgressMessage
) {
mUiState.value = UIState.OnDatabaseActionUpdated(database, progressMessage)
mActionState.value = ActionState.OnDatabaseActionUpdated(database, progressMessage)
}
override fun onActionStopped(database: ContextualDatabase?) {
mUiState.value = UIState.OnDatabaseActionStopped(database)
mActionState.value = ActionState.OnDatabaseActionStopped(database)
}
override fun onActionFinished(
@@ -87,7 +91,7 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
actionTask: String,
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
*/
private fun defineDatabase(database: ContextualDatabase?) {
this.database = database
this.mUiState.value = UIState.OnDatabaseRetrieved(database)
}
fun loadDatabase(
databaseUri: Uri,
mainCredential: MainCredential,
@@ -156,7 +155,9 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
}
fun closeDatabase() {
database?.clearAndClose(getApplication<Application>().getBinaryDir())
database?.clearAndClose(
filesDirectory = getApplication<Application>().getBinaryDir()
)
}
fun onDatabaseChangeValidated() {
@@ -273,6 +274,14 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
)
}
/*
* Attributes
*/
fun buildNewAttachment(): BinaryData? {
return database?.buildNewBinaryAttachment()
}
/*
* Settings actions
*/
@@ -466,36 +475,33 @@ class DatabaseViewModel(application: Application): AndroidViewModel(application)
mDatabaseTaskProvider.destroy()
}
sealed class UIState {
object Loading: UIState()
data class OnDatabaseRetrieved(
val database: ContextualDatabase?
): UIState()
object OnDatabaseReloaded: UIState()
sealed class ActionState {
object Loading: ActionState()
object OnDatabaseReloaded: ActionState()
data class OnDatabaseActionRequested(
val bundle: Bundle? = null,
val actionTask: String
): UIState()
): ActionState()
data class OnDatabaseInfoChanged(
val previousDatabaseInfo: SnapFileDatabaseInfo,
val newDatabaseInfo: SnapFileDatabaseInfo,
val readOnlyDatabase: Boolean
): UIState()
): ActionState()
data class OnDatabaseActionStarted(
val database: ContextualDatabase,
var database: ContextualDatabase,
val progressMessage: ProgressMessage
): UIState()
): ActionState()
data class OnDatabaseActionUpdated(
val database: ContextualDatabase,
var database: ContextualDatabase,
val progressMessage: ProgressMessage
): UIState()
): ActionState()
data class OnDatabaseActionStopped(
val database: ContextualDatabase?
): UIState()
var database: ContextualDatabase?
): ActionState()
data class OnDatabaseActionFinished(
val database: ContextualDatabase,
var database: ContextualDatabase,
val actionTask: String,
val result: ActionRunnable.Result
): UIState()
): ActionState()
}
}