Compare commits

...

3 Commits

Author SHA1 Message Date
johan12345
99e7ae45a8 fix endless loading with filters that do not support local SQL queries 2025-07-27 17:36:52 +02:00
johan12345
88bb527972 Release 1.9.19 2025-07-14 00:10:01 +02:00
johan12345
55fe921a9e API 35 compat: handle bottom nav bar insets 2025-07-14 00:08:30 +02:00
7 changed files with 75 additions and 17 deletions

View File

@@ -21,8 +21,8 @@ android {
minSdk = 21
targetSdk = 35
// NOTE: always increase versionCode by 2 since automotive flavor uses versionCode + 1
versionCode = 256
versionName = "1.9.18"
versionCode = 258
versionName = "1.9.19"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

View File

@@ -160,6 +160,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MenuProvider {
private var previousChargepointIds: Set<Long>? = null
private var mapTopPadding: Int = 0
private var popupMenu: PopupMenu? = null
private var insetBottom: Int = 0
private lateinit var clusterIconGenerator: ClusterIconGenerator
private lateinit var chargerIconGenerator: ChargerIconGenerator
@@ -279,6 +280,10 @@ class MapFragment : Fragment(), OnMapReadyCallback, MenuProvider {
// and cause an infinite loop. So we rely on onMapReady being called later than
// onApplyWindowInsets.
insetBottom = insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom
binding.navBarScrim.layoutParams.height = insetBottom
updatePeekHeight()
insets
}
@@ -293,6 +298,10 @@ class MapFragment : Fragment(), OnMapReadyCallback, MenuProvider {
return binding.root
}
private fun updatePeekHeight() {
bottomSheetBehavior.peekHeight = binding.detailView.topPart.bottom + insetBottom
}
private fun getMapProvider(provider: String) = when (provider) {
"mapbox" -> MapFactory.MAPLIBRE
"google" -> MapFactory.GOOGLE
@@ -322,7 +331,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MenuProvider {
}
binding.detailView.topPart.doOnNextLayout {
bottomSheetBehavior.peekHeight = binding.detailView.topPart.bottom
updatePeekHeight()
vm.bottomSheetState.value?.let { bottomSheetBehavior.state = it }
}
bottomSheetBehavior.isCollapsible = bottomSheetCollapsible
@@ -667,6 +676,14 @@ class MapFragment : Fragment(), OnMapReadyCallback, MenuProvider {
min(bottomSheetBehavior.peekHeight, height)
)
}
println(slideOffset)
if (bottomSheetBehavior.state != STATE_HIDDEN) {
binding.navBarScrim.visibility = View.VISIBLE
binding.navBarScrim.translationY =
(if (slideOffset < 0f) -slideOffset else 2 * slideOffset) * binding.navBarScrim.height
} else {
binding.navBarScrim.visibility = View.INVISIBLE
}
}
override fun onStateChanged(bottomSheet: View, newState: Int) {

View File

@@ -16,14 +16,15 @@ import java.time.Instant
* successful.
*/
class CacheLiveData<T>(
cache: LiveData<T>,
cache: LiveData<Resource<T>>,
api: LiveData<Resource<T>>,
skipApi: LiveData<Boolean>? = null
) :
MediatorLiveData<Resource<T>>() {
private var cacheResult: T? = null
private var cacheResult: Resource<T>? = null
private var apiResult: Resource<T>? = null
private var skipApiResult: Boolean = false
private val apiLiveData = api
init {
updateValue()
@@ -64,9 +65,21 @@ class CacheLiveData<T>(
Log.d("CacheLiveData", "cache has finished loading before API")
// cache has finished loading before API
if (skipApiResult) {
value = Resource.success(cache)
value = when (cache.status) {
Status.SUCCESS -> cache
Status.ERROR -> {
Log.d("CacheLiveData", "Cache returned an error, querying API")
addSource(apiLiveData) {
apiResult = it
updateValue()
}
Resource.loading(null)
}
Status.LOADING -> cache
}
} else {
value = Resource.loading(cache)
value = Resource.loading(cache.data)
}
} else if (cache == null && api != null) {
Log.d("CacheLiveData", "API has finished loading before cache")
@@ -81,7 +94,7 @@ class CacheLiveData<T>(
// Both cache and API have finished loading
value = when (api.status) {
Status.SUCCESS -> api
Status.ERROR -> Resource.error(api.message, cache)
Status.ERROR -> Resource.error(api.message, cache.data)
Status.LOADING -> api // should not occur
}
}

View File

@@ -165,10 +165,16 @@ class ChargeLocationsRepository(
bounds.northeast.longitude,
api.id,
cacheLimitDate(api)
)
).map { Resource.success(it) }
} else {
queryWithFilters(api, filters, bounds)
}.map { ChargepointList(applyLocalClustering(it, zoom), true) }
}.map {
Resource(
it.status,
it.data?.let { ChargepointList(applyLocalClustering(it, zoom), true) },
it.message
)
}
val filtersSerialized =
filters?.filter { it.value != it.filter.defaultValue() }?.takeIf { it.isNotEmpty() }
?.serialize()
@@ -263,10 +269,16 @@ class ChargeLocationsRepository(
radiusMeters,
api.id,
cacheLimitDate(api)
)
).map { Resource.success(it) }
} else {
queryWithFilters(api, filters, location, radiusMeters)
}.map { ChargepointList(applyLocalClustering(it, zoom), true) }
}.map {
Resource(
it.status,
it.data?.let { ChargepointList(applyLocalClustering(it, zoom), true) },
it.message
)
}
val filtersSerialized =
filters?.filter { it.value != it.filter.defaultValue() }?.takeIf { it.isNotEmpty() }
?.serialize()
@@ -400,7 +412,7 @@ class ChargeLocationsRepository(
api: ChargepointApi<ReferenceData>,
filters: FilterValues,
bounds: LatLngBounds
): LiveData<List<ChargeLocation>> {
): LiveData<Resource<List<ChargeLocation>>> {
val region =
"Within(coordinates, BuildMbr(${bounds.southwest.longitude}, ${bounds.southwest.latitude}, ${bounds.northeast.longitude}, ${bounds.northeast.latitude}))"
return queryWithFilters(api, filters, region)
@@ -411,7 +423,7 @@ class ChargeLocationsRepository(
filters: FilterValues,
location: LatLng,
radius: Double
): LiveData<List<ChargeLocation>> {
): LiveData<Resource<List<ChargeLocation>>> {
val region =
"PtDistWithin(coordinates, MakePoint(${location.longitude}, ${location.latitude}, 4326), ${radius})"
val order =
@@ -424,7 +436,7 @@ class ChargeLocationsRepository(
filters: FilterValues,
regionSql: String,
orderSql: String? = null
): LiveData<List<ChargeLocation>> = referenceData.singleSwitchMap { refData ->
): LiveData<Resource<List<ChargeLocation>>> = referenceData.singleSwitchMap { refData ->
try {
val query = api.convertFiltersToSQL(filters, refData)
val after = cacheLimitDate(api)
@@ -454,9 +466,14 @@ class ChargeLocationsRepository(
sql,
null
)
)
).map { Resource.success(it) }
} catch (e: NotImplementedError) {
MutableLiveData() // in this case we cannot get a DB result
MutableLiveData(
Resource.error(
e.message,
null
)
) // in this case we cannot get a DB result
}
}

View File

@@ -245,6 +245,15 @@
app:layout_behavior="@string/hide_on_scroll_fab_behavior"
android:theme="@style/NoElevationOverlay" />
<View
android:id="@+id/navBarScrim"
android:layout_width="match_parent"
android:layout_height="16dp"
android:background="?android:colorBackground"
android:layout_gravity="bottom"
app:invisibleUnless="@{vm.bottomSheetState == BottomSheetBehaviorGoogleMapsLike.STATE_COLLAPSED}"
tools:visibility="invisible" />
<androidx.cardview.widget.CardView
android:id="@+id/layers_sheet"
android:layout_height="wrap_content"

View File

@@ -0,0 +1 @@
Kompatibilität mit Android 15

View File

@@ -0,0 +1 @@
Android 15 compatibility