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 de84f7ff8..bfcdef5ea 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/EntryEditActivity.kt @@ -171,9 +171,15 @@ class EntryEditActivity : LockingActivity(), mEntryEditViewModel.requestDateTimeSelection.observe(this) { dateInstant -> if (dateInstant.type == DateInstant.Type.TIME) { - selectTime(dateInstant) + // Launch the time picker + val dateTime = DateTime(dateInstant.date) + TimePickerFragment.getInstance(dateTime.hourOfDay, dateTime.minuteOfHour) + .show(supportFragmentManager, "TimePickerFragment") } else { - selectDate(dateInstant) + // Launch the date picker + val dateTime = DateTime(dateInstant.date) + DatePickerFragment.getInstance(dateTime.year, dateTime.monthOfYear - 1, dateTime.dayOfMonth) + .show(supportFragmentManager, "DatePickerFragment") } } @@ -587,25 +593,6 @@ class EntryEditActivity : LockingActivity(), return super.onOptionsItemSelected(item) } - // Launch the date picker - private fun selectDate(dateInstant: DateInstant) { - val dateTime = DateTime(dateInstant.date) - val defaultYear = dateTime.year - val defaultMonth = dateTime.monthOfYear - 1 - val defaultDay = dateTime.dayOfMonth - DatePickerFragment.getInstance(defaultYear, defaultMonth, defaultDay) - .show(supportFragmentManager, "DatePickerFragment") - } - - // Launch the time picker - private fun selectTime(dateInstant: DateInstant) { - val dateTime = DateTime(dateInstant.date) - val defaultHour = dateTime.hourOfDay - val defaultMinute = dateTime.minuteOfHour - TimePickerFragment.getInstance(defaultHour, defaultMinute) - .show(supportFragmentManager, "TimePickerFragment") - } - override fun onDateSet(datePicker: DatePicker?, year: Int, month: Int, day: Int) { // To fix android 4.4 issue // https://stackoverflow.com/questions/12436073/datepicker-ondatechangedlistener-called-twice diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt index 7690ed529..ce5c903ab 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/GroupActivity.kt @@ -77,6 +77,7 @@ import com.kunzisoft.keepass.tasks.ActionRunnable import com.kunzisoft.keepass.timeout.TimeoutHelper import com.kunzisoft.keepass.utils.MenuUtil import com.kunzisoft.keepass.view.* +import com.kunzisoft.keepass.viewmodels.GroupEditViewModel import com.kunzisoft.keepass.viewmodels.GroupViewModel import org.joda.time.DateTime @@ -102,6 +103,7 @@ class GroupActivity : LockingActivity(), private var groupNameView: TextView? = null private val mGroupViewModel: GroupViewModel by viewModels() + private val mGroupEditViewModel: GroupEditViewModel by viewModels() // TODO Remove and pass through viewModel private var mGroupFragment: GroupFragment? = null @@ -280,6 +282,24 @@ class GroupActivity : LockingActivity(), Log.i(TAG, "Finished creating tree") } + + mGroupEditViewModel.requestIconSelection.observe(this) { iconImage -> + IconPickerActivity.launch(this@GroupActivity, iconImage) + } + + mGroupEditViewModel.requestDateTimeSelection.observe(this) { dateInstant -> + if (dateInstant.type == DateInstant.Type.TIME) { + // Launch the time picker + val dateTime = DateTime(dateInstant.date) + TimePickerFragment.getInstance(dateTime.hourOfDay, dateTime.minuteOfHour) + .show(supportFragmentManager, "TimePickerFragment") + } else { + // Launch the date picker + val dateTime = DateTime(dateInstant.date) + DatePickerFragment.getInstance(dateTime.year, dateTime.monthOfYear - 1, dateTime.dayOfMonth) + .show(supportFragmentManager, "DatePickerFragment") + } + } } override fun onDatabaseRetrieved(database: Database?) { @@ -686,33 +706,12 @@ class GroupActivity : LockingActivity(), // To fix android 4.4 issue // https://stackoverflow.com/questions/12436073/datepicker-ondatechangedlistener-called-twice if (datePicker?.isShown == true) { - val groupEditFragment = supportFragmentManager.findFragmentByTag(GroupEditDialogFragment.TAG_CREATE_GROUP) as? GroupEditDialogFragment - groupEditFragment?.getExpiryTime()?.date?.let { expiresDate -> - groupEditFragment.setExpiryTime(DateInstant(DateTime(expiresDate) - .withYear(year) - .withMonthOfYear(month + 1) - .withDayOfMonth(day) - .toDate())) - // Launch the time picker - val dateTime = DateTime(expiresDate) - val defaultHour = dateTime.hourOfDay - val defaultMinute = dateTime.minuteOfHour - TimePickerFragment.getInstance(defaultHour, defaultMinute) - .show(supportFragmentManager, "TimePickerFragment") - } + mGroupEditViewModel.selectDate(year, month, day) } } override fun onTimeSet(view: TimePicker?, hours: Int, minutes: Int) { - val groupEditFragment = supportFragmentManager.findFragmentByTag(GroupEditDialogFragment.TAG_CREATE_GROUP) as? GroupEditDialogFragment - groupEditFragment?.getExpiryTime()?.date?.let { expiresDate -> - // Save the date - groupEditFragment.setExpiryTime( - DateInstant(DateTime(expiresDate) - .withHourOfDay(hours) - .withMinuteOfHour(minutes) - .toDate())) - } + mGroupEditViewModel.selectTime(hours, minutes) } private fun finishNodeAction() { @@ -1059,9 +1058,7 @@ class GroupActivity : LockingActivity(), // To create tree dialog for icon IconPickerActivity.onActivityResult(requestCode, resultCode, data) { icon -> - (supportFragmentManager - .findFragmentByTag(GroupEditDialogFragment.TAG_CREATE_GROUP) as GroupEditDialogFragment) - .setIcon(icon) + mGroupEditViewModel.selectIcon(icon) } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupEditDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupEditDialogFragment.kt index fad888043..43125c450 100644 --- a/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupEditDialogFragment.kt +++ b/app/src/main/java/com/kunzisoft/keepass/activities/dialogs/GroupEditDialogFragment.kt @@ -28,28 +28,31 @@ import android.widget.Button import android.widget.ImageView import android.widget.TextView import androidx.appcompat.app.AlertDialog -import androidx.fragment.app.DialogFragment +import androidx.fragment.app.activityViewModels import com.google.android.material.textfield.TextInputLayout import com.kunzisoft.keepass.R -import com.kunzisoft.keepass.activities.IconPickerActivity import com.kunzisoft.keepass.activities.dialogs.GroupEditDialogFragment.EditGroupDialogAction.CREATION import com.kunzisoft.keepass.activities.dialogs.GroupEditDialogFragment.EditGroupDialogAction.UPDATE +import com.kunzisoft.keepass.activities.fragments.DatabaseDialogFragment import com.kunzisoft.keepass.database.element.Database import com.kunzisoft.keepass.database.element.DateInstant import com.kunzisoft.keepass.database.element.icon.IconImage import com.kunzisoft.keepass.model.GroupInfo import com.kunzisoft.keepass.view.DateTimeEditFieldView +import com.kunzisoft.keepass.viewmodels.GroupEditViewModel import org.joda.time.DateTime -class GroupEditDialogFragment : DialogFragment() { +class GroupEditDialogFragment : DatabaseDialogFragment() { private var mEditGroupListener: EditGroupListener? = null + private val mGroupEditViewModel: GroupEditViewModel by activityViewModels() + private var populateIconMethod: ((ImageView, IconImage) -> Unit)? = null private var mEditGroupDialogAction = EditGroupDialogAction.NONE private var mGroupInfo = GroupInfo() private lateinit var iconButtonView: ImageView - private var iconColor: Int = 0 + private var mIconColor: Int = 0 private lateinit var nameTextLayoutView: TextInputLayout private lateinit var nameTextView: TextView private lateinit var notesTextLayoutView: TextInputLayout @@ -74,8 +77,10 @@ class GroupEditDialogFragment : DialogFragment() { mEditGroupListener = context as EditGroupListener } catch (e: ClassCastException) { // The activity doesn't implement the interface, throw exception - throw ClassCastException(context.toString() - + " must implement " + GroupEditDialogFragment::class.java.name) + throw ClassCastException( + context.toString() + + " must implement " + GroupEditDialogFragment::class.java.name + ) } } @@ -84,6 +89,48 @@ class GroupEditDialogFragment : DialogFragment() { super.onDetach() } + override fun onDatabaseRetrieved(database: Database?) { + populateIconMethod = { imageView, icon -> + database?.iconDrawableFactory?.assignDatabaseIcon(imageView, icon, mIconColor) + } + populateIconMethod?.invoke(iconButtonView, mGroupInfo.icon) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + mGroupEditViewModel.onIconSelected.observe(this) { iconImage -> + mGroupInfo.icon = iconImage + populateIconMethod?.invoke(iconButtonView, mGroupInfo.icon) + } + + mGroupEditViewModel.onDateSelected.observe(this) { viewModelDate -> + // Save the date + mGroupInfo.expiryTime = DateInstant( + DateTime(mGroupInfo.expiryTime.date) + .withYear(viewModelDate.year) + .withMonthOfYear(viewModelDate.month + 1) + .withDayOfMonth(viewModelDate.day) + .toDate()) + expirationView.dateTime = mGroupInfo.expiryTime + if (expirationView.dateTime.type == DateInstant.Type.DATE_TIME) { + val instantTime = DateInstant(mGroupInfo.expiryTime.date, DateInstant.Type.TIME) + // Trick to recall selection with time + mGroupEditViewModel.requestDateTimeSelection(instantTime) + } + } + + mGroupEditViewModel.onTimeSelected.observe(this) { viewModelTime -> + // Save the time + mGroupInfo.expiryTime = DateInstant( + DateTime(mGroupInfo.expiryTime.date) + .withHourOfDay(viewModelTime.hours) + .withMinuteOfHour(viewModelTime.minutes) + .toDate(), mGroupInfo.expiryTime.type) + expirationView.dateTime = mGroupInfo.expiryTime + } + } + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { activity?.let { activity -> val root = activity.layoutInflater.inflate(R.layout.fragment_group_edit, null) @@ -96,7 +143,7 @@ class GroupEditDialogFragment : DialogFragment() { // Retrieve the textColor to tint the icon val ta = activity.theme.obtainStyledAttributes(intArrayOf(android.R.attr.textColor)) - iconColor = ta.getColor(0, Color.WHITE) + mIconColor = ta.getColor(0, Color.WHITE) ta.recycle() if (savedInstanceState != null @@ -115,16 +162,13 @@ class GroupEditDialogFragment : DialogFragment() { } // populate info in views - populateInfoToViews() - expirationView.setOnDateClickListener = { - expirationView.dateTime.date.let { expiresDate -> - val dateTime = DateTime(expiresDate) - val defaultYear = dateTime.year - val defaultMonth = dateTime.monthOfYear-1 - val defaultDay = dateTime.dayOfMonth - DatePickerFragment.getInstance(defaultYear, defaultMonth, defaultDay) - .show(parentFragmentManager, "DatePickerFragment") - } + populateInfoToViews(mGroupInfo) + + iconButtonView.setOnClickListener { _ -> + mGroupEditViewModel.requestIconSelection(mGroupInfo.icon) + } + expirationView.setOnDateClickListener = { dateInstant -> + mGroupEditViewModel.requestDateTimeSelection(dateInstant) } val builder = AlertDialog.Builder(activity) @@ -137,10 +181,6 @@ class GroupEditDialogFragment : DialogFragment() { mGroupInfo) } - iconButtonView.setOnClickListener { _ -> - IconPickerActivity.launch(activity, mGroupInfo.icon) - } - return builder.create() } return super.onCreateDialog(savedInstanceState) @@ -165,25 +205,15 @@ class GroupEditDialogFragment : DialogFragment() { } } - fun getExpiryTime(): DateInstant { - retrieveGroupInfoFromViews() - return mGroupInfo.expiryTime - } - - fun setExpiryTime(expiryTime: DateInstant) { - mGroupInfo.expiryTime = expiryTime - populateInfoToViews() - } - - private fun populateInfoToViews() { - assignIconView() - nameTextView.text = mGroupInfo.title - notesTextLayoutView.visibility = if (mGroupInfo.notes == null) View.GONE else View.VISIBLE - mGroupInfo.notes?.let { + private fun populateInfoToViews(groupInfo: GroupInfo) { + mGroupEditViewModel.selectIcon(groupInfo.icon) + nameTextView.text = groupInfo.title + notesTextLayoutView.visibility = if (groupInfo.notes == null) View.GONE else View.VISIBLE + groupInfo.notes?.let { notesTextView.text = it } - expirationView.activation = mGroupInfo.expires - expirationView.dateTime = mGroupInfo.expiryTime + expirationView.activation = groupInfo.expires + expirationView.dateTime = groupInfo.expiryTime } private fun retrieveGroupInfoFromViews() { @@ -197,16 +227,6 @@ class GroupEditDialogFragment : DialogFragment() { mGroupInfo.expiryTime = expirationView.dateTime } - private fun assignIconView() { - // TODO Database - Database.getInstance()?.iconDrawableFactory?.assignDatabaseIcon(iconButtonView, mGroupInfo.icon, iconColor) - } - - fun setIcon(icon: IconImage) { - mGroupInfo.icon = icon - assignIconView() - } - override fun onSaveInstanceState(outState: Bundle) { retrieveGroupInfoFromViews() outState.putInt(KEY_ACTION_ID, mEditGroupDialogAction.ordinal) diff --git a/app/src/main/java/com/kunzisoft/keepass/activities/fragments/DatabaseDialogFragment.kt b/app/src/main/java/com/kunzisoft/keepass/activities/fragments/DatabaseDialogFragment.kt new file mode 100644 index 000000000..116cb5fb9 --- /dev/null +++ b/app/src/main/java/com/kunzisoft/keepass/activities/fragments/DatabaseDialogFragment.kt @@ -0,0 +1,31 @@ +package com.kunzisoft.keepass.activities.fragments + +import android.os.Bundle +import androidx.fragment.app.DialogFragment +import androidx.fragment.app.activityViewModels +import com.kunzisoft.keepass.activities.DatabaseRetrieval +import com.kunzisoft.keepass.database.element.Database +import com.kunzisoft.keepass.tasks.ActionRunnable +import com.kunzisoft.keepass.viewmodels.DatabaseViewModel + +abstract class DatabaseDialogFragment : DialogFragment(), DatabaseRetrieval { + + private val mDatabaseViewModel: DatabaseViewModel by activityViewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + mDatabaseViewModel.database.observe(this) { database -> + // TODO requireView().resetAppTimeoutWhenViewFocusedOrChanged(requireContext(), database) + onDatabaseRetrieved(database) + } + } + + override fun onDatabaseActionFinished( + database: Database, + actionTask: String, + result: ActionRunnable.Result + ) { + // Can be overridden by a subclass + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kunzisoft/keepass/viewmodels/EntryEditViewModel.kt b/app/src/main/java/com/kunzisoft/keepass/viewmodels/EntryEditViewModel.kt index e9ea4febd..f2cf83b92 100644 --- a/app/src/main/java/com/kunzisoft/keepass/viewmodels/EntryEditViewModel.kt +++ b/app/src/main/java/com/kunzisoft/keepass/viewmodels/EntryEditViewModel.kt @@ -3,7 +3,6 @@ package com.kunzisoft.keepass.viewmodels import android.net.Uri import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel import com.kunzisoft.keepass.app.database.IOActionTask import com.kunzisoft.keepass.database.element.* import com.kunzisoft.keepass.database.element.icon.IconImage @@ -12,13 +11,12 @@ import com.kunzisoft.keepass.database.element.node.NodeId import com.kunzisoft.keepass.database.element.template.Template import com.kunzisoft.keepass.model.* import com.kunzisoft.keepass.otp.OtpElement -import com.kunzisoft.keepass.view.DataDate -import com.kunzisoft.keepass.view.DataTime import java.util.* -class EntryEditViewModel: ViewModel() { +class EntryEditViewModel: NodeEditViewModel() { + // TODO Better variable implementation private var mDatabase: Database? = null private var mParent: Group? = null private var mEntry: Entry? = null @@ -39,11 +37,6 @@ class EntryEditViewModel: ViewModel() { val onTemplateChanged : LiveData