Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ViewModel is now access based on taskId using Bundle #2748

Closed
wants to merge 14 commits into from
Closed
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
@Inject lateinit var navigator: Navigator
@Inject lateinit var viewPagerAdapterFactory: DataCollectionViewPagerAdapterFactory

private val viewModel: DataCollectionViewModel by hiltNavGraphViewModels(R.id.data_collection)
val viewModel: DataCollectionViewModel by hiltNavGraphViewModels(R.id.data_collection)

private lateinit var binding: DataCollectionFragBinding
private lateinit var progressBar: ProgressBar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,10 @@ class CaptureLocationTaskFragment : AbstractTaskFragment<CaptureLocationTaskView
// 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() * 11149 }
val fragment = CaptureLocationTaskMapFragment.newInstance(map, taskId)
parentFragmentManager
.beginTransaction()
.add(
rowLayout.id,
CaptureLocationTaskMapFragment.newInstance(viewModel, map),
CaptureLocationTaskMapFragment::class.java.simpleName,
)
.add(rowLayout.id, fragment, CaptureLocationTaskMapFragment::class.java.simpleName)
.commit()
return rowLayout
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,33 @@
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.MapFragment
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.launch
import timber.log.Timber

@AndroidEntryPoint
class CaptureLocationTaskMapFragment(private val viewModel: CaptureLocationTaskViewModel) :
AbstractMapFragmentWithControls() {
class CaptureLocationTaskMapFragment : AbstractMapFragmentWithControls() {

private lateinit var mapViewModel: CaptureLocationTaskMapViewModel
private lateinit var viewModel: CaptureLocationTaskViewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mapViewModel = getViewModel(CaptureLocationTaskMapViewModel::class.java)
arguments?.let {
try {
val taskId = it.getString("taskId")
taskId?.let {
viewModel =
(requireParentFragment() as DataCollectionFragment).viewModel.getTaskViewModel(taskId)

Check warning on line 45 in ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt

View check run for this annotation

Codecov / codecov/patch

ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt#L45

Added line #L45 was not covered by tests
as CaptureLocationTaskViewModel
}

Check warning on line 47 in ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt

View check run for this annotation

Codecov / codecov/patch

ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt#L47

Added line #L47 was not covered by tests
} catch (e: Exception) {
Timber.e(e)
}
}
}

override fun getMapViewModel(): BaseMapViewModel = mapViewModel
Expand All @@ -46,18 +60,28 @@
): View {
val root = super.onCreateView(inflater, container, savedInstanceState)
viewLifecycleOwner.lifecycleScope.launch {
getMapViewModel().getLocationUpdates().collect { viewModel.updateLocation(it) }
if (this@CaptureLocationTaskMapFragment::viewModel.isInitialized) {
getMapViewModel().getLocationUpdates().collect { viewModel.updateLocation(it) }
}
}
return root
}

override fun onMapReady(map: MapFragment) {
binding.locationLockBtn.isClickable = false
viewLifecycleOwner.lifecycleScope.launch { viewModel.onMapReady(mapViewModel) }
viewLifecycleOwner.lifecycleScope.launch {

Check warning on line 72 in ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt

View check run for this annotation

Codecov / codecov/patch

ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt#L72

Added line #L72 was not covered by tests
if (this@CaptureLocationTaskMapFragment::viewModel.isInitialized) {
viewModel.onMapReady(mapViewModel)
}
}

Check warning on line 76 in ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt

View check run for this annotation

Codecov / codecov/patch

ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/location/CaptureLocationTaskMapFragment.kt#L76

Added line #L76 was not covered by tests
}

