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 @@ -39,8 +39,8 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
Expand All @@ -57,12 +57,14 @@ 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.map.NewCameraPositionViaCoordinatesAndZoomLevel
import org.groundplatform.android.ui.map.gms.GmsExt.contains
import org.groundplatform.android.ui.map.gms.GmsExt.toBounds
import org.groundplatform.android.ui.map.gms.toCoordinates
import org.groundplatform.android.ui.util.getDefaultColor
import org.groundplatform.domain.model.Survey
import org.groundplatform.domain.model.geometry.Coordinates
import org.groundplatform.domain.model.imagery.TileSource
import org.groundplatform.domain.model.locationofinterest.LocationOfInterest
import org.groundplatform.domain.model.map.CameraPosition
import org.groundplatform.domain.model.map.MapType
import org.groundplatform.domain.repository.LocationOfInterestRepositoryInterface
Expand Down Expand Up @@ -135,32 +137,33 @@ constructor(
.asLiveData()

/**
* Read-only LOI features for the active survey. Lazily initialized to avoid unnecessary database
* queries when not rendered.
* Read-only LOI features for the active survey which fall within the visible viewport. Lazily
* initialized to avoid unnecessary database queries when not rendered.
*/
val existingLoiFeatures: Flow<Set<Feature>> by lazy {
val existingLoiFeatures: StateFlow<Set<Feature>> by lazy {
surveyRepository.activeSurveyFlow
.flatMapLatest { survey ->
if (survey == null) flowOf(emptySet())
else locationOfInterestRepository.getValidLois(survey)
}
.map { lois ->
lois
.map {
Feature(
id = it.id,
type = Feature.Type.LOCATION_OF_INTEREST,
geometry = it.geometry,
style = Feature.Style(it.job.getDefaultColor()),
clusterable = false,
)
}
.toSet()
.combine(getCurrentCameraPosition().mapNotNull { it.bounds }.distinctUntilChanged()) {
lois,
bounds ->
lois.filter { bounds.contains(it.geometry) }
}
.onStart { emit(setOf()) }
.distinctUntilChanged()
.map { lois -> lois.map { it.toFeature() }.toSet() }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5_000), setOf())
}

private fun LocationOfInterest.toFeature() =
Feature(
id = id,
type = Feature.Type.LOCATION_OF_INTEREST,
geometry = geometry,
style = Feature.Style(job.getDefaultColor()),
clusterable = false,
)

/** Returns whether the user has granted fine location permission. */
fun hasLocationPermission() =
permissionsManager.isGranted(Manifest.permission.ACCESS_FINE_LOCATION)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,9 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -479,11 +476,6 @@ internal constructor(
}
}

fun isCurrentActiveTaskFlow(taskId: String): Flow<Boolean> =
uiState
.map { (it as? DataCollectionUiState.Ready)?.currentTaskId == taskId }
.distinctUntilChanged()

