Location: add icons for available payment methods (#1408)
* add backend for PaymentMethod.kt * change type of acceptedPaymentMethods to Map<PaymentMethod, Boolean> * add icons to UI and reduce PaymentMethod.kt to Cash and Card * make OSM parsing for acceptedPaymentMethods correct (in an opinionated way) * use Toll and TollOff icons * fix seperator on empty payment methods * fix sharedElement and animateEnterExit labels that are not part of the sharedElement * (feat) shape schemes --------- Co-authored-by: MM20 <15646950+MM2-0@users.noreply.github.com>
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package de.mm20.launcher2.locations
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import de.mm20.launcher2.locations.providers.PluginLocation
|
||||
import de.mm20.launcher2.locations.providers.PluginLocationProvider
|
||||
import de.mm20.launcher2.locations.providers.openstreetmaps.OsmLocation
|
||||
@@ -18,10 +17,10 @@ import de.mm20.launcher2.search.location.Attribution
|
||||
import de.mm20.launcher2.search.location.Departure
|
||||
import de.mm20.launcher2.search.location.LocationIcon
|
||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||
import de.mm20.launcher2.search.location.PaymentMethod
|
||||
import de.mm20.launcher2.serialization.Json
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.encodeToString
|
||||
|
||||
@Serializable
|
||||
internal data class SerializedLocation(
|
||||
@@ -42,6 +41,7 @@ internal data class SerializedLocation(
|
||||
val departures: List<Departure>? = null,
|
||||
val fixMeUrl: String? = null,
|
||||
val attribution: Attribution? = null,
|
||||
val acceptedPaymentMethods: Map<PaymentMethod, Boolean>? = null,
|
||||
val authority: String? = null,
|
||||
val storageStrategy: StorageStrategy? = null,
|
||||
)
|
||||
@@ -67,6 +67,7 @@ internal class OsmLocationSerializer : SearchableSerializer {
|
||||
timestamp = searchable.timestamp,
|
||||
departures = searchable.departures,
|
||||
fixMeUrl = searchable.fixMeUrl,
|
||||
acceptedPaymentMethods = searchable.acceptedPaymentMethods
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -96,6 +97,7 @@ internal class OsmLocationDeserializer(
|
||||
userRating = json.userRating,
|
||||
openingSchedule = json.openingSchedule,
|
||||
timestamp = json.timestamp ?: return null,
|
||||
acceptedPaymentMethods = json.acceptedPaymentMethods,
|
||||
updatedSelf = {
|
||||
osmProvider.update(id)
|
||||
}
|
||||
@@ -134,6 +136,7 @@ internal class PluginLocationSerializer : SearchableSerializer {
|
||||
openingSchedule = searchable.openingSchedule,
|
||||
timestamp = searchable.timestamp,
|
||||
departures = searchable.departures,
|
||||
acceptedPaymentMethods = searchable.acceptedPaymentMethods,
|
||||
fixMeUrl = searchable.fixMeUrl,
|
||||
authority = searchable.authority,
|
||||
storageStrategy = searchable.storageStrategy,
|
||||
@@ -185,6 +188,7 @@ internal class PluginLocationDeserializer(
|
||||
departures = json.departures,
|
||||
fixMeUrl = json.fixMeUrl,
|
||||
attribution = json.attribution,
|
||||
acceptedPaymentMethods = json.acceptedPaymentMethods,
|
||||
authority = authority,
|
||||
storageStrategy = strategy,
|
||||
updatedSelf = {
|
||||
|
||||
@@ -14,6 +14,7 @@ import de.mm20.launcher2.search.location.Attribution
|
||||
import de.mm20.launcher2.search.location.Departure
|
||||
import de.mm20.launcher2.search.location.LocationIcon
|
||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||
import de.mm20.launcher2.search.location.PaymentMethod
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@@ -34,6 +35,7 @@ data class PluginLocation(
|
||||
override val label: String,
|
||||
override val timestamp: Long,
|
||||
override val attribution: Attribution?,
|
||||
override val acceptedPaymentMethods: Map<PaymentMethod, Boolean>?,
|
||||
override val updatedSelf: (suspend (SavableSearchable) -> UpdateResult<Location>)?,
|
||||
override val labelOverride: String? = null,
|
||||
val authority: String,
|
||||
|
||||
+2
@@ -84,6 +84,7 @@ internal class PluginLocationProvider(
|
||||
userRatingCount = cursor[LocationColumns.UserRatingCount],
|
||||
departures = cursor[LocationColumns.Departures],
|
||||
attribution = cursor[LocationColumns.Attribution],
|
||||
acceptedPaymentMethods = cursor[LocationColumns.AcceptedPaymentMethods],
|
||||
authority = pluginAuthority,
|
||||
updatedSelf = {
|
||||
if (it !is PluginLocation) UpdateResult.TemporarilyUnavailable()
|
||||
@@ -117,6 +118,7 @@ internal class PluginLocationProvider(
|
||||
set(LocationColumns.UserRatingCount, userRatingCount)
|
||||
set(LocationColumns.Departures, departures)
|
||||
set(LocationColumns.Attribution, attribution)
|
||||
set(LocationColumns.AcceptedPaymentMethods, acceptedPaymentMethods)
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-2
@@ -4,6 +4,7 @@ import android.content.Context
|
||||
import de.mm20.launcher2.ktx.ifNullOrEmpty
|
||||
import de.mm20.launcher2.ktx.into
|
||||
import de.mm20.launcher2.ktx.map
|
||||
import de.mm20.launcher2.ktx.stripStartOrNull
|
||||
import de.mm20.launcher2.locations.OsmLocationSerializer
|
||||
import de.mm20.launcher2.openstreetmaps.R
|
||||
import de.mm20.launcher2.search.Location
|
||||
@@ -16,6 +17,7 @@ import de.mm20.launcher2.search.location.Departure
|
||||
import de.mm20.launcher2.search.location.LocationIcon
|
||||
import de.mm20.launcher2.search.location.OpeningHours
|
||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||
import de.mm20.launcher2.search.location.PaymentMethod
|
||||
import de.westnordost.osm_opening_hours.model.ClockTime
|
||||
import de.westnordost.osm_opening_hours.model.ExtendedClockTime
|
||||
import de.westnordost.osm_opening_hours.model.LastNth
|
||||
@@ -62,7 +64,8 @@ internal data class OsmLocation(
|
||||
override val labelOverride: String? = null,
|
||||
override val timestamp: Long,
|
||||
override var updatedSelf: (suspend (SavableSearchable) -> UpdateResult<Location>)? = null,
|
||||
override val userRating: Float?
|
||||
override val userRating: Float?,
|
||||
override val acceptedPaymentMethods: Map<PaymentMethod, Boolean>?
|
||||
) : Location, UpdatableSearchable<Location> {
|
||||
|
||||
override val domain: String
|
||||
@@ -115,7 +118,25 @@ internal data class OsmLocation(
|
||||
emailAddress = it.tags["email"] ?: it.tags["contact:email"],
|
||||
timestamp = System.currentTimeMillis(),
|
||||
userRating = it.tags["stars"]?.runCatching { this.toInt() }?.getOrNull()
|
||||
?.let { min(it, 5) / 5.0f }
|
||||
?.let { min(it, 5) / 5.0f },
|
||||
acceptedPaymentMethods = with(
|
||||
it.tags.mapNotNull { (key, value) ->
|
||||
(key.stripStartOrNull("payment:") ?: return@mapNotNull null) to value
|
||||
}.toMap()
|
||||
) {
|
||||
// best-effort way to take any method payment as it being available,
|
||||
// otherwise as being unavailable, or undefined
|
||||
mapOf(
|
||||
PaymentMethod.Card to listOf("credit_cards", "debit_cards", "cards"),
|
||||
PaymentMethod.Cash to listOf("cash")
|
||||
).mapNotNull { (method, values) ->
|
||||
when {
|
||||
values.any { this[it] in listOf("yes", "only") } -> method to true
|
||||
values.any { this[it] == "no" } -> method to false
|
||||
else -> null
|
||||
}
|
||||
}.toMap().takeUnless { it.isEmpty() }
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user