Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ import org.groundplatform.android.ui.map.NewCameraPositionViaBounds
import org.groundplatform.android.ui.map.NewCameraPositionViaCoordinates
import org.groundplatform.android.ui.map.NewCameraPositionViaCoordinatesAndZoomLevel
import org.groundplatform.android.util.createComposeView
import org.groundplatform.domain.model.geometry.Coordinates
import org.groundplatform.domain.model.map.Bounds
import org.groundplatform.ui.map.MapConfig
import timber.log.Timber

Expand Down Expand Up @@ -79,7 +77,7 @@ abstract class AbstractMapContainerFragment : AbstractFragment() {
launchWhenStarted { map.startDragEvents.collect { viewModel.onMapDragged() } }
launchWhenStarted { viewModel.locationLock.collect { onLocationLockStateChange(it, map) } }
launchWhenStarted {
viewModel.getCameraUpdateRequests().collect { onCameraUpdateRequest(it, map) }
viewModel.getCameraUpdateRequests().collect { applyCameraUpdateRequest(it) }
}

applyMapConfig(map)
Expand Down Expand Up @@ -153,17 +151,8 @@ abstract class AbstractMapContainerFragment : AbstractFragment() {
Toast.makeText(context, messageId, Toast.LENGTH_LONG).show()
}

/** Moves the camera to the given bounds. */
fun moveToBounds(bounds: Bounds, padding: Int, shouldAnimate: Boolean) {
onCameraUpdateRequest(NewCameraPositionViaBounds(bounds, padding, shouldAnimate), map)
}

/** Moves the camera to a given position. */
fun moveToPosition(coordinates: Coordinates) {
onCameraUpdateRequest(NewCameraPositionViaCoordinates(coordinates, shouldAnimate = true), map)
}

private fun onCameraUpdateRequest(request: CameraUpdateRequest, map: MapFragment) {
/** Moves the camera as described by the given [CameraUpdateRequest]. */
fun applyCameraUpdateRequest(request: CameraUpdateRequest) {
Timber.v("Update camera: $request")
when (request) {
is NewCameraPositionViaCoordinates -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.lifecycle.withStarted
import java.math.RoundingMode
import java.text.DecimalFormat
import kotlinx.coroutines.flow.Flow
Expand Down Expand Up @@ -153,8 +154,7 @@ abstract class AbstractTaskMapFragment<TVM : AbstractTaskViewModel> :
getMapViewModel().getCurrentCameraPosition().collect { onMapCameraMoved(it) }
}
launchWhenStarted { renderFeatures().collect { map.setFeatures(it) } }
// Allow the fragment to restore map viewport to previously drawn feature.
launchWhenStarted { setDefaultViewPort() }
lifecycleScope.launch { withStarted { setDefaultViewPort() } }
}

/** Must be overridden by subclasses. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import kotlinx.coroutines.flow.combine
import org.groundplatform.android.ui.datacollection.tasks.AbstractTaskMapFragment
import org.groundplatform.android.ui.map.Feature
import org.groundplatform.android.ui.map.MapFragment
import org.groundplatform.android.ui.map.NewCameraPositionViaCoordinates
import org.groundplatform.domain.model.map.CameraPosition

@AndroidEntryPoint
Expand Down Expand Up @@ -58,6 +59,6 @@ class DropPinTaskMapFragment @Inject constructor() :
override fun setDefaultViewPort() {
val feature = taskViewModel.features.value?.firstOrNull() ?: return
val coordinates = feature.geometry.center()
moveToPosition(coordinates)
applyCameraUpdateRequest(NewCameraPositionViaCoordinates(coordinates, shouldAnimate = true))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import org.groundplatform.android.ui.datacollection.tasks.AbstractTaskMapFragment
import org.groundplatform.android.ui.map.Feature
import org.groundplatform.domain.model.map.Bounds
import org.groundplatform.android.ui.map.NewCameraPositionViaCoordinates
import org.groundplatform.domain.model.map.CameraPosition

@AndroidEntryPoint
Expand All @@ -51,15 +51,15 @@ class DrawAreaTaskMapFragment @Inject constructor() :
}

launchWhenStarted {
taskViewModel.cameraMoveEvents.collect { coordinates -> moveToPosition(coordinates) }
taskViewModel.cameraMoveEvents.collect { coordinates ->
applyCameraUpdateRequest(NewCameraPositionViaCoordinates(coordinates, shouldAnimate = true))
}
}
}

override fun setDefaultViewPort() {
val feature = taskViewModel.draftArea.value
val geometry = feature?.geometry ?: return
val bounds = Bounds.fromGeometry(geometry) ?: return
moveToBounds(bounds, padding = 200, shouldAnimate = false)
val request = taskViewModel.getDefaultViewPort() ?: return
applyCameraUpdateRequest(request)
}

override fun renderFeatures(): Flow<Set<Feature>> =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ import org.groundplatform.android.ui.datacollection.components.ButtonActionState
import org.groundplatform.android.ui.datacollection.tasks.AbstractMapTaskViewModel
import org.groundplatform.android.ui.datacollection.tasks.DataCollectionEvent
import org.groundplatform.android.ui.datacollection.tasks.TaskPositionInterface
import org.groundplatform.android.ui.map.CameraUpdateRequest
import org.groundplatform.android.ui.map.Feature
import org.groundplatform.android.ui.map.NewCameraPositionViaBounds
import org.groundplatform.android.ui.map.NewCameraPositionViaCoordinates
import org.groundplatform.android.ui.util.LocaleAwareMeasureFormatter
import org.groundplatform.android.ui.util.VibrationHelper
import org.groundplatform.android.ui.util.getDefaultColor
Expand All @@ -50,6 +53,7 @@ import org.groundplatform.domain.model.geometry.LineString
import org.groundplatform.domain.model.geometry.LinearRing
import org.groundplatform.domain.model.geometry.Polygon
import org.groundplatform.domain.model.job.Job
import org.groundplatform.domain.model.map.Bounds
import org.groundplatform.domain.model.settings.MeasurementUnits
import org.groundplatform.domain.model.submission.DrawAreaTaskData
import org.groundplatform.domain.model.submission.DrawAreaTaskIncompleteData
Expand Down Expand Up @@ -124,6 +128,19 @@ internal constructor(
.stateIn(viewModelScope, WhileSubscribed(5_000), emptyList())
}

/** Restores the viewport to the area drawn so far or null if nothing has been drawn yet. */
fun getDefaultViewPort(): CameraUpdateRequest? {
val vertices = session.vertices.distinct()
return when (vertices.size) {
0 -> null
1 -> NewCameraPositionViaCoordinates(vertices.first())
else ->
Bounds.fromCoordinates(vertices)?.let {
NewCameraPositionViaBounds(it, padding = 200, shouldAnimate = false)
}
}
}

override fun initialize(
job: Job,
task: Task,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,15 @@ import org.groundplatform.android.ui.datacollection.components.ButtonAction
import org.groundplatform.android.ui.datacollection.tasks.TaskPositionInterface
import org.groundplatform.android.ui.datacollection.tasks.polygon.PolygonDrawingSession.Companion.DISTANCE_THRESHOLD_DP
import org.groundplatform.android.ui.map.Feature
import org.groundplatform.android.ui.map.NewCameraPositionViaBounds
import org.groundplatform.android.ui.map.NewCameraPositionViaCoordinates
import org.groundplatform.domain.model.geometry.Coordinates
import org.groundplatform.domain.model.geometry.LineString
import org.groundplatform.domain.model.geometry.LinearRing
import org.groundplatform.domain.model.geometry.Polygon
import org.groundplatform.domain.model.job.Job
import org.groundplatform.domain.model.job.Style
import org.groundplatform.domain.model.map.Bounds
import org.groundplatform.domain.model.settings.MeasurementUnits
import org.groundplatform.domain.model.submission.DrawAreaTaskData
import org.groundplatform.domain.model.submission.DrawAreaTaskIncompleteData
Expand Down Expand Up @@ -105,6 +108,47 @@ class DrawAreaTaskViewModelTest : BaseHiltTest() {
assertThat(viewModel.isMarkedComplete()).isFalse()
}

@Test
fun `getDefaultViewPort returns null when nothing has been drawn`() {
setupViewModel()

assertThat(viewModel.getDefaultViewPort()).isNull()
}

@Test
fun `getDefaultViewPort centers on the first vertex`() {
setupViewModel()

updateLastVertexAndAdd(COORDINATE_1)

assertThat(viewModel.getDefaultViewPort())
.isEqualTo(NewCameraPositionViaCoordinates(COORDINATE_1))
}

@Test
fun `getDefaultViewPort centers on a restored draft of a single vertex`() {
setupViewModel(taskData = DrawAreaTaskIncompleteData(LineString(listOf(COORDINATE_1))))

assertThat(viewModel.getDefaultViewPort())
.isEqualTo(NewCameraPositionViaCoordinates(COORDINATE_1))
}

@Test
fun `getDefaultViewPort fits the camera to a draft covering an area`() {
setupViewModel()
updateLastVertexAndAdd(COORDINATE_1)

updateLastVertex(COORDINATE_2)

assertThat(viewModel.getDefaultViewPort())
.isEqualTo(
NewCameraPositionViaBounds(
Bounds.fromCoordinates(listOf(COORDINATE_1, COORDINATE_2))!!,
padding = 200,
)
)
}

@Test
fun `Removing last vertex on complete polygon`() {
setupViewModel()
Expand Down
Loading