private fun DataCollectionUiState.Ready.withTask(taskId: String): DataCollectionUiState.Ready {
savedStateHandle[TASK_POSITION_ID] = taskId
return copy(currentTaskId = taskId, position = taskSequenceHandler.getTaskPosition(taskId))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,12 +149,12 @@ abstract class AbstractTaskMapFragment<TVM : AbstractTaskViewModel> :

@MustBeInvokedByOverriders
override fun onMapReady(map: MapFragment) {
launchWhenTaskVisible(dataCollectionViewModel, taskId) {
launch { getMapViewModel().getCurrentCameraPosition().collect { onMapCameraMoved(it) } }
launch { renderFeatures().collect { map.setFeatures(it) } }
// Allow the fragment to restore map viewport to previously drawn feature.
setDefaultViewPort()
launchWhenStarted {
getMapViewModel().getCurrentCameraPosition().collect { onMapCameraMoved(it) }
}
launchWhenStarted { renderFeatures().collect { map.setFeatures(it) } }
// Allow the fragment to restore map viewport to previously drawn feature.
launchWhenStarted { setDefaultViewPort() }
}

/** Must be overridden by subclasses. */
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import org.groundplatform.android.ui.common.MapConfig
import org.groundplatform.android.ui.datacollection.tasks.AbstractTaskMapFragment
import org.groundplatform.android.ui.datacollection.tasks.launchWhenTaskVisible
import org.groundplatform.android.ui.map.MapFragment

@AndroidEntryPoint
Expand All @@ -30,7 +29,7 @@ class CaptureLocationTaskMapFragment @Inject constructor() :

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
launchWhenTaskVisible(dataCollectionViewModel, taskId) {
launchWhenStarted {
getMapViewModel().getLocationUpdates().collect { taskViewModel.updateLocation(it) }
}
}
Expand All @@ -39,8 +38,6 @@ class CaptureLocationTaskMapFragment @Inject constructor() :

override fun onMapReady(map: MapFragment) {
super.onMapReady(map)
launchWhenTaskVisible(dataCollectionViewModel, taskId) {
taskViewModel.initLocationUpdates(getMapViewModel())
}
launchWhenStarted { taskViewModel.initLocationUpdates(getMapViewModel()) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import org.groundplatform.android.ui.datacollection.tasks.AbstractTaskMapFragment
import org.groundplatform.android.ui.datacollection.tasks.launchWhenTaskVisible
import org.groundplatform.android.ui.map.Feature
import org.groundplatform.android.ui.map.MapFragment
import org.groundplatform.domain.model.map.CameraPosition
Expand All @@ -33,9 +32,7 @@ class DropPinTaskMapFragment @Inject constructor() :
super.onMapReady(map)

// Disable pan/zoom gestures if a marker has been placed on the map.
launchWhenTaskVisible(dataCollectionViewModel, taskId) {
taskViewModel.features.collect { features -> updateGestures(features) }
}
launchWhenStarted { taskViewModel.features.collect { features -> updateGestures(features) } }
}

private fun updateGestures(features: Set<Feature>) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import org.groundplatform.android.ui.datacollection.tasks.AbstractTaskMapFragment
import org.groundplatform.android.ui.datacollection.tasks.launchWhenTaskVisible
import org.groundplatform.android.ui.map.Feature
import org.groundplatform.android.ui.map.gms.GmsExt.toBounds
import org.groundplatform.domain.model.map.CameraPosition
Expand All @@ -36,26 +34,24 @@ class DrawAreaTaskMapFragment @Inject constructor() :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)

launchWhenTaskVisible(dataCollectionViewModel, taskId) {
launch {
taskViewModel.sessionState
.map { state -> !state.isTooClose && !state.isMarkedComplete }
.collect { shouldShow -> setCenterMarkerVisibility(shouldShow) }
}
launchWhenStarted {
taskViewModel.sessionState
.map { state -> !state.isTooClose && !state.isMarkedComplete }
.collect { shouldShow -> setCenterMarkerVisibility(shouldShow) }
}

launch {
map.cameraDragEvents.collect { coord ->
if (!taskViewModel.isMarkedComplete()) {
taskViewModel.updateLastVertexAndMaybeCompletePolygon(coord) { c1, c2 ->
map.getDistanceInPixels(c1, c2)
}
launchWhenStarted {
map.cameraDragEvents.collect { coord ->
if (!taskViewModel.isMarkedComplete()) {
taskViewModel.updateLastVertexAndMaybeCompletePolygon(coord) { c1, c2 ->
map.getDistanceInPixels(c1, c2)
}
}
}
}

launch {
taskViewModel.cameraMoveEvents.collect { coordinates -> moveToPosition(coordinates) }
}
launchWhenStarted {
taskViewModel.cameraMoveEvents.collect { coordinates -> moveToPosition(coordinates) }
}
}

Expand Down
Loading
Loading