-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Add info button to trace/shape questions #7021
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
Changes from 11 commits
4c65541
fb86f34
dd9055f
b2b123c
4e0812e
41ae741
793cb69
f7c3f7a
d2686d7
e2bb2f4
800e0a2
6815817
69a034f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
|
|
||
| import androidx.activity.ComponentActivity; | ||
| import androidx.lifecycle.MutableLiveData; | ||
| import androidx.test.core.app.ApplicationProvider; | ||
| import androidx.test.ext.junit.runners.AndroidJUnit4; | ||
|
|
||
| import org.javarosa.form.api.FormEntryPrompt; | ||
|
|
@@ -31,6 +32,7 @@ public class InternalRecordingRequesterTest { | |
|
|
||
| @Before | ||
| public void setup() { | ||
| ApplicationProvider.getApplicationContext().setTheme(com.google.android.material.R.style.Theme_MaterialComponents); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this change needed? If I take it out, then there's a failure, but it seems completely unrelated to everything else here.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This happens because |
||
| ComponentActivity activity = Robolectric.buildActivity(ComponentActivity.class).get(); | ||
| when(audioRecorder.getCurrentSession()).thenReturn(new MutableLiveData<>(null)); | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,7 @@ import org.odk.collect.maps.PolygonDescription | |
| import org.odk.collect.maps.layers.OfflineMapLayersPickerBottomSheetDialogFragment | ||
| import org.odk.collect.maps.layers.ReferenceLayerRepository | ||
| import org.odk.collect.settings.SettingsProvider | ||
| import org.odk.collect.strings.R.string | ||
| import org.odk.collect.webpage.WebPageService | ||
| import javax.inject.Inject | ||
|
|
||
|
|
@@ -75,15 +76,7 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| private var map: MapFragment? = null | ||
| private var featureId = -1 // will be a positive featureId once map is ready | ||
| private var originalPoly: List<MapPoint>? = null | ||
|
|
||
| private var inputActive = false // whether we are ready for the user to add points | ||
| private var recordingEnabled = | ||
| false // whether points are taken from GPS readings (if not, placed by tapping) | ||
| private var recordingAutomatic = | ||
| false // whether GPS readings are taken at regular intervals (if not, only when user-directed) | ||
|
|
||
| private var intervalIndex: Int = DEFAULT_INTERVAL_INDEX | ||
|
|
||
| private var accuracyThresholdIndex: Int = DEFAULT_ACCURACY_THRESHOLD_INDEX | ||
|
|
||
| private val onBackPressedCallback: OnBackPressedCallback = | ||
|
|
@@ -143,9 +136,6 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| previousState = savedInstanceState | ||
|
|
||
| if (savedInstanceState != null) { | ||
| inputActive = savedInstanceState.getBoolean(INPUT_ACTIVE_KEY, false) | ||
| recordingEnabled = savedInstanceState.getBoolean(RECORDING_ENABLED_KEY, false) | ||
| recordingAutomatic = savedInstanceState.getBoolean(RECORDING_AUTOMATIC_KEY, false) | ||
| intervalIndex = savedInstanceState.getInt(INTERVAL_INDEX_KEY, DEFAULT_INTERVAL_INDEX) | ||
| accuracyThresholdIndex = savedInstanceState.getInt( | ||
| ACCURACY_THRESHOLD_INDEX_KEY, DEFAULT_ACCURACY_THRESHOLD_INDEX | ||
|
|
@@ -172,20 +162,17 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| } | ||
| return | ||
| } | ||
| state.putBoolean(INPUT_ACTIVE_KEY, inputActive) | ||
| state.putBoolean(RECORDING_ENABLED_KEY, recordingEnabled) | ||
| state.putBoolean(RECORDING_AUTOMATIC_KEY, recordingAutomatic) | ||
| state.putInt(INTERVAL_INDEX_KEY, intervalIndex) | ||
| state.putInt(ACCURACY_THRESHOLD_INDEX_KEY, accuracyThresholdIndex) | ||
| } | ||
|
|
||
| fun initMap(newMapFragment: MapFragment?, binding: GeopolyLayoutBinding) { | ||
| map = newMapFragment | ||
|
|
||
| binding.info.setOnClickListener { showInfoDialog(false) } | ||
| binding.clear.setOnClickListener { showClearDialog() } | ||
| binding.pause.setOnClickListener { | ||
| viewModel.stopRecording() | ||
| inputActive = false | ||
| updateUi() | ||
| } | ||
|
|
||
|
|
@@ -247,7 +234,14 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| } | ||
| } | ||
|
|
||
| val snackbar = SnackbarUtils.make(requireView(), "", Snackbar.LENGTH_INDEFINITE) | ||
| val snackbar = SnackbarUtils.make( | ||
| requireView(), | ||
| "", | ||
| Snackbar.LENGTH_INDEFINITE, | ||
| action = SnackbarUtils.Action(getString(string.how_to_modify)) { | ||
| showInfoDialog(true) | ||
| } | ||
| ) | ||
| val viewData = viewModel.points.asLiveData().zip(invalidMessage) | ||
| viewData.observe(viewLifecycleOwner) { (points, invalidMessage) -> | ||
| val isValid = invalidMessage == null | ||
|
|
@@ -354,8 +348,8 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| } | ||
|
|
||
| override fun startInput() { | ||
| inputActive = true | ||
| if (recordingEnabled && recordingAutomatic) { | ||
| viewModel.enableInput() | ||
| if (viewModel.recordingMode == GeoPolyViewModel.RecordingMode.AUTOMATIC) { | ||
| locationTracker.warm(map!!.getGpsLocation()?.toLocation()) | ||
| viewModel.startRecording( | ||
| ACCURACY_THRESHOLD_OPTIONS[accuracyThresholdIndex], | ||
|
|
@@ -366,15 +360,18 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| } | ||
|
|
||
| override fun updateRecordingMode(id: Int) { | ||
| recordingEnabled = id != R.id.placement_mode | ||
| recordingAutomatic = id == R.id.automatic_mode | ||
| when (id) { | ||
| R.id.placement_mode -> viewModel.setRecordingMode(GeoPolyViewModel.RecordingMode.PLACEMENT) | ||
| R.id.manual_mode -> viewModel.setRecordingMode(GeoPolyViewModel.RecordingMode.MANUAL) | ||
| R.id.automatic_mode -> viewModel.setRecordingMode(GeoPolyViewModel.RecordingMode.AUTOMATIC) | ||
| } | ||
| } | ||
|
|
||
| override fun getCheckedId(): Int { | ||
| return if (recordingEnabled) { | ||
| if (recordingAutomatic) R.id.automatic_mode else R.id.manual_mode | ||
| } else { | ||
| R.id.placement_mode | ||
| return when (viewModel.recordingMode) { | ||
| GeoPolyViewModel.RecordingMode.PLACEMENT -> R.id.placement_mode | ||
| GeoPolyViewModel.RecordingMode.MANUAL -> R.id.manual_mode | ||
| GeoPolyViewModel.RecordingMode.AUTOMATIC -> R.id.automatic_mode | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -410,21 +407,21 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| } | ||
|
|
||
| private fun onClick(point: MapPoint) { | ||
| if (inputActive && !recordingEnabled) { | ||
| if (viewModel.inputActive && viewModel.recordingMode == GeoPolyViewModel.RecordingMode.PLACEMENT) { | ||
| viewModel.add(point) | ||
| } | ||
| } | ||
|
|
||
| private fun onGpsLocationReady(map: MapFragment) { | ||
| // Don't zoom to current location if a user is manually entering points | ||
| if (requireActivity().window.isActive && (!inputActive || recordingEnabled)) { | ||
| if (requireActivity().window.isActive && (!viewModel.inputActive || viewModel.recordingMode != GeoPolyViewModel.RecordingMode.PLACEMENT)) { | ||
| map.zoomToCurrentLocation(map.getGpsLocation()) | ||
| } | ||
| updateUi() | ||
| } | ||
|
|
||
| private fun onGpsLocation(point: MapPoint?) { | ||
| if (inputActive && recordingEnabled) { | ||
| if (viewModel.inputActive && viewModel.recordingMode != GeoPolyViewModel.RecordingMode.PLACEMENT) { | ||
| map!!.setCenter(point, false) | ||
| } | ||
| updateUi() | ||
|
|
@@ -447,7 +444,7 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| get() { | ||
| val meters: Int = | ||
| ACCURACY_THRESHOLD_OPTIONS[accuracyThresholdIndex] | ||
| return recordingEnabled && recordingAutomatic && meters > 0 | ||
| return viewModel.recordingMode == GeoPolyViewModel.RecordingMode.AUTOMATIC && meters > 0 | ||
| } | ||
|
|
||
| private fun removeLastPoint() { | ||
|
|
@@ -457,7 +454,7 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| } | ||
|
|
||
| private fun clear() { | ||
| inputActive = false | ||
| viewModel.disableInput() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need this? The tests pass without it and I think whenever we call
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
No, it’s not guaranteed. I didn’t think much about whether it’s mandatory here or not I just tried to mirror the old implementation. So if we used to set the flag to false here, I’m doing the same now.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gotcha. I can maybe just pull it out in the next PR if it's not needed. |
||
| viewModel.update(emptyList()) | ||
| } | ||
|
|
||
|
|
@@ -469,14 +466,14 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| val location = map!!.getGpsLocation() | ||
|
|
||
| // Visibility state | ||
| binding.play.isVisible = !inputActive | ||
| binding.pause.isVisible = inputActive | ||
| binding.recordButton.isVisible = inputActive && recordingEnabled && !recordingAutomatic | ||
| binding.play.isVisible = !viewModel.inputActive | ||
| binding.pause.isVisible = viewModel.inputActive | ||
| binding.recordButton.isVisible = viewModel.inputActive && viewModel.recordingMode == GeoPolyViewModel.RecordingMode.MANUAL | ||
|
|
||
| // Enabled state | ||
| binding.zoom.isEnabled = location != null | ||
| binding.backspace.isEnabled = numPoints > 0 | ||
| binding.clear.isEnabled = !inputActive && numPoints > 0 | ||
| binding.clear.isEnabled = !viewModel.inputActive && numPoints > 0 | ||
|
|
||
| if (readOnly) { | ||
| binding.play.isEnabled = false | ||
|
|
@@ -501,16 +498,16 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| } | ||
| } | ||
|
|
||
| binding.collectionStatus.text = if (!inputActive) { | ||
| binding.collectionStatus.text = if (!viewModel.inputActive) { | ||
| getString(org.odk.collect.strings.R.string.collection_status_paused, numPoints) | ||
| } else { | ||
| if (!recordingEnabled) { | ||
| if (viewModel.recordingMode == GeoPolyViewModel.RecordingMode.PLACEMENT) { | ||
| getString( | ||
| org.odk.collect.strings.R.string.collection_status_placement, | ||
| numPoints | ||
| ) | ||
| } else { | ||
| if (!recordingAutomatic) { | ||
| if (viewModel.recordingMode == GeoPolyViewModel.RecordingMode.MANUAL) { | ||
| getString( | ||
| org.odk.collect.strings.R.string.collection_status_manual, | ||
| numPoints | ||
|
|
@@ -552,6 +549,10 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| } | ||
| } | ||
|
|
||
| private fun showInfoDialog(fromSnackbar: Boolean) { | ||
| InfoDialog.show(requireContext(), viewModel, fromSnackbar) | ||
| } | ||
|
|
||
| private fun showClearDialog() { | ||
| if (!viewModel.points.value.isEmpty()) { | ||
| MaterialAlertDialogBuilder(requireContext()) | ||
|
|
@@ -578,10 +579,6 @@ class GeoPolyFragment @JvmOverloads constructor( | |
| const val REQUEST_GEOPOLY: String = "geopoly" | ||
| const val RESULT_GEOPOLY: String = "geopoly" | ||
| const val RESULT_GEOPOLY_CHANGE: String = "geopoly_change" | ||
|
|
||
| const val INPUT_ACTIVE_KEY: String = "input_active" | ||
| const val RECORDING_ENABLED_KEY: String = "recording_enabled" | ||
| const val RECORDING_AUTOMATIC_KEY: String = "recording_automatic" | ||
| const val INTERVAL_INDEX_KEY: String = "interval_index" | ||
| const val ACCURACY_THRESHOLD_INDEX_KEY: String = "accuracy_threshold_index" | ||
| val INTERVAL_OPTIONS = intArrayOf( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.