mirror of
https://github.com/ev-map/EVMap.git
synced 2025-12-26 00:27:45 -05:00
Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d335d7cab0 | ||
|
|
f7c3faa7bd | ||
|
|
1338e2306e | ||
|
|
83a2b42408 | ||
|
|
0ce5938f5b | ||
|
|
5ab50e04ae | ||
|
|
ee0fd4e8d8 | ||
|
|
369b7d9410 | ||
|
|
c9a0b270cd | ||
|
|
c8aa64fa7c | ||
|
|
d5b18bd6fb |
@@ -18,6 +18,8 @@ Features
|
||||
- Realtime availability information (beta)
|
||||
- Search places
|
||||
- Favorites list, also with availability information
|
||||
- Charging price comparison, powered by [Chargeprice.app](https://chargeprice.app)
|
||||
- Android Auto integration
|
||||
- No ads, fully open source
|
||||
- Compatible with Android 5.0 and above
|
||||
- Can use Google Maps or Mapbox (OpenStreetMap) as map backends - the version available on F-Droid only uses Mapbox.
|
||||
@@ -33,7 +35,8 @@ Development setup
|
||||
The App is developed using Android Studio.
|
||||
|
||||
For testing the app, you need to obtain free API Keys for the
|
||||
[GoingElectric API](https://www.goingelectric.de/stromtankstellen/api/)
|
||||
[GoingElectric API](https://www.goingelectric.de/stromtankstellen/api/),
|
||||
the [Chargeprice API](https://github.com/chargeprice/chargeprice-api-docs)
|
||||
as well as for [Google APIs](https://console.developers.google.com/)
|
||||
("Maps SDK for Android" and "Places API" need to be activated) and/or [Mapbox](https://www.mapbox.com/). These APIs need to be put into the
|
||||
app in the form of a resource file called `apikeys.xml` under `app/src/main/res/values`, with the
|
||||
@@ -50,5 +53,8 @@ following content:
|
||||
<string name="goingelectric_key" translatable="false">
|
||||
insert your GoingElectric key here
|
||||
</string>
|
||||
<string name="chargeprice_key" translatable="false">
|
||||
insert your Chargeprice key here
|
||||
</string>
|
||||
</resources>
|
||||
```
|
||||
|
||||
@@ -13,8 +13,8 @@ android {
|
||||
applicationId "net.vonforst.evmap"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 30
|
||||
versionCode 45
|
||||
versionName "0.7.1"
|
||||
versionCode 46
|
||||
versionName "0.7.2"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
|
||||
@@ -107,6 +107,16 @@ class ChargepriceAdapter() :
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
var myTariffs: Set<String>? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
var myTariffsAll: Boolean? = null
|
||||
set(value) {
|
||||
field = value
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
override fun getItemViewType(position: Int): Int = R.layout.item_chargeprice
|
||||
|
||||
@@ -127,7 +137,11 @@ class ChargepriceAdapter() :
|
||||
|
||||
override fun bind(holder: ViewHolder<ChargePrice>, item: ChargePrice) {
|
||||
super.bind(holder, item)
|
||||
(holder.binding as ItemChargepriceBinding).meta = meta
|
||||
(holder.binding as ItemChargepriceBinding).apply {
|
||||
this.meta = this@ChargepriceAdapter.meta
|
||||
this.myTariffs = this@ChargepriceAdapter.myTariffs
|
||||
this.myTariffsAll = this@ChargepriceAdapter.myTariffsAll
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,9 @@ interface ChargepriceApi {
|
||||
@GET("vehicles")
|
||||
suspend fun getVehicles(): ArrayDocument<ChargepriceCar>
|
||||
|
||||
@GET("tariffs")
|
||||
suspend fun getTariffs(): ArrayDocument<ChargepriceTariff>
|
||||
|
||||
companion object {
|
||||
private val cacheSize = 1L * 1024 * 1024 // 1MB
|
||||
val supportedLanguages = setOf("de", "en", "fr", "nl")
|
||||
|
||||
@@ -70,13 +70,46 @@ data class ChargepriceOptions(
|
||||
)
|
||||
|
||||
@JsonApi(type = "tariff")
|
||||
data class ChargepriceTariff(
|
||||
val provider: String,
|
||||
val name: String,
|
||||
@field:Json(name = "direct_payment") val directPayment: Boolean,
|
||||
@field:Json(name = "provider_customer_tariff") val providerCustomerTariff: Boolean,
|
||||
@field:Json(name = "charge_card_id") val chargeCardId: String // GE charge card ID
|
||||
) : Resource()
|
||||
class ChargepriceTariff() : Resource() {
|
||||
lateinit var provider: String
|
||||
lateinit var name: String
|
||||
@field:Json(name = "direct_payment")
|
||||
var directPayment: Boolean = false
|
||||
@field:Json(name = "provider_customer_tariff")
|
||||
var providerCustomerTariff: Boolean = false
|
||||
@field:Json(name = "supported_cuntries")
|
||||
lateinit var supportedCountries: Set<String>
|
||||
@field:Json(name = "charge_card_id")
|
||||
lateinit var chargeCardId: String // GE charge card ID
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
if (!super.equals(other)) return false
|
||||
|
||||
other as ChargepriceTariff
|
||||
|
||||
if (provider != other.provider) return false
|
||||
if (name != other.name) return false
|
||||
if (directPayment != other.directPayment) return false
|
||||
if (providerCustomerTariff != other.providerCustomerTariff) return false
|
||||
if (supportedCountries != other.supportedCountries) return false
|
||||
if (chargeCardId != other.chargeCardId) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = super.hashCode()
|
||||
result = 31 * result + provider.hashCode()
|
||||
result = 31 * result + name.hashCode()
|
||||
result = 31 * result + directPayment.hashCode()
|
||||
result = 31 * result + providerCustomerTariff.hashCode()
|
||||
result = 31 * result + supportedCountries.hashCode()
|
||||
result = 31 * result + chargeCardId.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
@JsonApi(type = "car")
|
||||
class ChargepriceCar : Resource() {
|
||||
@@ -146,6 +179,8 @@ class ChargePrice : Resource(), Equatable, Cloneable {
|
||||
@field:Json(name = "charge_point_prices")
|
||||
lateinit var chargepointPrices: List<ChargepointPrice>
|
||||
|
||||
var tariff: HasOne<ChargepriceTariff>? = null
|
||||
|
||||
|
||||
fun formatMonthlyFees(ctx: Context): String {
|
||||
return listOfNotNull(
|
||||
@@ -212,6 +247,7 @@ class ChargePrice : Resource(), Equatable, Cloneable {
|
||||
tariffName = this@ChargePrice.tariffName
|
||||
totalMonthlyFee = this@ChargePrice.totalMonthlyFee
|
||||
url = this@ChargePrice.url
|
||||
tariff = this@ChargePrice.tariff
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,6 +112,12 @@ class ChargepriceFragment : DialogFragment() {
|
||||
vm.chargepriceMetaForChargepoint.observe(viewLifecycleOwner) {
|
||||
chargepriceAdapter.meta = it?.data
|
||||
}
|
||||
vm.myTariffs.observe(viewLifecycleOwner) {
|
||||
chargepriceAdapter.myTariffs = it
|
||||
}
|
||||
vm.myTariffsAll.observe(viewLifecycleOwner) {
|
||||
chargepriceAdapter.myTariffsAll = it
|
||||
}
|
||||
|
||||
val connectorsAdapter = CheckableConnectorAdapter()
|
||||
|
||||
@@ -168,6 +174,7 @@ class ChargepriceFragment : DialogFragment() {
|
||||
vm.chargePricesForChargepoint.observe(viewLifecycleOwner) { res ->
|
||||
when (res?.status) {
|
||||
Status.ERROR -> {
|
||||
if (vm.vehicle.value == null) return@observe
|
||||
connectionErrorSnackbar?.dismiss()
|
||||
connectionErrorSnackbar = Snackbar
|
||||
.make(
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.MultiSelectListPreference
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceFragmentCompat
|
||||
import net.vonforst.evmap.MapsActivity
|
||||
@@ -32,6 +33,7 @@ class SettingsFragment : PreferenceFragmentCompat(),
|
||||
})
|
||||
|
||||
private lateinit var myVehiclePreference: ListPreference
|
||||
private lateinit var myTariffsPreference: MultiSelectListPreference
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
@@ -44,7 +46,7 @@ class SettingsFragment : PreferenceFragmentCompat(),
|
||||
(requireActivity() as MapsActivity).appBarConfiguration
|
||||
)
|
||||
|
||||
myVehiclePreference = findPreference<ListPreference>("chargeprice_my_vehicle")!!
|
||||
myVehiclePreference = findPreference("chargeprice_my_vehicle")!!
|
||||
myVehiclePreference.isEnabled = false
|
||||
vm.vehicles.observe(viewLifecycleOwner) { res ->
|
||||
res.data?.let { cars ->
|
||||
@@ -57,6 +59,32 @@ class SettingsFragment : PreferenceFragmentCompat(),
|
||||
?.let { "${it.brand} ${it.name}" }
|
||||
}
|
||||
}
|
||||
|
||||
myTariffsPreference = findPreference("chargeprice_my_tariffs")!!
|
||||
vm.tariffs.observe(viewLifecycleOwner) { res ->
|
||||
res.data?.let { tariffs ->
|
||||
myTariffsPreference.entryValues = tariffs.map { it.id }.toTypedArray()
|
||||
myTariffsPreference.entries = tariffs.map {
|
||||
if (!it.name.startsWith(it.provider)) {
|
||||
"${it.provider} ${it.name}"
|
||||
} else {
|
||||
it.name
|
||||
}
|
||||
}.toTypedArray()
|
||||
myTariffsPreference.isEnabled = true
|
||||
updateMyTariffsSummary()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMyTariffsSummary() {
|
||||
myTariffsPreference.summary = if (prefs.chargepriceMyTariffsAll) {
|
||||
getString(R.string.chargeprice_all_tariffs_selected)
|
||||
} else {
|
||||
val n = prefs.chargepriceMyTariffs?.size ?: 0
|
||||
requireContext().resources
|
||||
.getQuantityString(R.plurals.chargeprice_some_tariffs_selected, n, n)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
@@ -89,6 +117,9 @@ class SettingsFragment : PreferenceFragmentCompat(),
|
||||
}
|
||||
}
|
||||
}
|
||||
"chargeprice_my_tariffs" -> {
|
||||
updateMyTariffsSummary()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -111,6 +111,18 @@ class PreferenceDataSource(val context: Context) {
|
||||
.apply()
|
||||
}
|
||||
|
||||
var chargepriceMyTariffs: Set<String>?
|
||||
get() = sp.getStringSet("chargeprice_my_tariffs", null)
|
||||
set(value) {
|
||||
sp.edit().putStringSet("chargeprice_my_tariffs", value).apply()
|
||||
}
|
||||
|
||||
var chargepriceMyTariffsAll: Boolean
|
||||
get() = sp.getBoolean("chargeprice_my_tariffs_all", true)
|
||||
set(value) {
|
||||
sp.edit().putBoolean("chargeprice_my_tariffs_all", value).apply()
|
||||
}
|
||||
|
||||
var chargepriceNoBaseFee: Boolean
|
||||
get() = sp.getBoolean("chargeprice_no_base_fee", false)
|
||||
set(value) {
|
||||
@@ -122,4 +134,21 @@ class PreferenceDataSource(val context: Context) {
|
||||
set(value) {
|
||||
sp.edit().putBoolean("chargeprice_show_provider_customer_tariffs", value).apply()
|
||||
}
|
||||
|
||||
var chargepriceCurrency: String
|
||||
get() = sp.getString("chargeprice_currency", null) ?: "EUR"
|
||||
set(value) {
|
||||
sp.edit().putString("chargeprice_currency", value).apply()
|
||||
}
|
||||
|
||||
var chargepriceBatteryRange: List<Float>
|
||||
get() = listOf(
|
||||
sp.getFloat("chargeprice_battery_range_min", 20f),
|
||||
sp.getFloat("chargeprice_battery_range_max", 80f),
|
||||
)
|
||||
set(value) {
|
||||
sp.edit().putFloat("chargeprice_battery_range_min", value[0])
|
||||
.putFloat("chargeprice_battery_range_max", value[1])
|
||||
.apply()
|
||||
}
|
||||
}
|
||||
@@ -255,7 +255,7 @@ fun currency(currency: String): String {
|
||||
"USD" -> "$"
|
||||
"DKK", "SEK", "NOK" -> "kr."
|
||||
"PLN" -> "zł"
|
||||
"CHF" -> "Fr."
|
||||
"CHF" -> "Fr. "
|
||||
"CZK" -> "Kč"
|
||||
"GBP" -> "£"
|
||||
"HRK" -> "kn"
|
||||
@@ -291,4 +291,15 @@ fun colorEnabled(ctx: Context, enabled: Boolean): Int {
|
||||
@BindingAdapter("app:tint")
|
||||
fun setImageTintList(view: ImageView, @ColorInt color: Int) {
|
||||
view.imageTintList = ColorStateList.valueOf(color)
|
||||
}
|
||||
|
||||
@BindingAdapter("myTariffsBackground")
|
||||
fun myTariffsBackground(view: View, myTariff: Boolean) {
|
||||
if (myTariff) {
|
||||
view.background = ContextCompat.getDrawable(view.context, R.drawable.my_tariff_background)
|
||||
} else {
|
||||
view.context.obtainStyledAttributes(intArrayOf(R.attr.selectableItemBackground)).use {
|
||||
view.background = it.getDrawable(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package net.vonforst.evmap.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.preference.MultiSelectListPreference
|
||||
import net.vonforst.evmap.fragment.MultiSelectDialog
|
||||
|
||||
class MultiSelectDialogPreference(ctx: Context, attrs: AttributeSet) :
|
||||
MultiSelectListPreference(ctx, attrs) {
|
||||
override fun onClick() {
|
||||
val dialog =
|
||||
MultiSelectDialog.getInstance(
|
||||
title.toString(),
|
||||
entryValues.map { it.toString() }.zip(entries.map { it.toString() }).toMap(),
|
||||
if (all) entryValues.map { it.toString() }.toSet() else values,
|
||||
emptySet()
|
||||
)
|
||||
dialog.okListener = { selected ->
|
||||
all = selected == entryValues.toSet()
|
||||
values = selected
|
||||
}
|
||||
dialog.show((context as AppCompatActivity).supportFragmentManager, null)
|
||||
}
|
||||
|
||||
var all: Boolean
|
||||
get() = sharedPreferences.getBoolean(key + "_all", true)
|
||||
set(value) {
|
||||
sharedPreferences.edit().putBoolean(key + "_all", value).apply()
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,10 @@ class ChargepriceViewModel(application: Application, chargepriceApiKey: String)
|
||||
|
||||
val batteryRange: MutableLiveData<List<Float>> by lazy {
|
||||
MutableLiveData<List<Float>>().apply {
|
||||
value = listOf(20f, 80f)
|
||||
value = prefs.chargepriceBatteryRange
|
||||
observeForever {
|
||||
prefs.chargepriceBatteryRange = it
|
||||
}
|
||||
}
|
||||
}
|
||||
val batteryRangeSliderDragging: MutableLiveData<Boolean> by lazy {
|
||||
@@ -112,6 +115,7 @@ class ChargepriceViewModel(application: Application, chargepriceApiKey: String)
|
||||
} else if (cps.status == Status.LOADING) {
|
||||
value = Resource.loading(null)
|
||||
} else {
|
||||
val myTariffs = prefs.chargepriceMyTariffs
|
||||
value = Resource.success(cps.data!!.map { cp ->
|
||||
val filteredPrices =
|
||||
cp.chargepointPrices.filter { it.plug == chargepoint.type && it.power == chargepoint.power }
|
||||
@@ -122,13 +126,30 @@ class ChargepriceViewModel(application: Application, chargepriceApiKey: String)
|
||||
chargepointPrices = filteredPrices
|
||||
}
|
||||
}
|
||||
}.filterNotNull().sortedBy { it.chargepointPrices.first().price })
|
||||
}.filterNotNull()
|
||||
.sortedBy { it.chargepointPrices.first().price }
|
||||
.sortedByDescending {
|
||||
prefs.chargepriceMyTariffsAll ||
|
||||
myTariffs != null && it.tariff?.get()?.id in myTariffs
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val myTariffs: LiveData<Set<String>> by lazy {
|
||||
MutableLiveData<Set<String>>().apply {
|
||||
value = prefs.chargepriceMyTariffs
|
||||
}
|
||||
}
|
||||
val myTariffsAll: LiveData<Boolean> by lazy {
|
||||
MutableLiveData<Boolean>().apply {
|
||||
value = prefs.chargepriceMyTariffsAll
|
||||
}
|
||||
}
|
||||
|
||||
val chargepriceMetaForChargepoint: MediatorLiveData<Resource<ChargepriceChargepointMeta>> by lazy {
|
||||
MediatorLiveData<Resource<ChargepriceChargepointMeta>>().apply {
|
||||
listOf(chargePriceMeta, chargepoint).forEach {
|
||||
@@ -173,7 +194,8 @@ class ChargepriceViewModel(application: Application, chargepriceApiKey: String)
|
||||
options = ChargepriceOptions(
|
||||
batteryRange = batteryRange.value!!.map { it.toDouble() },
|
||||
providerCustomerTariffs = prefs.chargepriceShowProviderCustomerTariffs,
|
||||
maxMonthlyFees = if (prefs.chargepriceNoBaseFee) 0.0 else null
|
||||
maxMonthlyFees = if (prefs.chargepriceNoBaseFee) 0.0 else null,
|
||||
currency = prefs.chargepriceCurrency
|
||||
)
|
||||
}, getChargepriceLanguage())
|
||||
val meta =
|
||||
|
||||
@@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.launch
|
||||
import net.vonforst.evmap.api.chargeprice.ChargepriceApi
|
||||
import net.vonforst.evmap.api.chargeprice.ChargepriceCar
|
||||
import net.vonforst.evmap.api.chargeprice.ChargepriceTariff
|
||||
import java.io.IOException
|
||||
|
||||
class SettingsViewModel(application: Application, chargepriceApiKey: String) :
|
||||
@@ -20,6 +21,13 @@ class SettingsViewModel(application: Application, chargepriceApiKey: String) :
|
||||
}
|
||||
}
|
||||
|
||||
val tariffs: MutableLiveData<Resource<List<ChargepriceTariff>>> by lazy {
|
||||
MutableLiveData<Resource<List<ChargepriceTariff>>>().apply {
|
||||
value = Resource.loading(null)
|
||||
loadTariffs()
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadVehicles() {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
@@ -30,4 +38,15 @@ class SettingsViewModel(application: Application, chargepriceApiKey: String) :
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loadTariffs() {
|
||||
viewModelScope.launch {
|
||||
try {
|
||||
val result = api.getTariffs()
|
||||
tariffs.value = Resource.success(result)
|
||||
} catch (e: IOException) {
|
||||
tariffs.value = Resource.error(e.message, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
5
app/src/main/res/drawable/my_tariff_background.xml
Normal file
5
app/src/main/res/drawable/my_tariff_background.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@color/chip_background" />
|
||||
<item android:drawable="?selectableItemBackground" />
|
||||
</layer-list>
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
<import type="net.vonforst.evmap.ui.BindingAdaptersKt" />
|
||||
|
||||
<import type="java.util.Set" />
|
||||
|
||||
<variable
|
||||
name="item"
|
||||
type="ChargePrice" />
|
||||
@@ -18,6 +20,14 @@
|
||||
<variable
|
||||
name="meta"
|
||||
type="ChargepriceChargepointMeta" />
|
||||
|
||||
<variable
|
||||
name="myTariffs"
|
||||
type="Set<String>" />
|
||||
|
||||
<variable
|
||||
name="myTariffsAll"
|
||||
type="Boolean" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
@@ -27,7 +37,7 @@
|
||||
android:paddingTop="8dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:background="?selectableItemBackground">
|
||||
app:myTariffsBackground="@{!myTariffsAll && myTariffs.contains(item.tariff.get().id)}">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtTariff"
|
||||
@@ -50,7 +60,7 @@
|
||||
android:layout_marginEnd="4dp"
|
||||
android:text="@{item.provider}"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
|
||||
app:goneUnless="@{!item.provider.equals(item.tariffName)}"
|
||||
app:goneUnless="@{!item.tariffName.startsWith(item.provider)}"
|
||||
app:layout_constraintBottom_toTopOf="@+id/rvTags"
|
||||
app:layout_constraintEnd_toStartOf="@+id/guideline5"
|
||||
app:layout_constraintStart_toStartOf="@+id/txtTariff"
|
||||
|
||||
@@ -186,6 +186,27 @@
|
||||
<string name="edit_on_goingelectric_info">Falls hier nur eine leere Seite erscheint, logge dich bitte zuerst bei GoingElectric.de ein.</string>
|
||||
<string name="close">schließen</string>
|
||||
<string name="chargeprice_title">Preisvergleich</string>
|
||||
<string name="chargeprice_connection_error">Could not load prices</string>
|
||||
<string name="chargeprice_connection_error">Preise konnten nicht geladen werden</string>
|
||||
<string name="chargeprice_no_compatible_connectors">Keiner der Anschlüsse dieser Ladestation ist mit deinem Fahrzeug kompatibel.</string>
|
||||
<string name="pref_chargeprice_currency">Währung</string>
|
||||
<string name="pref_my_tariffs">Meine Tarife</string>
|
||||
<string name="chargeprice_all_tariffs_selected">alle Tarife ausgewählt</string>
|
||||
<string-array name="pref_chargeprice_currency_names">
|
||||
<item>Schweizer Franken (CHF)</item>
|
||||
<item>Tschechische Krone (CZK)</item>
|
||||
<item>Dänische Krone (DKK)</item>
|
||||
<item>Euro (EUR)</item>
|
||||
<item>Britisches Pfund (GBP)</item>
|
||||
<item>Kroatische Kuna (HRK)</item>
|
||||
<item>Ungarischer Forint (HUF)</item>
|
||||
<item>Isländische Krone (ISK)</item>
|
||||
<item>Norwegische Krone (NOK)</item>
|
||||
<item>Polnischer Złoty (PLN)</item>
|
||||
<item>Schwedische Krone (SEK)</item>
|
||||
<item>US-Dollar (USD)</item>
|
||||
</string-array>
|
||||
<plurals name="chargeprice_some_tariffs_selected">
|
||||
<item quantity="one">%d Tarif ausgewählt</item>
|
||||
<item quantity="other">%d Tarife ausgewählt</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
||||
@@ -20,4 +20,32 @@
|
||||
<item>on</item>
|
||||
<item>off</item>
|
||||
</string-array>
|
||||
<string-array name="pref_chargeprice_currency_names">
|
||||
<item>Swiss franc (CHF)</item>
|
||||
<item>Czech koruna (CZK)</item>
|
||||
<item>Danish krone (DKK)</item>
|
||||
<item>Euro (EUR)</item>
|
||||
<item>Pound sterling (GBP)</item>
|
||||
<item>Croatian kuna (HRK)</item>
|
||||
<item>Hungarian forint (HUF)</item>
|
||||
<item>Icelandic króna (ISK)</item>
|
||||
<item>Norwegian krone (NOK)</item>
|
||||
<item>Polish złoty (PLN)</item>
|
||||
<item>Swedish krona (SEK)</item>
|
||||
<item>US dollar (USD)</item>
|
||||
</string-array>
|
||||
<string-array name="pref_chargeprice_currency_values" donottranslate="true">
|
||||
<item>CHF</item>
|
||||
<item>CZK</item>
|
||||
<item>DKK</item>
|
||||
<item>EUR</item>
|
||||
<item>GBP</item>
|
||||
<item>HRK</item>
|
||||
<item>HUF</item>
|
||||
<item>ISK</item>
|
||||
<item>NOK</item>
|
||||
<item>PLN</item>
|
||||
<item>SEK</item>
|
||||
<item>USD</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
@@ -187,4 +187,11 @@
|
||||
<string name="chargeprice_title">Prices</string>
|
||||
<string name="chargeprice_connection_error">Could not load prices</string>
|
||||
<string name="chargeprice_no_compatible_connectors">None of the connectors on this charging station is compatible with your vehicle.</string>
|
||||
<string name="pref_chargeprice_currency">Currency</string>
|
||||
<string name="pref_my_tariffs">My charging plans</string>
|
||||
<string name="chargeprice_all_tariffs_selected">all plans selected</string>
|
||||
<plurals name="chargeprice_some_tariffs_selected">
|
||||
<item quantity="one">%d plan selected</item>
|
||||
<item quantity="other">%d plans selected</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
||||
@@ -42,6 +42,16 @@
|
||||
<ListPreference
|
||||
android:key="chargeprice_my_vehicle"
|
||||
android:title="@string/pref_my_vehicle" />
|
||||
<net.vonforst.evmap.ui.MultiSelectDialogPreference
|
||||
android:key="chargeprice_my_tariffs"
|
||||
android:title="@string/pref_my_tariffs" />
|
||||
<ListPreference
|
||||
android:key="chargeprice_currency"
|
||||
android:title="@string/pref_chargeprice_currency"
|
||||
android:entries="@array/pref_chargeprice_currency_names"
|
||||
android:entryValues="@array/pref_chargeprice_currency_values"
|
||||
android:defaultValue="EUR"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
<CheckBoxPreference
|
||||
android:key="chargeprice_no_base_fee"
|
||||
android:title="@string/pref_chargeprice_no_base_fee"
|
||||
|
||||
4
fastlane/metadata/android/de-DE/changelogs/46.txt
Normal file
4
fastlane/metadata/android/de-DE/changelogs/46.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Verbesserungen für Chargeprice.app-Integration:
|
||||
- Währung kann in den Einstellungen gewählt werden
|
||||
- Ausgewählter Ladebereich wird gespeichert
|
||||
- Eigene Tarife können in den Einstellungen ausgewählt werden
|
||||
4
fastlane/metadata/android/en-US/changelogs/46.txt
Normal file
4
fastlane/metadata/android/en-US/changelogs/46.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Improvements for Chargeprice.app integration:
|
||||
- Currency selection in settings
|
||||
- Save selected charging range
|
||||
- Own charging plans can be selected in settings
|
||||
Reference in New Issue
Block a user