From c769c471ae89bc7fff5bb4b2789cb1d34ffddfbd Mon Sep 17 00:00:00 2001 From: Mohamed <mohamed.metwalli@sap.com> Date: Fri, 12 Mar 2021 14:01:23 +0100 Subject: [PATCH] Generic duration picker (DEV) (#2546) - Rename Picker to a more generic name - Move it to a suitable package - Avoid using Target API - Implement Builder pattern Co-authored-by: harambasicluka <64483219+harambasicluka@users.noreply.github.com> Co-authored-by: Matthias Urhahn <matthias.urhahn@sap.com> --- .../ui/ContactDiaryTestFragment.kt | 20 ++++---- .../ContactDiaryLocationListFragment.kt | 26 ++++------- .../tabs/location/DiaryLocationViewHolder.kt | 2 +- .../ui/exporter/ContactDiaryExporter.kt | 2 +- .../adapter/day/DayDataNestedAdapter.kt | 2 +- .../ui/durationpicker/DurationExtension.kt | 2 +- .../durationpicker/DurationPicker.kt} | 46 +++++++++++++------ ...ialog_fragment.xml => duration_picker.xml} | 1 + .../ContactDiaryDurationPickerFragmentTest.kt | 43 ----------------- .../durationpicker/DurationExtensionKtTest.kt | 2 +- .../ui/durationpicker/DurationPickerTest.kt | 43 +++++++++++++++++ 11 files changed, 100 insertions(+), 89 deletions(-) rename Corona-Warn-App/src/main/java/de/rki/coronawarnapp/{contactdiary => }/ui/durationpicker/DurationExtension.kt (93%) rename Corona-Warn-App/src/main/java/de/rki/coronawarnapp/{contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragment.kt => ui/durationpicker/DurationPicker.kt} (60%) rename Corona-Warn-App/src/main/res/layout/{contact_diary_duration_picker_dialog_fragment.xml => duration_picker.xml} (98%) delete mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragmentTest.kt rename Corona-Warn-App/src/test/java/de/rki/coronawarnapp/{contactdiary => }/ui/durationpicker/DurationExtensionKtTest.kt (96%) create mode 100644 Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/durationpicker/DurationPickerTest.kt diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/contactdiary/ui/ContactDiaryTestFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/contactdiary/ui/ContactDiaryTestFragment.kt index 7ff3c8f20..cfdd87475 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/contactdiary/ui/ContactDiaryTestFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/contactdiary/ui/ContactDiaryTestFragment.kt @@ -5,8 +5,8 @@ import android.os.Bundle import android.view.View import androidx.fragment.app.Fragment import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.contactdiary.ui.durationpicker.ContactDiaryDurationPickerFragment -import de.rki.coronawarnapp.contactdiary.ui.durationpicker.toContactDiaryFormat +import de.rki.coronawarnapp.ui.durationpicker.DurationPicker +import de.rki.coronawarnapp.ui.durationpicker.toContactDiaryFormat import de.rki.coronawarnapp.databinding.FragmentTestContactDiaryBinding import de.rki.coronawarnapp.test.menu.ui.TestMenuItem import de.rki.coronawarnapp.util.di.AutoInject @@ -21,7 +21,7 @@ import javax.inject.Inject class ContactDiaryTestFragment : Fragment(R.layout.fragment_test_contact_diary), AutoInject, - ContactDiaryDurationPickerFragment.OnChangeListener { + DurationPicker.OnChangeListener { @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory private val vm: ContactDiaryTestFragmentViewModel by cwaViewModels { viewModelFactory } @@ -49,15 +49,11 @@ class ContactDiaryTestFragment : locationVisitsCleanButton.setOnClickListener { vm.clearLocationVisits() } personEncountersCleanButton.setOnClickListener { vm.clearPersonEncounters() } durationValue.setOnClickListener { - val args = Bundle() - args.putString( - ContactDiaryDurationPickerFragment.DURATION_ARGUMENT_KEY, - binding.durationValue.text.toString() - ) - - val durationPicker = ContactDiaryDurationPickerFragment() - durationPicker.arguments = args - durationPicker.setTargetFragment(this@ContactDiaryTestFragment, 0) + val durationPicker = DurationPicker.Builder() + .duration(binding.durationValue.text.toString()) + .title(getString(R.string.duration_dialog_title)) + .build() + durationPicker.setDurationChangeListener(this@ContactDiaryTestFragment) durationPicker.show(parentFragmentManager, "ContactDiaryDurationPickerFragment") } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/ContactDiaryLocationListFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/ContactDiaryLocationListFragment.kt index 0f0c7b707..534f274d5 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/ContactDiaryLocationListFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/ContactDiaryLocationListFragment.kt @@ -8,10 +8,9 @@ import androidx.navigation.fragment.navArgs import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.ui.day.ContactDiaryDayFragment import de.rki.coronawarnapp.contactdiary.ui.day.ContactDiaryDayFragmentDirections -import de.rki.coronawarnapp.contactdiary.ui.durationpicker.ContactDiaryDurationPickerFragment +import de.rki.coronawarnapp.ui.durationpicker.DurationPicker import de.rki.coronawarnapp.contactdiary.util.MarginRecyclerViewDecoration import de.rki.coronawarnapp.databinding.ContactDiaryLocationListFragmentBinding -import de.rki.coronawarnapp.ui.doNavigate import de.rki.coronawarnapp.util.di.AutoInject import de.rki.coronawarnapp.util.lists.diffutil.update import de.rki.coronawarnapp.util.onScroll @@ -20,13 +19,11 @@ import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.viewBindingLazy import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider import de.rki.coronawarnapp.util.viewmodel.cwaViewModelsAssisted -import org.joda.time.Duration import javax.inject.Inject class ContactDiaryLocationListFragment : Fragment(R.layout.contact_diary_location_list_fragment), - AutoInject, - ContactDiaryDurationPickerFragment.OnChangeListener { + AutoInject { private val binding: ContactDiaryLocationListFragmentBinding by viewBindingLazy() @@ -64,13 +61,14 @@ class ContactDiaryLocationListFragment : } viewModel.openDialog.observe2(this) { - val args = Bundle() - args.putString(ContactDiaryDurationPickerFragment.DURATION_ARGUMENT_KEY, it) - - val durationPicker = ContactDiaryDurationPickerFragment() - durationPicker.arguments = args - durationPicker.setTargetFragment(this@ContactDiaryLocationListFragment, 0) - durationPicker.show(parentFragmentManager, "ContactDiaryDurationPickerFragment") + val durationPicker = DurationPicker.Builder() + .duration(it) + .title(getString(R.string.duration_dialog_title)) + .build() + durationPicker.show(parentFragmentManager, "DurationPicker") + durationPicker.setDurationChangeListener { duration -> + viewModel.onDurationSelected(duration) + } } viewModel.openCommentInfo.observe2(this) { @@ -80,8 +78,4 @@ class ContactDiaryLocationListFragment : ) } } - - override fun onChange(duration: Duration) { - viewModel.onDurationSelected(duration) - } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/DiaryLocationViewHolder.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/DiaryLocationViewHolder.kt index 04b900270..20ebb6550 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/DiaryLocationViewHolder.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/day/tabs/location/DiaryLocationViewHolder.kt @@ -3,8 +3,8 @@ package de.rki.coronawarnapp.contactdiary.ui.day.tabs.location import android.view.ViewGroup import android.view.accessibility.AccessibilityEvent import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.contactdiary.ui.durationpicker.toContactDiaryFormat import de.rki.coronawarnapp.contactdiary.util.setClickLabel +import de.rki.coronawarnapp.ui.durationpicker.toContactDiaryFormat import de.rki.coronawarnapp.databinding.ContactDiaryLocationListItemBinding import de.rki.coronawarnapp.ui.lists.BaseAdapter import de.rki.coronawarnapp.util.lists.BindableVH diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/exporter/ContactDiaryExporter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/exporter/ContactDiaryExporter.kt index 56cf164df..4cb7160f8 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/exporter/ContactDiaryExporter.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/exporter/ContactDiaryExporter.kt @@ -5,7 +5,7 @@ import dagger.Reusable import de.rki.coronawarnapp.R import de.rki.coronawarnapp.contactdiary.model.ContactDiaryLocationVisit import de.rki.coronawarnapp.contactdiary.model.ContactDiaryPersonEncounter -import de.rki.coronawarnapp.contactdiary.ui.durationpicker.toReadableDuration +import de.rki.coronawarnapp.ui.durationpicker.toReadableDuration import de.rki.coronawarnapp.util.TimeAndDateExtensions.toLocalDate import de.rki.coronawarnapp.util.TimeStamper import de.rki.coronawarnapp.util.coroutine.DispatcherProvider diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt index adeb5f4ab..b0cc6fb87 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/day/DayDataNestedAdapter.kt @@ -3,7 +3,7 @@ package de.rki.coronawarnapp.contactdiary.ui.overview.adapter.day import android.view.View import android.view.ViewGroup import de.rki.coronawarnapp.R -import de.rki.coronawarnapp.contactdiary.ui.durationpicker.toReadableDuration +import de.rki.coronawarnapp.ui.durationpicker.toReadableDuration import de.rki.coronawarnapp.contactdiary.util.clearAndAddAll import de.rki.coronawarnapp.databinding.ContactDiaryOverviewNestedListItemBinding import de.rki.coronawarnapp.ui.lists.BaseAdapter diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/DurationExtension.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/durationpicker/DurationExtension.kt similarity index 93% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/DurationExtension.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/durationpicker/DurationExtension.kt index dad157251..40c79fb1f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/DurationExtension.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/durationpicker/DurationExtension.kt @@ -1,4 +1,4 @@ -package de.rki.coronawarnapp.contactdiary.ui.durationpicker +package de.rki.coronawarnapp.ui.durationpicker import org.joda.time.Duration diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/durationpicker/DurationPicker.kt similarity index 60% rename from Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragment.kt rename to Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/durationpicker/DurationPicker.kt index 5e14d2498..044f141c4 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/durationpicker/DurationPicker.kt @@ -1,26 +1,23 @@ -package de.rki.coronawarnapp.contactdiary.ui.durationpicker +package de.rki.coronawarnapp.ui.durationpicker import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.DialogFragment -import de.rki.coronawarnapp.databinding.ContactDiaryDurationPickerDialogFragmentBinding +import de.rki.coronawarnapp.databinding.DurationPickerBinding import org.joda.time.Duration import org.joda.time.format.PeriodFormatter import org.joda.time.format.PeriodFormatterBuilder -class ContactDiaryDurationPickerFragment : DialogFragment() { +class DurationPicker : DialogFragment() { - interface OnChangeListener { + fun interface OnChangeListener { fun onChange(duration: Duration) } - val binding: Lazy<ContactDiaryDurationPickerDialogFragmentBinding> = lazy { - ContactDiaryDurationPickerDialogFragmentBinding.inflate( - layoutInflater - ) - } + private var onChangeListener: OnChangeListener? = null + private val binding: Lazy<DurationPickerBinding> = lazy { DurationPickerBinding.inflate(layoutInflater) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { return binding.value.root @@ -42,7 +39,7 @@ class ContactDiaryDurationPickerFragment : DialogFragment() { } with(binding.value) { - var duration = requireArguments().getString(DURATION_ARGUMENT_KEY)!!.split(":").toTypedArray() + var duration = requireArguments().getString(DURATION_KEY)!!.split(":").toTypedArray() if (duration.size < 2) duration = arrayOf("00", "00") hours.value = hoursArray.indexOf(duration[0]) @@ -50,15 +47,19 @@ class ContactDiaryDurationPickerFragment : DialogFragment() { cancelButton.setOnClickListener { dismiss() } okButton.setOnClickListener { - (targetFragment as? OnChangeListener)?.onChange(getDuration(hours.value, minutes.value)) + onChangeListener?.onChange(getDuration(hours.value, minutes.value)) dismiss() } } } - companion object { - const val DURATION_ARGUMENT_KEY = "duration" + fun setDurationChangeListener(onChangeListener: OnChangeListener) { + this.onChangeListener = onChangeListener + } + companion object { + private const val DURATION_KEY = "duration" + private const val TITLE_KEY = "title" val minutesArray = arrayOf("00", "15", "30", "45") val hoursArray = Array(24) { "%02d".format(it) } @@ -71,5 +72,24 @@ class ContactDiaryDurationPickerFragment : DialogFragment() { .toFormatter() return formatter.parsePeriod(durationString).toStandardDuration() } + + private fun newInstance(builder: Builder) = DurationPicker() + .apply { + arguments = Bundle().apply { + putString(DURATION_KEY, builder.duration) + putString(TITLE_KEY, builder.title) + } + } + } + + class Builder { + var title: String = "" + private set + var duration: String = "" + private set + + fun title(title: String) = apply { this.title = title } + fun duration(duration: String) = apply { this.duration = duration } + fun build() = newInstance(this) } } diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_duration_picker_dialog_fragment.xml b/Corona-Warn-App/src/main/res/layout/duration_picker.xml similarity index 98% rename from Corona-Warn-App/src/main/res/layout/contact_diary_duration_picker_dialog_fragment.xml rename to Corona-Warn-App/src/main/res/layout/duration_picker.xml index 882b3e971..3e165988d 100644 --- a/Corona-Warn-App/src/main/res/layout/contact_diary_duration_picker_dialog_fragment.xml +++ b/Corona-Warn-App/src/main/res/layout/duration_picker.xml @@ -4,6 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:id="@+id/duration_container" android:layout_width="match_parent" + tools:context="de.rki.coronawarnapp.ui.durationpicker.DurationPicker" android:layout_height="wrap_content"> <TextView diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragmentTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragmentTest.kt deleted file mode 100644 index 3506e3065..000000000 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/ContactDiaryDurationPickerFragmentTest.kt +++ /dev/null @@ -1,43 +0,0 @@ -package de.rki.coronawarnapp.contactdiary.ui.durationpicker - -import io.kotest.matchers.shouldBe -import io.mockk.MockKAnnotations -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Test - -class ContactDiaryDurationPickerFragmentTest { - - @BeforeEach - fun setup() { - MockKAnnotations.init(this) - } - - @Test - fun `check hours array`() { - ContactDiaryDurationPickerFragment.hoursArray.count() shouldBe 24 - for (i in 0..9) { - ContactDiaryDurationPickerFragment.hoursArray[i] shouldBe "0$i" - } - for (i in 10..23) { - ContactDiaryDurationPickerFragment.hoursArray[i] shouldBe "$i" - } - } - - @Test - fun `check minutes array`() { - ContactDiaryDurationPickerFragment.minutesArray.count() shouldBe 4 - ContactDiaryDurationPickerFragment.minutesArray[0] shouldBe "00" - for (i in 1..3) { - ContactDiaryDurationPickerFragment.minutesArray[i] shouldBe "${i * 15}" - } - } - - @Test - fun `check duration`() { - ContactDiaryDurationPickerFragment.getDuration(0, 0).toContactDiaryFormat() shouldBe "00:00" - ContactDiaryDurationPickerFragment.getDuration(1, 0).toContactDiaryFormat() shouldBe "01:00" - ContactDiaryDurationPickerFragment.getDuration(23, 3).toContactDiaryFormat() shouldBe "23:45" - ContactDiaryDurationPickerFragment.getDuration(9, 2).toContactDiaryFormat() shouldBe "09:30" - ContactDiaryDurationPickerFragment.getDuration(10, 1).toContactDiaryFormat() shouldBe "10:15" - } -} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/DurationExtensionKtTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/durationpicker/DurationExtensionKtTest.kt similarity index 96% rename from Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/DurationExtensionKtTest.kt rename to Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/durationpicker/DurationExtensionKtTest.kt index 84d647ea2..78d19f9fd 100644 --- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/contactdiary/ui/durationpicker/DurationExtensionKtTest.kt +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/durationpicker/DurationExtensionKtTest.kt @@ -1,4 +1,4 @@ -package de.rki.coronawarnapp.contactdiary.ui.durationpicker +package de.rki.coronawarnapp.ui.durationpicker import io.kotest.matchers.shouldBe import org.joda.time.Duration diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/durationpicker/DurationPickerTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/durationpicker/DurationPickerTest.kt new file mode 100644 index 000000000..61c1b12ae --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/durationpicker/DurationPickerTest.kt @@ -0,0 +1,43 @@ +package de.rki.coronawarnapp.ui.durationpicker + +import io.kotest.matchers.shouldBe +import io.mockk.MockKAnnotations +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +class DurationPickerTest { + + @BeforeEach + fun setup() { + MockKAnnotations.init(this) + } + + @Test + fun `check hours array`() { + DurationPicker.hoursArray.count() shouldBe 24 + for (i in 0..9) { + DurationPicker.hoursArray[i] shouldBe "0$i" + } + for (i in 10..23) { + DurationPicker.hoursArray[i] shouldBe "$i" + } + } + + @Test + fun `check minutes array`() { + DurationPicker.minutesArray.count() shouldBe 4 + DurationPicker.minutesArray[0] shouldBe "00" + for (i in 1..3) { + DurationPicker.minutesArray[i] shouldBe "${i * 15}" + } + } + + @Test + fun `check duration`() { + DurationPicker.getDuration(0, 0).toContactDiaryFormat() shouldBe "00:00" + DurationPicker.getDuration(1, 0).toContactDiaryFormat() shouldBe "01:00" + DurationPicker.getDuration(23, 3).toContactDiaryFormat() shouldBe "23:45" + DurationPicker.getDuration(9, 2).toContactDiaryFormat() shouldBe "09:30" + DurationPicker.getDuration(10, 1).toContactDiaryFormat() shouldBe "10:15" + } +} -- GitLab