From 93c7b1767e03cd29889f1add5c2e7eb5d808e92b Mon Sep 17 00:00:00 2001 From: BMItter <46747780+BMItter@users.noreply.github.com> Date: Tue, 15 Dec 2020 21:00:27 +0100 Subject: [PATCH] Contact Diary - Overview Screen, Calender (Draft, EXPOSUREAPP-4155) (#1892) * Added basic layout * Added translation support * Added darkmode images * Included dimens in layout * Added navigation to onboarding fragment * Changed AndroidManifest to support new contact diary activity * Updated translation files * Added missing image Updated text styling Changed layout naming * Added back navigation * Updated layout * Added direct link to privacy information * repair PR commit * Changed back navigation * repair * skeleton for overview / calender view * Added classes to display the overview fragment Connected overview to onboarding fragment * Added missing classes * Added basic overview layout * Added list element Added new icons for light and dark mode * Added missing icons * Added recycler view adapter * Added icons for list items * added layout for nested recycler view * Replaced leftovers of ContactDiaryElement with ListItem * Added toolbar menu * Added back navigation to home screen * Changed layout to dimens * Combine data to list items * Show locations and persons * sourceCheck & lint clean * List item data as inner class * Fixed nested layout * Created nested recycler view for person and location data * Added pseudo navigation * changed inject position to the top * removed comment from layout * Added const val for count of days to boost the quality * Remove unused xml removed cast removed unused method from ContactDiaryActivity * Aligned Adapters to avoid confusion overload * cleaned * Updated layout * Added strings * fixed merge deletion * fix recycler height * added little scrollbar to recycler * little bit more space to top element * Updated layout * Created storage module for storage related stuff * Updated list items Remove return statement Co-authored-by: I502720 <axel.herbstreith@sap.com> --- .../contactdiary/ContactDiaryModule.kt | 43 +-------- .../storage/ContactDiaryStorageModule.kt | 40 ++++++++ .../contactdiary/ui/ContactDiaryModule.kt | 5 + .../ContactDiaryOnboardingFragment.kt | 12 +++ .../ContactDiaryOnboardingFragmentModul.kt | 23 +++++ ...ContactDiaryOnboardingFragmentViewModel.kt | 2 +- .../ContactDiaryOnboardingNavigationEvents.kt | 1 + .../overview/ContactDiaryOverviewFragment.kt | 69 +++++++++++++ .../ContactDiaryOverviewFragmentModule.kt | 23 +++++ .../ui/overview/ContactDiaryOverviewMenu.kt | 31 ++++++ .../ContactDiaryOverviewNavigationEvents.kt | 11 +++ .../overview/ContactDiaryOverviewViewModel.kt | 96 +++++++++++++++++++ .../adapter/ContactDiaryOverviewAdapter.kt | 63 ++++++++++++ .../ContactDiaryOverviewNestedAdapter.kt | 37 +++++++ .../ui/overview/adapter/ListItem.kt | 14 +++ .../ic_contact_diary_location_item.xml | 12 +++ .../ic_contact_diary_person_item.xml | 12 +++ .../ic_contact_diary_right_arrow.xml | 10 ++ .../ic_contact_diary_location_item.xml | 12 +++ .../drawable/ic_contact_diary_person_item.xml | 12 +++ .../drawable/ic_contact_diary_right_arrow.xml | 11 +++ .../contact_diary_overview_fragment.xml | 85 ++++++++++++++++ .../include_contact_diary_overview_header.xml | 78 +++++++++++++++ .../include_contact_diary_overview_item.xml | 59 ++++++++++++ ...ude_contact_diary_overview_nested_item.xml | 47 +++++++++ .../res/menu/menu_contact_diary_overview.xml | 15 +++ .../navigation/contact_diary_nav_graph.xml | 9 ++ .../res/values-de/contact_diary_strings.xml | 15 +++ .../main/res/values/contact_diary_strings.xml | 15 +++ .../src/main/res/values/dimens.xml | 3 + .../src/main/res/values/styles.xml | 9 ++ 31 files changed, 835 insertions(+), 39 deletions(-) create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryStorageModule.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragmentModul.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragmentModule.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewMenu.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewNavigationEvents.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt create mode 100644 Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ListItem.kt create mode 100644 Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_location_item.xml create mode 100644 Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_person_item.xml create mode 100644 Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_right_arrow.xml create mode 100644 Corona-Warn-App/src/main/res/drawable/ic_contact_diary_location_item.xml create mode 100644 Corona-Warn-App/src/main/res/drawable/ic_contact_diary_person_item.xml create mode 100644 Corona-Warn-App/src/main/res/drawable/ic_contact_diary_right_arrow.xml create mode 100644 Corona-Warn-App/src/main/res/layout/contact_diary_overview_fragment.xml create mode 100644 Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_header.xml create mode 100644 Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_item.xml create mode 100644 Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_nested_item.xml create mode 100644 Corona-Warn-App/src/main/res/menu/menu_contact_diary_overview.xml diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ContactDiaryModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ContactDiaryModule.kt index b32ac7a95..e2529d15f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ContactDiaryModule.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ContactDiaryModule.kt @@ -1,42 +1,9 @@ package de.rki.coronawarnapp.contactdiary import dagger.Module -import dagger.Provides -import de.rki.coronawarnapp.contactdiary.storage.ContactDiaryDatabase -import de.rki.coronawarnapp.contactdiary.storage.dao.ContactDiaryLocationDao -import de.rki.coronawarnapp.contactdiary.storage.dao.ContactDiaryLocationVisitDao -import de.rki.coronawarnapp.contactdiary.storage.dao.ContactDiaryPersonDao -import de.rki.coronawarnapp.contactdiary.storage.dao.ContactDiaryPersonEncounterDao -import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository -import de.rki.coronawarnapp.contactdiary.storage.repo.DefaultContactDiaryRepository -import javax.inject.Singleton +import de.rki.coronawarnapp.contactdiary.storage.ContactDiaryStorageModule -@Module -class ContactDiaryModule { - - @Singleton - @Provides - fun contactDiaryDatabase(contactDiaryDatabaseFactory: ContactDiaryDatabase.Factory): ContactDiaryDatabase = - contactDiaryDatabaseFactory.create() - - @Provides - fun locationDao(contactDiaryDatabase: ContactDiaryDatabase): ContactDiaryLocationDao = - contactDiaryDatabase.locationDao() - - @Provides - fun locationVisitDao(contactDiaryDatabase: ContactDiaryDatabase): ContactDiaryLocationVisitDao = - contactDiaryDatabase.locationVisitDao() - - @Provides - fun personDao(contactDiaryDatabase: ContactDiaryDatabase): ContactDiaryPersonDao = - contactDiaryDatabase.personDao() - - @Provides - fun personEncounterDao(contactDiaryDatabase: ContactDiaryDatabase): ContactDiaryPersonEncounterDao = - contactDiaryDatabase.personEncounterDao() - - @Singleton - @Provides - fun contactDiaryRepo(defaultContactDiaryRepository: DefaultContactDiaryRepository): ContactDiaryRepository = - defaultContactDiaryRepository -} +@Module( + includes = [ContactDiaryStorageModule::class] +) +class ContactDiaryModule diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryStorageModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryStorageModule.kt new file mode 100644 index 000000000..8954837fc --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/storage/ContactDiaryStorageModule.kt @@ -0,0 +1,40 @@ +package de.rki.coronawarnapp.contactdiary.storage + +import dagger.Module +import dagger.Provides +import de.rki.coronawarnapp.contactdiary.storage.dao.ContactDiaryLocationDao +import de.rki.coronawarnapp.contactdiary.storage.dao.ContactDiaryLocationVisitDao +import de.rki.coronawarnapp.contactdiary.storage.dao.ContactDiaryPersonDao +import de.rki.coronawarnapp.contactdiary.storage.dao.ContactDiaryPersonEncounterDao +import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository +import de.rki.coronawarnapp.contactdiary.storage.repo.DefaultContactDiaryRepository +import javax.inject.Singleton + +@Module +class ContactDiaryStorageModule { + @Singleton + @Provides + fun contactDiaryDatabase(contactDiaryDatabaseFactory: ContactDiaryDatabase.Factory): ContactDiaryDatabase = + contactDiaryDatabaseFactory.create() + + @Provides + fun locationDao(contactDiaryDatabase: ContactDiaryDatabase): ContactDiaryLocationDao = + contactDiaryDatabase.locationDao() + + @Provides + fun locationVisitDao(contactDiaryDatabase: ContactDiaryDatabase): ContactDiaryLocationVisitDao = + contactDiaryDatabase.locationVisitDao() + + @Provides + fun personDao(contactDiaryDatabase: ContactDiaryDatabase): ContactDiaryPersonDao = + contactDiaryDatabase.personDao() + + @Provides + fun personEncounterDao(contactDiaryDatabase: ContactDiaryDatabase): ContactDiaryPersonEncounterDao = + contactDiaryDatabase.personEncounterDao() + + @Singleton + @Provides + fun contactDiaryRepo(defaultContactDiaryRepository: DefaultContactDiaryRepository): ContactDiaryRepository = + defaultContactDiaryRepository +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/ContactDiaryModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/ContactDiaryModule.kt index 9b3577952..8aca513cd 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/ContactDiaryModule.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/ContactDiaryModule.kt @@ -4,9 +4,14 @@ import dagger.Module import dagger.android.ContributesAndroidInjector import de.rki.coronawarnapp.contactdiary.ui.onboarding.ContactDiaryOnboardingFragment import de.rki.coronawarnapp.contactdiary.ui.onboarding.ContactDiaryOnboardingFragmentModule +import de.rki.coronawarnapp.contactdiary.ui.overview.ContactDiaryOverviewFragment +import de.rki.coronawarnapp.contactdiary.ui.overview.ContactDiaryOverviewFragmentModule @Module abstract class ContactDiaryModule { @ContributesAndroidInjector(modules = [ContactDiaryOnboardingFragmentModule::class]) abstract fun contactDiaryOnboardingFragment(): ContactDiaryOnboardingFragment + + @ContributesAndroidInjector(modules = [ContactDiaryOverviewFragmentModule::class]) + abstract fun contactDiaryOverviewFragment(): ContactDiaryOverviewFragment } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragment.kt index 6dc68b561..065596dcd 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragment.kt @@ -51,7 +51,19 @@ class ContactDiaryOnboardingFragment : Fragment(R.layout.contact_diary_onboardin ) ) } + + ContactDiaryOnboardingNavigationEvents.NavigateToOverviewFragment -> { + doNavigate( + ActionOnlyNavDirections( + R.id.action_contactDiaryOnboardingFragment_to_contactDiaryOverviewFragment + ) + ) + } } } } + + override fun onResume() { + super.onResume() + } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragmentModul.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragmentModul.kt new file mode 100644 index 000000000..0b338fb70 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragmentModul.kt @@ -0,0 +1,23 @@ +package de.rki.coronawarnapp.contactdiary.ui.onboarding + +import dagger.Binds +import dagger.Module +import dagger.android.ContributesAndroidInjector +import dagger.multibindings.IntoMap +import de.rki.coronawarnapp.util.viewmodel.CWAViewModel +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelKey + +@Module +abstract class ContactDiaryOnboardingFragmentModul { + + @Binds + @IntoMap + @CWAViewModelKey(ContactDiaryOnboardingFragmentViewModel::class) + abstract fun contactDiaryOnboardingFragmentVM( + factory: ContactDiaryOnboardingFragmentViewModel.Factory + ): CWAViewModelFactory<out CWAViewModel> + + @ContributesAndroidInjector + abstract fun contactDiaryOnboardingFragmentVM(): ContactDiaryOnboardingFragment +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragmentViewModel.kt index e50e4a367..0edf3bfbb 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragmentViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingFragmentViewModel.kt @@ -9,7 +9,7 @@ class ContactDiaryOnboardingFragmentViewModel @AssistedInject constructor() : CW val routeToScreen: SingleLiveEvent<ContactDiaryOnboardingNavigationEvents> = SingleLiveEvent() fun onNextButtonClick() { - TODO("handle this") + routeToScreen.postValue(ContactDiaryOnboardingNavigationEvents.NavigateToOverviewFragment) } fun onBackButtonPress() { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingNavigationEvents.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingNavigationEvents.kt index 138c7ce4c..62578f22e 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingNavigationEvents.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/onboarding/ContactDiaryOnboardingNavigationEvents.kt @@ -4,4 +4,5 @@ sealed class ContactDiaryOnboardingNavigationEvents { object NavigateToMainActivity : ContactDiaryOnboardingNavigationEvents() object NavigateToPrivacyFragment : ContactDiaryOnboardingNavigationEvents() + object NavigateToOverviewFragment : ContactDiaryOnboardingNavigationEvents() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt new file mode 100644 index 000000000..b68f69c5b --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragment.kt @@ -0,0 +1,69 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview + +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.View +import android.widget.Toast +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.ContactDiaryOverviewAdapter +import de.rki.coronawarnapp.databinding.ContactDiaryOverviewFragmentBinding +import de.rki.coronawarnapp.util.di.AutoInject +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.cwaViewModels +import javax.inject.Inject + +class ContactDiaryOverviewFragment : Fragment(R.layout.contact_diary_overview_fragment), AutoInject { + + @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory + @Inject lateinit var contactDiaryOverviewMenu: ContactDiaryOverviewMenu + private val vm: ContactDiaryOverviewViewModel by cwaViewModels { viewModelFactory } + private val binding: ContactDiaryOverviewFragmentBinding by viewBindingLazy() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + val adapter = ContactDiaryOverviewAdapter { + vm.onItemPress(it) + } + + setupToolbar() + + binding.apply { + contactDiaryOverviewRecyclerview.adapter = adapter + + contactDiaryOverviewHeader.contactDiaryHeaderButtonBack.buttonIcon.setOnClickListener { + vm.onBackButtonPress() + } + } + + vm.listItems.observe2(this) { + adapter.setItems(it) + } + + vm.routeToScreen.observe2(this) { + when (it) { + ContactDiaryOverviewNavigationEvents.NavigateToMainActivity -> { + requireActivity().finish() + } + + is ContactDiaryOverviewNavigationEvents.NavigateToContactDiaryDayFragment -> { + // TODO(Really navigate to ContactDiaryDayFragment once it is merged) + Toast.makeText( + requireContext(), + "Navigate to ContactDiaryDayFragment with date ${it.localDateString}", + Toast.LENGTH_SHORT + ).show() + } + } + } + } + + private fun setupToolbar() { + + binding.contactDiaryOverviewHeader.contactDiaryHeaderOptionsMenu.buttonIcon.apply { + contentDescription = getString(R.string.button_menu) + setOnClickListener { contactDiaryOverviewMenu.showMenuFor(it) } + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragmentModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragmentModule.kt new file mode 100644 index 000000000..23c65456c --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewFragmentModule.kt @@ -0,0 +1,23 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview + +import dagger.Binds +import dagger.Module +import dagger.android.ContributesAndroidInjector +import dagger.multibindings.IntoMap +import de.rki.coronawarnapp.util.viewmodel.CWAViewModel +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelKey + +@Module +abstract class ContactDiaryOverviewFragmentModule { + + @Binds + @IntoMap + @CWAViewModelKey(ContactDiaryOverviewViewModel::class) + abstract fun contactDiaryOverviewFragmentVM( + factory: ContactDiaryOverviewViewModel.Factory + ): CWAViewModelFactory<out CWAViewModel> + + @ContributesAndroidInjector + abstract fun contactDiaryOverviewFragmentVM(): ContactDiaryOverviewFragment +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewMenu.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewMenu.kt new file mode 100644 index 000000000..e3827f479 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewMenu.kt @@ -0,0 +1,31 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview + +import android.content.Context +import android.view.View +import android.widget.PopupMenu +import androidx.navigation.NavController +import androidx.navigation.fragment.findNavController +import de.rki.coronawarnapp.R +import javax.inject.Inject + +class ContactDiaryOverviewMenu @Inject constructor( + private val contactDiaryOverviewFragment: ContactDiaryOverviewFragment +) { + private val context: Context = contactDiaryOverviewFragment.requireContext() + + private val navController: NavController + get() = contactDiaryOverviewFragment.findNavController() + + fun showMenuFor(view: View) = PopupMenu(context, view).apply { + inflate(R.menu.menu_contact_diary_overview) + setOnMenuItemClickListener { + when (it.itemId) { + R.id.menu_contact_diary_information -> { true } + R.id.menu_contact_diary_export_entries -> { true } + R.id.menu_contact_diary_edit_persons -> { true } + R.id.menu_contact_diary_edit_locations -> { true } + else -> contactDiaryOverviewFragment.onOptionsItemSelected(it) + } + } + }.show() +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewNavigationEvents.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewNavigationEvents.kt new file mode 100644 index 000000000..dc5c1b920 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewNavigationEvents.kt @@ -0,0 +1,11 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview + +import org.joda.time.LocalDate + +sealed class ContactDiaryOverviewNavigationEvents { + + object NavigateToMainActivity : ContactDiaryOverviewNavigationEvents() + class NavigateToContactDiaryDayFragment(localDate: LocalDate) : ContactDiaryOverviewNavigationEvents() { + val localDateString = localDate.toString() + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt new file mode 100644 index 000000000..6040579a7 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/ContactDiaryOverviewViewModel.kt @@ -0,0 +1,96 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview + +import androidx.lifecycle.asLiveData +import com.squareup.inject.assisted.AssistedInject +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.contactdiary.model.ContactDiaryLocationVisit +import de.rki.coronawarnapp.contactdiary.model.ContactDiaryPersonEncounter +import de.rki.coronawarnapp.contactdiary.storage.repo.ContactDiaryRepository +import de.rki.coronawarnapp.contactdiary.ui.overview.adapter.ListItem +import de.rki.coronawarnapp.ui.SingleLiveEvent +import de.rki.coronawarnapp.util.viewmodel.CWAViewModel +import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flowOf +import org.joda.time.LocalDate +import timber.log.Timber + +class ContactDiaryOverviewViewModel @AssistedInject constructor( + contactDiaryRepository: ContactDiaryRepository +) : CWAViewModel() { + + val routeToScreen: SingleLiveEvent<ContactDiaryOverviewNavigationEvents> = SingleLiveEvent() + + private val dates = flowOf((0 until DAY_COUNT).map { LocalDate.now().minusDays(it) }) + + val listItems = combine( + dates, + contactDiaryRepository.locationVisits, + contactDiaryRepository.personEncounters + ) { dateList, locationVisitList, personEncounterList -> + createListItemList(dateList, locationVisitList, personEncounterList) + }.asLiveData() + + private fun createListItemList( + dateList: List<LocalDate>, + locationVisitList: List<ContactDiaryLocationVisit>, + personEncounterList: List<ContactDiaryPersonEncounter> + ): List<ListItem> { + Timber.v( + "createListItemList(dateList=$dateList, " + + "locationVisitList=$locationVisitList, " + + "personEncounterList=$personEncounterList)" + ) + return dateList + .map { + ListItem(it) + .apply { + data.addPersonEncountersForDate(personEncounterList, date) + data.addLocationVisitsForDate(locationVisitList, date) + } + } + } + + private fun MutableList<ListItem.Data>.addPersonEncountersForDate( + personEncounterList: List<ContactDiaryPersonEncounter>, + date: LocalDate + ) { + this += personEncounterList + .filter { personEncounter -> personEncounter.date == date } + .map { personEncounter -> + ListItem.Data( + R.drawable.ic_contact_diary_person, + personEncounter.contactDiaryPerson.fullName + ) + } + } + + private fun MutableList<ListItem.Data>.addLocationVisitsForDate( + locationVisitList: List<ContactDiaryLocationVisit>, + date: LocalDate + ) { + this += locationVisitList + .filter { locationVisit -> locationVisit.date == date } + .map { locationVisit -> + ListItem.Data( + R.drawable.ic_contact_diary_location, + locationVisit.contactDiaryLocation.locationName + ) + } + } + + fun onBackButtonPress() { + routeToScreen.postValue(ContactDiaryOverviewNavigationEvents.NavigateToMainActivity) + } + + fun onItemPress(listItem: ListItem) { + routeToScreen.postValue(ContactDiaryOverviewNavigationEvents.NavigateToContactDiaryDayFragment(listItem.date)) + } + + @AssistedInject.Factory + interface Factory : SimpleCWAViewModelFactory<ContactDiaryOverviewViewModel> + + companion object { + const val DAY_COUNT = 14 + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt new file mode 100644 index 000000000..bd54f8b70 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewAdapter.kt @@ -0,0 +1,63 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import de.rki.coronawarnapp.databinding.IncludeContactDiaryOverviewItemBinding +import java.util.Locale + +class ContactDiaryOverviewAdapter(private val onItemSelectionListener: (ListItem) -> Unit) : + RecyclerView.Adapter<ContactDiaryOverviewAdapter.OverviewElementHolder>() { + private val elements: MutableList<ListItem> = mutableListOf() + + fun setItems(elements: List<ListItem>) { + this.elements.clear() + this.elements += elements + notifyDataSetChanged() + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): OverviewElementHolder { + val inflater = LayoutInflater.from(parent.context) + return OverviewElementHolder( + IncludeContactDiaryOverviewItemBinding.inflate( + inflater, + parent, + false + ) + ) + } + + override fun getItemCount() = elements.size + + override fun onBindViewHolder(holder: OverviewElementHolder, position: Int) { + holder.bind(elements[position], onItemSelectionListener) + } + + class OverviewElementHolder(private val viewDataBinding: IncludeContactDiaryOverviewItemBinding) : + RecyclerView.ViewHolder(viewDataBinding.root) { + private val nestedItemAdapter = ContactDiaryOverviewNestedAdapter() + + init { + viewDataBinding.contactDiaryOverviewNestedRecyclerView.adapter = nestedItemAdapter + } + + fun bind( + item: ListItem, + onElementSelectionListener: (ListItem) -> Unit + ) { + viewDataBinding.contactDiaryOverviewElementName.text = + item.date.toString("EEEE, dd.MM.yyyy", Locale.getDefault()) + + viewDataBinding.contactDiaryOverviewElementBody.setOnClickListener { onElementSelectionListener(item) } + + if (item.data.isNotEmpty()) { + viewDataBinding.contactDiaryOverviewElementDivider.visibility = View.VISIBLE + } else { + viewDataBinding.contactDiaryOverviewElementDivider.visibility = View.INVISIBLE + } + + nestedItemAdapter.setItems(item.data) + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt new file mode 100644 index 000000000..a1f06fe61 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ContactDiaryOverviewNestedAdapter.kt @@ -0,0 +1,37 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import de.rki.coronawarnapp.databinding.IncludeContactDiaryOverviewNestedItemBinding + +class ContactDiaryOverviewNestedAdapter : + RecyclerView.Adapter<ContactDiaryOverviewNestedAdapter.NestedItemViewHolder>() { + + private val dataList: MutableList<ListItem.Data> = mutableListOf() + + fun setItems(dataList: List<ListItem.Data>) { + this.dataList.clear() + this.dataList += dataList + notifyDataSetChanged() + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NestedItemViewHolder { + val inflater = LayoutInflater.from(parent.context) + return NestedItemViewHolder(IncludeContactDiaryOverviewNestedItemBinding.inflate(inflater, parent, false)) + } + + override fun onBindViewHolder(holder: NestedItemViewHolder, position: Int) { + holder.bind(dataList[position]) + } + + override fun getItemCount(): Int = dataList.size + + class NestedItemViewHolder(private val viewBinding: IncludeContactDiaryOverviewNestedItemBinding) : + RecyclerView.ViewHolder(viewBinding.root) { + fun bind(data: ListItem.Data) { + viewBinding.contactDiaryOverviewElementImage.setImageResource(data.drawableId) + viewBinding.contactDiaryOverviewElementName.text = data.text + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ListItem.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ListItem.kt new file mode 100644 index 000000000..34e64afb2 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/contactdiary/ui/overview/adapter/ListItem.kt @@ -0,0 +1,14 @@ +package de.rki.coronawarnapp.contactdiary.ui.overview.adapter + +import org.joda.time.LocalDate + +data class ListItem( + val date: LocalDate +) { + val data: MutableList<Data> = mutableListOf() + + data class Data( + val drawableId: Int, + val text: String + ) +} diff --git a/Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_location_item.xml b/Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_location_item.xml new file mode 100644 index 000000000..b28a0bf0f --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_location_item.xml @@ -0,0 +1,12 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="40dp" + android:height="40dp" + android:viewportWidth="40" + android:viewportHeight="40"> + <path + android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0" + android:fillColor="#434445"/> + <path + android:pathData="M20,10C16.13,10 13,13.13 13,17C13,22.25 20,30 20,30C20,30 27,22.25 27,17C27,13.13 23.87,10 20,10ZM20,19.5C18.62,19.5 17.5,18.38 17.5,17C17.5,15.62 18.62,14.5 20,14.5C21.38,14.5 22.5,15.62 22.5,17C22.5,18.38 21.38,19.5 20,19.5Z" + android:fillColor="#83D2F2"/> +</vector> diff --git a/Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_person_item.xml b/Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_person_item.xml new file mode 100644 index 000000000..6b5071820 --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_person_item.xml @@ -0,0 +1,12 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="40dp" + android:height="40dp" + android:viewportWidth="40" + android:viewportHeight="40"> + <path + android:pathData="M20,20m-20,0a20,20 0,1 1,40 0a20,20 0,1 1,-40 0" + android:fillColor="#434445"/> + <path + android:pathData="M20,20C22.21,20 24,18.21 24,16C24,13.79 22.21,12 20,12C17.79,12 16,13.79 16,16C16,18.21 17.79,20 20,20ZM20,22C17.33,22 12,23.34 12,26V28H28V26C28,23.34 22.67,22 20,22Z" + android:fillColor="#83D2F2"/> +</vector> diff --git a/Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_right_arrow.xml b/Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_right_arrow.xml new file mode 100644 index 000000000..ba5299266 --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable-night/ic_contact_diary_right_arrow.xml @@ -0,0 +1,10 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="18dp" + android:height="14dp" + android:viewportWidth="18" + android:viewportHeight="14"> + <path + android:pathData="M10.4356,0L9.0126,1.4851L13.3484,6.0099H0.0002V7.99H13.3484L9.0126,12.5149L10.4356,14L17.1431,7L10.4356,0Z" + android:fillColor="#A7A7A7" + android:fillType="evenOdd"/> +</vector> diff --git a/Corona-Warn-App/src/main/res/drawable/ic_contact_diary_location_item.xml b/Corona-Warn-App/src/main/res/drawable/ic_contact_diary_location_item.xml new file mode 100644 index 000000000..c92cf57c2 --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable/ic_contact_diary_location_item.xml @@ -0,0 +1,12 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportWidth="32" + android:viewportHeight="32"> + <path + android:pathData="M16,16m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0" + android:fillColor="#ffffff"/> + <path + android:pathData="M16,6C12.13,6 9,9.13 9,13C9,18.25 16,26 16,26C16,26 23,18.25 23,13C23,9.13 19.87,6 16,6ZM16,15.5C14.62,15.5 13.5,14.38 13.5,13C13.5,11.62 14.62,10.5 16,10.5C17.38,10.5 18.5,11.62 18.5,13C18.5,14.38 17.38,15.5 16,15.5Z" + android:fillColor="#007FAD"/> +</vector> diff --git a/Corona-Warn-App/src/main/res/drawable/ic_contact_diary_person_item.xml b/Corona-Warn-App/src/main/res/drawable/ic_contact_diary_person_item.xml new file mode 100644 index 000000000..79ca9aaf2 --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable/ic_contact_diary_person_item.xml @@ -0,0 +1,12 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="32dp" + android:height="32dp" + android:viewportWidth="32" + android:viewportHeight="32"> + <path + android:pathData="M16,16m-16,0a16,16 0,1 1,32 0a16,16 0,1 1,-32 0" + android:fillColor="#ffffff"/> + <path + android:pathData="M16,16C18.21,16 20,14.21 20,12C20,9.79 18.21,8 16,8C13.79,8 12,9.79 12,12C12,14.21 13.79,16 16,16ZM16,18C13.33,18 8,19.34 8,22V24H24V22C24,19.34 18.67,18 16,18Z" + android:fillColor="#007FAD"/> +</vector> diff --git a/Corona-Warn-App/src/main/res/drawable/ic_contact_diary_right_arrow.xml b/Corona-Warn-App/src/main/res/drawable/ic_contact_diary_right_arrow.xml new file mode 100644 index 000000000..a763aa41e --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable/ic_contact_diary_right_arrow.xml @@ -0,0 +1,11 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="18dp" + android:height="14dp" + android:viewportWidth="18" + android:viewportHeight="14"> + <path + android:pathData="M10.9572,0L9.463,1.4851L14.0156,6.0099H0V7.99H14.0156L9.463,12.5149L10.9572,14L18,7L10.9572,0Z" + android:fillColor="#17191A" + android:fillAlpha="0.6" + android:fillType="evenOdd"/> +</vector> diff --git a/Corona-Warn-App/src/main/res/layout/contact_diary_overview_fragment.xml b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_fragment.xml new file mode 100644 index 000000000..1f84b76c9 --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/contact_diary_overview_fragment.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="utf-8"?> +<layout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <include + android:id="@+id/contact_diary_overview_header" + layout="@layout/include_contact_diary_overview_header" + android:layout_width="@dimen/match_constraint" + android:layout_height="wrap_content" + app:icon="@{@drawable/ic_back}" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:title="@{@string/contact_diary_overview_header}" /> + + + <TextView + android:id="@+id/onboarding_headline" + style="@style/headline6" + android:layout_marginTop="@dimen/spacing_tiny" + android:layout_width="@dimen/match_constraint" + android:layout_height="wrap_content" + android:accessibilityHeading="true" + android:focusable="true" + android:text="@string/contact_diary_overview_title" + app:layout_constraintEnd_toStartOf="@+id/guideline_end" + app:layout_constraintStart_toStartOf="@+id/guideline_start" + app:layout_constraintTop_toBottomOf="@+id/contact_diary_overview_header" + tools:text="Kontakt-Tagebuch" /> + + + <TextView + android:id="@+id/contact_diary_overview_subtitle" + style="@style/subtitleMedium" + android:layout_width="@dimen/match_constraint" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_small" + android:focusable="true" + android:text="@string/contact_diary_overview_subtitle" + app:layout_constraintEnd_toEndOf="@id/guideline_end" + app:layout_constraintStart_toStartOf="@id/guideline_start" + app:layout_constraintTop_toBottomOf="@+id/onboarding_headline" + tools:text="Tragen Sie ein, mit wem Sie sich getroffen haben und wo Sie gewesen sind." /> + + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/contact_diary_overview_recyclerview" + android:layout_width="@dimen/match_constraint" + android:layout_height="@dimen/match_constraint" + android:layout_marginHorizontal="@dimen/spacing_mega_tiny" + android:layout_marginTop="@dimen/spacing_small" + android:layout_marginBottom="@dimen/spacing_mega_tiny" + android:background="@color/colorSurface1" + android:scrollbars="vertical" + android:scrollbarSize="@dimen/spacing_mega_tiny" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="@id/guideline_end" + app:layout_constraintStart_toStartOf="@+id/guideline_start" + app:layout_constraintTop_toBottomOf="@+id/contact_diary_overview_subtitle" + app:layout_constraintVertical_bias="0.0" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + tools:listitem="@layout/include_contact_diary_overview_item" /> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_start" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + app:layout_constraintGuide_begin="@dimen/guideline_start" /> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_end" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + app:layout_constraintGuide_end="@dimen/guideline_end" /> + + </androidx.constraintlayout.widget.ConstraintLayout> + +</layout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_header.xml b/Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_header.xml new file mode 100644 index 000000000..b748919f8 --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_header.xml @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="utf-8"?> +<layout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools"> + + <data> + + <variable + name="icon" + type="android.graphics.drawable.Drawable" /> + + <variable + name="title" + type="String" /> + </data> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:layout_height="@dimen/header_main" + android:id="@+id/contact_diary_header" + android:paddingTop="@dimen/spacing_tiny" + android:paddingBottom="@dimen/spacing_tiny"> + + <include + android:id="@+id/contact_diary_header_button_back" + layout="@layout/include_button_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + app:icon="@{icon}" + app:iconDescription="@{@string/accessibility_back}" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="@id/guideline_back" + app:layout_constraintTop_toTopOf="parent" /> + + <TextView + android:id="@+id/contact_diary_header_title" + style="@style/headline6" + android:layout_width="@dimen/match_constraint" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/guideline_body_title" + android:accessibilityHeading="true" + android:text="@{title}" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@+id/contact_diary_header_options_menu" + app:layout_constraintStart_toStartOf="@id/guideline_start" + app:layout_constraintTop_toTopOf="parent" + tools:text="@string/settings_title" /> + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_start" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + app:layout_constraintGuide_begin="@dimen/guideline_start" /> + + + <androidx.constraintlayout.widget.Guideline + android:id="@+id/guideline_back" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical" + app:layout_constraintGuide_begin="@dimen/guideline_back" /> + + <include + android:id="@+id/contact_diary_header_options_menu" + layout="@layout/include_button_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginEnd="@dimen/spacing_small" + android:focusable="true" + app:icon="@{@drawable/ic_main_settings}" + app:iconDescription="@{@string/button_menu}" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + </androidx.constraintlayout.widget.ConstraintLayout> +</layout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_item.xml b/Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_item.xml new file mode 100644 index 000000000..2c3efdd8b --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_item.xml @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="utf-8"?> +<layout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/contact_diary_overview_element_body" + style="@style/cardGrey" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_mega_tiny" + android:layout_marginBottom="@dimen/spacing_mega_tiny" + android:focusable="true"> + + <TextView + android:id="@+id/contact_diary_overview_element_name" + style="@style/contactDiaryListItem" + android:layout_width="@dimen/match_constraint" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/spacing_small" + android:focusable="true" + android:text="Donnerstag, 01.12.2020" + app:layout_constraintBottom_toTopOf="@id/contact_diary_overview_element_divider" + app:layout_constraintEnd_toStartOf="@+id/contact_diary_overview_element_right_arrow" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <ImageView + android:id="@+id/contact_diary_overview_element_right_arrow" + android:layout_width="@dimen/match_constraint" + android:layout_height="wrap_content" + android:layout_marginVertical="@dimen/spacing_tiny" + android:layout_marginEnd="@dimen/spacing_small" + android:importantForAccessibility="no" + android:scaleType="centerInside" + android:src="@drawable/ic_contact_diary_right_arrow" + app:layout_constraintBottom_toTopOf="@id/contact_diary_overview_element_divider" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <View + android:id="@+id/contact_diary_overview_element_divider" + android:layout_width="match_parent" + android:layout_height="@dimen/card_divider" + android:background="?android:attr/listDivider" + android:layout_marginTop="@dimen/contact_diary_list_item" + app:layout_constraintTop_toTopOf="parent"/> + + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/contact_diary_overview_nested_recycler_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:nestedScrollingEnabled="false" + app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toBottomOf="@id/contact_diary_overview_element_divider"/> + + </androidx.constraintlayout.widget.ConstraintLayout> + +</layout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_nested_item.xml b/Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_nested_item.xml new file mode 100644 index 000000000..3bdcce318 --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/include_contact_diary_overview_nested_item.xml @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="utf-8"?> +<layout xmlns:tools="http://schemas.android.com/tools" + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/contact_diary_overview_element_nested_body" + style="@style/cardGrey" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:focusable="true" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> + + <ImageView + android:id="@+id/contact_diary_overview_element_image" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginVertical="@dimen/spacing_tiny" + android:layout_marginStart="@dimen/spacing_small" + android:importantForAccessibility="no" + android:scaleType="centerInside" + android:src="@drawable/ic_contact_diary_person_item" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <TextView + android:id="@+id/contact_diary_overview_element_name" + style="@style/headline5" + android:layout_width="@dimen/match_constraint" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/spacing_small" + android:focusable="true" + android:text="Andrea Steinhauer" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@+id/contact_diary_overview_element_image" + app:layout_constraintTop_toTopOf="parent" /> + + + </androidx.constraintlayout.widget.ConstraintLayout> + +</layout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/menu/menu_contact_diary_overview.xml b/Corona-Warn-App/src/main/res/menu/menu_contact_diary_overview.xml new file mode 100644 index 000000000..25bde48e7 --- /dev/null +++ b/Corona-Warn-App/src/main/res/menu/menu_contact_diary_overview.xml @@ -0,0 +1,15 @@ +<menu xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools"> + <item + android:id="@+id/menu_contact_diary_information" + android:title="@string/menu_contact_diary_information" /> + <item + android:id="@+id/menu_contact_diary_export_entries" + android:title="@string/menu_contact_export_entries" /> + <item + android:id="@+id/menu_contact_diary_edit_persons" + android:title="@string/menu_contact_diary_edit_persons" /> + <item + android:id="@+id/menu_contact_diary_edit_locations" + android:title="@string/menu_contact_diary_edit_locations" /> +</menu> diff --git a/Corona-Warn-App/src/main/res/navigation/contact_diary_nav_graph.xml b/Corona-Warn-App/src/main/res/navigation/contact_diary_nav_graph.xml index ae8e26f5d..80999eff0 100644 --- a/Corona-Warn-App/src/main/res/navigation/contact_diary_nav_graph.xml +++ b/Corona-Warn-App/src/main/res/navigation/contact_diary_nav_graph.xml @@ -1,6 +1,7 @@ <?xml version="1.0" encoding="utf-8"?> <navigation xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" android:id="@+id/contact_diary_nav_graph" app:startDestination="@id/contactDiaryOnboardingFragment"> <fragment @@ -10,9 +11,17 @@ <action android:id="@+id/action_contactDiaryOnboardingFragment_to_contactDiaryInformationPrivacyFragment" app:destination="@id/contactDiaryInformationPrivacyFragment" /> + <action + android:id="@+id/action_contactDiaryOnboardingFragment_to_contactDiaryOverviewFragment" + app:destination="@id/contactDiaryOverviewFragment" /> </fragment> <fragment android:id="@+id/contactDiaryInformationPrivacyFragment" android:name="de.rki.coronawarnapp.ui.information.InformationPrivacyFragment" android:label="InformationPrivacyFragment" /> + <fragment + android:id="@+id/contactDiaryOverviewFragment" + android:name="de.rki.coronawarnapp.contactdiary.ui.overview.ContactDiaryOverviewFragment" + android:label="contact_diary_overview_fragment" + tools:layout="@layout/contact_diary_overview_fragment" /> </navigation> diff --git a/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml index d7d239cc4..1124c81da 100644 --- a/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/contact_diary_strings.xml @@ -60,4 +60,19 @@ <!-- XTXT: Title for legal information of the contact diary onboarding screen --> <string name="contact_diary_onboarding_privacy_information_title">Datenschutz und Datensicherheit</string> + <!-- XTXT: Menu information entry for contact diary overview screen --> + <string name="menu_contact_diary_information">Information</string> + <!-- XTXT: Menu export entry for contact diary overview screen --> + <string name="menu_contact_export_entries">Einträge exportieren</string> + <!-- XTXT: Menu edit persons entry for contact diary overview screen --> + <string name="menu_contact_diary_edit_persons">Personen bearbeiten</string> + <!-- XTXT: Menu edit locations entry for contact diary overview screen --> + <string name="menu_contact_diary_edit_locations">Orte bearbeiten</string> + <!-- XTXT: Title for contact diary overview screen --> + <string name="contact_diary_overview_title">Kontakt-Tagebuch</string> + <!-- XTXT: Subtitle for contact diary overview screen --> + <string name="contact_diary_overview_subtitle">Tragen Sie ein, mit wem Sie sich getroffen haben und wo Sie gewesen sind.</string> + <!-- XTXT: Header for contact diary overview screen --> + <string name="contact_diary_overview_header">Startseite</string> + </resources> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml b/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml index 1bd726524..31d261f1c 100644 --- a/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml +++ b/Corona-Warn-App/src/main/res/values/contact_diary_strings.xml @@ -59,4 +59,19 @@ <!-- XTXT: Title for legal information of the contact diary onboarding screen --> <string name="contact_diary_onboarding_privacy_information_title"/> + <!-- XTXT: Menu information entry for contact diary overview screen --> + <string name="menu_contact_diary_information"/> + <!-- XTXT: Menu export entry for contact diary overview screen --> + <string name="menu_contact_export_entries"/> + <!-- XTXT: Menu edit persons entry for contact diary overview screen --> + <string name="menu_contact_diary_edit_persons"/> + <!-- XTXT: Menu edit locations entry for contact diary overview screen --> + <string name="menu_contact_diary_edit_locations"/> + <!-- XTXT: Title for contact diary overview screen --> + <string name="contact_diary_overview_title"/> + <!-- XTXT: Subtitle for contact diary overview screen --> + <string name="contact_diary_overview_subtitle"/> + <!-- XTXT: Header for contact diary overview screen --> + <string name="contact_diary_overview_header"/> + </resources> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/values/dimens.xml b/Corona-Warn-App/src/main/res/values/dimens.xml index 931435ba6..2b9975b56 100644 --- a/Corona-Warn-App/src/main/res/values/dimens.xml +++ b/Corona-Warn-App/src/main/res/values/dimens.xml @@ -136,4 +136,7 @@ <dimen name="calendar_layout_stroke">2dp</dimen> <dimen name="calendar_day_size">40dp</dimen> <dimen name="calendar_day_spacing">4dp</dimen> + + <!-- Contact Diary --> + <dimen name="contact_diary_list_item">65dp</dimen> </resources> diff --git a/Corona-Warn-App/src/main/res/values/styles.xml b/Corona-Warn-App/src/main/res/values/styles.xml index fb0b8a3a4..f52ee4665 100644 --- a/Corona-Warn-App/src/main/res/values/styles.xml +++ b/Corona-Warn-App/src/main/res/values/styles.xml @@ -318,4 +318,13 @@ <item name="android:fontFamily">sans-serif-black</item> <item name="android:letterSpacing">2</item> </style> + + <!-- #################################### + Contact Diary + ###################################### --> + <style name="contactDiaryListItem" parent="@style/TextAppearance.MaterialComponents.Subtitle1"> + <item name="android:textColor">@color/colorTextPrimary1</item> + <item name="android:textStyle">bold</item> + </style> + </resources> -- GitLab