Merge branch 'main' of github.com:MM2-0/Kvaesitso
This commit is contained in:
commit
cac2469b2e
@ -21,7 +21,6 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.gestures.detectTapGestures
|
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@ -49,6 +48,9 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
|
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
|
||||||
import androidx.compose.material.icons.automirrored.rounded.NavigateNext
|
import androidx.compose.material.icons.automirrored.rounded.NavigateNext
|
||||||
import androidx.compose.material.icons.automirrored.rounded.OpenInNew
|
import androidx.compose.material.icons.automirrored.rounded.OpenInNew
|
||||||
|
import androidx.compose.material.icons.outlined.CreditCardOff
|
||||||
|
import androidx.compose.material.icons.outlined.CreditScore
|
||||||
|
import androidx.compose.material.icons.outlined.Toll
|
||||||
import androidx.compose.material.icons.rounded.AirplanemodeActive
|
import androidx.compose.material.icons.rounded.AirplanemodeActive
|
||||||
import androidx.compose.material.icons.rounded.BugReport
|
import androidx.compose.material.icons.rounded.BugReport
|
||||||
import androidx.compose.material.icons.rounded.Commute
|
import androidx.compose.material.icons.rounded.Commute
|
||||||
@ -92,9 +94,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.graphics.TransformOrigin
|
import androidx.compose.ui.graphics.TransformOrigin
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.graphics.toArgb
|
import androidx.compose.ui.graphics.toArgb
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
@ -102,7 +102,6 @@ import androidx.compose.ui.unit.Dp
|
|||||||
import androidx.compose.ui.unit.IntOffset
|
import androidx.compose.ui.unit.IntOffset
|
||||||
import androidx.compose.ui.unit.IntRect
|
import androidx.compose.ui.unit.IntRect
|
||||||
import androidx.compose.ui.unit.IntSize
|
import androidx.compose.ui.unit.IntSize
|
||||||
import androidx.compose.ui.unit.LayoutDirection
|
|
||||||
import androidx.compose.ui.unit.TextUnit
|
import androidx.compose.ui.unit.TextUnit
|
||||||
import androidx.compose.ui.unit.TextUnitType
|
import androidx.compose.ui.unit.TextUnitType
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@ -115,6 +114,7 @@ import blend.Blend.harmonize
|
|||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import de.mm20.launcher2.i18n.R
|
import de.mm20.launcher2.i18n.R
|
||||||
import de.mm20.launcher2.icons.CableCar
|
import de.mm20.launcher2.icons.CableCar
|
||||||
|
import de.mm20.launcher2.icons.TollOff
|
||||||
import de.mm20.launcher2.ktx.tryStartActivity
|
import de.mm20.launcher2.ktx.tryStartActivity
|
||||||
import de.mm20.launcher2.search.Location
|
import de.mm20.launcher2.search.Location
|
||||||
import de.mm20.launcher2.search.isOpen
|
import de.mm20.launcher2.search.isOpen
|
||||||
@ -124,6 +124,7 @@ import de.mm20.launcher2.search.location.LineNameComparator
|
|||||||
import de.mm20.launcher2.search.location.LineType
|
import de.mm20.launcher2.search.location.LineType
|
||||||
import de.mm20.launcher2.search.location.OpeningHours
|
import de.mm20.launcher2.search.location.OpeningHours
|
||||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||||
|
import de.mm20.launcher2.search.location.PaymentMethod
|
||||||
import de.mm20.launcher2.search.location.isNotEmpty
|
import de.mm20.launcher2.search.location.isNotEmpty
|
||||||
import de.mm20.launcher2.ui.base.LocalTime
|
import de.mm20.launcher2.ui.base.LocalTime
|
||||||
import de.mm20.launcher2.ui.component.DefaultToolbarAction
|
import de.mm20.launcher2.ui.component.DefaultToolbarAction
|
||||||
@ -229,24 +230,33 @@ fun LocationItem(
|
|||||||
)
|
)
|
||||||
val formattedDistance =
|
val formattedDistance =
|
||||||
distance?.metersToLocalizedString(context, imperialUnits)
|
distance?.metersToLocalizedString(context, imperialUnits)
|
||||||
val isOpenString = location.openingSchedule?.isOpen()
|
val sublabel = listOf(location.category, formattedDistance)
|
||||||
?.let { stringResource(if (it) R.string.location_open else R.string.location_closed) }
|
|
||||||
val sublabel = listOf(location.category, formattedDistance, isOpenString)
|
|
||||||
.fastFilterNotNull()
|
.fastFilterNotNull()
|
||||||
.joinToString(" • ")
|
.joinToString(" • ")
|
||||||
|
val isOpenString = location.openingSchedule?.isOpen()
|
||||||
|
?.let { stringResource(if (it) R.string.location_open else R.string.location_closed) }
|
||||||
|
|
||||||
if (sublabel.isNotBlank()) {
|
Row(modifier = Modifier.padding(top = 2.dp)) {
|
||||||
Text(
|
if (sublabel.isNotBlank()) {
|
||||||
sublabel,
|
Text(
|
||||||
style = MaterialTheme.typography.bodySmall,
|
sublabel,
|
||||||
color = MaterialTheme.colorScheme.secondary,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
modifier = Modifier
|
color = MaterialTheme.colorScheme.secondary,
|
||||||
.padding(top = 2.dp)
|
modifier = Modifier
|
||||||
.sharedElement(
|
.sharedElement(
|
||||||
rememberSharedContentState("sublabel"),
|
rememberSharedContentState("sublabel"),
|
||||||
this@AnimatedContent
|
this@AnimatedContent
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
if (!isOpenString.isNullOrBlank()) {
|
||||||
|
Text(
|
||||||
|
" • $isOpenString",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.secondary,
|
||||||
|
modifier = Modifier.animateEnterExit()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Compass(
|
Compass(
|
||||||
@ -324,28 +334,55 @@ fun LocationItem(
|
|||||||
this@AnimatedContent
|
this@AnimatedContent
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
val category = location.category
|
Row(
|
||||||
val formattedDistance = distance?.metersToLocalizedString(
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
context, imperialUnits
|
modifier = Modifier.padding(top = 2.dp)
|
||||||
)
|
) {
|
||||||
if (category != null || formattedDistance != null) {
|
val category = location.category
|
||||||
Text(
|
val acceptedPaymentMethods = location.acceptedPaymentMethods
|
||||||
when {
|
val formattedDistance = distance?.metersToLocalizedString(
|
||||||
category != null && formattedDistance != null -> "$category • $formattedDistance"
|
context, imperialUnits
|
||||||
|
|
||||||
category != null -> category
|
|
||||||
formattedDistance != null -> formattedDistance
|
|
||||||
else -> ""
|
|
||||||
},
|
|
||||||
style = MaterialTheme.typography.bodySmall,
|
|
||||||
color = MaterialTheme.colorScheme.secondary,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(top = 2.dp)
|
|
||||||
.sharedElement(
|
|
||||||
rememberSharedContentState("sublabel"),
|
|
||||||
this@AnimatedContent
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
if (category != null || formattedDistance != null) {
|
||||||
|
Text(
|
||||||
|
when {
|
||||||
|
category != null && formattedDistance != null -> "$category • $formattedDistance"
|
||||||
|
|
||||||
|
category != null -> category
|
||||||
|
formattedDistance != null -> formattedDistance
|
||||||
|
else -> ""
|
||||||
|
},
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.secondary,
|
||||||
|
modifier = Modifier
|
||||||
|
.sharedElement(
|
||||||
|
rememberSharedContentState("sublabel"),
|
||||||
|
this@AnimatedContent
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (!acceptedPaymentMethods.isNullOrEmpty()) {
|
||||||
|
Text(
|
||||||
|
" • ",
|
||||||
|
style = MaterialTheme.typography.bodySmall,
|
||||||
|
color = MaterialTheme.colorScheme.secondary,
|
||||||
|
modifier = Modifier.animateEnterExit()
|
||||||
|
)
|
||||||
|
for ((method, available) in acceptedPaymentMethods) {
|
||||||
|
Icon(
|
||||||
|
when (method) {
|
||||||
|
PaymentMethod.Cash -> if (available) Icons.Outlined.Toll else Icons.Outlined.TollOff
|
||||||
|
PaymentMethod.Card -> if (available) Icons.Outlined.CreditScore else Icons.Outlined.CreditCardOff
|
||||||
|
},
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.secondary,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(14.5.dp)
|
||||||
|
.padding(end = 2.dp)
|
||||||
|
.animateEnterExit()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (location.userRating != null) {
|
if (location.userRating != null) {
|
||||||
RatingBar(
|
RatingBar(
|
||||||
|
|||||||
@ -75,6 +75,7 @@ import de.mm20.launcher2.search.location.Departure
|
|||||||
import de.mm20.launcher2.search.location.LineType
|
import de.mm20.launcher2.search.location.LineType
|
||||||
import de.mm20.launcher2.search.location.LocationIcon
|
import de.mm20.launcher2.search.location.LocationIcon
|
||||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||||
|
import de.mm20.launcher2.search.location.PaymentMethod
|
||||||
import de.mm20.launcher2.ui.ktx.DegreesConverter
|
import de.mm20.launcher2.ui.ktx.DegreesConverter
|
||||||
import de.mm20.launcher2.ui.ktx.contrast
|
import de.mm20.launcher2.ui.ktx.contrast
|
||||||
import de.mm20.launcher2.ui.ktx.hue
|
import de.mm20.launcher2.ui.ktx.hue
|
||||||
@ -505,6 +506,9 @@ private object MockLocation : Location {
|
|||||||
override val openingSchedule: OpeningSchedule =
|
override val openingSchedule: OpeningSchedule =
|
||||||
OpeningSchedule.TwentyFourSeven
|
OpeningSchedule.TwentyFourSeven
|
||||||
|
|
||||||
|
override val acceptedPaymentMethods: Map<PaymentMethod, Boolean>?
|
||||||
|
get() = mapOf(PaymentMethod.Card to true, PaymentMethod.Cash to false)
|
||||||
|
|
||||||
override val websiteUrl: String = "https://en.wikipedia.org/wiki/Brandenburg_Gate"
|
override val websiteUrl: String = "https://en.wikipedia.org/wiki/Brandenburg_Gate"
|
||||||
|
|
||||||
override val phoneNumber: String = "+49 1234567"
|
override val phoneNumber: String = "+49 1234567"
|
||||||
|
|||||||
@ -1742,6 +1742,60 @@ private val _BreezyWeather = materialIcon("Icons.Rounded.BreezyWeather") {
|
|||||||
val Icons.Rounded.BreezyWeather
|
val Icons.Rounded.BreezyWeather
|
||||||
get() = _BreezyWeather
|
get() = _BreezyWeather
|
||||||
|
|
||||||
|
private val _TollOff = materialIcon("Icons.Rounded.TollOff") {
|
||||||
|
materialPath {
|
||||||
|
moveTo(2.8066406f, 3.2207031f)
|
||||||
|
curveToRelative(-0.2556191f, 0f, -0.5111625f, 0.099053f, -0.7070312f, 0.2949219f)
|
||||||
|
curveToRelative(-0.3917371f, 0.3917372f, -0.3917371f, 1.0223253f, 0f, 1.4140625f)
|
||||||
|
lineToRelative(1.3339844f, 1.3320312f)
|
||||||
|
verticalLineToRelative(0.00195f)
|
||||||
|
curveTo(1.933574f, 7.7156369f, 0.99999996f, 9.7483802f, 1f, 12f)
|
||||||
|
curveToRelative(3e-7f, 3.23f, 1.9196876f, 6.009532f, 4.6796875f, 7.269531f)
|
||||||
|
curveTo(6.2896876f, 19.549531f, 7.0000003f, 19.129219f, 7f, 18.449219f)
|
||||||
|
verticalLineToRelative(-0.179688f)
|
||||||
|
curveToRelative(-3e-7f, -0.37f, -0.2303127f, -0.689609f, -0.5703125f, -0.849609f)
|
||||||
|
curveTo(4.399687f, 16.459922f, 2.9999999f, 14.39f, 3f, 12f)
|
||||||
|
curveToRelative(-2e-7f, -1.698485f, 0.7060878f, -3.2344795f, 1.84375f, -4.3261719f)
|
||||||
|
lineToRelative(2.3925781f, 2.3906249f)
|
||||||
|
verticalLineToRelative(0.002f)
|
||||||
|
curveTo(7.0825208f, 10.685478f, 6.9999996f, 11.333026f, 7f, 12f)
|
||||||
|
curveToRelative(0f, 4.42f, 3.58f, 8f, 8f, 8f)
|
||||||
|
curveToRelative(0.666973f, 0f, 1.314475f, -0.08252f, 1.933594f, -0.236328f)
|
||||||
|
horizontalLineToRelative(0.002f)
|
||||||
|
lineToRelative(2.134765f, 2.136719f)
|
||||||
|
curveToRelative(0.391737f, 0.391737f, 1.022326f, 0.391737f, 1.414063f, 0f)
|
||||||
|
curveToRelative(0.391737f, -0.391738f, 0.391737f, -1.024279f, 0f, -1.416016f)
|
||||||
|
lineTo(18.955078f, 18.955078f)
|
||||||
|
lineTo(17.46875f, 17.46875f)
|
||||||
|
lineTo(9.53125f, 9.53125f)
|
||||||
|
lineTo(8.0449219f, 8.0449219f)
|
||||||
|
lineTo(6.5273437f, 6.5273437f)
|
||||||
|
lineTo(5.0507812f, 5.0507812f)
|
||||||
|
lineTo(3.515625f, 3.515625f)
|
||||||
|
curveTo(3.3197565f, 3.3197565f, 3.0622597f, 3.2207031f, 2.8066406f, 3.2207031f)
|
||||||
|
close()
|
||||||
|
moveTo(15f, 4f)
|
||||||
|
curveToRelative(-2.25366f, 2e-7f, -4.288489f, 0.9314658f, -5.7421875f, 2.4296875f)
|
||||||
|
lineTo(10.673828f, 7.8457031f)
|
||||||
|
curveTo(11.766133f, 6.7086818f, 13.30143f, 6.0000002f, 15f, 6f)
|
||||||
|
curveToRelative(3.31f, 4e-7f, 6f, 2.6899997f, 6f, 6f)
|
||||||
|
curveToRelative(0f, 1.69857f, -0.708682f, 3.233867f, -1.845703f, 4.326172f)
|
||||||
|
lineToRelative(1.416015f, 1.416015f)
|
||||||
|
curveTo(22.068533f, 16.288488f, 23f, 14.25366f, 23f, 12f)
|
||||||
|
curveTo(23f, 7.5799994f, 19.42f, 3.9999997f, 15f, 4f)
|
||||||
|
close()
|
||||||
|
moveToRelative(-5.9980469f, 7.832031f)
|
||||||
|
lineToRelative(6.1660159f, 6.166016f)
|
||||||
|
curveTo(15.112392f, 17.999575f, 15.055942f, 18f, 15f, 18f)
|
||||||
|
curveTo(11.69f, 18f, 9.0000004f, 15.31f, 9f, 12f)
|
||||||
|
curveToRelative(2e-7f, -0.05594f, 0.0004292f, -0.112391f, 0.00195f, -0.167969f)
|
||||||
|
close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val Icons.Outlined.TollOff
|
||||||
|
get() = _TollOff
|
||||||
|
|
||||||
val _CutCorner = materialIcon("Icons.Rounded.CutCorner") {
|
val _CutCorner = materialIcon("Icons.Rounded.CutCorner") {
|
||||||
materialPath {
|
materialPath {
|
||||||
moveTo(2f, 3f)
|
moveTo(2f, 3f)
|
||||||
|
|||||||
@ -129,6 +129,7 @@ import de.mm20.launcher2.search.location.Departure
|
|||||||
import de.mm20.launcher2.search.location.LocationIcon
|
import de.mm20.launcher2.search.location.LocationIcon
|
||||||
import de.mm20.launcher2.search.location.OpeningHours
|
import de.mm20.launcher2.search.location.OpeningHours
|
||||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||||
|
import de.mm20.launcher2.search.location.PaymentMethod
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.temporal.TemporalAdjusters
|
import java.time.temporal.TemporalAdjusters
|
||||||
import android.location.Location as AndroidLocation
|
import android.location.Location as AndroidLocation
|
||||||
@ -154,6 +155,8 @@ interface Location : SavableSearchable {
|
|||||||
val openingSchedule: OpeningSchedule?
|
val openingSchedule: OpeningSchedule?
|
||||||
val departures: List<Departure>?
|
val departures: List<Departure>?
|
||||||
|
|
||||||
|
val acceptedPaymentMethods: Map<PaymentMethod, Boolean>?
|
||||||
|
|
||||||
val attribution: Attribution?
|
val attribution: Attribution?
|
||||||
get() = null
|
get() = null
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import de.mm20.launcher2.search.location.Attribution
|
|||||||
import de.mm20.launcher2.search.location.Departure
|
import de.mm20.launcher2.search.location.Departure
|
||||||
import de.mm20.launcher2.search.location.LocationIcon
|
import de.mm20.launcher2.search.location.LocationIcon
|
||||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||||
|
import de.mm20.launcher2.search.location.PaymentMethod
|
||||||
|
|
||||||
abstract class LocationPluginContract {
|
abstract class LocationPluginContract {
|
||||||
object Paths {
|
object Paths {
|
||||||
@ -139,5 +140,11 @@ abstract class LocationPluginContract {
|
|||||||
* Type: String? (JSON)
|
* Type: String? (JSON)
|
||||||
*/
|
*/
|
||||||
val Attribution = column<Attribution>("attribution")
|
val Attribution = column<Attribution>("attribution")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepted payment methods at this location, encoded as JSON.
|
||||||
|
* Type: String? (JSON)
|
||||||
|
*/
|
||||||
|
val AcceptedPaymentMethods = column<Map<PaymentMethod, Boolean>>("accepted_payment_methods")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
package de.mm20.launcher2.search.location
|
||||||
|
|
||||||
|
enum class PaymentMethod {
|
||||||
|
Cash,
|
||||||
|
Card
|
||||||
|
}
|
||||||
@ -1,7 +1,6 @@
|
|||||||
package de.mm20.launcher2.locations
|
package de.mm20.launcher2.locations
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
|
||||||
import de.mm20.launcher2.locations.providers.PluginLocation
|
import de.mm20.launcher2.locations.providers.PluginLocation
|
||||||
import de.mm20.launcher2.locations.providers.PluginLocationProvider
|
import de.mm20.launcher2.locations.providers.PluginLocationProvider
|
||||||
import de.mm20.launcher2.locations.providers.openstreetmaps.OsmLocation
|
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.Departure
|
||||||
import de.mm20.launcher2.search.location.LocationIcon
|
import de.mm20.launcher2.search.location.LocationIcon
|
||||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||||
|
import de.mm20.launcher2.search.location.PaymentMethod
|
||||||
import de.mm20.launcher2.serialization.Json
|
import de.mm20.launcher2.serialization.Json
|
||||||
import kotlinx.coroutines.flow.firstOrNull
|
import kotlinx.coroutines.flow.firstOrNull
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.encodeToString
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
internal data class SerializedLocation(
|
internal data class SerializedLocation(
|
||||||
@ -42,6 +41,7 @@ internal data class SerializedLocation(
|
|||||||
val departures: List<Departure>? = null,
|
val departures: List<Departure>? = null,
|
||||||
val fixMeUrl: String? = null,
|
val fixMeUrl: String? = null,
|
||||||
val attribution: Attribution? = null,
|
val attribution: Attribution? = null,
|
||||||
|
val acceptedPaymentMethods: Map<PaymentMethod, Boolean>? = null,
|
||||||
val authority: String? = null,
|
val authority: String? = null,
|
||||||
val storageStrategy: StorageStrategy? = null,
|
val storageStrategy: StorageStrategy? = null,
|
||||||
)
|
)
|
||||||
@ -67,6 +67,7 @@ internal class OsmLocationSerializer : SearchableSerializer {
|
|||||||
timestamp = searchable.timestamp,
|
timestamp = searchable.timestamp,
|
||||||
departures = searchable.departures,
|
departures = searchable.departures,
|
||||||
fixMeUrl = searchable.fixMeUrl,
|
fixMeUrl = searchable.fixMeUrl,
|
||||||
|
acceptedPaymentMethods = searchable.acceptedPaymentMethods
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -96,6 +97,7 @@ internal class OsmLocationDeserializer(
|
|||||||
userRating = json.userRating,
|
userRating = json.userRating,
|
||||||
openingSchedule = json.openingSchedule,
|
openingSchedule = json.openingSchedule,
|
||||||
timestamp = json.timestamp ?: return null,
|
timestamp = json.timestamp ?: return null,
|
||||||
|
acceptedPaymentMethods = json.acceptedPaymentMethods,
|
||||||
updatedSelf = {
|
updatedSelf = {
|
||||||
osmProvider.update(id)
|
osmProvider.update(id)
|
||||||
}
|
}
|
||||||
@ -134,6 +136,7 @@ internal class PluginLocationSerializer : SearchableSerializer {
|
|||||||
openingSchedule = searchable.openingSchedule,
|
openingSchedule = searchable.openingSchedule,
|
||||||
timestamp = searchable.timestamp,
|
timestamp = searchable.timestamp,
|
||||||
departures = searchable.departures,
|
departures = searchable.departures,
|
||||||
|
acceptedPaymentMethods = searchable.acceptedPaymentMethods,
|
||||||
fixMeUrl = searchable.fixMeUrl,
|
fixMeUrl = searchable.fixMeUrl,
|
||||||
authority = searchable.authority,
|
authority = searchable.authority,
|
||||||
storageStrategy = searchable.storageStrategy,
|
storageStrategy = searchable.storageStrategy,
|
||||||
@ -185,6 +188,7 @@ internal class PluginLocationDeserializer(
|
|||||||
departures = json.departures,
|
departures = json.departures,
|
||||||
fixMeUrl = json.fixMeUrl,
|
fixMeUrl = json.fixMeUrl,
|
||||||
attribution = json.attribution,
|
attribution = json.attribution,
|
||||||
|
acceptedPaymentMethods = json.acceptedPaymentMethods,
|
||||||
authority = authority,
|
authority = authority,
|
||||||
storageStrategy = strategy,
|
storageStrategy = strategy,
|
||||||
updatedSelf = {
|
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.Departure
|
||||||
import de.mm20.launcher2.search.location.LocationIcon
|
import de.mm20.launcher2.search.location.LocationIcon
|
||||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
import de.mm20.launcher2.search.location.OpeningSchedule
|
||||||
|
import de.mm20.launcher2.search.location.PaymentMethod
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
@ -34,6 +35,7 @@ data class PluginLocation(
|
|||||||
override val label: String,
|
override val label: String,
|
||||||
override val timestamp: Long,
|
override val timestamp: Long,
|
||||||
override val attribution: Attribution?,
|
override val attribution: Attribution?,
|
||||||
|
override val acceptedPaymentMethods: Map<PaymentMethod, Boolean>?,
|
||||||
override val updatedSelf: (suspend (SavableSearchable) -> UpdateResult<Location>)?,
|
override val updatedSelf: (suspend (SavableSearchable) -> UpdateResult<Location>)?,
|
||||||
override val labelOverride: String? = null,
|
override val labelOverride: String? = null,
|
||||||
val authority: String,
|
val authority: String,
|
||||||
|
|||||||
@ -84,6 +84,7 @@ internal class PluginLocationProvider(
|
|||||||
userRatingCount = cursor[LocationColumns.UserRatingCount],
|
userRatingCount = cursor[LocationColumns.UserRatingCount],
|
||||||
departures = cursor[LocationColumns.Departures],
|
departures = cursor[LocationColumns.Departures],
|
||||||
attribution = cursor[LocationColumns.Attribution],
|
attribution = cursor[LocationColumns.Attribution],
|
||||||
|
acceptedPaymentMethods = cursor[LocationColumns.AcceptedPaymentMethods],
|
||||||
authority = pluginAuthority,
|
authority = pluginAuthority,
|
||||||
updatedSelf = {
|
updatedSelf = {
|
||||||
if (it !is PluginLocation) UpdateResult.TemporarilyUnavailable()
|
if (it !is PluginLocation) UpdateResult.TemporarilyUnavailable()
|
||||||
@ -117,6 +118,7 @@ internal class PluginLocationProvider(
|
|||||||
set(LocationColumns.UserRatingCount, userRatingCount)
|
set(LocationColumns.UserRatingCount, userRatingCount)
|
||||||
set(LocationColumns.Departures, departures)
|
set(LocationColumns.Departures, departures)
|
||||||
set(LocationColumns.Attribution, attribution)
|
set(LocationColumns.Attribution, attribution)
|
||||||
|
set(LocationColumns.AcceptedPaymentMethods, acceptedPaymentMethods)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,6 +4,7 @@ import android.content.Context
|
|||||||
import de.mm20.launcher2.ktx.ifNullOrEmpty
|
import de.mm20.launcher2.ktx.ifNullOrEmpty
|
||||||
import de.mm20.launcher2.ktx.into
|
import de.mm20.launcher2.ktx.into
|
||||||
import de.mm20.launcher2.ktx.map
|
import de.mm20.launcher2.ktx.map
|
||||||
|
import de.mm20.launcher2.ktx.stripStartOrNull
|
||||||
import de.mm20.launcher2.locations.OsmLocationSerializer
|
import de.mm20.launcher2.locations.OsmLocationSerializer
|
||||||
import de.mm20.launcher2.openstreetmaps.R
|
import de.mm20.launcher2.openstreetmaps.R
|
||||||
import de.mm20.launcher2.search.Location
|
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.LocationIcon
|
||||||
import de.mm20.launcher2.search.location.OpeningHours
|
import de.mm20.launcher2.search.location.OpeningHours
|
||||||
import de.mm20.launcher2.search.location.OpeningSchedule
|
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.ClockTime
|
||||||
import de.westnordost.osm_opening_hours.model.ExtendedClockTime
|
import de.westnordost.osm_opening_hours.model.ExtendedClockTime
|
||||||
import de.westnordost.osm_opening_hours.model.LastNth
|
import de.westnordost.osm_opening_hours.model.LastNth
|
||||||
@ -62,7 +64,8 @@ internal data class OsmLocation(
|
|||||||
override val labelOverride: String? = null,
|
override val labelOverride: String? = null,
|
||||||
override val timestamp: Long,
|
override val timestamp: Long,
|
||||||
override var updatedSelf: (suspend (SavableSearchable) -> UpdateResult<Location>)? = null,
|
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> {
|
) : Location, UpdatableSearchable<Location> {
|
||||||
|
|
||||||
override val domain: String
|
override val domain: String
|
||||||
@ -115,7 +118,25 @@ internal data class OsmLocation(
|
|||||||
emailAddress = it.tags["email"] ?: it.tags["contact:email"],
|
emailAddress = it.tags["email"] ?: it.tags["contact:email"],
|
||||||
timestamp = System.currentTimeMillis(),
|
timestamp = System.currentTimeMillis(),
|
||||||
userRating = it.tags["stars"]?.runCatching { this.toInt() }?.getOrNull()
|
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() }
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user