mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Fix multiple loading by move variables in entry edit view model
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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?)
|
||||
|
||||
Reference in New Issue
Block a user