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 #6118
base: master
Are you sure you want to change the base?
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!
@@ -112,4 +108,14 @@ open class GeoDependencyModule { | |||
} | |||
} | |||
} | |||
|
|||
@Provides | |||
open fun providesOfflineMapLayersPickerViewModelFactory(): OfflineMapLayersPickerViewModel.Factory { |
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 I'd prefer it if we just added providers for ReferenceLayerRepository
and SettingsProvider
here. We could then avoid a specific implementation of ViewModelProvider.Factory
for OfflineMapLayersPickerViewModel
and just have a shared view model factory for geo components that can construct one (like we do with form entry). This approach keeps a more specific set of components "injectable" (the "building blocks") and should reduce the amount of view model factories we need.
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 I'd prefer it if we just added providers for ReferenceLayerRepository and SettingsProvider here. We could then avoid a specific implementation of ViewModelProvider.Factory for OfflineMapLayersPickerViewModel and just have a shared view model factory for geo components that can construct one (like we do with form entry).
I see what you mean. I think the reason I did this in that way was that I wanted to have one class to wrap the three dependencies I need (ReferenceLayerRepository
, Scheduler
, SettingsProvider
and potentially more when I add importing/deleting layers) so that I don't have to inject all of them separately in GeoPolyActivity
, GeoPointMapActivity
, SelectionMapFragment
and MapsPreferencesFragment
(every place where we use the new maps picker). Do you think converting OfflineMapLayersPickerViewModel.Factory
to a more general one (but still injecting it in the same way) that would in the future as you said work like FormEntryViewModelFactory
would be a good trade off 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.
I think the reason I did this in that way was that I wanted to have one class to wrap the three dependencies I need (ReferenceLayerRepository, Scheduler, SettingsProvider and potentially more when I add importing/deleting layers) so that I don't have to inject all of them separately in GeoPolyActivity, GeoPointMapActivity, SelectionMapFragment and MapsPreferencesFragment (every place where we use the new maps picker).
I think it's ok to have all those injections. I like the model of dependency injection just handling the edges of the system. The hope there is you end up with more being injected into entry point "black boxes" (like Activity objects), but less actual depdencies being managed by the framework with plain ol' constructors doing most of the work.
Maybe a nice way of having our cake and eating it here is to create two Factory
implementations - one for geo
(GeoViewModelFactory
) and one for MapPreferenecesFragment
in collect_app
(MapPreferencesViewModelFactory
). Then we could just use @Inject
on their constructors. You still only have to deal with one @Inject
in both places, but we still don't have declare the factory as a dependency of geo
anywhere. I'd thought about doing this for FormEntryViewModelFactory
before, but hadn't got round to it. I like this approach as it gives us the convenience of Dagger in the Activity/Fragment, but doesn't mean managing dependencies outside (in the module etc) and you still have a simple ViewModel factory constructor.
ace1480
to
1791ec5
Compare
1791ec5
to
e41dc05
Compare
Closes #5845
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:
The bottom sheet can be expanded but only if it contains a long list of layers to choose. 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?
There should be a new map layers picker used everywhere the old one was used:
Please test the new picker with a long list of offline layers to make sure it behaves well. Please keep in mind that different map providers support different layer types: Google and OSM support only raster layers but Mapbox supports both raster and vector layers. It's important because unsupported layers should not be visible when you switch between those map providers and additionally, when a vector layer is set in Mapbox it should be set to
None
once you switch to Google or OSM since as I already said it's not supported there.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