diff --git a/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceApi.kt b/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceApi.kt index 24c410b9..120650d5 100644 --- a/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceApi.kt +++ b/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceApi.kt @@ -26,6 +26,9 @@ interface ChargepriceApi { @GET("vehicles") suspend fun getVehicles(): ArrayDocument + @GET("tariffs") + suspend fun getTariffs(): ArrayDocument + companion object { private val cacheSize = 1L * 1024 * 1024 // 1MB val supportedLanguages = setOf("de", "en", "fr", "nl") diff --git a/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceModel.kt b/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceModel.kt index 75824e38..d66738f7 100644 --- a/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceModel.kt +++ b/app/src/main/java/net/vonforst/evmap/api/chargeprice/ChargepriceModel.kt @@ -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 + @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() { diff --git a/app/src/main/java/net/vonforst/evmap/fragment/SettingsFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/SettingsFragment.kt index 3da3c37a..cc1c50ec 100644 --- a/app/src/main/java/net/vonforst/evmap/fragment/SettingsFragment.kt +++ b/app/src/main/java/net/vonforst/evmap/fragment/SettingsFragment.kt @@ -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("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() + } } } diff --git a/app/src/main/java/net/vonforst/evmap/storage/PreferenceDataSource.kt b/app/src/main/java/net/vonforst/evmap/storage/PreferenceDataSource.kt index d65c02d8..98fb2a76 100644 --- a/app/src/main/java/net/vonforst/evmap/storage/PreferenceDataSource.kt +++ b/app/src/main/java/net/vonforst/evmap/storage/PreferenceDataSource.kt @@ -111,6 +111,18 @@ class PreferenceDataSource(val context: Context) { .apply() } + var chargepriceMyTariffs: Set? + 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) { diff --git a/app/src/main/java/net/vonforst/evmap/ui/MultiSelectDialogPreference.kt b/app/src/main/java/net/vonforst/evmap/ui/MultiSelectDialogPreference.kt new file mode 100644 index 00000000..c35ae251 --- /dev/null +++ b/app/src/main/java/net/vonforst/evmap/ui/MultiSelectDialogPreference.kt @@ -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() + } +} \ No newline at end of file diff --git a/app/src/main/java/net/vonforst/evmap/viewmodel/SettingsViewModel.kt b/app/src/main/java/net/vonforst/evmap/viewmodel/SettingsViewModel.kt index e5123e72..5369e4ba 100644 --- a/app/src/main/java/net/vonforst/evmap/viewmodel/SettingsViewModel.kt +++ b/app/src/main/java/net/vonforst/evmap/viewmodel/SettingsViewModel.kt @@ -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>> by lazy { + MutableLiveData>>().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) + } + } + } } \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 5c8ac5d0..582f69e8 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -189,6 +189,8 @@ Preise konnten nicht geladen werden Keiner der Anschlüsse dieser Ladestation ist mit deinem Fahrzeug kompatibel. Währung + Meine Tarife + alle Tarife ausgewählt Schweizer Franken (CHF) Tschechische Krone (CZK) @@ -203,4 +205,8 @@ Schwedische Krone (SEK) US-Dollar (USD) + + %d Tarif ausgewählt + %d Tarife ausgewählt + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3ea3499d..2a4b72f5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -188,4 +188,10 @@ Could not load prices None of the connectors on this charging station is compatible with your vehicle. Currency + My charging plans + all plans selected + + %d plan selected + %d plans selected + diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index 91ed310c..d2209268 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -42,6 +42,9 @@ +