mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Refactor fragment edit entry, using EntryInfo
This commit is contained in:
@@ -311,7 +311,9 @@ class EntryActivity : LockingActivity() {
|
|||||||
// Assign custom fields
|
// Assign custom fields
|
||||||
if (mDatabase?.allowEntryCustomFields() == true) {
|
if (mDatabase?.allowEntryCustomFields() == true) {
|
||||||
entryContentsView?.clearExtraFields()
|
entryContentsView?.clearExtraFields()
|
||||||
for ((label, value) in entry.customFields) {
|
entry.getExtraFields().forEach { field ->
|
||||||
|
val label = field.name
|
||||||
|
val value = field.protectedValue
|
||||||
val allowCopyProtectedField = !value.isProtected || allowCopyPasswordAndProtectedFields
|
val allowCopyProtectedField = !value.isProtected || allowCopyPasswordAndProtectedFields
|
||||||
if (allowCopyProtectedField) {
|
if (allowCopyProtectedField) {
|
||||||
entryContentsView?.addExtraField(label, value, allowCopyProtectedField) {
|
entryContentsView?.addExtraField(label, value, allowCopyProtectedField) {
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ class EntryEditActivity : LockingActivity(),
|
|||||||
// Likely the app has been killed exit the activity
|
// Likely the app has been killed exit the activity
|
||||||
mDatabase = Database.getInstance()
|
mDatabase = Database.getInstance()
|
||||||
|
|
||||||
var tempEntry: Entry? = null
|
var tempEntryInfo: EntryInfo? = null
|
||||||
|
|
||||||
// Entry is retrieve, it's an entry to update
|
// Entry is retrieve, it's an entry to update
|
||||||
intent.getParcelableExtra<NodeId<UUID>>(KEY_ENTRY)?.let {
|
intent.getParcelableExtra<NodeId<UUID>>(KEY_ENTRY)?.let {
|
||||||
@@ -149,14 +149,7 @@ class EntryEditActivity : LockingActivity(),
|
|||||||
entry.parent = mParent
|
entry.parent = mParent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tempEntryInfo = mEntry?.getEntryInfo(mDatabase, true)
|
||||||
mEntry?.let { entry ->
|
|
||||||
// Create a copy to modify
|
|
||||||
tempEntry = Entry(entry).also { newEntry ->
|
|
||||||
// WARNING Remove the parent to keep memory with parcelable
|
|
||||||
newEntry.removeParent()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parent is retrieve, it's a new entry to create
|
// Parent is retrieve, it's a new entry to create
|
||||||
@@ -165,12 +158,15 @@ class EntryEditActivity : LockingActivity(),
|
|||||||
mParent = mDatabase?.getGroupById(it)
|
mParent = mDatabase?.getGroupById(it)
|
||||||
// Add the default icon from parent if not a folder
|
// Add the default icon from parent if not a folder
|
||||||
val parentIcon = mParent?.icon
|
val parentIcon = mParent?.icon
|
||||||
|
tempEntryInfo = mDatabase?.createEntry()?.getEntryInfo(mDatabase, true)
|
||||||
|
// Set default icon
|
||||||
if (parentIcon != null
|
if (parentIcon != null
|
||||||
&& parentIcon.iconId != IconImage.UNKNOWN_ID
|
&& parentIcon.iconId != IconImage.UNKNOWN_ID
|
||||||
&& parentIcon.iconId != IconImageStandard.FOLDER) {
|
&& parentIcon.iconId != IconImageStandard.FOLDER) {
|
||||||
tempEntry?.icon = parentIcon
|
tempEntryInfo?.icon = parentIcon
|
||||||
}
|
}
|
||||||
tempEntry = mDatabase?.createEntry()
|
// Set default username
|
||||||
|
tempEntryInfo?.username = mDatabase?.defaultUsername ?: ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build fragment to manage entry modification
|
// Build fragment to manage entry modification
|
||||||
@@ -181,16 +177,14 @@ class EntryEditActivity : LockingActivity(),
|
|||||||
supportFragmentManager.beginTransaction()
|
supportFragmentManager.beginTransaction()
|
||||||
.replace(R.id.entry_edit_contents, entryEditFragment!!, ENTRY_EDIT_FRAGMENT_TAG)
|
.replace(R.id.entry_edit_contents, entryEditFragment!!, ENTRY_EDIT_FRAGMENT_TAG)
|
||||||
.commit()
|
.commit()
|
||||||
mDatabase?.let { database ->
|
entryEditFragment?.drawFactory = mDatabase?.drawFactory
|
||||||
entryEditFragment?.setDatabase(database)
|
tempEntryInfo?.let {
|
||||||
}
|
entryEditFragment?.setEntryInfo(it)
|
||||||
tempEntry?.let {
|
|
||||||
entryEditFragment?.setEntry(it, mIsNew)
|
|
||||||
}
|
}
|
||||||
entryEditFragment?.apply {
|
entryEditFragment?.apply {
|
||||||
applyFontVisibilityToFields(PreferencesUtil.fieldFontIsInVisibility(this@EntryEditActivity))
|
applyFontVisibilityToFields(PreferencesUtil.fieldFontIsInVisibility(this@EntryEditActivity))
|
||||||
setOnDateClickListener = View.OnClickListener {
|
setOnDateClickListener = View.OnClickListener {
|
||||||
expiresDate.date.let { expiresDate ->
|
expiryTime.date.let { expiresDate ->
|
||||||
val dateTime = DateTime(expiresDate)
|
val dateTime = DateTime(expiresDate)
|
||||||
val defaultYear = dateTime.year
|
val defaultYear = dateTime.year
|
||||||
val defaultMonth = dateTime.monthOfYear-1
|
val defaultMonth = dateTime.monthOfYear-1
|
||||||
@@ -208,6 +202,7 @@ class EntryEditActivity : LockingActivity(),
|
|||||||
}
|
}
|
||||||
setOnRemoveAttachment = { attachment ->
|
setOnRemoveAttachment = { attachment ->
|
||||||
mAttachmentFileBinderManager?.removeBinaryAttachment(attachment)
|
mAttachmentFileBinderManager?.removeBinaryAttachment(attachment)
|
||||||
|
removeAttachment(EntryAttachmentState(attachment, StreamDirection.DOWNLOAD))
|
||||||
}
|
}
|
||||||
setOnEditCustomField = { field ->
|
setOnEditCustomField = { field ->
|
||||||
editCustomField(field)
|
editCustomField(field)
|
||||||
@@ -475,39 +470,47 @@ class EntryEditActivity : LockingActivity(),
|
|||||||
*/
|
*/
|
||||||
private fun saveEntry() {
|
private fun saveEntry() {
|
||||||
// Get the temp entry
|
// Get the temp entry
|
||||||
entryEditFragment?.getEntry()?.let { newEntry ->
|
entryEditFragment?.getEntryInfo()?.let { newEntryInfo ->
|
||||||
|
|
||||||
// WARNING Add the parent previously deleted
|
if (mIsNew) {
|
||||||
newEntry.parent = mEntry?.parent
|
// Create new one
|
||||||
// Build info
|
mDatabase?.createEntry()
|
||||||
newEntry.lastAccessTime = DateInstant()
|
} else {
|
||||||
newEntry.lastModificationTime = DateInstant()
|
// Create a clone
|
||||||
|
Entry(mEntry!!)
|
||||||
|
}?.let { newEntry ->
|
||||||
|
|
||||||
// Delete temp attachment if not used
|
newEntry.setEntryInfo(mDatabase, newEntryInfo)
|
||||||
mTempAttachments.forEach {
|
// Build info
|
||||||
mDatabase?.binaryPool?.let { binaryPool ->
|
newEntry.lastAccessTime = DateInstant()
|
||||||
if (!newEntry.getAttachments(binaryPool).contains(it)) {
|
newEntry.lastModificationTime = DateInstant()
|
||||||
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
|
// Open a progress dialog and save entry
|
||||||
if (mIsNew) {
|
if (mIsNew) {
|
||||||
mParent?.let { parent ->
|
mParent?.let { parent ->
|
||||||
mProgressDatabaseTaskProvider?.startDatabaseCreateEntry(
|
mProgressDatabaseTaskProvider?.startDatabaseCreateEntry(
|
||||||
newEntry,
|
newEntry,
|
||||||
parent,
|
parent,
|
||||||
!mReadOnly && mAutoSaveEnable
|
!mReadOnly && mAutoSaveEnable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mEntry?.let { oldEntry ->
|
mEntry?.let { oldEntry ->
|
||||||
mProgressDatabaseTaskProvider?.startDatabaseUpdateEntry(
|
mProgressDatabaseTaskProvider?.startDatabaseUpdateEntry(
|
||||||
oldEntry,
|
oldEntry,
|
||||||
newEntry,
|
newEntry,
|
||||||
!mReadOnly && mAutoSaveEnable
|
!mReadOnly && mAutoSaveEnable
|
||||||
)
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -603,7 +606,7 @@ class EntryEditActivity : LockingActivity(),
|
|||||||
// Update the otp field with otpauth:// url
|
// Update the otp field with otpauth:// url
|
||||||
val otpField = OtpEntryFields.buildOtpField(otpElement,
|
val otpField = OtpEntryFields.buildOtpField(otpElement,
|
||||||
mEntry?.title, mEntry?.username)
|
mEntry?.title, mEntry?.username)
|
||||||
mEntry?.putExtraField(otpField.name, otpField.protectedValue)
|
mEntry?.putExtraField(Field(otpField.name, otpField.protectedValue))
|
||||||
entryEditFragment?.apply {
|
entryEditFragment?.apply {
|
||||||
putExtraField(otpField)
|
putExtraField(otpField)
|
||||||
getExtraFieldViewPosition(otpField) { position ->
|
getExtraFieldViewPosition(otpField) { position ->
|
||||||
@@ -622,9 +625,9 @@ class EntryEditActivity : LockingActivity(),
|
|||||||
// To fix android 4.4 issue
|
// To fix android 4.4 issue
|
||||||
// https://stackoverflow.com/questions/12436073/datepicker-ondatechangedlistener-called-twice
|
// https://stackoverflow.com/questions/12436073/datepicker-ondatechangedlistener-called-twice
|
||||||
if (datePicker?.isShown == true) {
|
if (datePicker?.isShown == true) {
|
||||||
entryEditFragment?.expiresDate?.date?.let { expiresDate ->
|
entryEditFragment?.expiryTime?.date?.let { expiresDate ->
|
||||||
// Save the date
|
// Save the date
|
||||||
entryEditFragment?.expiresDate =
|
entryEditFragment?.expiryTime =
|
||||||
DateInstant(DateTime(expiresDate)
|
DateInstant(DateTime(expiresDate)
|
||||||
.withYear(year)
|
.withYear(year)
|
||||||
.withMonthOfYear(month + 1)
|
.withMonthOfYear(month + 1)
|
||||||
@@ -641,9 +644,9 @@ class EntryEditActivity : LockingActivity(),
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onTimeSet(timePicker: TimePicker?, hours: Int, minutes: Int) {
|
override fun onTimeSet(timePicker: TimePicker?, hours: Int, minutes: Int) {
|
||||||
entryEditFragment?.expiresDate?.date?.let { expiresDate ->
|
entryEditFragment?.expiryTime?.date?.let { expiresDate ->
|
||||||
// Save the date
|
// Save the date
|
||||||
entryEditFragment?.expiresDate =
|
entryEditFragment?.expiryTime =
|
||||||
DateInstant(DateTime(expiresDate)
|
DateInstant(DateTime(expiresDate)
|
||||||
.withHourOfDay(hours)
|
.withHourOfDay(hours)
|
||||||
.withMinuteOfHour(minutes)
|
.withMinuteOfHour(minutes)
|
||||||
|
|||||||
@@ -39,13 +39,12 @@ import com.kunzisoft.keepass.R
|
|||||||
import com.kunzisoft.keepass.activities.stylish.StylishFragment
|
import com.kunzisoft.keepass.activities.stylish.StylishFragment
|
||||||
import com.kunzisoft.keepass.adapters.EntryAttachmentsItemsAdapter
|
import com.kunzisoft.keepass.adapters.EntryAttachmentsItemsAdapter
|
||||||
import com.kunzisoft.keepass.database.element.Attachment
|
import com.kunzisoft.keepass.database.element.Attachment
|
||||||
import com.kunzisoft.keepass.database.element.Database
|
|
||||||
import com.kunzisoft.keepass.database.element.DateInstant
|
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.database.element.icon.IconImage
|
||||||
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
|
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||||
import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
import com.kunzisoft.keepass.icons.assignDatabaseIcon
|
||||||
import com.kunzisoft.keepass.model.EntryAttachmentState
|
import com.kunzisoft.keepass.model.EntryAttachmentState
|
||||||
|
import com.kunzisoft.keepass.model.EntryInfo
|
||||||
import com.kunzisoft.keepass.model.Field
|
import com.kunzisoft.keepass.model.Field
|
||||||
import com.kunzisoft.keepass.model.StreamDirection
|
import com.kunzisoft.keepass.model.StreamDirection
|
||||||
import com.kunzisoft.keepass.view.applyFontVisibility
|
import com.kunzisoft.keepass.view.applyFontVisibility
|
||||||
@@ -86,9 +85,7 @@ class EntryEditFragment: StylishFragment() {
|
|||||||
var setOnRemoveAttachment: ((Attachment) -> Unit)? = null
|
var setOnRemoveAttachment: ((Attachment) -> Unit)? = null
|
||||||
|
|
||||||
// Elements to modify the current entry
|
// Elements to modify the current entry
|
||||||
private var mDatabase: Database? = null
|
private var mEntryInfo = EntryInfo()
|
||||||
private var mEntry: Entry? = null
|
|
||||||
private var mIsNewEntry = true
|
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
super.onCreateView(inflater, container, savedInstanceState)
|
super.onCreateView(inflater, container, savedInstanceState)
|
||||||
@@ -149,94 +146,58 @@ class EntryEditFragment: StylishFragment() {
|
|||||||
taIconColor?.recycle()
|
taIconColor?.recycle()
|
||||||
|
|
||||||
// Retrieve the new entry after an orientation change
|
// Retrieve the new entry after an orientation change
|
||||||
if (savedInstanceState?.containsKey(KEY_TEMP_ENTRY) == true) {
|
if (savedInstanceState?.containsKey(KEY_TEMP_ENTRY_INFO) == true) {
|
||||||
mEntry = savedInstanceState.getParcelable(KEY_TEMP_ENTRY)
|
mEntryInfo = savedInstanceState.getParcelable(KEY_TEMP_ENTRY_INFO) ?: mEntryInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
mDatabase?.let { database ->
|
populateViewsWithEntry()
|
||||||
mEntry?.let { entry ->
|
|
||||||
populateViewsWithEntry(database, entry, mIsNewEntry)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rootView
|
return rootView
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setDatabase(database: Database) {
|
fun getEntryInfo(): EntryInfo? {
|
||||||
mDatabase = database
|
populateEntryWithViews()
|
||||||
|
return mEntryInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEntry(): Entry? {
|
fun setEntryInfo(entryInfo: EntryInfo) {
|
||||||
mDatabase?.let { database ->
|
populateViewsWithEntry()
|
||||||
mEntry?.let { entry ->
|
mEntryInfo = entryInfo
|
||||||
populateEntryWithViews(database, entry)
|
}
|
||||||
|
|
||||||
|
private fun populateViewsWithEntry() {
|
||||||
|
try {
|
||||||
|
// Set info in view
|
||||||
|
icon = mEntryInfo.icon
|
||||||
|
title = mEntryInfo.title
|
||||||
|
username = mEntryInfo.username
|
||||||
|
url = mEntryInfo.url
|
||||||
|
password = mEntryInfo.password
|
||||||
|
expires = mEntryInfo.expires
|
||||||
|
expiryTime = mEntryInfo.expiryTime
|
||||||
|
notes = mEntryInfo.notes
|
||||||
|
assignExtraFields(mEntryInfo.customFields) { fields ->
|
||||||
|
setOnEditCustomField?.invoke(fields)
|
||||||
}
|
}
|
||||||
}
|
assignAttachments(mEntryInfo.attachments, StreamDirection.UPLOAD) { attachment ->
|
||||||
return mEntry
|
setOnRemoveAttachment?.invoke(attachment)
|
||||||
}
|
|
||||||
|
|
||||||
fun setEntry(entry: Entry, isNewEntry: Boolean) {
|
|
||||||
mEntry = entry
|
|
||||||
mIsNewEntry = isNewEntry
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun populateViewsWithEntry(database: Database, entry: Entry, isNewEntry: Boolean) {
|
|
||||||
// Don't start the field reference manager, we want to see the raw ref
|
|
||||||
database.stopManageEntry(entry)
|
|
||||||
|
|
||||||
// Set info in view
|
|
||||||
icon = entry.icon
|
|
||||||
title = entry.title
|
|
||||||
username = if (isNewEntry && entry.username.isEmpty())
|
|
||||||
database.defaultUsername
|
|
||||||
else
|
|
||||||
entry.username
|
|
||||||
url = entry.url
|
|
||||||
password = entry.password
|
|
||||||
expires = entry.expires
|
|
||||||
if (expires)
|
|
||||||
expiresDate = entry.expiryTime
|
|
||||||
notes = entry.notes
|
|
||||||
assignExtraFields(entry.customFields.mapTo(ArrayList()) {
|
|
||||||
Field(it.key, it.value)
|
|
||||||
}) {
|
|
||||||
setOnEditCustomField?.invoke(it)
|
|
||||||
}
|
|
||||||
assignAttachments(entry.getAttachments(database.binaryPool).toSet(), StreamDirection.UPLOAD) { attachment ->
|
|
||||||
// Remove entry by clicking trash button
|
|
||||||
entry.removeAttachment(attachment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun populateEntryWithViews(database: Database, newEntry: Entry) {
|
|
||||||
|
|
||||||
database.startManageEntry(newEntry)
|
|
||||||
|
|
||||||
newEntry.apply {
|
|
||||||
// Build info from view
|
|
||||||
this@EntryEditFragment.let { entryView ->
|
|
||||||
removeAllFields()
|
|
||||||
title = entryView.title
|
|
||||||
username = entryView.username
|
|
||||||
url = entryView.url
|
|
||||||
password = entryView.password
|
|
||||||
expires = entryView.expires
|
|
||||||
if (entryView.expires) {
|
|
||||||
expiryTime = entryView.expiresDate
|
|
||||||
}
|
|
||||||
notes = entryView.notes
|
|
||||||
entryView.getExtraFields().forEach { customField ->
|
|
||||||
putExtraField(customField.name, customField.protectedValue)
|
|
||||||
}
|
|
||||||
database.binaryPool.let { binaryPool ->
|
|
||||||
entryView.getAttachments().forEach {
|
|
||||||
putAttachment(it, binaryPool)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
} catch (e: Exception) {}
|
||||||
|
}
|
||||||
|
|
||||||
database.stopManageEntry(newEntry)
|
private fun populateEntryWithViews() {
|
||||||
|
try {
|
||||||
|
// Icon already populate
|
||||||
|
mEntryInfo.title = title
|
||||||
|
mEntryInfo.username = username
|
||||||
|
mEntryInfo.url = url
|
||||||
|
mEntryInfo.password = password
|
||||||
|
mEntryInfo.expires = expires
|
||||||
|
mEntryInfo.expiryTime = expiryTime
|
||||||
|
mEntryInfo.notes = notes
|
||||||
|
mEntryInfo.customFields = getExtraFields()
|
||||||
|
mEntryInfo.attachments = getAttachments()
|
||||||
|
} catch (e: Exception) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyFontVisibilityToFields(fontInVisibility: Boolean) {
|
fun applyFontVisibilityToFields(fontInVisibility: Boolean) {
|
||||||
@@ -253,13 +214,15 @@ class EntryEditFragment: StylishFragment() {
|
|||||||
entryTitleView.applyFontVisibility()
|
entryTitleView.applyFontVisibility()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var drawFactory: IconDrawableFactory? = null
|
||||||
|
|
||||||
var icon: IconImage
|
var icon: IconImage
|
||||||
get() {
|
get() {
|
||||||
return mEntry?.icon ?: IconImageStandard()
|
return mEntryInfo.icon
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
mEntry?.icon = value
|
mEntryInfo.icon = value
|
||||||
mDatabase?.drawFactory?.let { drawFactory ->
|
drawFactory?.let { drawFactory ->
|
||||||
entryIconView.assignDatabaseIcon(drawFactory, value, iconColor)
|
entryIconView.assignDatabaseIcon(drawFactory, value, iconColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,7 +279,7 @@ class EntryEditFragment: StylishFragment() {
|
|||||||
assignExpiresDateText()
|
assignExpiresDateText()
|
||||||
}
|
}
|
||||||
|
|
||||||
var expiresDate: DateInstant
|
var expiryTime: DateInstant
|
||||||
get() {
|
get() {
|
||||||
return expiresInstant
|
return expiresInstant
|
||||||
}
|
}
|
||||||
@@ -471,7 +434,7 @@ class EntryEditFragment: StylishFragment() {
|
|||||||
return attachmentsAdapter.itemsList.map { it.attachment }
|
return attachmentsAdapter.itemsList.map { it.attachment }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun assignAttachments(attachments: Set<Attachment>,
|
fun assignAttachments(attachments: List<Attachment>,
|
||||||
streamDirection: StreamDirection,
|
streamDirection: StreamDirection,
|
||||||
onDeleteItem: (attachment: Attachment)->Unit) {
|
onDeleteItem: (attachment: Attachment)->Unit) {
|
||||||
attachmentsContainerView.visibility = if (attachments.isEmpty()) View.GONE else View.VISIBLE
|
attachmentsContainerView.visibility = if (attachments.isEmpty()) View.GONE else View.VISIBLE
|
||||||
@@ -513,18 +476,14 @@ class EntryEditFragment: StylishFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onSaveInstanceState(outState: Bundle) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
mEntry?.let { entry ->
|
populateEntryWithViews()
|
||||||
mDatabase?.let { database ->
|
outState.putParcelable(KEY_TEMP_ENTRY_INFO, mEntryInfo)
|
||||||
populateEntryWithViews(database, entry)
|
|
||||||
}
|
|
||||||
outState.putParcelable(KEY_TEMP_ENTRY, entry)
|
|
||||||
}
|
|
||||||
|
|
||||||
super.onSaveInstanceState(outState)
|
super.onSaveInstanceState(outState)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val KEY_TEMP_ENTRY = "KEY_TEMP_ENTRY"
|
const val KEY_TEMP_ENTRY_INFO = "KEY_TEMP_ENTRY_INFO"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,6 @@ import com.kunzisoft.keepass.database.element.node.Node
|
|||||||
import com.kunzisoft.keepass.database.element.node.NodeId
|
import com.kunzisoft.keepass.database.element.node.NodeId
|
||||||
import com.kunzisoft.keepass.database.element.node.NodeIdUUID
|
import com.kunzisoft.keepass.database.element.node.NodeIdUUID
|
||||||
import com.kunzisoft.keepass.database.element.node.Type
|
import com.kunzisoft.keepass.database.element.node.Type
|
||||||
import com.kunzisoft.keepass.database.element.security.ProtectedString
|
|
||||||
import com.kunzisoft.keepass.model.EntryInfo
|
import com.kunzisoft.keepass.model.EntryInfo
|
||||||
import com.kunzisoft.keepass.model.Field
|
import com.kunzisoft.keepass.model.Field
|
||||||
import com.kunzisoft.keepass.otp.OtpElement
|
import com.kunzisoft.keepass.otp.OtpElement
|
||||||
@@ -284,29 +283,43 @@ class Entry : Node, EntryVersionedInterface<Group> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve custom fields to show, key is the label, value is the value of field (protected or not)
|
* Retrieve extra fields to show, key is the label, value is the value of field (protected or not)
|
||||||
* @return Map of label/value
|
* @return Map of label/value
|
||||||
*/
|
*/
|
||||||
val customFields: HashMap<String, ProtectedString>
|
fun getExtraFields(): List<Field> {
|
||||||
get() = entryKDBX?.customFields ?: HashMap()
|
val extraFields = ArrayList<Field>()
|
||||||
|
entryKDBX?.let {
|
||||||
fun removeAllFields() {
|
for (field in it.customFields) {
|
||||||
entryKDBX?.removeAllFields()
|
extraFields.add(Field(field.key, field.value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return extraFields
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update or add an extra field to the list (standard or custom)
|
* Update or add an extra field to the list (standard or custom)
|
||||||
* @param label Label of field, must be unique
|
|
||||||
* @param value Value of field
|
|
||||||
*/
|
*/
|
||||||
fun putExtraField(label: String, value: ProtectedString) {
|
fun putExtraField(field: Field) {
|
||||||
entryKDBX?.putExtraField(label, value)
|
entryKDBX?.putExtraField(field.name, field.protectedValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addExtraFields(fields: List<Field>) {
|
||||||
|
fields.forEach {
|
||||||
|
putExtraField(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeAllFields() {
|
||||||
|
entryKDBX?.removeAllFields()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOtpElement(): OtpElement? {
|
fun getOtpElement(): OtpElement? {
|
||||||
return OtpEntryFields.parseFields { key ->
|
entryKDBX?.let {
|
||||||
customFields[key]?.toString()
|
return OtpEntryFields.parseFields { key ->
|
||||||
|
it.customFields[key]?.toString()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun startToManageFieldReferences(database: DatabaseKDBX) {
|
fun startToManageFieldReferences(database: DatabaseKDBX) {
|
||||||
@@ -333,16 +346,27 @@ class Entry : Node, EntryVersionedInterface<Group> {
|
|||||||
|| entryKDBX?.containsAttachment() == true
|
|| entryKDBX?.containsAttachment() == true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putAttachment(attachment: Attachment, binaryPool: BinaryPool) {
|
private fun addAttachments(binaryPool: BinaryPool, attachments: List<Attachment>) {
|
||||||
entryKDB?.putAttachment(attachment)
|
attachments.forEach {
|
||||||
entryKDBX?.putAttachment(attachment, binaryPool)
|
putAttachment(it, binaryPool)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeAttachment(attachment: Attachment) {
|
private fun removeAttachment(attachment: Attachment) {
|
||||||
entryKDB?.removeAttachment(attachment)
|
entryKDB?.removeAttachment(attachment)
|
||||||
entryKDBX?.removeAttachment(attachment)
|
entryKDBX?.removeAttachment(attachment)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun removeAllAttachments() {
|
||||||
|
entryKDB?.removeAttachment()
|
||||||
|
entryKDBX?.removeAttachments()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun putAttachment(attachment: Attachment, binaryPool: BinaryPool) {
|
||||||
|
entryKDB?.putAttachment(attachment)
|
||||||
|
entryKDBX?.putAttachment(attachment, binaryPool)
|
||||||
|
}
|
||||||
|
|
||||||
fun getHistory(): ArrayList<Entry> {
|
fun getHistory(): ArrayList<Entry> {
|
||||||
val history = ArrayList<Entry>()
|
val history = ArrayList<Entry>()
|
||||||
val entryKDBXHistory = entryKDBX?.history ?: ArrayList()
|
val entryKDBXHistory = entryKDBX?.history ?: ArrayList()
|
||||||
@@ -396,6 +420,7 @@ class Entry : Node, EntryVersionedInterface<Group> {
|
|||||||
database?.stopManageEntry(this)
|
database?.stopManageEntry(this)
|
||||||
else
|
else
|
||||||
database?.startManageEntry(this)
|
database?.startManageEntry(this)
|
||||||
|
|
||||||
entryInfo.id = nodeId.toString()
|
entryInfo.id = nodeId.toString()
|
||||||
entryInfo.title = title
|
entryInfo.title = title
|
||||||
entryInfo.icon = icon
|
entryInfo.icon = icon
|
||||||
@@ -403,19 +428,44 @@ class Entry : Node, EntryVersionedInterface<Group> {
|
|||||||
entryInfo.password = password
|
entryInfo.password = password
|
||||||
entryInfo.url = url
|
entryInfo.url = url
|
||||||
entryInfo.notes = notes
|
entryInfo.notes = notes
|
||||||
for (entry in customFields.entries) {
|
entryInfo.customFields = getExtraFields()
|
||||||
entryInfo.customFields.add(
|
|
||||||
Field(entry.key, entry.value))
|
|
||||||
}
|
|
||||||
// Add otpElement to generate token
|
// Add otpElement to generate token
|
||||||
entryInfo.otpModel = getOtpElement()?.otpModel
|
entryInfo.otpModel = getOtpElement()?.otpModel
|
||||||
// Replace parameter fields by generated OTP fields
|
if (!raw) {
|
||||||
entryInfo.customFields = OtpEntryFields.generateAutoFields(entryInfo.customFields)
|
// Replace parameter fields by generated OTP fields
|
||||||
|
entryInfo.customFields = OtpEntryFields.generateAutoFields(entryInfo.customFields)
|
||||||
|
}
|
||||||
|
database?.binaryPool?.let { binaryPool ->
|
||||||
|
entryInfo.attachments = getAttachments(binaryPool)
|
||||||
|
}
|
||||||
|
|
||||||
if (!raw)
|
if (!raw)
|
||||||
database?.stopManageEntry(this)
|
database?.stopManageEntry(this)
|
||||||
return entryInfo
|
return entryInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setEntryInfo(database: Database?, newEntryInfo: EntryInfo) {
|
||||||
|
database?.startManageEntry(this)
|
||||||
|
|
||||||
|
removeAllFields()
|
||||||
|
removeAllAttachments()
|
||||||
|
// NodeId stay as is
|
||||||
|
title = newEntryInfo.title
|
||||||
|
icon = newEntryInfo.icon
|
||||||
|
username = newEntryInfo.username
|
||||||
|
password = newEntryInfo.password
|
||||||
|
expires = newEntryInfo.expires
|
||||||
|
expiryTime = newEntryInfo.expiryTime
|
||||||
|
url = newEntryInfo.url
|
||||||
|
notes = newEntryInfo.notes
|
||||||
|
addExtraFields(newEntryInfo.customFields)
|
||||||
|
database?.binaryPool?.let { binaryPool ->
|
||||||
|
addAttachments(binaryPool, newEntryInfo.attachments)
|
||||||
|
}
|
||||||
|
|
||||||
|
database?.stopManageEntry(this)
|
||||||
|
}
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
if (javaClass != other?.javaClass) return false
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|||||||
@@ -153,8 +153,8 @@ class EntryKDB : EntryVersioned<Int, UUID, GroupKDB, EntryKDB>, NodeKDBInterface
|
|||||||
this.binaryData = attachment.binaryAttachment
|
this.binaryData = attachment.binaryAttachment
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeAttachment(attachment: Attachment) {
|
fun removeAttachment(attachment: Attachment? = null) {
|
||||||
if (this.binaryDescription == attachment.name) {
|
if (attachment == null || this.binaryDescription == attachment.name) {
|
||||||
this.binaryDescription = ""
|
this.binaryDescription = ""
|
||||||
this.binaryData = null
|
this.binaryData = null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -309,6 +309,12 @@ class EntryKDBX : EntryVersioned<UUID, UUID, GroupKDBX, EntryKDBX>, NodeKDBXInte
|
|||||||
binaries.remove(attachment.name)
|
binaries.remove(attachment.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeAttachments() {
|
||||||
|
binaries.keys.forEach {
|
||||||
|
binaries.remove(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getAttachmentsSize(binaryPool: BinaryPool): Long {
|
private fun getAttachmentsSize(binaryPool: BinaryPool): Long {
|
||||||
var size = 0L
|
var size = 0L
|
||||||
for ((label, poolId) in binaries) {
|
for ((label, poolId) in binaries) {
|
||||||
|
|||||||
@@ -21,7 +21,10 @@ package com.kunzisoft.keepass.model
|
|||||||
|
|
||||||
import android.os.Parcel
|
import android.os.Parcel
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import com.kunzisoft.keepass.database.element.Attachment
|
||||||
|
import com.kunzisoft.keepass.database.element.DateInstant
|
||||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||||
|
import com.kunzisoft.keepass.database.element.icon.IconImageStandard
|
||||||
import com.kunzisoft.keepass.otp.OtpElement
|
import com.kunzisoft.keepass.otp.OtpElement
|
||||||
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
|
import com.kunzisoft.keepass.otp.OtpEntryFields.OTP_TOKEN_FIELD
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -30,12 +33,15 @@ class EntryInfo : Parcelable {
|
|||||||
|
|
||||||
var id: String = ""
|
var id: String = ""
|
||||||
var title: String = ""
|
var title: String = ""
|
||||||
var icon: IconImage? = null
|
var icon: IconImage = IconImageStandard()
|
||||||
var username: String = ""
|
var username: String = ""
|
||||||
var password: String = ""
|
var password: String = ""
|
||||||
|
var expires: Boolean = false
|
||||||
|
var expiryTime: DateInstant = DateInstant.NEVER_EXPIRE
|
||||||
var url: String = ""
|
var url: String = ""
|
||||||
var notes: String = ""
|
var notes: String = ""
|
||||||
var customFields: MutableList<Field> = ArrayList()
|
var customFields: List<Field> = ArrayList()
|
||||||
|
var attachments: List<Attachment> = ArrayList()
|
||||||
var otpModel: OtpModel? = null
|
var otpModel: OtpModel? = null
|
||||||
|
|
||||||
constructor()
|
constructor()
|
||||||
@@ -43,12 +49,15 @@ class EntryInfo : Parcelable {
|
|||||||
private constructor(parcel: Parcel) {
|
private constructor(parcel: Parcel) {
|
||||||
id = parcel.readString() ?: id
|
id = parcel.readString() ?: id
|
||||||
title = parcel.readString() ?: title
|
title = parcel.readString() ?: title
|
||||||
icon = parcel.readParcelable(IconImage::class.java.classLoader)
|
icon = parcel.readParcelable(IconImage::class.java.classLoader) ?: icon
|
||||||
username = parcel.readString() ?: username
|
username = parcel.readString() ?: username
|
||||||
password = parcel.readString() ?: password
|
password = parcel.readString() ?: password
|
||||||
|
expires = parcel.readInt() != 0
|
||||||
|
expiryTime = parcel.readParcelable(DateInstant::class.java.classLoader) ?: expiryTime
|
||||||
url = parcel.readString() ?: url
|
url = parcel.readString() ?: url
|
||||||
notes = parcel.readString() ?: notes
|
notes = parcel.readString() ?: notes
|
||||||
parcel.readList(customFields as List<Field>, Field::class.java.classLoader)
|
parcel.readList(customFields, Field::class.java.classLoader)
|
||||||
|
parcel.readList(attachments, Attachment::class.java.classLoader)
|
||||||
otpModel = parcel.readParcelable(OtpModel::class.java.classLoader) ?: otpModel
|
otpModel = parcel.readParcelable(OtpModel::class.java.classLoader) ?: otpModel
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,9 +71,12 @@ class EntryInfo : Parcelable {
|
|||||||
parcel.writeParcelable(icon, flags)
|
parcel.writeParcelable(icon, flags)
|
||||||
parcel.writeString(username)
|
parcel.writeString(username)
|
||||||
parcel.writeString(password)
|
parcel.writeString(password)
|
||||||
|
parcel.writeInt(if (expires) 1 else 0)
|
||||||
|
parcel.writeParcelable(expiryTime, flags)
|
||||||
parcel.writeString(url)
|
parcel.writeString(url)
|
||||||
parcel.writeString(notes)
|
parcel.writeString(notes)
|
||||||
parcel.writeArray(customFields.toTypedArray())
|
parcel.writeArray(customFields.toTypedArray())
|
||||||
|
parcel.writeArray(attachments.toTypedArray())
|
||||||
parcel.writeParcelable(otpModel, flags)
|
parcel.writeParcelable(otpModel, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ object OtpEntryFields {
|
|||||||
* Build new generated fields in a new list from [fieldsToParse] in parameter,
|
* Build new generated fields in a new list from [fieldsToParse] in parameter,
|
||||||
* Remove parameters fields use to generate auto fields
|
* Remove parameters fields use to generate auto fields
|
||||||
*/
|
*/
|
||||||
fun generateAutoFields(fieldsToParse: MutableList<Field>): MutableList<Field> {
|
fun generateAutoFields(fieldsToParse: List<Field>): MutableList<Field> {
|
||||||
val newCustomFields: MutableList<Field> = ArrayList(fieldsToParse)
|
val newCustomFields: MutableList<Field> = ArrayList(fieldsToParse)
|
||||||
// Remove parameter fields
|
// Remove parameter fields
|
||||||
val otpField = Field(OTP_FIELD)
|
val otpField = Field(OTP_FIELD)
|
||||||
|
|||||||
Reference in New Issue
Block a user