Move temp entry in fragment

This commit is contained in:
J-Jamet
2020-09-15 16:50:04 +02:00
parent d157fea9be
commit 07af9f36b2
6 changed files with 131 additions and 134 deletions

View File

@@ -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

View File

@@ -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<NodeId<UUID>>(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<NodeId<*>>(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<Node> = 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

View File

@@ -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"
}
}

View File

@@ -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
*/

View File

@@ -290,14 +290,6 @@ class Entry : Node, EntryVersionedInterface<Group> {
val customFields: HashMap<String, ProtectedString>
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()
}

View File

@@ -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<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInterface {
@@ -272,10 +271,6 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
return field
}
fun allowCustomFields(): Boolean {
return true
}
fun removeAllFields() {
fields.clear()
}