Template and Attachment listener as view model

This commit is contained in:
J-Jamet
2021-06-09 17:06:06 +02:00
parent 82f5ab1446
commit cdfbcd873c
4 changed files with 103 additions and 69 deletions

View File

@@ -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()
}
}
else -> {}
}
}
// 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()
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,9 +280,7 @@ 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)
}
mEntryEditViewModel.assignTemplate(mEntryTemplate)
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
@@ -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")

View File

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

View File

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

View File

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