-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Convert reference layer selection to bottom sheet in select one from map #6118
Conversation
2f69ea9
to
d8901ce
Compare
@seadowg could you take a look at the test that is failing here please? collect/geo/src/test/java/org/odk/collect/geo/selection/SelectionMapFragmentTest.kt Line 407 in b3cd4a0
Here is the reason: Caused by: java.lang.ClassCastException: class org.odk.collect.geo.support.RobolectricApplication cannot be cast to class org.odk.collect.maps.MapsDependencyComponentProvider The test is in the |
The I do think that having Dagger dependencies go down multiple layers ( I think a setup like Happy to discuss more here on Slack if that's not clear! |
1278726
to
fd1d2d5
Compare
92568d7
to
2ee0d67
Compare
2ee0d67
to
14647e9
Compare
|
||
<org.odk.collect.androidshared.ui.multiclicksafe.MultiClickSafeMaterialButton | ||
android:id="@+id/save" | ||
style="?materialButtonStyle" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seadowg please take a look at this button. The styling does not work well. If it was an activity everything would be fine (for example we use the same styling in the crash-handler module and there it works well). There is something wrong with using it in fragments in separate modules I guess. Do you maybe know what is wrong?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wow that's weird! It looks to me like bottom sheets might get their own theme overlay set on them (although I haven't looked into it deeply). The hint for that is that you can set style to @style/Widget.Material3.Button
and get what you'd expect, but using ?materialButtonStyle
is just giving us a bolder text button. My guess is that bottom sheets have an overlay theme that overrides ?materialButtonStyle
and that we might need to customise and set our own theme for them (like we do with dialogs). The Material Components repo on Github is probably a good place to look into.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it looks like we need to set our own theme for bottom sheets.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just done a quick overview of the general structure and had one comment.
Also, I don't have an any mbtiles to try out, but how does the map reload with the new layer? It seems like the underlying setting changes when the user selects a tile, but it's not clear to me what then triggers that being used. I'm probably missing something obvious!
7b8887e
to
96ecc95
Compare
This is a thing I haven't had to touch even. There is a listener that is called whenever the settings are updated and then we update the map in the map fragment that we use (Google, Mapbox or OSM). |
Sorry I really think we should split this up. I've started going through it commit but commit, but because the PR builds things up iteratively (like d2517fe for example), I'd really like to be able to use "Files changed" to also keep track of the final state of things so I'm not commenting on intermediarey states. Just to be clear, I really like the step by step approach, it just hard to combine that with a partial review given the tooling we have. This should be split after d6c9705 - another branch should be created there and this one should be |
a109650
to
a194524
Compare
@seadowg ok the first part is ready. |
Thanks so much! That's going to be really helpful. |
collect_app/src/main/java/org/odk/collect/android/injection/config/AppDependencyModule.java
Show resolved
Hide resolved
maps/src/test/java/org/odk/collect/maps/layers/OfflineMapLayersPickerTest.kt
Outdated
Show resolved
Hide resolved
maps/src/test/java/org/odk/collect/maps/layers/OfflineMapLayersPickerTest.kt
Show resolved
Hide resolved
import org.odk.collect.settings.SettingsProvider | ||
import org.odk.collect.webpage.ExternalWebPageHelper | ||
|
||
class OfflineMapLayersPicker( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just something to consider: I'd be tempted to pass in the ViewModel
or ViewModelProvider.Factory
here instead of the ViewModel's dependencies. That would let you have more concentrated tests of the Fragment and ViewModel.
I don't think that would be very advantageous in this PR (OfflineMapsLayerPickerTest
is pretty simple and easy to read), but it might be useful down the line if you wanted to test something like the ordering of layers (which would be easier to test at the ViewModel level).
This is definitely related to our earlier discussion on the injection setup, and I think I'm again suggesting the approach I put forward in #6118 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's keep this in mind but do not change now. I'm not against but I also think it's not something we definitely need to change.
When it comes to testing I already verify the order of displayed layers in OfflineMapLayersPickerTest
.
Even if after merging this pr and creating a new one I change my mind and start thinking that yeah we should have it, it would be better to do that later so that I can cherry-pick the commits I've removed easier.
} | ||
|
||
override fun onBindViewHolder(holder: ViewHolder, position: Int) { | ||
holder.binding.radioButton.setChecked(false) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the recycling here isn't tested.
It could be worth extracting a helper adapter for single select lists like this (like we already have for multi select in MultiSelectAdapter
), but that potentially a follow up change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I wanted to avoid creating a custom view for list elements but that would make testing easier. Let's wait until it has its final form (expandable with the delete button).
private val settingsProvider: SettingsProvider | ||
) : ViewModel() { | ||
private val _data = MutableLiveData<Pair<List<ReferenceLayer>, String?>>() | ||
val data: LiveData<Pair<List<ReferenceLayer>, String?>> = _data |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably worth creating a specific data class to represent the view data here (rather than using Pair
) just so it's a little more readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree and I came to the same conclusion but at a later stage (while working on deleting layers when I need even more details like for example if the layer item is expanded or collapsed). If it's ok, let's maybe keep it unchanged for now so that I can cherry-pick commits that will improve this code without any conflicts (in one of the next prs).
android:layout_height="wrap_content" | ||
android:minWidth="0dp" | ||
android:minHeight="0dp" | ||
android:translationX="-5dp" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The RadioButton
has a margin that I remove using this. I don't want it. I want the button to start from the edge of the layout without any extra margin. The TriggerWIdget
uses the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I see now: offline_map_layers_picker.xml
defines a guideline that the RecyclerView
starts at so we don't need the built in margin in here. The problem there is that we end up with the start edge of the screen not being tappable, even though I'd expect the list item to be selectable across the full horizontal space. I think we should make the RecyclerView
full width and remove this (although we might want to adjus the start padding to one of our standard margins).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean not so long ago we decided not to make the RecyclerView
responsible for displaying choices in select_one
/select_multiple
questions full-width and I think that one is much more important so I thought it's ok. Do you really want it to be the way you described it? If so I'm ok to do that but to me it's not an issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that was more to do with how we controlled widget margins. I don't think we need to do anything special here and can just let the RecyclerView
be full width.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, done.
maps/src/main/java/org/odk/collect/maps/layers/DirectoryReferenceLayerRepository.kt
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
1a785dc
to
85a5900
Compare
@@ -0,0 +1,5 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<inset xmlns:android="http://schemas.android.com/apk/res/android" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's super confusing that you have to do this and can't just set some kind of padding on the MaterialRadioButton
. Could you file an issue with this example at https://github.com/material-components/material-components-android? That really needs to get fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
assertThat(repository.getAll().map { it.file }, containsInAnyOrder(file1, file2)) | ||
val file3 = TempFiles.createTempFile(dir) | ||
val mapConfigurator = mock<MapConfigurator>().also { | ||
whenever(it.supportsLayer(file1)).thenReturn(true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a little more readable (for each test) to write a stub outside of Mockito here. For example:
private class StubMapConfigurator : MapConfigurator {
private val files = mutableMapOf<File, Pair<Boolean, String>>()
override fun supportsLayer(file: File?): Boolean {
return files[file]!!.first
}
override fun getDisplayName(file: File?): String {
return files[file]!!.second
}
fun addFile(fike: File, displayName: String, isSupported: Boolean) {
}
override fun isAvailable(context: Context?): Boolean {
TODO("Not yet implemented")
}
override fun showUnavailableMessage(context: Context?) {
TODO("Not yet implemented")
}
override fun createPrefs(context: Context?, settings: Settings?): MutableList<Preference> {
TODO("Not yet implemented")
}
override fun getPrefKeys(): MutableCollection<String> {
TODO("Not yet implemented")
}
override fun buildConfig(prefs: Settings?): Bundle {
TODO("Not yet implemented")
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@getodk/testers going to skip "needs testing" here so you can test the whole feature once managing tiles is added. |
Closes #5845
Closes #5851
Closes #5852
Why is this the best possible solution? Were any other approaches considered?
Generally, everything has been implemented according to what we had discussed earlier. The only difference might be related to this acceptance criteria:
From #5845
The bottom sheet can be expanded but only if it contains a long list of layers. Otherwise, it's not possible because everything is visible and there is no need to do that. This is the default behavior and I think it doesn't make sense to change it.
How does this change affect users? Describe intentional changes to behavior and behavior that could have accidentally been affected by code changes. In other words, what are the regression risks?
I think it will be better to these the whole feature at once when all the issues are addressed.
Do we need any specific form for testing your changes? If so, please attach one.
No.
Does this change require updates to documentation? If so, please file an issue here and include the link below.
No.
Before submitting this PR, please make sure you have:
./gradlew connectedAndroidTest
(or./gradlew testLab
) and confirmed all checks still pass