Fix multiple loading by move variables in entry edit view model

This commit is contained in:
J-Jamet
2021-09-02 11:12:19 +02:00
parent 5467c61137
commit f8fdecdc8f
3 changed files with 157 additions and 128 deletions

View File

@@ -48,12 +48,9 @@ import com.kunzisoft.keepass.activities.helpers.EntrySelectionHelper
import com.kunzisoft.keepass.activities.helpers.ExternalFileHelper
import com.kunzisoft.keepass.activities.legacy.DatabaseLockActivity
import com.kunzisoft.keepass.adapters.TemplatesSelectorAdapter
import com.kunzisoft.keepass.app.database.IOActionTask
import com.kunzisoft.keepass.autofill.AutofillComponent
import com.kunzisoft.keepass.autofill.AutofillHelper
import com.kunzisoft.keepass.database.element.*
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
import com.kunzisoft.keepass.database.element.node.Node
import com.kunzisoft.keepass.database.element.node.NodeId
import com.kunzisoft.keepass.database.element.template.*
@@ -95,14 +92,8 @@ class EntryEditActivity : DatabaseLockActivity(),
private var lockView: View? = null
private var loadingView: ProgressBar? = null
private var mEntryId: NodeId<UUID>? = null
private var mParentId: NodeId<*>? = null
private var mRegisterInfo: RegisterInfo? = null
private var mSearchInfo: SearchInfo? = null
private val mEntryEditViewModel: EntryEditViewModel by viewModels()
private var mParent: Group? = null
private var mEntry: Entry? = null
private var mTemplate: Template? = null
private var mIsTemplate: Boolean = false
private var mAllowCustomFields = false
@@ -138,22 +129,27 @@ class EntryEditActivity : DatabaseLockActivity(),
stopService(Intent(this, ClipboardEntryNotificationService::class.java))
stopService(Intent(this, KeyboardEntryNotificationService::class.java))
mRegisterInfo = EntrySelectionHelper.retrieveRegisterInfoFromIntent(intent)
mSearchInfo = EntrySelectionHelper.retrieveSearchInfoFromIntent(intent)
// Entry is retrieve, it's an entry to update
var entryId: NodeId<UUID>? = null
intent.getParcelableExtra<NodeId<UUID>>(KEY_ENTRY)?.let { entryToUpdate ->
//intent.removeExtra(KEY_ENTRY)
mEntryId = entryToUpdate
intent.removeExtra(KEY_ENTRY)
entryId = entryToUpdate
}
// Parent is retrieve, it's a new entry to create
var parentId: NodeId<*>? = null
intent.getParcelableExtra<NodeId<*>>(KEY_PARENT)?.let { parent ->
//intent.removeExtra(KEY_PARENT)
mParentId = parent
intent.removeExtra(KEY_PARENT)
parentId = parent
}
retrieveEntry(mDatabase)
mEntryEditViewModel.loadTemplateEntry(
mDatabase,
entryId,
parentId,
EntrySelectionHelper.retrieveRegisterInfoFromIntent(intent),
EntrySelectionHelper.retrieveSearchInfoFromIntent(intent)
)
// To retrieve attachment
mExternalFileHelper = ExternalFileHelper(this)
@@ -166,10 +162,14 @@ class EntryEditActivity : DatabaseLockActivity(),
// Save button
validateButton?.setOnClickListener { saveEntry() }
mEntryEditViewModel.onTemplateChanged.observe(this) { template ->
this.mTemplate = template
}
mEntryEditViewModel.templatesEntry.observe(this) { templatesEntry ->
// Change template dynamically
this.mIsTemplate = templatesEntry.isTemplate
templatesEntry?.templates?.let { templates ->
val defaultTemplate = templatesEntry.defaultTemplate
templateSelectorSpinner?.apply {
// Build template selector
if (templates.isNotEmpty()) {
@@ -178,7 +178,11 @@ class EntryEditActivity : DatabaseLockActivity(),
mIconDrawableFactory,
templates
)
setSelection(templates.indexOf(defaultTemplate))
val selectedTemplate = if (mTemplate != null)
mTemplate
else
templatesEntry.defaultTemplate
setSelection(templates.indexOf(selectedTemplate))
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
override fun onItemSelected(
parent: AdapterView<*>?,
@@ -309,78 +313,7 @@ class EntryEditActivity : DatabaseLockActivity(),
super.onDatabaseRetrieved(database)
mAllowCustomFields = database?.allowEntryCustomFields() == true
mAllowOTP = database?.allowOTP == true
retrieveEntry(database)
}
private fun retrieveEntry(database: Database?) {
database?.let {
mEntryId?.let {
IOActionTask(
{
// Create an Entry copy to modify from the database entry
mEntry = database.getEntryById(it)
// Retrieve the parent
mEntry?.let { entry ->
// If no parent, add root group as parent
if (entry.parent == null) {
entry.parent = database.rootGroup
}
}
// Define if current entry is a template (in direct template group)
mIsTemplate = database.entryIsTemplate(mEntry)
},
{
mEntryEditViewModel.loadTemplateEntry(
database,
mEntry,
mIsTemplate,
mRegisterInfo,
mSearchInfo
)
}
).execute()
mEntryId = null
}
mParentId?.let {
IOActionTask(
{
mParent = database.getGroupById(it)
mParent?.let { parentGroup ->
mEntry = database.createEntry()?.apply {
// Add the default icon from parent if not a folder
val parentIcon = parentGroup.icon
// Set default icon
if (parentIcon.custom.isUnknown
&& parentIcon.standard.id != IconImageStandard.FOLDER_ID
) {
icon = IconImage(parentIcon.standard)
}
if (!parentIcon.custom.isUnknown) {
icon = IconImage(parentIcon.custom)
}
// Set default username
username = database.defaultUsername
// Warning only the entry recognize is parent, parent don't yet recognize the new entry
// Useful to recognize child state (ie: entry is a template)
parent = parentGroup
}
}
mIsTemplate = database.entryIsTemplate(mEntry)
},
{
mEntryEditViewModel.loadTemplateEntry(
database,
mEntry,
mIsTemplate,
mRegisterInfo,
mSearchInfo
)
}
).execute()
mParentId = null
}
}
mEntryEditViewModel.loadDatabase(database)
}
override fun onDatabaseActionFinished(
@@ -571,7 +504,7 @@ class EntryEditActivity : DatabaseLockActivity(),
*/
private fun saveEntry() {
mAttachmentFileBinderManager?.stopUploadAllAttachments()
mEntryEditViewModel.requestEntryInfoUpdate(mDatabase, mEntry, mParent)
mEntryEditViewModel.requestEntryInfoUpdate(mDatabase)
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {

View File

@@ -35,6 +35,7 @@ import com.kunzisoft.keepass.activities.dialogs.SetOTPDialogFragment
import com.kunzisoft.keepass.adapters.EntryAttachmentsItemsAdapter
import com.kunzisoft.keepass.database.element.Attachment
import com.kunzisoft.keepass.database.element.Database
import com.kunzisoft.keepass.database.element.template.Template
import com.kunzisoft.keepass.model.AttachmentState
import com.kunzisoft.keepass.model.EntryAttachmentState
import com.kunzisoft.keepass.model.EntryInfo
@@ -55,6 +56,7 @@ class EntryEditFragment: DatabaseFragment() {
private lateinit var attachmentsListView: RecyclerView
private var attachmentsAdapter: EntryAttachmentsItemsAdapter? = null
private var mTemplate: Template? = null
private var mAllowMultipleAttachments: Boolean = false
private var mIconColor: Int = 0
@@ -115,11 +117,16 @@ class EntryEditFragment: DatabaseFragment() {
}
mEntryEditViewModel.onTemplateChanged.observe(viewLifecycleOwner) { template ->
this.mTemplate = template
templateView.setTemplate(template)
}
mEntryEditViewModel.templatesEntry.observe(viewLifecycleOwner) { templateEntry ->
templateView.setTemplate(templateEntry.defaultTemplate)
val selectedTemplate = if (mTemplate != null)
mTemplate
else
templateEntry.defaultTemplate
templateView.setTemplate(selectedTemplate)
// Load entry info only the first time to keep change locally
if (savedInstanceState == null) {
assignEntryInfo(templateEntry.entryInfo)

View File

@@ -5,14 +5,24 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import com.kunzisoft.keepass.app.database.IOActionTask
import com.kunzisoft.keepass.database.element.*
import com.kunzisoft.keepass.database.element.icon.IconImage
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
import com.kunzisoft.keepass.database.element.node.NodeId
import com.kunzisoft.keepass.database.element.template.Template
import com.kunzisoft.keepass.model.*
import com.kunzisoft.keepass.otp.OtpElement
import java.util.*
class EntryEditViewModel: NodeEditViewModel() {
private var mTemplate: Template? = null
private var mEntryId: NodeId<UUID>? = null
private var mParentId: NodeId<*>? = null
private var mRegisterInfo: RegisterInfo? = null
private var mSearchInfo: SearchInfo? = null
private var mParent: Group? = null
private var mEntry: Entry? = null
private var mIsTemplate: Boolean = false
private val mTempAttachments = mutableListOf<EntryAttachmentState>()
val templatesEntry : LiveData<TemplatesEntry> get() = _templatesEntry
@@ -24,7 +34,7 @@ class EntryEditViewModel: NodeEditViewModel() {
private val _onEntrySaved = SingleLiveEvent<EntrySave>()
val onTemplateChanged : LiveData<Template> get() = _onTemplateChanged
private val _onTemplateChanged = SingleLiveEvent<Template>()
private val _onTemplateChanged = MutableLiveData<Template>()
val requestPasswordSelection : LiveData<Field> get() = _requestPasswordSelection
private val _requestPasswordSelection = SingleLiveEvent<Field>()
@@ -54,52 +64,128 @@ class EntryEditViewModel: NodeEditViewModel() {
val onBinaryPreviewLoaded : LiveData<AttachmentPosition> get() = _onBinaryPreviewLoaded
private val _onBinaryPreviewLoaded = SingleLiveEvent<AttachmentPosition>()
fun loadDatabase(database: Database?) {
loadTemplateEntry(database, mEntryId, mParentId, mRegisterInfo, mSearchInfo)
}
fun loadTemplateEntry(database: Database,
entry: Entry?,
isTemplate: Boolean,
fun loadTemplateEntry(database: Database?,
entryId: NodeId<UUID>?,
parentId: NodeId<*>?,
registerInfo: RegisterInfo?,
searchInfo: SearchInfo?) {
IOActionTask(
{
val templates = database.getTemplates(isTemplate)
val entryTemplate = mTemplate
?: (entry?.let { database.getTemplate(it) }
?: Template.STANDARD)
var entryInfo: EntryInfo? = null
// Decode the entry / load entry info
entry?.let {
database.decodeEntryWithTemplateConfiguration(it).let { entry ->
// Load entry info
entry.getEntryInfo(database, true).let { tempEntryInfo ->
// Retrieve data from registration
(registerInfo?.searchInfo ?: searchInfo)?.let { tempSearchInfo ->
tempEntryInfo.saveSearchInfo(database, tempSearchInfo)
this.mEntryId = entryId
this.mParentId = parentId
this.mRegisterInfo = registerInfo
this.mSearchInfo = searchInfo
database?.let {
mEntryId?.let {
IOActionTask(
{
// Create an Entry copy to modify from the database entry
mEntry = database.getEntryById(it)
// Retrieve the parent
mEntry?.let { entry ->
// If no parent, add root group as parent
if (entry.parent == null) {
entry.parent = database.rootGroup
}
registerInfo?.let { regInfo ->
tempEntryInfo.saveRegisterInfo(database, regInfo)
}
entryInfo = tempEntryInfo
}
// Define if current entry is a template (in direct template group)
mIsTemplate = database.entryIsTemplate(mEntry)
decodeTemplateEntry(
database,
mEntry,
mIsTemplate,
registerInfo,
searchInfo
)
},
{ templatesEntry ->
_templatesEntry.value = templatesEntry
}
}
TemplatesEntry(templates, entryTemplate, entryInfo)
},
{ templatesEntry ->
_templatesEntry.value = templatesEntry
).execute()
mEntryId = null
}
).execute()
mParentId?.let {
IOActionTask(
{
mParent = database.getGroupById(it)
mParent?.let { parentGroup ->
mEntry = database.createEntry()?.apply {
// Add the default icon from parent if not a folder
val parentIcon = parentGroup.icon
// Set default icon
if (parentIcon.custom.isUnknown
&& parentIcon.standard.id != IconImageStandard.FOLDER_ID
) {
icon = IconImage(parentIcon.standard)
}
if (!parentIcon.custom.isUnknown) {
icon = IconImage(parentIcon.custom)
}
// Set default username
username = database.defaultUsername
// Warning only the entry recognize is parent, parent don't yet recognize the new entry
// Useful to recognize child state (ie: entry is a template)
parent = parentGroup
}
}
mIsTemplate = database.entryIsTemplate(mEntry)
decodeTemplateEntry(
database,
mEntry,
mIsTemplate,
registerInfo,
searchInfo
)
},
{ templatesEntry ->
_templatesEntry.value = templatesEntry
}
).execute()
mParentId = null
}
}
}
private fun decodeTemplateEntry(database: Database,
entry: Entry?,
isTemplate: Boolean,
registerInfo: RegisterInfo?,
searchInfo: SearchInfo?): TemplatesEntry {
val templates = database.getTemplates(isTemplate)
val entryTemplate = entry?.let { database.getTemplate(it) }
?: Template.STANDARD
var entryInfo: EntryInfo? = null
// Decode the entry / load entry info
entry?.let {
database.decodeEntryWithTemplateConfiguration(it).let { entry ->
// Load entry info
entry.getEntryInfo(database, true).let { tempEntryInfo ->
// Retrieve data from registration
(registerInfo?.searchInfo ?: searchInfo)?.let { tempSearchInfo ->
tempEntryInfo.saveSearchInfo(database, tempSearchInfo)
}
registerInfo?.let { regInfo ->
tempEntryInfo.saveRegisterInfo(database, regInfo)
}
entryInfo = tempEntryInfo
}
}
}
return TemplatesEntry(isTemplate, templates, entryTemplate, entryInfo)
}
fun changeTemplate(template: Template) {
this.mTemplate = template
if (_onTemplateChanged.value != template) {
_onTemplateChanged.value = template
}
}
fun requestEntryInfoUpdate(database: Database?, entry: Entry?, parent: Group?) {
_requestEntryInfoUpdate.value = EntryUpdate(database, entry, parent)
fun requestEntryInfoUpdate(database: Database?) {
_requestEntryInfoUpdate.value = EntryUpdate(database, mEntry, mParent)
}
fun saveEntryInfo(database: Database?, entry: Entry?, parent: Group?, entryInfo: EntryInfo) {
@@ -226,7 +312,10 @@ class EntryEditViewModel: NodeEditViewModel() {
_onBinaryPreviewLoaded.value = AttachmentPosition(entryAttachmentState, viewPosition)
}
data class TemplatesEntry(val templates: List<Template>, val defaultTemplate: Template, val entryInfo: EntryInfo?)
data class TemplatesEntry(val isTemplate: Boolean,
val templates: List<Template>,
val defaultTemplate: Template,
val entryInfo: EntryInfo?)
data class EntryUpdate(val database: Database?, val entry: Entry?, val parent: Group?)
data class EntrySave(val oldEntry: Entry, val newEntry: Entry, val parent: Group?)
data class FieldEdition(val oldField: Field?, val newField: Field?)