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 d293edb5a..dd7cc9b7a 100644
--- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt
+++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt
@@ -41,10 +41,7 @@ import com.kunzisoft.keepass.activities.dialogs.*
import com.kunzisoft.keepass.activities.dialogs.FileTooBigDialogFragment.Companion.MAX_WARNING_BINARY_FILE
import com.kunzisoft.keepass.activities.helpers.SelectFileHelper
import com.kunzisoft.keepass.activities.lock.LockingActivity
-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.Group
+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
@@ -76,7 +73,8 @@ class EntryEditActivity : LockingActivity(),
SetOTPDialogFragment.CreateOtpListener,
DatePickerDialog.OnDateSetListener,
TimePickerDialog.OnTimeSetListener,
- FileTooBigDialogFragment.ActionChooseListener {
+ FileTooBigDialogFragment.ActionChooseListener,
+ ReplaceFileDialogFragment.ActionChooseListener {
private var mDatabase: Database? = null
@@ -437,9 +435,22 @@ class EntryEditActivity : LockingActivity(),
}
}
+ override fun onValidateReplaceFile(attachmentToUploadUri: Uri?, entryAttachment: EntryAttachment?) {
+ if (attachmentToUploadUri != null && entryAttachment != null) {
+ mAttachmentFileBinderManager?.startUploadAttachment(attachmentToUploadUri, entryAttachment)
+ }
+ }
+
private fun buildNewAttachment(attachmentToUploadUri: Uri, fileName: String) {
mDatabase?.buildNewAttachment(applicationContext.filesDir, fileName)?.let { entryAttachment ->
- mAttachmentFileBinderManager?.startUploadAttachment(attachmentToUploadUri, entryAttachment)
+ // Ask to replace the current attachment
+ if ((mDatabase?.allowMultipleAttachments != true && entryEditContentsView?.containsAttachment() == true) ||
+ entryEditContentsView?.containsAttachment(EntryAttachmentState(entryAttachment, StreamDirection.UPLOAD)) == true) {
+ ReplaceFileDialogFragment.build(attachmentToUploadUri, entryAttachment)
+ .show(supportFragmentManager, "replacementFileFragment")
+ } else {
+ mAttachmentFileBinderManager?.startUploadAttachment(attachmentToUploadUri, entryAttachment)
+ }
}
}
diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ReplaceAttachmentDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ReplaceAttachmentDialogFragment.kt
new file mode 100644
index 000000000..06d039a04
--- /dev/null
+++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/ReplaceAttachmentDialogFragment.kt
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2019 Jeremy Jamet / Kunzisoft.
+ *
+ * This file is part of KeePassDX.
+ *
+ * KeePassDX is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * KeePassDX is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with KeePassDX. If not, see .
+ *
+ */
+package com.kunzisoft.keepass.activities.dialogs
+
+import android.app.Dialog
+import android.content.Context
+import android.net.Uri
+import android.os.Bundle
+import android.text.SpannableStringBuilder
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.DialogFragment
+import com.kunzisoft.keepass.R
+import com.kunzisoft.keepass.database.element.EntryAttachment
+
+/**
+ * Custom Dialog to confirm big file to upload
+ */
+class ReplaceFileDialogFragment : DialogFragment() {
+
+ private var mActionChooseListener: ActionChooseListener? = null
+
+ override fun onAttach(context: Context) {
+ super.onAttach(context)
+ // Verify that the host activity implements the callback interface
+ try {
+ mActionChooseListener = context as ActionChooseListener
+ } catch (e: ClassCastException) {
+ throw ClassCastException(context.toString()
+ + " must implement " + ActionChooseListener::class.java.name)
+ }
+ }
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ activity?.let { activity ->
+ // Use the Builder class for convenient dialog construction
+ val builder = AlertDialog.Builder(activity)
+ builder.setMessage(SpannableStringBuilder().apply {
+ append(getString(R.string.warning_replace_file))
+ append("\n\n")
+ append(getString(R.string.warning_sure_add_file))
+ })
+ builder.setPositiveButton(android.R.string.yes) { _, _ ->
+ mActionChooseListener?.onValidateReplaceFile(
+ arguments?.getParcelable(KEY_FILE_URI),
+ arguments?.getParcelable(KEY_ENTRY_ATTACHMENT))
+ }
+ builder.setNegativeButton(android.R.string.no) { _, _ ->
+ dismiss()
+ }
+ // Create the AlertDialog object and return it
+ return builder.create()
+ }
+ return super.onCreateDialog(savedInstanceState)
+ }
+
+ interface ActionChooseListener {
+ fun onValidateReplaceFile(attachmentToUploadUri: Uri?, entryAttachment: EntryAttachment?)
+ }
+
+ companion object {
+ private const val KEY_FILE_URI = "KEY_FILE_URI"
+ private const val KEY_ENTRY_ATTACHMENT = "KEY_ENTRY_ATTACHMENT"
+
+ fun build(attachmentToUploadUri: Uri,
+ entryAttachment: EntryAttachment): ReplaceFileDialogFragment {
+ val fragment = ReplaceFileDialogFragment()
+ fragment.arguments = Bundle().apply {
+ putParcelable(KEY_FILE_URI, attachmentToUploadUri)
+ putParcelable(KEY_ENTRY_ATTACHMENT, entryAttachment)
+ }
+ return fragment
+ }
+ }
+}
diff --git a/app/src/main/java/com/kunzisoft/keepass/adapters/AnimatedItemsAdapter.kt b/app/src/main/java/com/kunzisoft/keepass/adapters/AnimatedItemsAdapter.kt
index a4deb31eb..d1fa9edc8 100644
--- a/app/src/main/java/com/kunzisoft/keepass/adapters/AnimatedItemsAdapter.kt
+++ b/app/src/main/java/com/kunzisoft/keepass/adapters/AnimatedItemsAdapter.kt
@@ -32,6 +32,14 @@ abstract class AnimatedItemsAdapter- (val contex
onListSizeChangedListener?.invoke(previousSize, itemsList.size)
}
+ open fun isEmpty(): Boolean {
+ return itemsList.isEmpty()
+ }
+
+ open fun contains(item: Item): Boolean {
+ return itemsList.contains(item)
+ }
+
open fun putItem(item: Item) {
val previousSize = itemsList.size
if (itemsList.contains(item)) {
diff --git a/app/src/main/java/com/kunzisoft/keepass/view/EntryEditContentsView.kt b/app/src/main/java/com/kunzisoft/keepass/view/EntryEditContentsView.kt
index ef585d882..1827e14af 100644
--- a/app/src/main/java/com/kunzisoft/keepass/view/EntryEditContentsView.kt
+++ b/app/src/main/java/com/kunzisoft/keepass/view/EntryEditContentsView.kt
@@ -294,6 +294,14 @@ class EntryEditContentsView @JvmOverloads constructor(context: Context,
}
}
+ fun containsAttachment(): Boolean {
+ return !attachmentsAdapter.isEmpty()
+ }
+
+ fun containsAttachment(attachment: EntryAttachmentState): Boolean {
+ return attachmentsAdapter.contains(attachment)
+ }
+
fun putAttachment(attachment: EntryAttachmentState) {
attachmentsContainerView.visibility = View.VISIBLE
attachmentsAdapter.putItem(attachment)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 02be54d4a..61a30a133 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -258,6 +258,7 @@
Continue without encryption key?
Permanently delete selected nodes?
A KeePass database is supposed to contain only small utility files (such as PGP key files).\n\nYour database may get very large and reduce performance with this upload.
+ Uploading this file will replace the existing one.
Add the file anyway?
Version %1$s
Build %1$s