From 07af9f36b24f88641244bc926a79ddabc6d92db3 Mon Sep 17 00:00:00 2001 From: J-Jamet Date: Tue, 15 Sep 2020 16:50:04 +0200 Subject: [PATCH] Move temp entry in fragment --- .../keepass/activities/EntryActivity.kt | 2 +- .../keepass/activities/EntryEditActivity.kt | 178 ++++++++---------- .../activities/EntryEditContentsFragment.kt | 65 +++++-- .../keepass/database/element/Database.kt | 7 + .../keepass/database/element/Entry.kt | 8 - .../database/element/entry/EntryKDBX.kt | 5 - 6 files changed, 131 insertions(+), 134 deletions(-) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt index 1ac1300f9..5fbab7c8f 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryActivity.kt @@ -309,7 +309,7 @@ class EntryActivity : LockingActivity() { entryContentsView?.assignNotes(entry.notes) // Assign custom fields - if (entry.allowCustomFields()) { + if (mDatabase?.allowEntryCustomFields() == true) { entryContentsView?.clearExtraFields() for ((label, value) in entry.customFields) { val allowCopyProtectedField = !value.isProtected || allowCopyPasswordAndProtectedFields diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt index e9f5feffc..5ec4b3b1e 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -45,11 +45,13 @@ import com.kunzisoft.keepass.activities.lock.LockingActivity 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.education.EntryEditActivityEducation import com.kunzisoft.keepass.model.* import com.kunzisoft.keepass.notifications.AttachmentFileNotificationService import com.kunzisoft.keepass.notifications.ClipboardEntryNotificationService +import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_CREATE_ENTRY_TASK import com.kunzisoft.keepass.notifications.DatabaseTaskNotificationService.Companion.ACTION_DATABASE_UPDATE_ENTRY_TASK import com.kunzisoft.keepass.notifications.KeyboardEntryNotificationService @@ -82,8 +84,6 @@ class EntryEditActivity : LockingActivity(), // Refs of an entry and group in database, are not modifiable private var mEntry: Entry? = null private var mParent: Group? = null - // New or copy of mEntry in the database to be modifiable - private var mNewEntry: Entry? = null private var mIsNew: Boolean = false // Views @@ -132,6 +132,8 @@ class EntryEditActivity : LockingActivity(), // Likely the app has been killed exit the activity mDatabase = Database.getInstance() + var tempEntry: Entry? = null + // Entry is retrieve, it's an entry to update intent.getParcelableExtra>(KEY_ENTRY)?.let { mIsNew = false @@ -148,14 +150,11 @@ class EntryEditActivity : LockingActivity(), } } - // Create the new entry from the current one - if (savedInstanceState?.containsKey(KEY_NEW_ENTRY) != true) { - mEntry?.let { entry -> - // Create a copy to modify - mNewEntry = Entry(entry).also { newEntry -> - // WARNING Remove the parent to keep memory with parcelable - newEntry.removeParent() - } + mEntry?.let { entry -> + // Create a copy to modify + tempEntry = Entry(entry).also { newEntry -> + // WARNING Remove the parent to keep memory with parcelable + newEntry.removeParent() } } } @@ -163,52 +162,32 @@ class EntryEditActivity : LockingActivity(), // Parent is retrieve, it's a new entry to create intent.getParcelableExtra>(KEY_PARENT)?.let { mIsNew = true - // Create an empty new entry - if (savedInstanceState?.containsKey(KEY_NEW_ENTRY) != true) { - mNewEntry = mDatabase?.createEntry() - } mParent = mDatabase?.getGroupById(it) // Add the default icon from parent if not a folder val parentIcon = mParent?.icon if (parentIcon != null && parentIcon.iconId != IconImage.UNKNOWN_ID && parentIcon.iconId != IconImageStandard.FOLDER) { - temporarilySaveAndShowSelectedIcon(parentIcon) - } else { - mDatabase?.drawFactory?.let { iconFactory -> - entryEditContentsFragment?.setDefaultIcon(iconFactory) - } + tempEntry?.icon = parentIcon } + tempEntry = mDatabase?.createEntry() } - // Retrieve the new entry after an orientation change - if (savedInstanceState?.containsKey(KEY_NEW_ENTRY) == true) { - mNewEntry = savedInstanceState.getParcelable(KEY_NEW_ENTRY) - } - - if (savedInstanceState?.containsKey(TEMP_ATTACHMENTS) == true) { - mTempAttachments = savedInstanceState.getParcelableArrayList(TEMP_ATTACHMENTS) ?: mTempAttachments - } - - // Close the activity if entry or parent can't be retrieve - if (mNewEntry == null || mParent == null) { - finish() - return - } - + // Build fragment to manage entry modification entryEditContentsFragment = supportFragmentManager.findFragmentByTag("entry_edit_contents") as? EntryEditContentsFragment? if (entryEditContentsFragment == null) { entryEditContentsFragment = EntryEditContentsFragment() - supportFragmentManager.beginTransaction() - .replace(R.id.entry_edit_contents, entryEditContentsFragment!!, "entry_edit_contents") - .commit() + } + supportFragmentManager.beginTransaction() + .replace(R.id.entry_edit_contents, entryEditContentsFragment!!, "entry_edit_contents") + .commit() + mDatabase?.let { database -> + entryEditContentsFragment?.setDatabase(database) + } + tempEntry?.let { + entryEditContentsFragment?.setEntry(it, mIsNew) } entryEditContentsFragment?.apply { - mDatabase?.let { database -> - mNewEntry?.let { newEntry -> - entryEditContentsFragment?.setEntry(database, newEntry, mIsNew) - } - } applyFontVisibilityToFields(PreferencesUtil.fieldFontIsInVisibility(this@EntryEditActivity)) setOnDateClickListener = View.OnClickListener { expiresDate.date.let { expiresDate -> @@ -235,6 +214,11 @@ class EntryEditActivity : LockingActivity(), } } + // Retrieve temp attachments in case of deletion + if (savedInstanceState?.containsKey(TEMP_ATTACHMENTS) == true) { + mTempAttachments = savedInstanceState.getParcelableArrayList(TEMP_ATTACHMENTS) ?: mTempAttachments + } + // Assign title title = if (mIsNew) getString(R.string.add_entry) else getString(R.string.edit_entry) @@ -244,7 +228,7 @@ class EntryEditActivity : LockingActivity(), menuInflater.inflate(R.menu.entry_edit, menu) menu.findItem(R.id.menu_add_field).apply { - val allowCustomField = mNewEntry?.allowCustomFields() == true + val allowCustomField = mDatabase?.allowEntryCustomFields() == true isEnabled = allowCustomField isVisible = allowCustomField } @@ -296,8 +280,22 @@ class EntryEditActivity : LockingActivity(), when (actionTask) { ACTION_DATABASE_CREATE_ENTRY_TASK, ACTION_DATABASE_UPDATE_ENTRY_TASK -> { - if (result.isSuccess) - finish() + try { + if (result.isSuccess) { + var newNodes: List = ArrayList() + result.data?.getBundle(DatabaseTaskNotificationService.NEW_NODES_KEY)?.let { newNodesBundle -> + mDatabase?.let { database -> + newNodes = DatabaseTaskNotificationService.getListNodesFromBundle(database, newNodesBundle) + } + } + if (newNodes.size == 1) { + mEntry = newNodes[0] as Entry? + finish() + } + } + } catch (e: Exception) { + Log.e(TAG, "Unable to retrieve entry after database action", e) + } } } coordinatorLayout?.showActionError(result) @@ -366,13 +364,6 @@ class EntryEditActivity : LockingActivity(), super.onPause() } - private fun temporarilySaveAndShowSelectedIcon(icon: IconImage) { - mNewEntry?.icon = icon - mDatabase?.drawFactory?.let { iconDrawFactory -> - entryEditContentsFragment?.setIcon(iconDrawFactory, icon) - } - } - /** * Open the password generator fragment */ @@ -483,47 +474,40 @@ class EntryEditActivity : LockingActivity(), * Saves the new entry or update an existing entry in the database */ private fun saveEntry() { - // Launch a validation and show the error if present - if (entryEditContentsFragment?.isValid() == true) { - // Clone the entry - mNewEntry?.let { newEntry -> + // Get the temp entry + entryEditContentsFragment?.getEntry()?.let { newEntry -> - // WARNING Add the parent previously deleted - newEntry.parent = mEntry?.parent - // Build info - newEntry.lastAccessTime = DateInstant() - newEntry.lastModificationTime = DateInstant() + // WARNING Add the parent previously deleted + newEntry.parent = mEntry?.parent + // Build info + newEntry.lastAccessTime = DateInstant() + newEntry.lastModificationTime = DateInstant() - mDatabase?.let { database -> - entryEditContentsFragment?.populateEntryWithViews(database, newEntry) - } - - // Delete temp attachment if not used - mTempAttachments.forEach { - mDatabase?.binaryPool?.let { binaryPool -> - if (!newEntry.getAttachments(binaryPool).contains(it)) { - mDatabase?.removeAttachmentIfNotUsed(it) - } + // Delete temp attachment if not used + mTempAttachments.forEach { + mDatabase?.binaryPool?.let { binaryPool -> + if (!newEntry.getAttachments(binaryPool).contains(it)) { + mDatabase?.removeAttachmentIfNotUsed(it) } } + } - // Open a progress dialog and save entry - if (mIsNew) { - mParent?.let { parent -> - mProgressDatabaseTaskProvider?.startDatabaseCreateEntry( - newEntry, - parent, - !mReadOnly && mAutoSaveEnable - ) - } - } else { - mEntry?.let { oldEntry -> - mProgressDatabaseTaskProvider?.startDatabaseUpdateEntry( - oldEntry, - newEntry, - !mReadOnly && mAutoSaveEnable - ) - } + // Open a progress dialog and save entry + if (mIsNew) { + mParent?.let { parent -> + mProgressDatabaseTaskProvider?.startDatabaseCreateEntry( + newEntry, + parent, + !mReadOnly && mAutoSaveEnable + ) + } + } else { + mEntry?.let { oldEntry -> + mProgressDatabaseTaskProvider?.startDatabaseUpdateEntry( + oldEntry, + newEntry, + !mReadOnly && mAutoSaveEnable + ) } } } @@ -559,8 +543,9 @@ class EntryEditActivity : LockingActivity(), ) if (!generatePasswordEducationPerformed) { val addNewFieldView: View? = entryEditAddToolBar?.findViewById(R.id.menu_add_field) - val addNewFieldEducationPerformed = mNewEntry != null - && mNewEntry!!.allowCustomFields() && addNewFieldView != null + val addNewFieldEducationPerformed = // TODO mNewEntry != null + // && mNewEntry!!.allowCustomFields() + addNewFieldView != null && addNewFieldView.visibility == View.VISIBLE && entryEditActivityEducation.checkAndPerformedEntryNewFieldEducation( addNewFieldView, @@ -629,7 +614,7 @@ class EntryEditActivity : LockingActivity(), override fun iconPicked(bundle: Bundle) { IconPickerDialogFragment.getIconStandardFromBundle(bundle)?.let { icon -> - temporarilySaveAndShowSelectedIcon(icon) + entryEditContentsFragment?.icon = icon } } @@ -667,12 +652,6 @@ class EntryEditActivity : LockingActivity(), } override fun onSaveInstanceState(outState: Bundle) { - mNewEntry?.let { newEntry -> - mDatabase?.let { database -> - entryEditContentsFragment?.populateEntryWithViews(database, newEntry) - } - outState.putParcelable(KEY_NEW_ENTRY, newEntry) - } outState.putParcelableArrayList(TEMP_ATTACHMENTS, mTempAttachments) @@ -705,10 +684,10 @@ class EntryEditActivity : LockingActivity(), override fun finish() { // Assign entry callback as a result in all case try { - mNewEntry?.let { + mEntry?.let { entry -> val bundle = Bundle() val intentEntry = Intent() - bundle.putParcelable(ADD_OR_UPDATE_ENTRY_KEY, mNewEntry) + bundle.putParcelable(ADD_OR_UPDATE_ENTRY_KEY, entry) intentEntry.putExtras(bundle) if (mIsNew) { setResult(ADD_ENTRY_RESULT_CODE, intentEntry) @@ -732,7 +711,6 @@ class EntryEditActivity : LockingActivity(), const val KEY_PARENT = "parent" // SaveInstanceState - const val KEY_NEW_ENTRY = "new_entry" const val TEMP_ATTACHMENTS = "TEMP_ATTACHMENTS" // Keys for callback diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditContentsFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditContentsFragment.kt index 9c7b2bb27..1be6cf308 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditContentsFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditContentsFragment.kt @@ -43,9 +43,8 @@ import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.DateInstant import com.kunzisoft.keepass.database.element.Entry import com.kunzisoft.keepass.database.element.icon.IconImage -import com.kunzisoft.keepass.icons.IconDrawableFactory +import com.kunzisoft.keepass.database.element.icon.IconImageStandard import com.kunzisoft.keepass.icons.assignDatabaseIcon -import com.kunzisoft.keepass.icons.assignDefaultDatabaseIcon import com.kunzisoft.keepass.model.EntryAttachmentState import com.kunzisoft.keepass.model.Field import com.kunzisoft.keepass.model.StreamDirection @@ -86,6 +85,7 @@ class EntryEditContentsFragment: StylishFragment() { var setOnEditCustomField: ((Field) -> Unit)? = null var setOnRemoveAttachment: ((Attachment) -> Unit)? = null + // Elements to modify the current entry private var mDatabase: Database? = null private var mEntry: Entry? = null private var mIsNewEntry = true @@ -148,6 +148,11 @@ class EntryEditContentsFragment: StylishFragment() { iconColor = taIconColor?.getColor(0, Color.WHITE) ?: Color.WHITE taIconColor?.recycle() + // Retrieve the new entry after an orientation change + if (savedInstanceState?.containsKey(KEY_TEMP_ENTRY) == true) { + mEntry = savedInstanceState.getParcelable(KEY_TEMP_ENTRY) + } + mDatabase?.let { database -> mEntry?.let { entry -> populateViewsWithEntry(database, entry, mIsNewEntry) @@ -157,8 +162,20 @@ class EntryEditContentsFragment: StylishFragment() { return rootView } - fun setEntry(database: Database, entry: Entry, isNewEntry: Boolean) { + fun setDatabase(database: Database) { mDatabase = database + } + + fun getEntry(): Entry? { + mDatabase?.let { database -> + mEntry?.let { entry -> + populateEntryWithViews(database, entry) + } + } + return mEntry + } + + fun setEntry(entry: Entry, isNewEntry: Boolean) { mEntry = entry mIsNewEntry = isNewEntry } @@ -168,7 +185,7 @@ class EntryEditContentsFragment: StylishFragment() { database.stopManageEntry(entry) // Set info in view - setIcon(database.drawFactory, entry.icon) + icon = entry.icon title = entry.title username = if (isNewEntry && entry.username.isEmpty()) database.defaultUsername @@ -191,7 +208,7 @@ class EntryEditContentsFragment: StylishFragment() { } } - fun populateEntryWithViews(database: Database, newEntry: Entry) { + private fun populateEntryWithViews(database: Database, newEntry: Entry) { database.startManageEntry(newEntry) @@ -236,13 +253,16 @@ class EntryEditContentsFragment: StylishFragment() { entryTitleView.applyFontVisibility() } - fun setDefaultIcon(iconFactory: IconDrawableFactory) { - entryIconView.assignDefaultDatabaseIcon(iconFactory, iconColor) - } - - fun setIcon(iconFactory: IconDrawableFactory, icon: IconImage) { - entryIconView.assignDatabaseIcon(iconFactory, icon, iconColor) - } + var icon: IconImage + get() { + return mEntry?.icon ?: IconImageStandard() + } + set(value) { + mEntry?.icon = value + mDatabase?.drawFactory?.let { drawFactory -> + entryIconView.assignDatabaseIcon(drawFactory, value, iconColor) + } + } var username: String get() { @@ -492,14 +512,19 @@ class EntryEditContentsFragment: StylishFragment() { }, 250) } - /** - * Validate or not the entry form - * - * @return ErrorValidation An error with a message or a validation without message - */ - fun isValid(): Boolean { - // TODO - return true + override fun onSaveInstanceState(outState: Bundle) { + mEntry?.let { entry -> + mDatabase?.let { database -> + populateEntryWithViews(database, entry) + } + outState.putParcelable(KEY_TEMP_ENTRY, entry) + } + + super.onSaveInstanceState(outState) + } + + companion object { + const val KEY_TEMP_ENTRY = "KEY_TEMP_ENTRY" } } \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt index 898ebce51..417a93f9b 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Database.kt @@ -834,6 +834,13 @@ class Database { } } + /** + * @return true if database allows custom field + */ + fun allowEntryCustomFields(): Boolean { + return mDatabaseKDBX != null + } + /** * Remove oldest history for each entry if more than max items or max memory */ diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt index 3643b5fb1..a0a39a98c 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/Entry.kt @@ -290,14 +290,6 @@ class Entry : Node, EntryVersionedInterface { val customFields: HashMap get() = entryKDBX?.customFields ?: HashMap() - /** - * To redefine if version of entry allow custom field, - * @return true if entry allows custom field - */ - fun allowCustomFields(): Boolean { - return entryKDBX?.allowCustomFields() ?: false - } - fun removeAllFields() { entryKDBX?.removeAllFields() } diff --git a/app/src/main/java/com/kunzisoft/keepass/database/element/entry/EntryKDBX.kt b/app/src/main/java/com/kunzisoft/keepass/database/element/entry/EntryKDBX.kt index 4fba1f477..4220e5bfb 100644 --- a/app/src/main/java/com/kunzisoft/keepass/database/element/entry/EntryKDBX.kt +++ b/app/src/main/java/com/kunzisoft/keepass/database/element/entry/EntryKDBX.kt @@ -38,7 +38,6 @@ import com.kunzisoft.keepass.utils.ParcelableUtil import com.kunzisoft.keepass.utils.UnsignedLong import java.util.* import kotlin.collections.ArrayList -import kotlin.collections.HashSet import kotlin.collections.LinkedHashMap class EntryKDBX : EntryVersioned, NodeKDBXInterface { @@ -272,10 +271,6 @@ class EntryKDBX : EntryVersioned, NodeKDBXInte return field } - fun allowCustomFields(): Boolean { - return true - } - fun removeAllFields() { fields.clear() }