companion object {
fun newInstance(viewModel: CaptureLocationTaskViewModel, map: MapFragment) =
CaptureLocationTaskMapFragment(viewModel).apply { this.map = map }
fun newInstance(map: MapFragment, taskId: String): CaptureLocationTaskMapFragment {
val fragment = CaptureLocationTaskMapFragment().apply { this.map = map }
val args = Bundle().apply { putString("taskId", taskId) }
fragment.arguments = args
return fragment
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@ class DropPinTaskFragment : AbstractTaskFragment<DropPinTaskViewModel>() {
// 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 = DropPinTaskMapFragment.newInstance(map, taskId)
parentFragmentManager
.beginTransaction()
.add(rowLayout.id, DropPinTaskMapFragment.newInstance(viewModel, map), "Drop a pin fragment")
.add(rowLayout.id, fragment, "Drop a pin fragment")
.commit()
return rowLayout
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,56 @@
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 timber.log.Timber

@AndroidEntryPoint
class DropPinTaskMapFragment(private val viewModel: DropPinTaskViewModel) :
AbstractMapFragmentWithControls() {
class DropPinTaskMapFragment : AbstractMapFragmentWithControls() {

private lateinit var mapViewModel: BaseMapViewModel
private lateinit var viewModel: DropPinTaskViewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mapViewModel = getViewModel(BaseMapViewModel::class.java)
arguments?.let {
try {
val taskId = it.getString("taskId")
taskId?.let {
viewModel =
(requireParentFragment() as DataCollectionFragment).viewModel.getTaskViewModel(taskId)

Check warning on line 41 in ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt

View check run for this annotation

Codecov / codecov/patch

ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt#L41

Added line #L41 was not covered by tests
as DropPinTaskViewModel
}
} catch (e: Exception) {

Check warning on line 44 in ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt

View check run for this annotation

Codecov / codecov/patch

ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/point/DropPinTaskMapFragment.kt#L43-L44

Added lines #L43 - L44 were not covered by tests
Timber.e(e)
}
}
}

override fun getMapViewModel(): BaseMapViewModel = mapViewModel

override fun onMapReady(map: MapFragment) {
viewModel.features.observe(this) { map.setFeatures(it) }
if (this@DropPinTaskMapFragment::viewModel.isInitialized) {
viewModel.features.observe(this) { map.setFeatures(it) }
}
}

override fun onMapCameraMoved(position: CameraPosition) {
super.onMapCameraMoved(position)
viewModel.updateCameraPosition(position)
if (this@DropPinTaskMapFragment::viewModel.isInitialized) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Swallowing the invalid state here as well will make the issue impossible to identify in prod and even difficult to find locally.

viewModel.updateCameraPosition(position)
}
}

companion object {
fun newInstance(viewModel: DropPinTaskViewModel, map: MapFragment) =
DropPinTaskMapFragment(viewModel).apply { this.map = map }
fun newInstance(map: MapFragment, taskId: String): DropPinTaskMapFragment {
val fragment = DropPinTaskMapFragment().apply { this.map = map }
val args = Bundle().apply { putString("taskId", taskId) }
fragment.arguments = args
return fragment
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class DrawAreaTaskFragment : AbstractTaskFragment<DrawAreaTaskViewModel>() {
// 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)
drawAreaTaskMapFragment = DrawAreaTaskMapFragment.newInstance(map, taskId)
parentFragmentManager
.beginTransaction()
.add(rowLayout.id, drawAreaTaskMapFragment, DrawAreaTaskMapFragment::class.java.simpleName)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,52 @@
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 kotlinx.coroutines.launch
import timber.log.Timber

@AndroidEntryPoint
class DrawAreaTaskMapFragment(private val viewModel: DrawAreaTaskViewModel) :
AbstractMapFragmentWithControls() {
class DrawAreaTaskMapFragment : AbstractMapFragmentWithControls() {

private lateinit var mapViewModel: BaseMapViewModel
private lateinit var viewModel: DrawAreaTaskViewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mapViewModel = getViewModel(BaseMapViewModel::class.java)
arguments?.let {
try {
val taskId = it.getString("taskId")
taskId?.let {
viewModel =
(requireParentFragment() as DataCollectionFragment).viewModel.getTaskViewModel(taskId)
as DrawAreaTaskViewModel
}

Check warning on line 46 in ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt

View check run for this annotation

Codecov / codecov/patch

ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt#L46

Added line #L46 was not covered by tests
} catch (e: Exception) {
Timber.e(e)
}
}
}

override fun getMapViewModel(): BaseMapViewModel = mapViewModel

override fun onMapReady(map: MapFragment) {
viewLifecycleOwner.lifecycleScope.launch {
viewModel.draftArea.collect { feature: Feature? ->
map.setFeatures(if (feature == null) setOf() else setOf(feature))
if (this@DrawAreaTaskMapFragment::viewModel.isInitialized) {
viewModel.draftArea.collect { feature: Feature? ->
map.setFeatures(if (feature == null) setOf() else setOf(feature))
}

Check warning on line 60 in ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt

View check run for this annotation

Codecov / codecov/patch

ground/src/main/java/com/google/android/ground/ui/datacollection/tasks/polygon/DrawAreaTaskMapFragment.kt#L60

Added line #L60 was not covered by tests
}
}
}

override fun onMapCameraMoved(position: CameraPosition) {
super.onMapCameraMoved(position)
if (!viewModel.isMarkedComplete()) {
if (this@DrawAreaTaskMapFragment::viewModel.isInitialized && !viewModel.isMarkedComplete()) {
val mapCenter = position.coordinates
viewModel.updateLastVertexAndMaybeCompletePolygon(mapCenter) { c1, c2 ->
map.getDistanceInPixels(c1, c2)
Expand All @@ -57,7 +73,11 @@
}

companion object {
fun newInstance(viewModel: DrawAreaTaskViewModel, map: MapFragment) =
DrawAreaTaskMapFragment(viewModel).apply { this.map = map }
fun newInstance(map: MapFragment, taskId: String): DrawAreaTaskMapFragment {
val fragment = DrawAreaTaskMapFragment().apply { this.map = map }
val args = Bundle().apply { putString("taskId", taskId) }
fragment.arguments = args
return fragment
}
}
}