mirror of
https://github.com/Kunzisoft/KeePassDX.git
synced 2025-12-04 15:49:33 +01:00
Template and Attachment listener as view model
This commit is contained in:
@@ -107,7 +107,6 @@ class EntryEditActivity : LockingActivity(),
|
||||
// To manage attachments
|
||||
private var mExternalFileHelper: ExternalFileHelper? = null
|
||||
private var mAttachmentFileBinderManager: AttachmentFileBinderManager? = null
|
||||
private var mAllowMultipleAttachments: Boolean = false
|
||||
|
||||
// Education
|
||||
private var entryEditActivityEducation: EntryEditActivityEducation? = null
|
||||
@@ -208,7 +207,15 @@ class EntryEditActivity : LockingActivity(),
|
||||
if (entryEditFragment == null) {
|
||||
entryEditFragment = EntryEditFragment.getInstance(tempEntryInfo, mEntryTemplate)
|
||||
}
|
||||
// To show Fragment asynchronously
|
||||
lifecycleScope.launchWhenResumed {
|
||||
loadingView?.hideByFading()
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.entry_edit_content, entryEditFragment!!, ENTRY_EDIT_FRAGMENT_TAG)
|
||||
.commit()
|
||||
}
|
||||
|
||||
// View model listeners
|
||||
mEntryEditViewModel.requestIconSelection.observe(this) { iconImage ->
|
||||
IconPickerActivity.launch(this@EntryEditActivity, iconImage)
|
||||
}
|
||||
@@ -234,22 +241,33 @@ class EntryEditActivity : LockingActivity(),
|
||||
.show()
|
||||
}
|
||||
}
|
||||
entryEditFragment?.apply {
|
||||
onRemoveAttachment = { attachment ->
|
||||
mAttachmentFileBinderManager?.removeBinaryAttachment(attachment)
|
||||
removeAttachment(EntryAttachmentState(attachment, StreamDirection.DOWNLOAD))
|
||||
mEntryEditViewModel.onAttachmentAction.observe(this) { attachmentState ->
|
||||
when (attachmentState?.downloadState) {
|
||||
AttachmentState.START -> {
|
||||
// Add in temp list
|
||||
mTempAttachments.add(attachmentState)
|
||||
}
|
||||
AttachmentState.ERROR -> {
|
||||
coordinatorLayout?.let {
|
||||
Snackbar.make(it, R.string.error_file_not_create, Snackbar.LENGTH_LONG).asError().show()
|
||||
}
|
||||
}
|
||||
|
||||
// To show Fragment asynchronously
|
||||
lifecycleScope.launchWhenResumed {
|
||||
loadingView?.hideByFading()
|
||||
entryEditFragment?.let { fragment ->
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(R.id.entry_edit_content, fragment, ENTRY_EDIT_FRAGMENT_TAG)
|
||||
.commit()
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
mEntryEditViewModel.onBinaryPreviewLoaded.observe(this) {
|
||||
// Scroll to the attachment position
|
||||
when (it.entryAttachmentState.downloadState) {
|
||||
AttachmentState.START,
|
||||
AttachmentState.COMPLETE -> {
|
||||
scrollView?.smoothScrollTo(0, it.viewPosition.toInt())
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
mEntryEditViewModel.attachmentDeleted.observe(this) {
|
||||
mAttachmentFileBinderManager?.removeBinaryAttachment(it)
|
||||
}
|
||||
|
||||
// Change template dynamically
|
||||
templateSelectorSpinner = findViewById(R.id.entry_edit_template_selector)
|
||||
@@ -262,10 +280,8 @@ class EntryEditActivity : LockingActivity(),
|
||||
onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
mEntryTemplate = templates[position]
|
||||
entryEditFragment?.apply {
|
||||
mEntryEditViewModel.assignTemplate(mEntryTemplate)
|
||||
}
|
||||
}
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
} else {
|
||||
@@ -443,44 +459,11 @@ class EntryEditActivity : LockingActivity(),
|
||||
// Padding if lock button visible
|
||||
entryEditAddToolBar?.updateLockPaddingLeft()
|
||||
|
||||
mAllowMultipleAttachments = mDatabase?.allowMultipleAttachments == true
|
||||
mAttachmentFileBinderManager?.apply {
|
||||
registerProgressTask()
|
||||
onActionTaskListener = object : AttachmentFileNotificationService.ActionTaskListener {
|
||||
override fun onAttachmentAction(fileUri: Uri, entryAttachmentState: EntryAttachmentState) {
|
||||
when (entryAttachmentState.downloadState) {
|
||||
AttachmentState.START -> {
|
||||
entryEditFragment?.apply {
|
||||
putAttachment(entryAttachmentState)
|
||||
// Scroll to the attachment position
|
||||
getAttachmentViewPosition(entryAttachmentState) {
|
||||
scrollView?.smoothScrollTo(0, it.toInt())
|
||||
}
|
||||
}
|
||||
// Add in temp list
|
||||
mTempAttachments.add(entryAttachmentState)
|
||||
}
|
||||
AttachmentState.IN_PROGRESS -> {
|
||||
entryEditFragment?.putAttachment(entryAttachmentState)
|
||||
}
|
||||
AttachmentState.COMPLETE -> {
|
||||
entryEditFragment?.putAttachment(entryAttachmentState) {
|
||||
entryEditFragment?.getAttachmentViewPosition(entryAttachmentState) {
|
||||
scrollView?.smoothScrollTo(0, it.toInt())
|
||||
}
|
||||
}
|
||||
}
|
||||
AttachmentState.CANCELED -> {
|
||||
entryEditFragment?.removeAttachment(entryAttachmentState)
|
||||
}
|
||||
AttachmentState.ERROR -> {
|
||||
entryEditFragment?.removeAttachment(entryAttachmentState)
|
||||
coordinatorLayout?.let {
|
||||
Snackbar.make(it, R.string.error_file_not_create, Snackbar.LENGTH_LONG).asError().show()
|
||||
}
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
mEntryEditViewModel.onAttachmentAction(entryAttachmentState)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -542,21 +525,16 @@ class EntryEditActivity : LockingActivity(),
|
||||
|
||||
private fun startUploadAttachment(attachmentToUploadUri: Uri?, attachment: Attachment?) {
|
||||
if (attachmentToUploadUri != null && attachment != null) {
|
||||
// When only one attachment is allowed
|
||||
if (!mAllowMultipleAttachments) {
|
||||
entryEditFragment?.clearAttachments()
|
||||
}
|
||||
// Start uploading in service
|
||||
mAttachmentFileBinderManager?.startUploadAttachment(attachmentToUploadUri, attachment)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildNewAttachment(attachmentToUploadUri: Uri, fileName: String) {
|
||||
val compression = mDatabase?.compressionForNewEntry() ?: false
|
||||
mDatabase?.buildNewBinaryAttachment(compression)?.let { binaryAttachment ->
|
||||
mDatabase?.buildNewBinaryAttachment()?.let { binaryAttachment ->
|
||||
val entryAttachment = Attachment(fileName, binaryAttachment)
|
||||
// Ask to replace the current attachment
|
||||
if ((mDatabase?.allowMultipleAttachments != true && entryEditFragment?.containsAttachment() == true) ||
|
||||
if ((mDatabase?.allowMultipleAttachments == false && entryEditFragment?.containsAttachment() == true) ||
|
||||
entryEditFragment?.containsAttachment(EntryAttachmentState(entryAttachment, StreamDirection.UPLOAD)) == true) {
|
||||
ReplaceFileDialogFragment.build(attachmentToUploadUri, entryAttachment)
|
||||
.show(supportFragmentManager, "replacementFileFragment")
|
||||
|
||||
@@ -52,6 +52,7 @@ import com.kunzisoft.keepass.database.element.template.TemplateField.LABEL_URL
|
||||
import com.kunzisoft.keepass.database.element.template.TemplateField.LABEL_USERNAME
|
||||
import com.kunzisoft.keepass.education.EntryEditActivityEducation
|
||||
import com.kunzisoft.keepass.icons.IconDrawableFactory
|
||||
import com.kunzisoft.keepass.model.AttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryAttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
import com.kunzisoft.keepass.model.StreamDirection
|
||||
@@ -79,7 +80,6 @@ class EntryEditFragment: DatabaseFragment(), SetOTPDialogFragment.CreateOtpListe
|
||||
private var iconColor: Int = 0
|
||||
|
||||
var drawFactory: IconDrawableFactory? = null
|
||||
var onRemoveAttachment: ((Attachment) -> Unit)? = null
|
||||
|
||||
private val mEntryEditViewModel: EntryEditViewModel by activityViewModels()
|
||||
// Elements to modify the current entry
|
||||
@@ -229,7 +229,36 @@ class EntryEditFragment: DatabaseFragment(), SetOTPDialogFragment.CreateOtpListe
|
||||
}
|
||||
|
||||
assignAttachments(mEntryInfo.attachments, StreamDirection.UPLOAD) { attachment ->
|
||||
onRemoveAttachment?.invoke(attachment)
|
||||
removeAttachment(EntryAttachmentState(attachment, StreamDirection.DOWNLOAD))
|
||||
mEntryEditViewModel.deleteAttachment(attachment)
|
||||
}
|
||||
|
||||
mEntryEditViewModel.onAttachmentAction.observe(viewLifecycleOwner) { entryAttachmentState ->
|
||||
when (entryAttachmentState?.downloadState) {
|
||||
AttachmentState.START -> {
|
||||
putAttachment(entryAttachmentState)
|
||||
getAttachmentViewPosition(entryAttachmentState) {
|
||||
mEntryEditViewModel.binaryPreviewLoaded(entryAttachmentState, it)
|
||||
}
|
||||
}
|
||||
AttachmentState.IN_PROGRESS -> {
|
||||
putAttachment(entryAttachmentState)
|
||||
}
|
||||
AttachmentState.COMPLETE -> {
|
||||
putAttachment(entryAttachmentState) {
|
||||
getAttachmentViewPosition(entryAttachmentState) {
|
||||
mEntryEditViewModel.binaryPreviewLoaded(entryAttachmentState, it)
|
||||
}
|
||||
}
|
||||
mEntryEditViewModel.onAttachmentAction(null)
|
||||
}
|
||||
AttachmentState.CANCELED,
|
||||
AttachmentState.ERROR -> {
|
||||
removeAttachment(entryAttachmentState)
|
||||
mEntryEditViewModel.onAttachmentAction(null)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
rootView.showByFading()
|
||||
@@ -246,7 +275,6 @@ class EntryEditFragment: DatabaseFragment(), SetOTPDialogFragment.CreateOtpListe
|
||||
super.onDetach()
|
||||
|
||||
drawFactory = null
|
||||
onRemoveAttachment = null
|
||||
}
|
||||
|
||||
fun generatePasswordEducationPerformed(entryEditActivityEducation: EntryEditActivityEducation): Boolean {
|
||||
@@ -662,11 +690,11 @@ class EntryEditFragment: DatabaseFragment(), SetOTPDialogFragment.CreateOtpListe
|
||||
* -------------
|
||||
*/
|
||||
|
||||
fun getAttachments(): List<Attachment> {
|
||||
private fun getAttachments(): List<Attachment> {
|
||||
return attachmentsAdapter?.itemsList?.map { it.attachment } ?: listOf()
|
||||
}
|
||||
|
||||
fun assignAttachments(attachments: List<Attachment>,
|
||||
private fun assignAttachments(attachments: List<Attachment>,
|
||||
streamDirection: StreamDirection,
|
||||
onDeleteItem: (attachment: Attachment) -> Unit) {
|
||||
attachmentsContainerView.visibility = if (attachments.isEmpty()) View.GONE else View.VISIBLE
|
||||
@@ -684,8 +712,12 @@ class EntryEditFragment: DatabaseFragment(), SetOTPDialogFragment.CreateOtpListe
|
||||
return attachmentsAdapter?.contains(attachment) ?: false
|
||||
}
|
||||
|
||||
fun putAttachment(attachment: EntryAttachmentState,
|
||||
private fun putAttachment(attachment: EntryAttachmentState,
|
||||
onPreviewLoaded: (() -> Unit)? = null) {
|
||||
// When only one attachment is allowed
|
||||
if (mDatabase?.allowMultipleAttachments == false) {
|
||||
clearAttachments()
|
||||
}
|
||||
attachmentsContainerView.visibility = View.VISIBLE
|
||||
attachmentsAdapter?.putItem(attachment)
|
||||
attachmentsAdapter?.onBinaryPreviewLoaded = {
|
||||
@@ -693,15 +725,15 @@ class EntryEditFragment: DatabaseFragment(), SetOTPDialogFragment.CreateOtpListe
|
||||
}
|
||||
}
|
||||
|
||||
fun removeAttachment(attachment: EntryAttachmentState) {
|
||||
private fun removeAttachment(attachment: EntryAttachmentState) {
|
||||
attachmentsAdapter?.removeItem(attachment)
|
||||
}
|
||||
|
||||
fun clearAttachments() {
|
||||
private fun clearAttachments() {
|
||||
attachmentsAdapter?.clear()
|
||||
}
|
||||
|
||||
fun getAttachmentViewPosition(attachment: EntryAttachmentState, position: (Float) -> Unit) {
|
||||
private fun getAttachmentViewPosition(attachment: EntryAttachmentState, position: (Float) -> Unit) {
|
||||
attachmentsListView.postDelayed({
|
||||
attachmentsAdapter?.indexOf(attachment)?.let { index ->
|
||||
position.invoke(attachmentsContainerView.y
|
||||
|
||||
@@ -640,10 +640,11 @@ class Database {
|
||||
return false
|
||||
}
|
||||
|
||||
fun buildNewBinaryAttachment(compressed: Boolean = false,
|
||||
protected: Boolean = false): BinaryData? {
|
||||
fun buildNewBinaryAttachment(): BinaryData? {
|
||||
return mDatabaseKDB?.buildNewAttachment()
|
||||
?: mDatabaseKDBX?.buildNewAttachment( false, compressed, protected)
|
||||
?: mDatabaseKDBX?.buildNewAttachment( false,
|
||||
compressionForNewEntry(),
|
||||
false)
|
||||
}
|
||||
|
||||
fun removeAttachmentIfNotUsed(attachment: Attachment) {
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package com.kunzisoft.keepass.viewmodels
|
||||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.kunzisoft.keepass.database.element.Attachment
|
||||
import com.kunzisoft.keepass.database.element.DateInstant
|
||||
import com.kunzisoft.keepass.database.element.Field
|
||||
import com.kunzisoft.keepass.database.element.icon.IconImage
|
||||
import com.kunzisoft.keepass.database.element.template.Template
|
||||
import com.kunzisoft.keepass.model.EntryAttachmentState
|
||||
import com.kunzisoft.keepass.model.EntryInfo
|
||||
|
||||
|
||||
@@ -43,6 +46,13 @@ class EntryEditViewModel: ViewModel() {
|
||||
val onTimeSelected : LiveData<Time> get() = _onTimeSelected
|
||||
private val _onTimeSelected = SingleLiveEvent<Time>()
|
||||
|
||||
val attachmentDeleted : LiveData<Attachment> get() = _attachmentDeleted
|
||||
private val _attachmentDeleted = SingleLiveEvent<Attachment>()
|
||||
val onAttachmentAction : LiveData<EntryAttachmentState?> get() = _onAttachmentAction
|
||||
private val _onAttachmentAction = MutableLiveData<EntryAttachmentState?>()
|
||||
val onBinaryPreviewLoaded : LiveData<AttachmentPosition> get() = _onBinaryPreviewLoaded
|
||||
private val _onBinaryPreviewLoaded = SingleLiveEvent<AttachmentPosition>()
|
||||
|
||||
fun requestEntryInfoUpdate() {
|
||||
_requestEntryInfoUpdate.call()
|
||||
}
|
||||
@@ -105,9 +115,22 @@ class EntryEditViewModel: ViewModel() {
|
||||
_onTimeSelected.value = Time(hours, minutes)
|
||||
}
|
||||
|
||||
fun deleteAttachment(attachment: Attachment) {
|
||||
_attachmentDeleted.value = attachment
|
||||
}
|
||||
|
||||
fun onAttachmentAction(entryAttachmentState: EntryAttachmentState?) {
|
||||
_onAttachmentAction.value = entryAttachmentState
|
||||
}
|
||||
|
||||
fun binaryPreviewLoaded(entryAttachmentState: EntryAttachmentState, viewPosition: Float) {
|
||||
_onBinaryPreviewLoaded.value = AttachmentPosition(entryAttachmentState, viewPosition)
|
||||
}
|
||||
|
||||
data class Date(val year: Int, val month: Int, val day: Int)
|
||||
data class Time(val hours: Int, val minutes: Int)
|
||||
data class FieldEdition(val oldField: Field?, val newField: Field?)
|
||||
data class AttachmentPosition(val entryAttachmentState: EntryAttachmentState, val viewPosition: Float)
|
||||
|
||||
companion object {
|
||||
private val TAG = EntryEditViewModel::class.java.name
|
||||
|
||||
Reference in New Issue
Block a user