From 5160407ee65239f32c0379d5921633b86a88e6a8 Mon Sep 17 00:00:00 2001 From: Gino Miceli Date: Sun, 22 Sep 2024 22:50:45 -0400 Subject: [PATCH 01/21] Get view model from parent fragment --- ground/src/main/AndroidManifest.xml | 13 +++++++----- .../common/AbstractMapFragmentWithControls.kt | 9 +++++++-- .../datacollection/DataCollectionFragment.kt | 2 +- .../DataCollectionViewPagerAdapter.kt | 10 +++++++--- .../tasks/polygon/DrawAreaTaskFragment.kt | 20 ++++++++++--------- .../tasks/polygon/DrawAreaTaskMapFragment.kt | 16 ++++++++------- .../ground/ui/map/gms/GoogleMapsFragment.kt | 1 + 7 files changed, 44 insertions(+), 27 deletions(-) diff --git a/ground/src/main/AndroidManifest.xml b/ground/src/main/AndroidManifest.xml index e267119d07..596ea09700 100644 --- a/ground/src/main/AndroidManifest.xml +++ b/ground/src/main/AndroidManifest.xml @@ -25,8 +25,13 @@ - - + + + @@ -84,8 +88,7 @@ - + tools:node="remove"> ) : - FragmentStateAdapter(fragment) { +constructor( + private val drawAreaTaskFragmentProvider: Provider, + @Assisted fragment: Fragment, + @Assisted val tasks: List, +) : FragmentStateAdapter(fragment) { override fun getItemCount(): Int = tasks.size override fun createFragment(position: Int): Fragment { @@ -48,7 +52,7 @@ constructor(@Assisted fragment: Fragment, @Assisted val tasks: List) : Task.Type.MULTIPLE_CHOICE -> MultipleChoiceTaskFragment() Task.Type.PHOTO -> PhotoTaskFragment() Task.Type.DROP_PIN -> DropPinTaskFragment() - Task.Type.DRAW_AREA -> DrawAreaTaskFragment() + Task.Type.DRAW_AREA -> drawAreaTaskFragmentProvider.get() Task.Type.NUMBER -> NumberTaskFragment() Task.Type.DATE -> DateTaskFragment() Task.Type.TIME -> TimeTaskFragment() diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt index 80452ee2fa..461644fae6 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt @@ -15,6 +15,7 @@ */ package com.google.android.ground.ui.datacollection.tasks.polygon +import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -33,24 +34,22 @@ import com.google.android.ground.ui.datacollection.components.TaskView import com.google.android.ground.ui.datacollection.components.TaskViewFactory import com.google.android.ground.ui.datacollection.tasks.AbstractTaskFragment import com.google.android.ground.ui.map.Feature -import com.google.android.ground.ui.map.MapFragment import com.google.android.ground.ui.theme.AppTheme import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject +import javax.inject.Provider import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch @AndroidEntryPoint -class DrawAreaTaskFragment : AbstractTaskFragment() { - - @Inject lateinit var map: MapFragment - +class DrawAreaTaskFragment @Inject constructor() : AbstractTaskFragment() { + @Inject lateinit var drawAreaTaskMapFragmentProvider: Provider // Action buttons private lateinit var completeButton: TaskButton private lateinit var addPointButton: TaskButton private lateinit var nextButton: TaskButton - private lateinit var drawAreaTaskMapFragment: DrawAreaTaskMapFragment + private lateinit var mapFragment: DrawAreaTaskMapFragment override fun onCreateTaskView(inflater: LayoutInflater): TaskView = TaskViewFactory.createWithCombinedHeader(inflater, R.drawable.outline_draw) @@ -59,10 +58,13 @@ class DrawAreaTaskFragment : AbstractTaskFragment() { // NOTE(#2493): Multiplying by a random prime to allow for some mathematical "uniqueness". // Otherwise, the sequentially generated ID might conflict with an ID produced by Google Maps. val rowLayout = LinearLayout(requireContext()).apply { id = View.generateViewId() * 11411 } - drawAreaTaskMapFragment = DrawAreaTaskMapFragment.newInstance(viewModel, map) + mapFragment = drawAreaTaskMapFragmentProvider.get() + val args = Bundle() + args.putString("taskId", taskId) + mapFragment.arguments = args parentFragmentManager .beginTransaction() - .add(rowLayout.id, drawAreaTaskMapFragment, DrawAreaTaskMapFragment::class.java.simpleName) + .add(rowLayout.id, mapFragment, DrawAreaTaskMapFragment::class.java.simpleName) .commit() return rowLayout } @@ -83,7 +85,7 @@ class DrawAreaTaskFragment : AbstractTaskFragment() { // Move the camera to the last vertex, if any. val lastVertex = viewModel.getLastVertex() ?: return - drawAreaTaskMapFragment.moveToPosition(lastVertex) + mapFragment.moveToPosition(lastVertex) } override fun onTaskViewAttached() { diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt index fa32c8c052..5048514c5a 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt @@ -19,26 +19,33 @@ import android.os.Bundle import androidx.lifecycle.lifecycleScope import com.google.android.ground.ui.common.AbstractMapFragmentWithControls import com.google.android.ground.ui.common.BaseMapViewModel +import com.google.android.ground.ui.datacollection.DataCollectionFragment import com.google.android.ground.ui.map.CameraPosition import com.google.android.ground.ui.map.Feature import com.google.android.ground.ui.map.MapFragment import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject import kotlinx.coroutines.launch @AndroidEntryPoint -class DrawAreaTaskMapFragment(private val viewModel: DrawAreaTaskViewModel) : - AbstractMapFragmentWithControls() { +class DrawAreaTaskMapFragment @Inject constructor() : AbstractMapFragmentWithControls() { private lateinit var mapViewModel: BaseMapViewModel + private lateinit var viewModel: DrawAreaTaskViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + mapViewModel = getViewModel(BaseMapViewModel::class.java) + val taskId = arguments?.getString("taskId") + val dcf = requireParentFragment() as DataCollectionFragment + viewModel = dcf.viewModel.getTaskViewModel(taskId!!) as DrawAreaTaskViewModel } override fun getMapViewModel(): BaseMapViewModel = mapViewModel override fun onMapReady(map: MapFragment) { + super.onMapReady(map) viewLifecycleOwner.lifecycleScope.launch { viewModel.draftArea.collect { feature: Feature? -> map.setFeatures(if (feature == null) setOf() else setOf(feature)) @@ -55,9 +62,4 @@ class DrawAreaTaskMapFragment(private val viewModel: DrawAreaTaskViewModel) : } } } - - companion object { - fun newInstance(viewModel: DrawAreaTaskViewModel, map: MapFragment) = - DrawAreaTaskMapFragment(viewModel).apply { this.map = map } - } } diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt index 73e027db41..e9d14bfdc1 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt @@ -160,6 +160,7 @@ class GoogleMapsFragment : SupportMapFragment(), MapFragment { private fun onMapReady(map: GoogleMap) { Timber.v("Map event: onMapReady()") + Timber.e("!!! onMapReady $this") this.map = map featureManager.onMapReady(map) From 50617dfb3a8ff5305f21addca0ae95893a2645ab Mon Sep 17 00:00:00 2001 From: Gino Miceli Date: Sun, 22 Sep 2024 22:55:22 -0400 Subject: [PATCH 02/21] Revert variable rename for cleaner diff --- .../tasks/polygon/DrawAreaTaskFragment.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt index 461644fae6..2ce6514679 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt @@ -49,7 +49,7 @@ class DrawAreaTaskFragment @Inject constructor() : AbstractTaskFragment Date: Mon, 23 Sep 2024 12:53:38 -0400 Subject: [PATCH 03/21] Replace uiState with navigationRequests --- .../java/com/google/android/ground/MainActivity.kt | 2 +- .../com/google/android/ground/MainViewModel.kt | 14 ++++++++------ .../com/google/android/ground/MainViewModelTest.kt | 2 +- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/MainActivity.kt b/ground/src/main/java/com/google/android/ground/MainActivity.kt index 183afead81..bfd35cd9d3 100644 --- a/ground/src/main/java/com/google/android/ground/MainActivity.kt +++ b/ground/src/main/java/com/google/android/ground/MainActivity.kt @@ -90,7 +90,7 @@ class MainActivity : AbstractActivity() { viewModel = viewModelFactory[this, MainViewModel::class.java] lifecycleScope.launch { - viewModel.uiState.filterNotNull().collect { updateUi(binding.root, it) } + viewModel.navigationRequests.filterNotNull().collect { updateUi(binding.root, it) } } } diff --git a/ground/src/main/java/com/google/android/ground/MainViewModel.kt b/ground/src/main/java/com/google/android/ground/MainViewModel.kt index 944008a652..8400ee78a0 100644 --- a/ground/src/main/java/com/google/android/ground/MainViewModel.kt +++ b/ground/src/main/java/com/google/android/ground/MainViewModel.kt @@ -32,9 +32,9 @@ import com.google.android.ground.ui.common.SharedViewModel import com.google.android.ground.util.isPermissionDeniedException import javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import timber.log.Timber @@ -53,8 +53,8 @@ constructor( authenticationManager: AuthenticationManager, ) : AbstractViewModel() { - private val _uiState: MutableStateFlow = MutableStateFlow(null) - var uiState: StateFlow = _uiState.asStateFlow() + private val _navigationRequests: MutableSharedFlow = MutableSharedFlow() + var navigationRequests: SharedFlow = _navigationRequests.asSharedFlow() /** The window insets determined by the activity. */ val windowInsets: MutableLiveData = MutableLiveData() @@ -62,7 +62,9 @@ constructor( init { viewModelScope.launch { // TODO: Check auth status whenever fragments resumes - authenticationManager.signInState.collect { _uiState.emit(onSignInStateChange(it)) } + authenticationManager.signInState.collect { + _navigationRequests.emit(onSignInStateChange(it)) + } } } diff --git a/ground/src/test/java/com/google/android/ground/MainViewModelTest.kt b/ground/src/test/java/com/google/android/ground/MainViewModelTest.kt index c29f638b98..0cbe01eb4e 100644 --- a/ground/src/test/java/com/google/android/ground/MainViewModelTest.kt +++ b/ground/src/test/java/com/google/android/ground/MainViewModelTest.kt @@ -72,7 +72,7 @@ class MainViewModelTest : BaseHiltTest() { } private fun verifyUiState(uiState: MainUiState) = runWithTestDispatcher { - viewModel.uiState.test { assertThat(expectMostRecentItem()).isEqualTo(uiState) } + viewModel.navigationRequests.test { assertThat(expectMostRecentItem()).isEqualTo(uiState) } } @Test From 8bab43525c24fc73ea2560730205dbad5a5693b1 Mon Sep 17 00:00:00 2001 From: Gino Miceli Date: Mon, 23 Sep 2024 17:13:52 -0400 Subject: [PATCH 04/21] Reinit view model on config change --- .../datacollection/DataCollectionFragment.kt | 7 ++++-- .../datacollection/DataCollectionViewModel.kt | 25 +++++++------------ 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionFragment.kt index 79ceee37c4..d1d66d229c 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionFragment.kt @@ -36,9 +36,9 @@ import com.google.android.ground.ui.common.AbstractFragment import com.google.android.ground.ui.common.BackPressListener import com.google.android.ground.ui.common.Navigator import dagger.hilt.android.AndroidEntryPoint -import javax.inject.Inject import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.launch +import javax.inject.Inject /** Fragment allowing the user to collect data to complete a task. */ @AndroidEntryPoint @@ -100,7 +100,10 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener { } ) - lifecycleScope.launch { viewModel.uiState.filterNotNull().collect { updateUI(it) } } + lifecycleScope.launch { + viewModel.init() + viewModel.uiState.filterNotNull().collect { updateUI(it) } + } } private fun updateUI(uiState: UiState) { diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt index 8d564232db..f62504f38f 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt @@ -51,12 +51,6 @@ import com.google.android.ground.ui.datacollection.tasks.text.TextTaskViewModel import com.google.android.ground.ui.datacollection.tasks.time.TimeTaskViewModel import com.google.android.ground.ui.home.HomeScreenFragmentDirections import dagger.hilt.android.lifecycle.HiltViewModel -import javax.inject.Inject -import javax.inject.Provider -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.set -import kotlin.math.abs import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow @@ -68,6 +62,12 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import timber.log.Timber +import javax.inject.Inject +import javax.inject.Provider +import kotlin.collections.component1 +import kotlin.collections.component2 +import kotlin.collections.set +import kotlin.math.abs /** View model for the Data Collection fragment. */ @HiltViewModel @@ -89,7 +89,7 @@ internal constructor( ) : AbstractViewModel() { private val _uiState: MutableStateFlow = MutableStateFlow(null) - var uiState: StateFlow + var uiState = _uiState.asStateFlow().stateIn(viewModelScope, SharingStarted.Lazily, null) private val jobId: String = requireNotNull(savedStateHandle[TASK_JOB_ID_KEY]) private val loiId: String? = savedStateHandle[TASK_LOI_ID_KEY] @@ -143,15 +143,8 @@ internal constructor( lateinit var submissionId: String - init { - uiState = - _uiState - .asStateFlow() - .stateIn( - viewModelScope, - SharingStarted.Lazily, - UiState.TaskListAvailable(tasks, getTaskPosition()), - ) + suspend fun init() { + _uiState.emit(UiState.TaskListAvailable(tasks, getTaskPosition())) } fun setLoiName(name: String) { From f884dbcdde86d12df668804e4a26ba16e6eadb17 Mon Sep 17 00:00:00 2001 From: Gino Miceli Date: Mon, 23 Sep 2024 17:14:22 -0400 Subject: [PATCH 05/21] Remove debugging log --- .../com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt b/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt index e9d14bfdc1..73e027db41 100644 --- a/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/map/gms/GoogleMapsFragment.kt @@ -160,7 +160,6 @@ class GoogleMapsFragment : SupportMapFragment(), MapFragment { private fun onMapReady(map: GoogleMap) { Timber.v("Map event: onMapReady()") - Timber.e("!!! onMapReady $this") this.map = map featureManager.onMapReady(map) From 731437fcf1d95c33d4714dd9575bce0dc458c991 Mon Sep 17 00:00:00 2001 From: Gino Miceli Date: Mon, 23 Sep 2024 17:16:47 -0400 Subject: [PATCH 06/21] Move arg key into const --- .../datacollection/tasks/polygon/DrawAreaTaskFragment.kt | 2 +- .../tasks/polygon/DrawAreaTaskMapFragment.kt | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt index 2ce6514679..0f9493c924 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt @@ -60,7 +60,7 @@ class DrawAreaTaskFragment @Inject constructor() : AbstractTaskFragment Date: Mon, 23 Sep 2024 17:18:14 -0400 Subject: [PATCH 07/21] Log error --- .../datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt index 0aae678c38..0abd8a19df 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt @@ -24,8 +24,8 @@ import com.google.android.ground.ui.map.CameraPosition import com.google.android.ground.ui.map.Feature import com.google.android.ground.ui.map.MapFragment import dagger.hilt.android.AndroidEntryPoint -import kotlinx.coroutines.launch import javax.inject.Inject +import kotlinx.coroutines.launch @AndroidEntryPoint class DrawAreaTaskMapFragment @Inject constructor() : AbstractMapFragmentWithControls() { @@ -37,9 +37,9 @@ class DrawAreaTaskMapFragment @Inject constructor() : AbstractMapFragmentWithCon super.onCreate(savedInstanceState) mapViewModel = getViewModel(BaseMapViewModel::class.java) - val taskId = arguments?.getString(TASK_ID_ARG_KEY) + val taskId = arguments?.getString(TASK_ID_ARG_KEY) ?: error("null taskId arg") val dcf = requireParentFragment() as DataCollectionFragment - viewModel = dcf.viewModel.getTaskViewModel(taskId!!) as DrawAreaTaskViewModel + viewModel = dcf.viewModel.getTaskViewModel(taskId) as DrawAreaTaskViewModel } override fun getMapViewModel(): BaseMapViewModel = mapViewModel From d19e353373b31c44ee8d488e85125b46584d5df5 Mon Sep 17 00:00:00 2001 From: Gino Miceli Date: Mon, 23 Sep 2024 17:21:03 -0400 Subject: [PATCH 08/21] Fix failing check --- .../ui/datacollection/DataCollectionFragment.kt | 2 +- .../ui/datacollection/DataCollectionViewModel.kt | 12 ++++++------ .../tasks/polygon/DrawAreaTaskMapFragment.kt | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionFragment.kt index b05dc62fb9..63dfbfd909 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionFragment.kt @@ -41,9 +41,9 @@ import com.google.android.ground.ui.common.Navigator import com.google.android.ground.ui.home.HomeScreenFragmentDirections import com.google.android.ground.ui.theme.AppTheme import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.launch -import javax.inject.Inject /** Fragment allowing the user to collect data to complete a task. */ @AndroidEntryPoint diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt index 7c55123d54..ed5ef8b70c 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewModel.kt @@ -49,6 +49,12 @@ import com.google.android.ground.ui.datacollection.tasks.polygon.DrawAreaTaskVie import com.google.android.ground.ui.datacollection.tasks.text.TextTaskViewModel import com.google.android.ground.ui.datacollection.tasks.time.TimeTaskViewModel import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject +import javax.inject.Provider +import kotlin.collections.component1 +import kotlin.collections.component2 +import kotlin.collections.set +import kotlin.math.abs import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow @@ -60,12 +66,6 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import timber.log.Timber -import javax.inject.Inject -import javax.inject.Provider -import kotlin.collections.component1 -import kotlin.collections.component2 -import kotlin.collections.set -import kotlin.math.abs /** View model for the Data Collection fragment. */ @HiltViewModel diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt index 0abd8a19df..77c778d8a4 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt @@ -64,6 +64,6 @@ class DrawAreaTaskMapFragment @Inject constructor() : AbstractMapFragmentWithCon } companion object { - val TASK_ID_ARG_KEY = "taskId" + const val TASK_ID_ARG_KEY = "taskId" } } From 0d69e4ff10f1233b56253ee94731a9176bb019ad Mon Sep 17 00:00:00 2001 From: Gino Miceli Date: Mon, 23 Sep 2024 17:26:34 -0400 Subject: [PATCH 09/21] Revert changes to manifest --- ground/src/main/AndroidManifest.xml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/ground/src/main/AndroidManifest.xml b/ground/src/main/AndroidManifest.xml index 596ea09700..f917ec9728 100644 --- a/ground/src/main/AndroidManifest.xml +++ b/ground/src/main/AndroidManifest.xml @@ -25,13 +25,8 @@ - - - + + From 262c66927fff8e1dad4e6ded70f05146be90f252 Mon Sep 17 00:00:00 2001 From: Gino Miceli Date: Mon, 23 Sep 2024 22:11:57 -0400 Subject: [PATCH 10/21] Fix tests --- .../android/ground/MainViewModelTest.kt | 91 ++++++++++--------- 1 file changed, 50 insertions(+), 41 deletions(-) diff --git a/ground/src/test/java/com/google/android/ground/MainViewModelTest.kt b/ground/src/test/java/com/google/android/ground/MainViewModelTest.kt index 0cbe01eb4e..149e2a331d 100644 --- a/ground/src/test/java/com/google/android/ground/MainViewModelTest.kt +++ b/ground/src/test/java/com/google/android/ground/MainViewModelTest.kt @@ -71,31 +71,31 @@ class MainViewModelTest : BaseHiltTest() { assertFailsWith { userRepository.getUser(FakeData.USER.id) } } - private fun verifyUiState(uiState: MainUiState) = runWithTestDispatcher { - viewModel.navigationRequests.test { assertThat(expectMostRecentItem()).isEqualTo(uiState) } - } - @Test fun testSignInStateChanged_onSignedOut() = runWithTestDispatcher { setupUserPreferences() - fakeAuthenticationManager.signOut() - advanceUntilIdle() + viewModel.navigationRequests.test { + fakeAuthenticationManager.signOut() + advanceUntilIdle() - verifyUiState(MainUiState.OnUserSignedOut) - verifyUserPreferencesCleared() - verifyUserNotSaved() - assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + assertThat(awaitItem()).isEqualTo(MainUiState.OnUserSignedOut) + verifyUserPreferencesCleared() + verifyUserNotSaved() + assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + } } @Test fun testSignInStateChanged_onSigningIn() = runWithTestDispatcher { - fakeAuthenticationManager.setState(SignInState.SigningIn) - advanceUntilIdle() + viewModel.navigationRequests.test { + fakeAuthenticationManager.setState(SignInState.SigningIn) + advanceUntilIdle() - verifyUiState(MainUiState.OnUserSigningIn) - verifyUserNotSaved() - assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + assertThat(awaitItem()).isEqualTo(MainUiState.OnUserSigningIn) + verifyUserNotSaved() + assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + } } // TODO(#1612): Add back testSignInStateChanged_onSignedIn_whenTosAcceptedAndActiveSurveyAvailable @@ -106,12 +106,14 @@ class MainViewModelTest : BaseHiltTest() { tosRepository.isTermsOfServiceAccepted = false fakeRemoteDataStore.termsOfService = Result.success(FakeData.TERMS_OF_SERVICE) - fakeAuthenticationManager.signIn() - advanceUntilIdle() + viewModel.navigationRequests.test { + fakeAuthenticationManager.signIn() + advanceUntilIdle() - verifyUiState(MainUiState.TosNotAccepted) - verifyUserSaved() - assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + assertThat(awaitItem()).isEqualTo(MainUiState.TosNotAccepted) + verifyUserSaved() + assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + } } @Test @@ -119,12 +121,14 @@ class MainViewModelTest : BaseHiltTest() { tosRepository.isTermsOfServiceAccepted = false fakeRemoteDataStore.termsOfService = null - fakeAuthenticationManager.signIn() - advanceUntilIdle() + viewModel.navigationRequests.test { + fakeAuthenticationManager.signIn() + advanceUntilIdle() - verifyUiState(MainUiState.TosNotAccepted) - verifyUserSaved() - assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + assertThat(awaitItem()).isEqualTo(MainUiState.TosNotAccepted) + verifyUserSaved() + assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + } } @Test @@ -138,12 +142,13 @@ class MainViewModelTest : BaseHiltTest() { ) ) - fakeAuthenticationManager.signIn() - advanceUntilIdle() - - assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() - // TODO(#2667): Update these implementation to make it clearer why this would be the case. - verifyUiState(MainUiState.TosNotAccepted) + viewModel.navigationRequests.test { + fakeAuthenticationManager.signIn() + advanceUntilIdle() + // TODO(#2667): Update these implementation to make it clearer why this would be the case. + assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + assertThat(awaitItem()).isEqualTo(MainUiState.TosNotAccepted) + } } @Test @@ -152,23 +157,27 @@ class MainViewModelTest : BaseHiltTest() { tosRepository.isTermsOfServiceAccepted = false fakeRemoteDataStore.termsOfService = Result.failure(Error("user error")) - fakeAuthenticationManager.signIn() - advanceUntilIdle() + viewModel.navigationRequests.test { + fakeAuthenticationManager.signIn() + advanceUntilIdle() - assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() - verifyUiState(MainUiState.TosNotAccepted) + assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + assertThat(awaitItem()).isEqualTo(MainUiState.TosNotAccepted) + } } @Test fun testSignInStateChanged_onSignInError() = runWithTestDispatcher { setupUserPreferences() - fakeAuthenticationManager.setState(SignInState.Error(Exception())) - advanceUntilIdle() + viewModel.navigationRequests.test { + fakeAuthenticationManager.setState(SignInState.Error(Exception())) + advanceUntilIdle() - verifyUiState(MainUiState.OnUserSignedOut) - verifyUserPreferencesCleared() - verifyUserNotSaved() - assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + assertThat(awaitItem()).isEqualTo(MainUiState.OnUserSignedOut) + verifyUserPreferencesCleared() + verifyUserNotSaved() + assertThat(tosRepository.isTermsOfServiceAccepted).isFalse() + } } } From 8ba3d92b13cb231eba31b36b0135ad33662d9d8c Mon Sep 17 00:00:00 2001 From: Gino Miceli Date: Mon, 23 Sep 2024 22:40:52 -0400 Subject: [PATCH 11/21] Add TODOs --- .../ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt index 698e14d41e..07ddd1b022 100644 --- a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt +++ b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt @@ -30,6 +30,7 @@ import com.google.android.ground.model.job.Job import com.google.android.ground.model.submission.TaskData import com.google.android.ground.model.task.Task import com.google.android.ground.ui.common.ViewModelFactory +import com.google.android.ground.ui.datacollection.DataCollectionFragment import com.google.android.ground.ui.datacollection.DataCollectionViewModel import com.google.android.ground.ui.datacollection.TaskFragmentRunner import com.google.android.ground.ui.datacollection.components.ButtonAction @@ -95,6 +96,8 @@ abstract class BaseTaskFragmentTest, VM : AbstractT preTransactionAction = { fragment = this as F fragment.taskId = task.id + // TODO: Attach `fragment` to mock DataCollectionFragment + // TODO: Mock out `DataCollectionFragment.viewModel` as `dataCollectionViewModel` }, ) } From e678e0f5d92b80832134ed75c34f021467db7c78 Mon Sep 17 00:00:00 2001 From: Gino Miceli <228050+gino-m@users.noreply.github.com> Date: Mon, 23 Sep 2024 22:42:43 -0400 Subject: [PATCH 12/21] Revert formatting change --- ground/src/main/AndroidManifest.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ground/src/main/AndroidManifest.xml b/ground/src/main/AndroidManifest.xml index f917ec9728..aab89bebf8 100644 --- a/ground/src/main/AndroidManifest.xml +++ b/ground/src/main/AndroidManifest.xml @@ -84,7 +84,8 @@ + tools:node="remove"> + - \ No newline at end of file + From b908177ecc993483e818b129c716786a12f5bde8 Mon Sep 17 00:00:00 2001 From: Akshay Nandwana Date: Tue, 24 Sep 2024 08:26:08 +0530 Subject: [PATCH 13/21] copied same to other map frag --- .../DataCollectionViewPagerAdapter.kt | 6 ++++-- .../location/CaptureLocationTaskFragment.kt | 21 +++++++++++-------- .../CaptureLocationTaskMapFragment.kt | 14 +++++++++---- .../tasks/point/DropPinTaskFragment.kt | 15 ++++++++----- .../tasks/point/DropPinTaskMapFragment.kt | 13 ++++++++---- .../tasks/polygon/DrawAreaTaskFragment.kt | 2 +- 6 files changed, 46 insertions(+), 25 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewPagerAdapter.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewPagerAdapter.kt index a8de0b3a47..9fe557baa4 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewPagerAdapter.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/DataCollectionViewPagerAdapter.kt @@ -38,6 +38,8 @@ class DataCollectionViewPagerAdapter @AssistedInject constructor( private val drawAreaTaskFragmentProvider: Provider, + private val captureLocationTaskFragmentProvider: Provider, + private val dropPinTaskFragmentProvider: Provider, @Assisted fragment: Fragment, @Assisted val tasks: List, ) : FragmentStateAdapter(fragment) { @@ -51,12 +53,12 @@ constructor( Task.Type.TEXT -> TextTaskFragment() Task.Type.MULTIPLE_CHOICE -> MultipleChoiceTaskFragment() Task.Type.PHOTO -> PhotoTaskFragment() - Task.Type.DROP_PIN -> DropPinTaskFragment() + Task.Type.DROP_PIN -> dropPinTaskFragmentProvider.get() Task.Type.DRAW_AREA -> drawAreaTaskFragmentProvider.get() Task.Type.NUMBER -> NumberTaskFragment() Task.Type.DATE -> DateTaskFragment() Task.Type.TIME -> TimeTaskFragment() - Task.Type.CAPTURE_LOCATION -> CaptureLocationTaskFragment() + Task.Type.CAPTURE_LOCATION -> captureLocationTaskFragmentProvider.get() Task.Type.UNKNOWN -> throw UnsupportedOperationException("Unsupported task type: ${task.type}") } diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt index 8c05dc0c51..1770d4340b 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt @@ -15,6 +15,7 @@ */ package com.google.android.ground.ui.datacollection.tasks.location +import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.widget.LinearLayout @@ -25,14 +26,16 @@ import com.google.android.ground.ui.datacollection.components.ButtonAction import com.google.android.ground.ui.datacollection.components.TaskView import com.google.android.ground.ui.datacollection.components.TaskViewFactory import com.google.android.ground.ui.datacollection.tasks.AbstractTaskFragment -import com.google.android.ground.ui.map.MapFragment +import com.google.android.ground.ui.datacollection.tasks.location.CaptureLocationTaskMapFragment.Companion.TASK_ID_ARG_KEY import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject +import javax.inject.Provider @AndroidEntryPoint -class CaptureLocationTaskFragment : AbstractTaskFragment() { - - @Inject lateinit var map: MapFragment +class CaptureLocationTaskFragment @Inject constructor() : + AbstractTaskFragment() { + @Inject + lateinit var captureLocationTaskMapFragmentProvider: Provider override fun onCreateTaskView(inflater: LayoutInflater): TaskView = TaskViewFactory.createWithCombinedHeader(inflater, R.drawable.outline_pin_drop) @@ -41,13 +44,13 @@ class CaptureLocationTaskFragment : AbstractTaskFragment() { - - @Inject lateinit var map: MapFragment +class DropPinTaskFragment @Inject constructor() : AbstractTaskFragment() { + @Inject lateinit var dropPinTaskMapFragmentProvider: Provider override fun onCreateTaskView(inflater: LayoutInflater): TaskView = TaskViewFactory.createWithCombinedHeader(inflater, R.drawable.outline_pin_drop) @@ -47,9 +48,13 @@ class DropPinTaskFragment : AbstractTaskFragment() { // NOTE(#2493): Multiplying by a random prime to allow for some mathematical "uniqueness". // Otherwise, the sequentially generated ID might conflict with an ID produced by Google Maps. val rowLayout = LinearLayout(requireContext()).apply { id = View.generateViewId() * 11617 } + val fragment = dropPinTaskMapFragmentProvider.get() + val args = Bundle() + args.putString(TASK_ID_ARG_KEY, taskId) + fragment.arguments = args parentFragmentManager .beginTransaction() - .add(rowLayout.id, DropPinTaskMapFragment.newInstance(viewModel, map), "Drop a pin fragment") + .add(rowLayout.id, fragment, "Drop a pin fragment") .commit() return rowLayout } diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt index 748970ec75..59c58a9d6c 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt @@ -18,24 +18,30 @@ package com.google.android.ground.ui.datacollection.tasks.point import android.os.Bundle import com.google.android.ground.ui.common.AbstractMapFragmentWithControls import com.google.android.ground.ui.common.BaseMapViewModel +import com.google.android.ground.ui.datacollection.DataCollectionFragment import com.google.android.ground.ui.map.CameraPosition import com.google.android.ground.ui.map.MapFragment import dagger.hilt.android.AndroidEntryPoint +import javax.inject.Inject @AndroidEntryPoint -class DropPinTaskMapFragment(private val viewModel: DropPinTaskViewModel) : - AbstractMapFragmentWithControls() { +class DropPinTaskMapFragment @Inject constructor() : AbstractMapFragmentWithControls() { private lateinit var mapViewModel: BaseMapViewModel + private lateinit var viewModel: DropPinTaskViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mapViewModel = getViewModel(BaseMapViewModel::class.java) + val taskId = arguments?.getString(TASK_ID_ARG_KEY) ?: error("null taskId arg") + val dcf = requireParentFragment() as DataCollectionFragment + viewModel = dcf.viewModel.getTaskViewModel(taskId) as DropPinTaskViewModel } override fun getMapViewModel(): BaseMapViewModel = mapViewModel override fun onMapReady(map: MapFragment) { + super.onMapReady(map) viewModel.features.observe(this) { map.setFeatures(it) } } @@ -45,7 +51,6 @@ class DropPinTaskMapFragment(private val viewModel: DropPinTaskViewModel) : } companion object { - fun newInstance(viewModel: DropPinTaskViewModel, map: MapFragment) = - DropPinTaskMapFragment(viewModel).apply { this.map = map } + const val TASK_ID_ARG_KEY = "taskId" } } diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt index 0f9493c924..7d01c8fda7 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt @@ -58,7 +58,7 @@ class DrawAreaTaskFragment @Inject constructor() : AbstractTaskFragment Date: Tue, 24 Sep 2024 08:48:05 +0530 Subject: [PATCH 14/21] viewmodel check --- .../tasks/location/CaptureLocationTaskFragment.kt | 4 +++- .../ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt index 1770d4340b..22fab20550 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt @@ -57,7 +57,9 @@ class CaptureLocationTaskFragment @Inject constructor() : override fun onTaskResume() { // Ensure that the location lock is enabled, if it hasn't been. - viewModel.enableLocationLock() + if (isVisible) { + viewModel.enableLocationLock() + } } override fun onCreateActionButtons() { diff --git a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt index 07ddd1b022..33ce8778ac 100644 --- a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt +++ b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt @@ -30,7 +30,6 @@ import com.google.android.ground.model.job.Job import com.google.android.ground.model.submission.TaskData import com.google.android.ground.model.task.Task import com.google.android.ground.ui.common.ViewModelFactory -import com.google.android.ground.ui.datacollection.DataCollectionFragment import com.google.android.ground.ui.datacollection.DataCollectionViewModel import com.google.android.ground.ui.datacollection.TaskFragmentRunner import com.google.android.ground.ui.datacollection.components.ButtonAction From 43eed3b0912f864faded58c6a5dc13dd0db4c837 Mon Sep 17 00:00:00 2001 From: Gino Miceli <228050+gino-m@users.noreply.github.com> Date: Tue, 24 Sep 2024 11:27:07 -0400 Subject: [PATCH 15/21] Remove final CR From 6cd2594b39e5fbf0271caf0e6046d7650a70e506 Mon Sep 17 00:00:00 2001 From: Gino Miceli <228050+gino-m@users.noreply.github.com> Date: Wed, 25 Sep 2024 11:48:31 -0400 Subject: [PATCH 16/21] Remove final CR From 6446159d2eb8a71537eb301f64b124cf65ced4f5 Mon Sep 17 00:00:00 2001 From: Akshay Nandwana Date: Fri, 27 Sep 2024 15:02:00 +0530 Subject: [PATCH 17/21] test try --- .../tasks/AbstractTaskFragment.kt | 2 ++ .../tasks/polygon/DrawAreaTaskFragment.kt | 1 + .../tasks/polygon/DrawAreaTaskMapFragment.kt | 2 ++ .../java/com/google/android/ground/HiltExt.kt | 6 ++++ .../tasks/BaseTaskFragmentTest.kt | 30 +++++++++++++++++-- 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt index 71312e8f79..33b1accd52 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt @@ -89,9 +89,11 @@ abstract class AbstractTaskFragment : AbstractFragmen super.onViewCreated(view, savedInstanceState) view.doOnAttach { @Suppress("UNCHECKED_CAST", "LabeledExpression") + println("========= onViewCreated ${taskId} --- ${dataCollectionViewModel.getTaskViewModel(taskId)}") val vm = dataCollectionViewModel.getTaskViewModel(taskId) as? T ?: return@doOnAttach viewModel = vm + println("========= onViewCreated ${viewModel}") taskView.bind(this, viewModel) taskView.addTaskView(onCreateTaskBody(layoutInflater)) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt index 0f9493c924..5a501b3606 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt @@ -59,6 +59,7 @@ class DrawAreaTaskFragment @Inject constructor() : AbstractTaskFragment launchFragmentWithNavController( fragmentArgs: Bundle? = null, @StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme, destId: Int, + fragment: Fragment?=null, crossinline preTransactionAction: Fragment.() -> Unit = {}, crossinline postTransactionAction: Fragment.() -> Unit = {}, ): ActivityScenario = hiltActivityScenario(themeResId).launchFragment( fragmentArgs, { + println("========= ${parentFragment.toString()} ----- ${parentFragment?.childFragmentManager.toString()} ") + parentFragment?.childFragmentManager?.beginTransaction() + ?.add(R.id.data_collection_fragment, fragment!!, "childFragmentTag") + ?.commitNow() + this.preTransactionAction() viewLifecycleOwnerLiveData.observeForever { viewLifecycleOwner -> if (viewLifecycleOwner != null) { diff --git a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt index 07ddd1b022..4d94cd95e1 100644 --- a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt +++ b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt @@ -34,15 +34,20 @@ import com.google.android.ground.ui.datacollection.DataCollectionFragment import com.google.android.ground.ui.datacollection.DataCollectionViewModel import com.google.android.ground.ui.datacollection.TaskFragmentRunner import com.google.android.ground.ui.datacollection.components.ButtonAction +import com.google.android.ground.ui.datacollection.tasks.polygon.DrawAreaTaskFragment +import com.google.android.ground.ui.datacollection.tasks.polygon.DrawAreaTaskMapFragment import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import org.hamcrest.core.IsNot.not +import org.mockito.Mock +import org.mockito.Mockito.mock import org.mockito.kotlin.whenever +import javax.inject.Provider abstract class BaseTaskFragmentTest, VM : AbstractTaskViewModel> : BaseHiltTest() { - abstract val dataCollectionViewModel: DataCollectionViewModel + abstract var dataCollectionViewModel: DataCollectionViewModel abstract val viewModelFactory: ViewModelFactory lateinit var fragment: F @@ -86,16 +91,37 @@ abstract class BaseTaskFragmentTest, VM : AbstractT } } + @Mock + lateinit var drawAreaTaskMapFragmentProvider: Provider + @Mock + lateinit var drawAreaTaskMapFragment: DrawAreaTaskMapFragment + + protected inline fun setupTaskFragment(job: Job, task: Task) { viewModel = viewModelFactory.create(DataCollectionViewModel.getViewModelClass(task.type)) as VM - viewModel.initialize(job, task, null) + println("========= ${viewModel} ") whenever(dataCollectionViewModel.getTaskViewModel(task.id)).thenReturn(viewModel) + viewModel.initialize(job, task, null) + + val mockDataCollectionFragment = mock(DataCollectionFragment::class.java) + whenever(mockDataCollectionFragment.viewModel).thenReturn(dataCollectionViewModel) + + whenever(drawAreaTaskMapFragment.requireParentFragment()).thenReturn(mockDataCollectionFragment) + + println("========= mockDrawAreaTaskMapFragment ${drawAreaTaskMapFragmentProvider.get()} ") + whenever(drawAreaTaskMapFragmentProvider.get()).thenReturn(drawAreaTaskMapFragment) + launchFragmentWithNavController( destId = R.id.data_collection_fragment, + fragment = mockDataCollectionFragment, preTransactionAction = { fragment = this as F fragment.taskId = task.id + + + println("========= preTransactionAction ${fragment.toString()} ") + // TODO: Attach `fragment` to mock DataCollectionFragment // TODO: Mock out `DataCollectionFragment.viewModel` as `dataCollectionViewModel` }, From 66b07ac49cb077b73bdcc5722cadd1b3295e76f8 Mon Sep 17 00:00:00 2001 From: Akshay Nandwana Date: Fri, 27 Sep 2024 15:05:49 +0530 Subject: [PATCH 18/21] nit fix --- .../ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt index 4a69c73fd6..4d94cd95e1 100644 --- a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt +++ b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt @@ -30,6 +30,7 @@ import com.google.android.ground.model.job.Job import com.google.android.ground.model.submission.TaskData import com.google.android.ground.model.task.Task import com.google.android.ground.ui.common.ViewModelFactory +import com.google.android.ground.ui.datacollection.DataCollectionFragment import com.google.android.ground.ui.datacollection.DataCollectionViewModel import com.google.android.ground.ui.datacollection.TaskFragmentRunner import com.google.android.ground.ui.datacollection.components.ButtonAction From 436517f3f667235af65ed8974f581c7b2eb1f5c7 Mon Sep 17 00:00:00 2001 From: Akshay Nandwana Date: Thu, 3 Oct 2024 08:16:07 +0530 Subject: [PATCH 19/21] updated --- .../tasks/AbstractTaskFragment.kt | 2 -- .../location/CaptureLocationTaskFragment.kt | 4 +-- .../CaptureLocationTaskMapFragment.kt | 20 +++++++---- .../tasks/point/DropPinTaskFragment.kt | 4 +-- .../tasks/point/DropPinTaskMapFragment.kt | 19 ++++++---- .../tasks/BaseTaskFragmentTest.kt | 35 ++----------------- 6 files changed, 33 insertions(+), 51 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt index 33b1accd52..71312e8f79 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/AbstractTaskFragment.kt @@ -89,11 +89,9 @@ abstract class AbstractTaskFragment : AbstractFragmen super.onViewCreated(view, savedInstanceState) view.doOnAttach { @Suppress("UNCHECKED_CAST", "LabeledExpression") - println("========= onViewCreated ${taskId} --- ${dataCollectionViewModel.getTaskViewModel(taskId)}") val vm = dataCollectionViewModel.getTaskViewModel(taskId) as? T ?: return@doOnAttach viewModel = vm - println("========= onViewCreated ${viewModel}") taskView.bind(this, viewModel) taskView.addTaskView(onCreateTaskBody(layoutInflater)) diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt index 22fab20550..fffff44fee 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt @@ -26,7 +26,7 @@ import com.google.android.ground.ui.datacollection.components.ButtonAction import com.google.android.ground.ui.datacollection.components.TaskView import com.google.android.ground.ui.datacollection.components.TaskViewFactory import com.google.android.ground.ui.datacollection.tasks.AbstractTaskFragment -import com.google.android.ground.ui.datacollection.tasks.location.CaptureLocationTaskMapFragment.Companion.TASK_ID_ARG_KEY +import com.google.android.ground.ui.datacollection.tasks.location.CaptureLocationTaskMapFragment.Companion.TASK_ID_FRAGMENT_ARG_KEY import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject import javax.inject.Provider @@ -46,7 +46,7 @@ class CaptureLocationTaskFragment @Inject constructor() : val rowLayout = LinearLayout(requireContext()).apply { id = View.generateViewId() * 11149 } val fragment = captureLocationTaskMapFragmentProvider.get() val args = Bundle() - args.putString(TASK_ID_ARG_KEY, taskId) + args.putString(TASK_ID_FRAGMENT_ARG_KEY, taskId) fragment.arguments = args parentFragmentManager .beginTransaction() diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt index b0629bb044..3d4df2ebb6 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt @@ -19,11 +19,12 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.hilt.navigation.fragment.hiltNavGraphViewModels import androidx.lifecycle.lifecycleScope +import com.google.android.ground.R import com.google.android.ground.ui.common.AbstractMapFragmentWithControls import com.google.android.ground.ui.common.BaseMapViewModel -import com.google.android.ground.ui.datacollection.DataCollectionFragment -import com.google.android.ground.ui.datacollection.tasks.polygon.DrawAreaTaskMapFragment.Companion.TASK_ID_ARG_KEY +import com.google.android.ground.ui.datacollection.DataCollectionViewModel import com.google.android.ground.ui.map.MapFragment import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -33,14 +34,19 @@ import kotlinx.coroutines.launch class CaptureLocationTaskMapFragment @Inject constructor() : AbstractMapFragmentWithControls() { private lateinit var mapViewModel: CaptureLocationTaskMapViewModel - private lateinit var viewModel: CaptureLocationTaskViewModel + private val dataCollectionViewModel: DataCollectionViewModel by + hiltNavGraphViewModels(R.id.data_collection) + private val viewModel: CaptureLocationTaskViewModel by lazy { + // Access to this viewModel is lazy for testing. This is because the NavHostController could + // not be initialized before the Fragment under test is created, leading to + // hiltNavGraphViewModels() to fail when called on launch. + val taskId = arguments?.getString(TASK_ID_FRAGMENT_ARG_KEY) ?: error("null taskId fragment arg") + dataCollectionViewModel.getTaskViewModel(taskId) as CaptureLocationTaskViewModel + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mapViewModel = getViewModel(CaptureLocationTaskMapViewModel::class.java) - val taskId = arguments?.getString(TASK_ID_ARG_KEY) ?: error("null taskId arg") - val dcf = requireParentFragment() as DataCollectionFragment - viewModel = dcf.viewModel.getTaskViewModel(taskId) as CaptureLocationTaskViewModel } override fun getMapViewModel(): BaseMapViewModel = mapViewModel @@ -64,6 +70,6 @@ class CaptureLocationTaskMapFragment @Inject constructor() : AbstractMapFragment } companion object { - const val TASK_ID_ARG_KEY = "taskId" + const val TASK_ID_FRAGMENT_ARG_KEY = "taskId" } } diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskFragment.kt index 87e534dbd4..6a7bd6e255 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskFragment.kt @@ -31,7 +31,7 @@ import com.google.android.ground.ui.datacollection.components.InstructionsDialog import com.google.android.ground.ui.datacollection.components.TaskView import com.google.android.ground.ui.datacollection.components.TaskViewFactory import com.google.android.ground.ui.datacollection.tasks.AbstractTaskFragment -import com.google.android.ground.ui.datacollection.tasks.point.DropPinTaskMapFragment.Companion.TASK_ID_ARG_KEY +import com.google.android.ground.ui.datacollection.tasks.point.DropPinTaskMapFragment.Companion.TASK_ID_FRAGMENT_ARG_KEY import com.google.android.ground.ui.theme.AppTheme import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -50,7 +50,7 @@ class DropPinTaskFragment @Inject constructor() : AbstractTaskFragment, VM : AbstractTaskViewModel> : BaseHiltTest() { - abstract var dataCollectionViewModel: DataCollectionViewModel + abstract val dataCollectionViewModel: DataCollectionViewModel abstract val viewModelFactory: ViewModelFactory lateinit var fragment: F @@ -91,39 +85,16 @@ abstract class BaseTaskFragmentTest, VM : AbstractT } } - @Mock - lateinit var drawAreaTaskMapFragmentProvider: Provider - @Mock - lateinit var drawAreaTaskMapFragment: DrawAreaTaskMapFragment - - protected inline fun setupTaskFragment(job: Job, task: Task) { viewModel = viewModelFactory.create(DataCollectionViewModel.getViewModelClass(task.type)) as VM - println("========= ${viewModel} ") - whenever(dataCollectionViewModel.getTaskViewModel(task.id)).thenReturn(viewModel) - viewModel.initialize(job, task, null) - - val mockDataCollectionFragment = mock(DataCollectionFragment::class.java) - whenever(mockDataCollectionFragment.viewModel).thenReturn(dataCollectionViewModel) - - whenever(drawAreaTaskMapFragment.requireParentFragment()).thenReturn(mockDataCollectionFragment) - - println("========= mockDrawAreaTaskMapFragment ${drawAreaTaskMapFragmentProvider.get()} ") - whenever(drawAreaTaskMapFragmentProvider.get()).thenReturn(drawAreaTaskMapFragment) + whenever(dataCollectionViewModel.getTaskViewModel(task.id)).thenReturn(viewModel) launchFragmentWithNavController( destId = R.id.data_collection_fragment, - fragment = mockDataCollectionFragment, preTransactionAction = { fragment = this as F fragment.taskId = task.id - - - println("========= preTransactionAction ${fragment.toString()} ") - - // TODO: Attach `fragment` to mock DataCollectionFragment - // TODO: Mock out `DataCollectionFragment.viewModel` as `dataCollectionViewModel` }, ) } From aec6466c940c6fd55f4999829b940c6bdcf5c8d9 Mon Sep 17 00:00:00 2001 From: Akshay Nandwana Date: Thu, 3 Oct 2024 08:17:59 +0530 Subject: [PATCH 20/21] nit fix --- .../ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt index 518896a50a..698e14d41e 100644 --- a/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt +++ b/ground/src/test/java/com/google/android/ground/ui/datacollection/tasks/BaseTaskFragmentTest.kt @@ -32,7 +32,7 @@ import com.google.android.ground.model.task.Task import com.google.android.ground.ui.common.ViewModelFactory import com.google.android.ground.ui.datacollection.DataCollectionViewModel import com.google.android.ground.ui.datacollection.TaskFragmentRunner -import com.google.android.ground.ui.datacollection.components.ButtonAction\ +import com.google.android.ground.ui.datacollection.components.ButtonAction import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import org.hamcrest.core.IsNot.not From 5b8a5658360159dfa03176327f773823c005d5c2 Mon Sep 17 00:00:00 2001 From: Akshay Nandwana Date: Fri, 4 Oct 2024 08:05:18 +0530 Subject: [PATCH 21/21] moved to base --- .../ui/common/AbstractMapFragmentWithControls.kt | 13 +++++++++++++ .../tasks/location/CaptureLocationTaskFragment.kt | 2 +- .../location/CaptureLocationTaskMapFragment.kt | 10 ---------- .../tasks/point/DropPinTaskFragment.kt | 2 +- .../tasks/point/DropPinTaskMapFragment.kt | 10 ---------- .../tasks/polygon/DrawAreaTaskFragment.kt | 3 ++- .../tasks/polygon/DrawAreaTaskMapFragment.kt | 11 +---------- 7 files changed, 18 insertions(+), 33 deletions(-) diff --git a/ground/src/main/java/com/google/android/ground/ui/common/AbstractMapFragmentWithControls.kt b/ground/src/main/java/com/google/android/ground/ui/common/AbstractMapFragmentWithControls.kt index cba083913d..290b65234f 100644 --- a/ground/src/main/java/com/google/android/ground/ui/common/AbstractMapFragmentWithControls.kt +++ b/ground/src/main/java/com/google/android/ground/ui/common/AbstractMapFragmentWithControls.kt @@ -20,12 +20,14 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.annotation.StringRes +import androidx.hilt.navigation.fragment.hiltNavGraphViewModels import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import com.google.android.ground.R import com.google.android.ground.databinding.MapTaskFragBinding import com.google.android.ground.model.submission.CaptureLocationTaskData.Companion.toCaptureLocationResult +import com.google.android.ground.ui.datacollection.DataCollectionViewModel import com.google.android.ground.ui.map.CameraPosition import com.google.android.ground.ui.map.MapFragment import com.google.android.ground.util.toDmsFormat @@ -42,6 +44,13 @@ abstract class AbstractMapFragmentWithControls : AbstractMapContainerFragment() protected lateinit var binding: MapTaskFragBinding + protected val dataCollectionViewModel: DataCollectionViewModel by + hiltNavGraphViewModels(R.id.data_collection) + + protected val taskId: String by lazy { + arguments?.getString(TASK_ID_FRAGMENT_ARG_KEY) ?: error("null taskId fragment arg") + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -112,4 +121,8 @@ abstract class AbstractMapFragmentWithControls : AbstractMapContainerFragment() } updateLocationInfoCard(R.string.map_location, position.coordinates.toDmsFormat()) } + + companion object { + const val TASK_ID_FRAGMENT_ARG_KEY = "taskId" + } } diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt index fffff44fee..8fa5904d70 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskFragment.kt @@ -22,11 +22,11 @@ import android.widget.LinearLayout import com.google.android.ground.R import com.google.android.ground.model.submission.isNotNullOrEmpty import com.google.android.ground.model.submission.isNullOrEmpty +import com.google.android.ground.ui.common.AbstractMapFragmentWithControls.Companion.TASK_ID_FRAGMENT_ARG_KEY import com.google.android.ground.ui.datacollection.components.ButtonAction import com.google.android.ground.ui.datacollection.components.TaskView import com.google.android.ground.ui.datacollection.components.TaskViewFactory import com.google.android.ground.ui.datacollection.tasks.AbstractTaskFragment -import com.google.android.ground.ui.datacollection.tasks.location.CaptureLocationTaskMapFragment.Companion.TASK_ID_FRAGMENT_ARG_KEY import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject import javax.inject.Provider diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt index 3d4df2ebb6..474a00e138 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt @@ -19,12 +19,9 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.hilt.navigation.fragment.hiltNavGraphViewModels import androidx.lifecycle.lifecycleScope -import com.google.android.ground.R import com.google.android.ground.ui.common.AbstractMapFragmentWithControls import com.google.android.ground.ui.common.BaseMapViewModel -import com.google.android.ground.ui.datacollection.DataCollectionViewModel import com.google.android.ground.ui.map.MapFragment import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject @@ -34,13 +31,10 @@ import kotlinx.coroutines.launch class CaptureLocationTaskMapFragment @Inject constructor() : AbstractMapFragmentWithControls() { private lateinit var mapViewModel: CaptureLocationTaskMapViewModel - private val dataCollectionViewModel: DataCollectionViewModel by - hiltNavGraphViewModels(R.id.data_collection) private val viewModel: CaptureLocationTaskViewModel by lazy { // Access to this viewModel is lazy for testing. This is because the NavHostController could // not be initialized before the Fragment under test is created, leading to // hiltNavGraphViewModels() to fail when called on launch. - val taskId = arguments?.getString(TASK_ID_FRAGMENT_ARG_KEY) ?: error("null taskId fragment arg") dataCollectionViewModel.getTaskViewModel(taskId) as CaptureLocationTaskViewModel } @@ -68,8 +62,4 @@ class CaptureLocationTaskMapFragment @Inject constructor() : AbstractMapFragment binding.locationLockBtn.isClickable = false viewLifecycleOwner.lifecycleScope.launch { viewModel.onMapReady(mapViewModel) } } - - companion object { - const val TASK_ID_FRAGMENT_ARG_KEY = "taskId" - } } diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskFragment.kt index 6a7bd6e255..801dc80bc1 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskFragment.kt @@ -26,12 +26,12 @@ import androidx.compose.ui.platform.ComposeView import com.google.android.ground.R import com.google.android.ground.model.submission.isNotNullOrEmpty import com.google.android.ground.model.submission.isNullOrEmpty +import com.google.android.ground.ui.common.AbstractMapFragmentWithControls.Companion.TASK_ID_FRAGMENT_ARG_KEY import com.google.android.ground.ui.datacollection.components.ButtonAction import com.google.android.ground.ui.datacollection.components.InstructionsDialog import com.google.android.ground.ui.datacollection.components.TaskView import com.google.android.ground.ui.datacollection.components.TaskViewFactory import com.google.android.ground.ui.datacollection.tasks.AbstractTaskFragment -import com.google.android.ground.ui.datacollection.tasks.point.DropPinTaskMapFragment.Companion.TASK_ID_FRAGMENT_ARG_KEY import com.google.android.ground.ui.theme.AppTheme import dagger.hilt.android.AndroidEntryPoint import javax.inject.Inject diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt index 006078ce74..d36a69e184 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt @@ -16,11 +16,8 @@ package com.google.android.ground.ui.datacollection.tasks.point import android.os.Bundle -import androidx.hilt.navigation.fragment.hiltNavGraphViewModels -import com.google.android.ground.R import com.google.android.ground.ui.common.AbstractMapFragmentWithControls import com.google.android.ground.ui.common.BaseMapViewModel -import com.google.android.ground.ui.datacollection.DataCollectionViewModel import com.google.android.ground.ui.map.CameraPosition import com.google.android.ground.ui.map.MapFragment import dagger.hilt.android.AndroidEntryPoint @@ -30,13 +27,10 @@ import javax.inject.Inject class DropPinTaskMapFragment @Inject constructor() : AbstractMapFragmentWithControls() { private lateinit var mapViewModel: BaseMapViewModel - private val dataCollectionViewModel: DataCollectionViewModel by - hiltNavGraphViewModels(R.id.data_collection) private val viewModel: DropPinTaskViewModel by lazy { // Access to this viewModel is lazy for testing. This is because the NavHostController could // not be initialized before the Fragment under test is created, leading to // hiltNavGraphViewModels() to fail when called on launch. - val taskId = arguments?.getString(TASK_ID_FRAGMENT_ARG_KEY) ?: error("null taskId fragment arg") dataCollectionViewModel.getTaskViewModel(taskId) as DropPinTaskViewModel } @@ -56,8 +50,4 @@ class DropPinTaskMapFragment @Inject constructor() : AbstractMapFragmentWithCont super.onMapCameraMoved(position) viewModel.updateCameraPosition(position) } - - companion object { - const val TASK_ID_FRAGMENT_ARG_KEY = "taskId" - } } diff --git a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt index f2f9a2d0c3..acb700ae00 100644 --- a/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt +++ b/ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskFragment.kt @@ -27,6 +27,7 @@ import androidx.lifecycle.lifecycleScope import com.google.android.ground.R import com.google.android.ground.model.geometry.LineString import com.google.android.ground.model.geometry.LineString.Companion.lineStringOf +import com.google.android.ground.ui.common.AbstractMapFragmentWithControls.Companion.TASK_ID_FRAGMENT_ARG_KEY import com.google.android.ground.ui.datacollection.components.ButtonAction import com.google.android.ground.ui.datacollection.components.InstructionsDialog import com.google.android.ground.ui.datacollection.components.TaskButton @@ -60,7 +61,7 @@ class DrawAreaTaskFragment @Inject constructor() : AbstractTaskFragment