diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaOnboardingFragmentViewModel.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaOnboardingFragmentViewModel.kt index 49daaf6fa2da7d161058154d3607cca0196ca57c..9152f953ae3a51042e5a7e816e5a0f5998b3dc6b 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaOnboardingFragmentViewModel.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaOnboardingFragmentViewModel.kt @@ -6,6 +6,7 @@ import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject import de.rki.coronawarnapp.contactdiary.ui.ContactDiarySettings import de.rki.coronawarnapp.environment.BuildConfigWrap +import de.rki.coronawarnapp.eventregistration.TraceLocationSettings import de.rki.coronawarnapp.main.CWASettings import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.viewmodel.CWAViewModel @@ -13,6 +14,7 @@ import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory class DeltaOnboardingFragmentViewModel @AssistedInject constructor( private val settings: CWASettings, + private val traceLocationSettings: TraceLocationSettings, private val contactDiarySettings: ContactDiarySettings, dispatcherProvider: DispatcherProvider ) : CWAViewModel(dispatcherProvider = dispatcherProvider) { @@ -43,10 +45,21 @@ class DeltaOnboardingFragmentViewModel @AssistedInject constructor( fun isDeltaOnboardingDone() = settings.wasInteroperabilityShownAtLeastOnce - fun setDeltaOboardinDone(value: Boolean) { + fun setDeltaOnboardingDone(value: Boolean) { settings.wasInteroperabilityShownAtLeastOnce = value } + fun isAttendeeOnboardingDone() = + traceLocationSettings.onboardingStatus == TraceLocationSettings.OnboardingStatus.ONBOARDED_2_0 + + fun setAttendeeOnboardingDone(value: Boolean) { + traceLocationSettings.onboardingStatus = + if (value) + TraceLocationSettings.OnboardingStatus.ONBOARDED_2_0 + else + TraceLocationSettings.OnboardingStatus.NOT_ONBOARDED + } + @AssistedFactory interface Factory : SimpleCWAViewModelFactory<DeltaOnboardingFragmentViewModel> } diff --git a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaonboardingFragment.kt b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaonboardingFragment.kt index 1179e8e0701823179fafe78cb56af5e5dc210d98..1308cff1b13d6ab80567562b9d346df0fb14a5d2 100644 --- a/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaonboardingFragment.kt +++ b/Corona-Warn-App/src/deviceForTesters/java/de/rki/coronawarnapp/test/deltaonboarding/ui/DeltaonboardingFragment.kt @@ -26,6 +26,7 @@ class DeltaonboardingFragment : Fragment(R.layout.fragment_test_deltaonboarding) binding.switchContactJournalOnboarding.isChecked = viewModel.isContactJournalOnboardingDone() binding.switchDeltaOnboarding.isChecked = viewModel.isDeltaOnboardingDone() + binding.switchAttendeeOnboarding.isChecked = viewModel.isAttendeeOnboardingDone() viewModel.changelogVersion.observe(viewLifecycleOwner) { binding.lastChangelogEdittext.setText(it.toString()) } @@ -48,7 +49,11 @@ class DeltaonboardingFragment : Fragment(R.layout.fragment_test_deltaonboarding) } binding.switchDeltaOnboarding.setOnCheckedChangeListener { _, value -> - viewModel.setDeltaOboardinDone(value) + viewModel.setDeltaOnboardingDone(value) + } + + binding.switchAttendeeOnboarding.setOnCheckedChangeListener { _, value -> + viewModel.setAttendeeOnboardingDone(value) } } diff --git a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_deltaonboarding.xml b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_deltaonboarding.xml index 374995566303f641149887fb280e156f3eec5f80..b1305ae31eaabe74c88dd174a649dcb4787db6be 100644 --- a/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_deltaonboarding.xml +++ b/Corona-Warn-App/src/deviceForTesters/res/layout/fragment_test_deltaonboarding.xml @@ -146,5 +146,32 @@ </androidx.constraintlayout.widget.ConstraintLayout> + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/debug_container4" + style="@style/Card" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="@dimen/spacing_tiny"> + + <TextView + android:id="@+id/event_creation_title" + style="@style/headline6" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="Event Creation Onboarding" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <com.google.android.material.switchmaterial.SwitchMaterial + android:id="@+id/switch_attendee_onboarding" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_small" + android:text="Attendee onboarding finished" + app:layout_constraintTop_toBottomOf="@id/event_creation_title" /> + + </androidx.constraintlayout.widget.ConstraintLayout> + </LinearLayout> </androidx.core.widget.NestedScrollView> diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/onboarding/CheckInOnboardingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/onboarding/CheckInOnboardingFragment.kt index c66e18b87292ea60bd1ecf994c8588fe33770faf..3f00d809e243df58aa8b1fe5ad32a8095b834d35 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/onboarding/CheckInOnboardingFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/attendee/onboarding/CheckInOnboardingFragment.kt @@ -26,6 +26,10 @@ class CheckInOnboardingFragment : Fragment(R.layout.fragment_trace_location_onbo override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + if (viewModel.isOnboardingComplete && args.uri != null) { + doNavigate(CheckInOnboardingFragmentDirections.actionCheckInOnboardingFragmentToCheckInsFragment(args.uri)) + } + with(binding) { checkInOnboardingAcknowledge.setOnClickListener { viewModel.onAcknowledged() } // TODO if consent is already given: should the text be changed? @@ -45,7 +49,7 @@ class CheckInOnboardingFragment : Fragment(R.layout.fragment_trace_location_onbo doNavigate( when (navEvent) { CheckInOnboardingNavigation.AcknowledgedNavigation -> - CheckInOnboardingFragmentDirections.actionCheckInOnboardingFragmentToCheckInsFragment() + CheckInOnboardingFragmentDirections.actionCheckInOnboardingFragmentToCheckInsFragment(args.uri) CheckInOnboardingNavigation.DataProtectionNavigation -> CheckInOnboardingFragmentDirections.actionCheckInOnboardingFragmentToPrivacyFragment() } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationEvent.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationEvent.kt index 5909c982933269feaeeb47a6fa3d1f3aebc0e2f8..a4576f0ae318ae641605d530e667d128c0bae926 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationEvent.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationEvent.kt @@ -6,6 +6,8 @@ sealed class TraceLocationEvent { data class DuplicateItem(val traceLocation: TraceLocation) : TraceLocationEvent() + data class SelfCheckIn(val traceLocation: TraceLocation) : TraceLocationEvent() + data class ConfirmDeleteItem(val traceLocation: TraceLocation) : TraceLocationEvent() data class ConfirmSwipeItem(val traceLocation: TraceLocation, val position: Int) : TraceLocationEvent() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationsFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationsFragment.kt index 1847e8f7b3912ec7198198b0986705753f2e1952..35ad5d4c44c50f69776a334383dd10979ef9767b 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationsFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationsFragment.kt @@ -7,12 +7,14 @@ import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.Toolbar import androidx.core.view.isGone import androidx.fragment.app.Fragment +import androidx.navigation.NavOptions import androidx.navigation.fragment.FragmentNavigatorExtras import androidx.navigation.fragment.findNavController import com.google.android.material.transition.Hold import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.TraceLocationOrganizerTraceLocationsListFragmentBinding import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation +import de.rki.coronawarnapp.ui.eventregistration.attendee.checkins.CheckInsFragment import de.rki.coronawarnapp.ui.eventregistration.organizer.category.adapter.category.traceLocationCategories import de.rki.coronawarnapp.ui.eventregistration.organizer.details.QrCodeDetailFragmentArgs import de.rki.coronawarnapp.util.DialogHelper @@ -105,6 +107,14 @@ class TraceLocationsFragment : Fragment(R.layout.trace_location_organizer_trace_ it.traceLocation.id ) ) + is TraceLocationEvent.SelfCheckIn -> { + findNavController().navigate( + CheckInsFragment.createCheckInUri(it.traceLocation.locationUrl), + NavOptions.Builder() + .setPopUpTo(R.id.checkInsFragment, true) + .build() + ) + } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationsViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationsViewModel.kt index d4167ccd56634c989b0e015f00cffb71b9aeebaa..dbbb8ad2d0afa7bc77dbd49bcc04a4f20ff3b3aa 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationsViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/TraceLocationsViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.asLiveData import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import de.rki.coronawarnapp.eventregistration.checkins.CheckInRepository import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation import de.rki.coronawarnapp.eventregistration.storage.repo.TraceLocationRepository import de.rki.coronawarnapp.ui.eventregistration.organizer.list.items.TraceLocationItem @@ -13,10 +14,12 @@ import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.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.map class TraceLocationsViewModel @AssistedInject constructor( dispatcherProvider: DispatcherProvider, + checkInsRepository: CheckInRepository, private val traceLocationRepository: TraceLocationRepository, private val timeStamper: TimeStamper ) : CWAViewModel(dispatcherProvider = dispatcherProvider) { @@ -29,11 +32,20 @@ class TraceLocationsViewModel @AssistedInject constructor( .filter { it.endDate == null || it.endDate.isAfter(timeStamper.nowUTC.toDateTime().minusDays(15)) } .sortedBy { it.description } } - .map { traceLocations -> + .combine(checkInsRepository.allCheckIns) { traceLocations, checkIns -> traceLocations.map { traceLocation -> + Pair( + traceLocation, + checkIns.firstOrNull { traceLocation.locationId == it.traceLocationId && !it.completed } == null + ) + } + } + .map { traceLocations -> + traceLocations.map { item -> TraceLocationVH.Item( - traceLocation = traceLocation, - onCheckIn = { /* TODO */ }, + traceLocation = item.first, + canCheckIn = item.second, + onCheckIn = { events.postValue(TraceLocationEvent.SelfCheckIn(it)) }, onDuplicate = { events.postValue(TraceLocationEvent.DuplicateItem(it)) }, onShowPrint = { events.postValue(TraceLocationEvent.StartQrCodePosterFragment(it)) }, onDeleteItem = { events.postValue(TraceLocationEvent.ConfirmDeleteItem(it)) }, diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/items/TraceLocationVH.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/items/TraceLocationVH.kt index da8cca4747fd735671ea02fdfed288116addb87a..8756cf1d08e23e091547eae7a21ff7bfc623e21f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/items/TraceLocationVH.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/eventregistration/organizer/list/items/TraceLocationVH.kt @@ -2,6 +2,7 @@ package de.rki.coronawarnapp.ui.eventregistration.organizer.list.items import android.view.ViewGroup import androidx.core.view.isGone +import androidx.core.view.isVisible import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.TraceLocationOrganizerTraceLocationsItemBinding import de.rki.coronawarnapp.eventregistration.checkins.qrcode.TraceLocation @@ -62,12 +63,14 @@ class TraceLocationVH(parent: ViewGroup) : } } + checkinAction.isVisible = item.canCheckIn checkinAction.setOnClickListener { item.onCheckIn(item.traceLocation) } itemView.setOnClickListener { item.onCardClicked(item.traceLocation, adapterPosition) } } data class Item( val traceLocation: TraceLocation, + val canCheckIn: Boolean, val onCheckIn: (TraceLocation) -> Unit, val onDuplicate: (TraceLocation) -> Unit, val onShowPrint: (TraceLocation) -> Unit, diff --git a/Corona-Warn-App/src/main/res/layout/trace_location_organizer_trace_locations_item.xml b/Corona-Warn-App/src/main/res/layout/trace_location_organizer_trace_locations_item.xml index 8434f98f0f523dbcd52056d8547b74c966ebb31b..867ff02490673af3047ae14aa20c8ffb32a0de22 100644 --- a/Corona-Warn-App/src/main/res/layout/trace_location_organizer_trace_locations_item.xml +++ b/Corona-Warn-App/src/main/res/layout/trace_location_organizer_trace_locations_item.xml @@ -85,6 +85,11 @@ app:barrierDirection="bottom" app:constraint_referenced_ids="address,duration,icon" /> + <Space + android:layout_width="match_parent" + android:layout_height="16dp" + app:layout_constraintTop_toBottomOf="@id/button_barrier" /> + <com.google.android.material.button.MaterialButton android:id="@+id/checkin_action" style="@style/Widget.MaterialComponents.Button.OutlinedButton" diff --git a/Corona-Warn-App/src/main/res/navigation/trace_location_attendee_nav_graph.xml b/Corona-Warn-App/src/main/res/navigation/trace_location_attendee_nav_graph.xml index cb34d67595e1f9efb9d3d33b0cce121e8e26c77b..bbf7abe775c1afe85f8994a4eba64e519d054a59 100644 --- a/Corona-Warn-App/src/main/res/navigation/trace_location_attendee_nav_graph.xml +++ b/Corona-Warn-App/src/main/res/navigation/trace_location_attendee_nav_graph.xml @@ -9,6 +9,7 @@ android:name="de.rki.coronawarnapp.ui.eventregistration.attendee.onboarding.CheckInOnboardingFragment" android:label="CheckInOnboardingFragment" tools:layout="@layout/fragment_trace_location_onboarding"> + <deepLink app:uri="coronawarnapp://check-ins/{uri}" /> <action android:id="@+id/action_checkInOnboardingFragment_to_checkInsFragment" app:destination="@id/checkInsFragment" @@ -21,6 +22,11 @@ android:name="showBottomNav" android:defaultValue="true" app:argType="boolean" /> + <argument + android:name="uri" + android:defaultValue="@null" + app:argType="string" + app:nullable="true" /> </fragment> <fragment android:id="@+id/checkInPrivacyFragment" @@ -56,7 +62,6 @@ android:name="de.rki.coronawarnapp.ui.eventregistration.attendee.checkins.CheckInsFragment" android:label="CheckInsFragment" tools:layout="@layout/trace_location_attendee_checkins_fragment"> - <deepLink app:uri="coronawarnapp://check-ins/{uri}" /> <action android:id="@+id/action_checkInsFragment_to_scanCheckInQrCodeFragment" app:destination="@id/scanCheckInQrCodeFragment" />