Compare commits

...

28 Commits
1.9.2 ... 1.9.6

Author SHA1 Message Date
Johan von Forstner
398f159e27 Release 1.9.6 2024-07-31 16:37:23 +02:00
Johan von Forstner
6ab3ba2ed2 Mapbox Autocomplete: catch HttpExceptions 2024-07-31 16:10:36 +02:00
Johan von Forstner
f59fd9b3aa OpenChargeMap API: fix nullability 2024-07-31 16:04:14 +02:00
Johan von Forstner
9e18c62d9d remove unused method 2024-07-31 16:03:07 +02:00
Johan von Forstner
3626c9a72f update spatia-room 2024-07-31 15:56:48 +02:00
Johan von Forstner
36805d8224 AAOS: fallback to regular navigation intent if car app intent fails 2024-07-30 21:21:41 +02:00
johan12345
b1dee90068 docs improvements 2024-07-13 14:11:51 +02:00
johan12345
dfc7de75ad Release 1.9.5 2024-06-30 17:37:53 +02:00
johan12345
32c7774a3a update MapLibre
may help with #351
2024-06-30 16:34:03 +02:00
johan12345
02ef25b961 rework navigation handling to avoid changing start destination
fixes the following issue:
- start app for the first time, go through onboarding
- go to settings, change to dark mode
- try to go back to the map using the drawer
-> stuck, only back button helps
2024-06-30 16:22:35 +02:00
johan12345
e535e77b7a update build tools 2024-06-30 15:08:30 +02:00
johan12345
5b0b4e4337 remove "noinspection JCenterRepositoryObsolete" 2024-06-30 15:07:50 +02:00
johan12345
a6bbf635c5 Update AnyMaps & Google Maps
uses new Google Maps dark mode
2024-06-30 14:08:24 +02:00
johan12345
591f99dea4 update to released locale-config-x version 2024-06-22 11:53:52 +02:00
johan12345
0c5bd69205 Release 1.9.4 2024-06-21 00:25:13 +02:00
johan12345
72e98cf611 fix NoSuchElementExceptions in intent handling 2024-06-21 00:23:37 +02:00
johan12345
0fefffda2f update MapLibre
may help with #351
2024-06-21 00:19:38 +02:00
johan12345
49e555ef04 switch to fork of locale-config-x
fixes crash #352 until https://github.com/erfansn/locale-config-x/pull/2 is merged
2024-06-21 00:00:42 +02:00
johan12345
d6d1e915ee updated TeslaGuestApi 2024-06-19 00:19:36 +02:00
johan12345
546d7a11ce maybe fix rare NPE in GoingElectricAPI 2024-06-16 17:54:59 +02:00
johan12345
4849944c23 Release 1.9.3 2024-06-05 20:32:10 +02:00
johan12345
77b38661dd fix b9354e77: use correct exception type 2024-06-05 19:05:57 +02:00
johan12345
3723ee161b update AnyMaps
fixes issue where satellite map would not load correctly under some conditions
2024-06-04 21:41:26 +02:00
johan12345
1d3efe5295 update AnyMaps
fixes #346 through a5b09b5fda
2024-06-04 21:17:53 +02:00
johan12345
f011944135 fix lint error 2024-05-30 17:28:38 +02:00
johan12345
1d81bb5d37 Simplify currency handling
removes the need to translate all the currency names
2024-05-30 17:15:06 +02:00
johan12345
e8adb759a6 Simplify locale handling
using Locale Config X library
https://github.com/erfansn/locale-config-x
2024-05-30 16:52:02 +02:00
johan12345
f4384b4b60 update Android Gradle plugin 2024-05-30 13:10:20 +02:00
42 changed files with 316 additions and 378 deletions

View File

@@ -46,8 +46,7 @@ features and how they can be obtained in our [documentation page](doc/api_keys.m
There are four different build flavors, `googleNormal`, `fossNormal`, `googleAutomotive`, and
`fossAutomotive`.
- The `foss` variants only use OSM data and should run on most Android devices, even without
Google Play Services.
- The `foss` variants only use OSM data for the base map and place search. They should run on most Android devices, even those without Google Play Services.
- `fossNormal` is intended to run on smartphones and tablets, and also includes the Android
Auto app for use on the car display (however Android Auto may not work if the app is not
installed from Google Play, see https://github.com/ev-map/EVMap/issues/319).

View File

@@ -20,8 +20,8 @@ android {
minSdk = 21
targetSdk = 34
// NOTE: always increase versionCode by 2 since automotive flavor uses versionCode + 1
versionCode = 222
versionName = "1.9.2"
versionCode = 230
versionName = "1.9.6"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
@@ -306,6 +306,7 @@ dependencies {
implementation("com.google.guava:guava:29.0-android")
implementation("com.github.pengrad:mapscaleview:1.6.0")
implementation("com.github.romandanylyk:PageIndicatorView:b1bad589b5")
implementation("com.github.erfansn:locale-config-x:1.0.1")
// Android Auto
val carAppVersion = "1.4.0"
@@ -314,14 +315,17 @@ dependencies {
automotiveImplementation("androidx.car.app:app-automotive:$carAppVersion")
// AnyMaps
val anyMapsVersion = "a5b9abca40"
val anyMapsVersion = "3e6c71410f"
implementation("com.github.ev-map.AnyMaps:anymaps-base:$anyMapsVersion")
googleImplementation("com.github.ev-map.AnyMaps:anymaps-google:$anyMapsVersion")
googleImplementation("com.google.android.gms:play-services-maps:18.2.0")
googleImplementation("com.google.android.gms:play-services-maps:19.0.0")
implementation("com.github.ev-map.AnyMaps:anymaps-maplibre:$anyMapsVersion") {
// duplicates classes from mapbox-sdk-services
exclude("org.maplibre.gl", "android-sdk-geojson")
}
implementation("org.maplibre.gl:android-sdk:10.3.2-pre3") {
exclude("org.maplibre.gl", "android-sdk-geojson")
}
// Google Places
googleImplementation("com.google.android.libraries.places:places:3.5.0")
@@ -344,10 +348,7 @@ dependencies {
implementation("androidx.room:room-runtime:$room_version")
kapt("androidx.room:room-compiler:$room_version")
implementation("androidx.room:room-ktx:$room_version")
implementation("com.github.anboralabs:spatia-room:0.2.9") {
exclude(group = "com.github.dalgarins", module = "android-spatialite")
}
implementation("com.github.EV-map:android-spatialite:e5495c83ad") // version with minSdk increased to 21 & FORTIFY_SOURCE enabled
implementation("com.github.anboralabs:spatia-room:0.3.0")
// billing library
val billing_version = "7.0.0"

View File

@@ -3,7 +3,11 @@ package net.vonforst.evmap
import android.app.Activity
import android.app.Application
import android.os.Build
import androidx.work.*
import androidx.work.Configuration
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import net.vonforst.evmap.storage.CleanupCacheWorker
import net.vonforst.evmap.storage.PreferenceDataSource
import net.vonforst.evmap.ui.updateAppLocale
@@ -24,7 +28,7 @@ class EvMapApplication : Application(), Configuration.Provider {
// Convert to new AppCompat storage for app language
val lang = prefs.language
if (lang != null && lang !in listOf("", "default")) {
if (lang != null) {
updateAppLocale(lang)
prefs.language = null
}

View File

@@ -60,6 +60,7 @@ class MapsActivity : AppCompatActivity(),
setContentView(R.layout.activity_maps)
val drawerLayout = findViewById<DrawerLayout>(R.id.drawer_layout)
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.map,
@@ -67,7 +68,7 @@ class MapsActivity : AppCompatActivity(),
R.id.about,
R.id.settings
),
findViewById<DrawerLayout>(R.id.drawer_layout)
drawerLayout
)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
@@ -87,6 +88,17 @@ class MapsActivity : AppCompatActivity(),
checkPlayServices(this)
navController.setGraph(navGraph, MapFragmentArgs(appStart = true).toBundle())
var deepLink: PendingIntent? = null
navController.addOnDestinationChangedListener { _, destination, _ ->
if (destination.id == R.id.onboarding) {
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
} else {
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
}
}
if (!prefs.welcomeDialogShown || !prefs.dataSourceSet) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
// wait for splash screen animation to finish on first start
@@ -104,134 +116,125 @@ class MapsActivity : AppCompatActivity(),
}
})
}
navGraph.setStartDestination(R.id.onboarding)
navController.graph = navGraph
return
} else if (!prefs.privacyAccepted) {
navGraph.setStartDestination(R.id.onboarding)
navController.graph = navGraph
return
} else {
navGraph.setStartDestination(R.id.map)
navController.setGraph(navGraph, MapFragmentArgs(appStart = true).toBundle())
var deepLink: PendingIntent? = null
} else if (intent?.scheme == "geo") {
val query = intent.data?.query?.split("=")?.get(1)
val coords = getLocationFromIntent(intent)
if (intent?.scheme == "geo") {
val query = intent.data?.query?.split("=")?.get(1)
val coords = getLocationFromIntent(intent)
if (coords != null) {
val lat = coords[0]
val lon = coords[1]
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(latLng = LatLng(lat, lon)).toBundle())
.createPendingIntent()
} else if (!query.isNullOrEmpty()) {
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(locationName = query).toBundle())
.createPendingIntent()
}
} else if (intent?.scheme == "https" && intent?.data?.host == "www.goingelectric.de") {
val id = intent.data?.pathSegments?.last()?.toLongOrNull()
if (id != null) {
if (prefs.dataSource != "goingelectric") {
prefs.dataSource = "goingelectric"
Toast.makeText(
this,
getString(
R.string.data_source_switched_to,
getString(R.string.data_source_goingelectric)
),
Toast.LENGTH_LONG
).show()
}
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(chargerId = id).toBundle())
.createPendingIntent()
}
} else if (intent?.scheme == "https" && intent?.data?.host in listOf("openchargemap.org", "map.openchargemap.io")) {
val id = when (intent.data?.host) {
"openchargemap.org" -> intent.data?.pathSegments?.last()?.toLongOrNull()
"map.openchargemap.io" -> intent.data?.getQueryParameter("id")?.toLongOrNull()
else -> null
}
if (id != null) {
if (prefs.dataSource != "openchargemap") {
prefs.dataSource = "openchargemap"
Toast.makeText(
this,
getString(
R.string.data_source_switched_to,
getString(R.string.data_source_openchargemap)
),
Toast.LENGTH_LONG
).show()
}
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(chargerId = id).toBundle())
.createPendingIntent()
}
} else if (intent.scheme == "net.vonforst.evmap") {
intent.data?.let {
if (it.host == "find_charger") {
val lat = it.getQueryParameter("latitude")?.toDouble()
val lon = it.getQueryParameter("longitude")?.toDouble()
val name = it.getQueryParameter("name")
if (lat != null && lon != null) {
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(
MapFragmentArgs(
latLng = LatLng(lat, lon),
locationName = name
).toBundle()
)
.createPendingIntent()
} else if (name != null) {
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(locationName = name).toBundle())
.createPendingIntent()
}
}
}
} else if (intent.hasExtra(EXTRA_CHARGER_ID)) {
if (coords != null) {
val lat = coords[0]
val lon = coords[1]
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(
MapFragmentArgs(
chargerId = intent.getLongExtra(EXTRA_CHARGER_ID, 0),
latLng = LatLng(
intent.getDoubleExtra(EXTRA_LAT, 0.0),
intent.getDoubleExtra(EXTRA_LON, 0.0)
)
).toBundle()
)
.setArguments(MapFragmentArgs(latLng = LatLng(lat, lon)).toBundle())
.createPendingIntent()
} else if (intent.hasExtra(EXTRA_FAVORITES)) {
} else if (!query.isNullOrEmpty()) {
deepLink = navController.createDeepLink()
.setGraph(navGraph)
.setDestination(R.id.favs)
.createPendingIntent()
} else if (intent.hasExtra(EXTRA_DONATE)) {
deepLink = navController.createDeepLink()
.setGraph(navGraph)
.setDestination(R.id.donate)
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(locationName = query).toBundle())
.createPendingIntent()
}
deepLink?.send()
} else if (intent?.scheme == "https" && intent?.data?.host == "www.goingelectric.de") {
val id = intent.data?.pathSegments?.lastOrNull()?.toLongOrNull()
if (id != null) {
if (prefs.dataSource != "goingelectric") {
prefs.dataSource = "goingelectric"
Toast.makeText(
this,
getString(
R.string.data_source_switched_to,
getString(R.string.data_source_goingelectric)
),
Toast.LENGTH_LONG
).show()
}
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(chargerId = id).toBundle())
.createPendingIntent()
}
} else if (intent?.scheme == "https" && intent?.data?.host in listOf(
"openchargemap.org",
"map.openchargemap.io"
)
) {
val id = when (intent.data?.host) {
"openchargemap.org" -> intent.data?.pathSegments?.lastOrNull()?.toLongOrNull()
"map.openchargemap.io" -> intent.data?.getQueryParameter("id")?.toLongOrNull()
else -> null
}
if (id != null) {
if (prefs.dataSource != "openchargemap") {
prefs.dataSource = "openchargemap"
Toast.makeText(
this,
getString(
R.string.data_source_switched_to,
getString(R.string.data_source_openchargemap)
),
Toast.LENGTH_LONG
).show()
}
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(chargerId = id).toBundle())
.createPendingIntent()
}
} else if (intent.scheme == "net.vonforst.evmap") {
intent.data?.let {
if (it.host == "find_charger") {
val lat = it.getQueryParameter("latitude")?.toDouble()
val lon = it.getQueryParameter("longitude")?.toDouble()
val name = it.getQueryParameter("name")
if (lat != null && lon != null) {
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(
MapFragmentArgs(
latLng = LatLng(lat, lon),
locationName = name
).toBundle()
)
.createPendingIntent()
} else if (name != null) {
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(locationName = name).toBundle())
.createPendingIntent()
}
}
}
} else if (intent.hasExtra(EXTRA_CHARGER_ID)) {
deepLink = navController.createDeepLink()
.setDestination(R.id.map)
.setArguments(
MapFragmentArgs(
chargerId = intent.getLongExtra(EXTRA_CHARGER_ID, 0),
latLng = LatLng(
intent.getDoubleExtra(EXTRA_LAT, 0.0),
intent.getDoubleExtra(EXTRA_LON, 0.0)
)
).toBundle()
)
.createPendingIntent()
} else if (intent.hasExtra(EXTRA_FAVORITES)) {
deepLink = navController.createDeepLink()
.setGraph(navGraph)
.setDestination(R.id.favs)
.createPendingIntent()
} else if (intent.hasExtra(EXTRA_DONATE)) {
deepLink = navController.createDeepLink()
.setGraph(navGraph)
.setDestination(R.id.donate)
.createPendingIntent()
}
deepLink?.send()
}
fun navigateTo(charger: ChargeLocation) {

View File

@@ -17,6 +17,7 @@ import android.text.SpannedString
import android.text.TextUtils
import android.text.style.StyleSpan
import net.vonforst.evmap.storage.PreferenceDataSource
import java.util.Currency
import java.util.Locale
fun Bundle.optDouble(name: String): Double? {
@@ -139,4 +140,6 @@ fun PackageManager.isAppInstalled(packageName: String): Boolean {
} catch (e: PackageManager.NameNotFoundException) {
false
}
}
}
fun currencyDisplayName(code: String) = "${Currency.getInstance(code).displayName} ($code)"

View File

@@ -9,7 +9,6 @@ import androidx.core.text.buildSpannedString
import net.vonforst.evmap.R
import net.vonforst.evmap.api.availability.tesla.Pricing
import net.vonforst.evmap.api.availability.tesla.Rates
import net.vonforst.evmap.api.availability.tesla.TeslaChargingOwnershipGraphQlApi
import net.vonforst.evmap.bold
import net.vonforst.evmap.joinToSpannedString
import net.vonforst.evmap.model.ChargeCard

View File

@@ -7,8 +7,6 @@ import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import net.vonforst.evmap.addDebugInterceptors
import net.vonforst.evmap.api.RateLimitInterceptor
import net.vonforst.evmap.api.await
import net.vonforst.evmap.api.chargeprice.ChargepriceApi
import net.vonforst.evmap.api.equivalentPlugTypes
import net.vonforst.evmap.cartesianProduct
import net.vonforst.evmap.model.ChargeLocation
@@ -18,7 +16,6 @@ import net.vonforst.evmap.viewmodel.Resource
import okhttp3.Cache
import okhttp3.JavaNetCookieJar
import okhttp3.OkHttpClient
import okhttp3.Request
import retrofit2.HttpException
import java.io.IOException
import java.net.CookieManager
@@ -41,16 +38,6 @@ interface AvailabilityDetector {
abstract class BaseAvailabilityDetector(private val client: OkHttpClient) : AvailabilityDetector {
protected val radius = 150 // max radius in meters
protected suspend fun httpGet(url: String): String {
val request = Request.Builder().url(url).build()
val response = client.newCall(request).await()
if (!response.isSuccessful) throw IOException(response.message)
val str = response.body!!.string()
return str
}
protected fun getCorrespondingChargepoint(
cps: Iterable<Chargepoint>, type: String, power: Double
): Chargepoint? {

View File

@@ -52,32 +52,31 @@ class TeslaGuestAvailabilityDetector(
val (detailsA, guestPricing) = coroutineScope {
val details = async {
api.getChargingSiteDetails(
TeslaChargingGuestGraphQlApi.GetChargingSiteDetailsRequest(
TeslaChargingGuestGraphQlApi.GetChargingSiteInformationVariables(
api.getSiteDetails(
TeslaChargingGuestGraphQlApi.GetSiteDetailsRequest(
TeslaChargingGuestGraphQlApi.GetSiteDetailsVariables(
TeslaChargingGuestGraphQlApi.Identifier(
TeslaChargingGuestGraphQlApi.ChargingSiteIdentifier(
trtId
trtId, TeslaChargingGuestGraphQlApi.Experience.ADHOC
)
),
TeslaChargingGuestGraphQlApi.Experience.ADHOC
)
)
).data.site ?: throw AvailabilityDetectorException("no candidates found.")
).data.chargingNetwork?.site
?: throw AvailabilityDetectorException("no candidates found.")
}
val guestPricing = async {
api.getChargingSiteDetails(
TeslaChargingGuestGraphQlApi.GetChargingSiteDetailsRequest(
TeslaChargingGuestGraphQlApi.GetChargingSiteInformationVariables(
api.getSiteDetails(
TeslaChargingGuestGraphQlApi.GetSiteDetailsRequest(
TeslaChargingGuestGraphQlApi.GetSiteDetailsVariables(
TeslaChargingGuestGraphQlApi.Identifier(
TeslaChargingGuestGraphQlApi.ChargingSiteIdentifier(
trtId
trtId, TeslaChargingGuestGraphQlApi.Experience.GUEST
)
),
TeslaChargingGuestGraphQlApi.Experience.GUEST
)
)
).data.site?.pricing
).data.chargingNetwork?.site?.pricing
}
details to guestPricing
}
@@ -103,12 +102,9 @@ class TeslaGuestAvailabilityDetector(
"charger has unknown connectors"
)
val chargerDetails = details.chargersAvailable.chargerDetails
val chargers = details.chargers.associateBy { it.id }
var detailsSorted = chargerDetails
.sortedBy { chargers[it.id]?.labelLetter }
.sortedBy { chargers[it.id]?.labelNumber }
var detailsSorted = details.chargerList
.sortedBy { c -> c.labelLetter }
.sortedBy { c -> c.labelNumber }
if (detailsSorted.size != scV2Connectors.sumOf { it.count } + scV3Connectors.sumOf { it.count }) {
// apparently some connectors are missing in Tesla data
@@ -120,7 +116,7 @@ class TeslaGuestAvailabilityDetector(
detailsSorted + List(numMissing) {
TeslaChargingGuestGraphQlApi.ChargerDetail(
ChargerAvailability.UNKNOWN,
""
"", ""
)
}
} else {
@@ -151,7 +147,7 @@ class TeslaGuestAvailabilityDetector(
}
val statusMap = detailsMap.mapValues { it.value.map { it.availability.toStatus() } }
val labelsMap = detailsMap.mapValues { it.value.map { chargers[it.id]?.label } }
val labelsMap = detailsMap.mapValues { it.value.map { it.label } }
val pricing = details.pricing.copy(memberRates = guestPricing.await()?.userRates)

View File

@@ -1,12 +1,8 @@
package net.vonforst.evmap.api.availability.tesla
import com.squareup.moshi.Json
import com.squareup.moshi.JsonAdapter
import com.squareup.moshi.JsonClass
import com.squareup.moshi.JsonReader
import com.squareup.moshi.JsonWriter
import com.squareup.moshi.Moshi
import com.squareup.moshi.Types
import okhttp3.CacheControl
import okhttp3.OkHttpClient
import retrofit2.Retrofit
@@ -15,7 +11,6 @@ import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Query
import java.lang.reflect.Type
import java.util.concurrent.TimeUnit
interface TeslaCuaApi {
@@ -71,24 +66,22 @@ interface TeslaCuaApi {
interface TeslaChargingGuestGraphQlApi {
@POST("graphql")
suspend fun getChargingSiteDetails(
@Body request: GetChargingSiteDetailsRequest,
@Query("operationName") operationName: String = "getGuestChargingSiteDetails"
suspend fun getSiteDetails(
@Body request: GetSiteDetailsRequest,
@Query("operationName") operationName: String = "GetSiteDetails"
): GetChargingSiteDetailsResponse
@JsonClass(generateAdapter = true)
data class GetChargingSiteDetailsRequest(
override val variables: GetChargingSiteInformationVariables,
override val operationName: String = "getGuestChargingSiteDetails",
data class GetSiteDetailsRequest(
override val variables: GetSiteDetailsVariables,
override val operationName: String = "GetSiteDetails",
override val query: String =
"\n query getGuestChargingSiteDetails(\$identifier: ChargingSiteIdentifierInput!, \$deviceLocale: String!, \$experience: ChargingExperienceEnum!) {\n site(\n identifier: \$identifier\n deviceLocale: \$deviceLocale\n experience: \$experience\n ) {\n activeOutages\n address {\n countryCode\n }\n chargers {\n id\n label\n }\n chargersAvailable {\n chargerDetails {\n id\n availability\n }\n }\n holdAmount {\n holdAmount\n currencyCode\n }\n maxPowerKw\n name\n programType\n publicStallCount\n id\n pricing(experience: \$experience) {\n userRates {\n activePricebook {\n charging {\n uom\n rates\n buckets {\n start\n end\n }\n bucketUom\n currencyCode\n programType\n vehicleMakeType\n touRates {\n enabled\n activeRatesByTime {\n startTime\n endTime\n rates\n }\n }\n }\n parking {\n uom\n rates\n buckets {\n start\n end\n }\n bucketUom\n currencyCode\n programType\n vehicleMakeType\n touRates {\n enabled\n activeRatesByTime {\n startTime\n endTime\n rates\n }\n }\n }\n congestion {\n uom\n rates\n buckets {\n start\n end\n }\n bucketUom\n currencyCode\n programType\n vehicleMakeType\n touRates {\n enabled\n activeRatesByTime {\n startTime\n endTime\n rates\n }\n }\n }\n }\n }\n }\n }\n}\n "
"\n query GetSiteDetails(\$siteId: SiteIdInput!) {\n chargingNetwork {\n site(siteId: \$siteId) {\n address {\n countryCode\n }\n chargerList {\n id\n label\n availability\n }\n holdAmount {\n amount\n currencyCode\n }\n maxPowerKw\n name\n programType\n publicStallCount\n trtId\n pricing {\n userRates {\n activePricebook {\n charging {\n ...ChargingRate\n }\n parking {\n ...ChargingRate\n }\n congestion {\n ...ChargingRate\n }\n }\n }\n }\n }\n }\n}\n \n fragment ChargingRate on ChargingUserRate {\n uom\n rates\n buckets {\n start\n end\n }\n bucketUom\n currencyCode\n programType\n vehicleMakeType\n touRates {\n enabled\n activeRatesByTime {\n startTime\n endTime\n rates\n }\n }\n}\n "
) : GraphQlRequest()
@JsonClass(generateAdapter = true)
data class GetChargingSiteInformationVariables(
val identifier: Identifier,
val experience: Experience,
val deviceLocale: String = "de-DE",
data class GetSiteDetailsVariables(
val siteId: Identifier,
)
enum class Experience {
@@ -97,22 +90,22 @@ interface TeslaChargingGuestGraphQlApi {
@JsonClass(generateAdapter = true)
data class Identifier(
val siteId: ChargingSiteIdentifier
val byTrtId: ChargingSiteIdentifier
)
@JsonClass(generateAdapter = true)
data class ChargingSiteIdentifier(
val id: Long,
val siteType: SiteType = SiteType.SUPERCHARGER
val trtId: Long,
val chargingExperience: Experience,
val programType: String = "PTSCH",
val locale: String = "de-DE",
)
enum class SiteType {
@Json(name = "SITE_TYPE_SUPERCHARGER")
SUPERCHARGER
}
@JsonClass(generateAdapter = true)
data class GetChargingSiteDetailsResponse(val data: GetChargingSiteDetailsResponseDataNetwork)
@JsonClass(generateAdapter = true)
data class GetChargingSiteDetailsResponse(val data: GetChargingSiteDetailsResponseData)
data class GetChargingSiteDetailsResponseDataNetwork(val chargingNetwork: GetChargingSiteDetailsResponseData?)
@JsonClass(generateAdapter = true)
data class GetChargingSiteDetailsResponseData(val site: ChargingSiteInformation?)
@@ -120,9 +113,8 @@ interface TeslaChargingGuestGraphQlApi {
@JsonClass(generateAdapter = true)
data class ChargingSiteInformation(
val activeOutages: List<Outage>?,
val chargers: List<ChargerId>,
val chargersAvailable: ChargersAvailable,
val id: Long,
val chargerList: List<ChargerDetail>,
val trtId: Long,
val maxPowerKw: Int,
val name: String,
val pricing: Pricing,
@@ -130,9 +122,10 @@ interface TeslaChargingGuestGraphQlApi {
)
@JsonClass(generateAdapter = true)
data class ChargerId(
val id: String,
data class ChargerDetail(
val availability: ChargerAvailability,
val label: String?,
val id: String
) {
val labelNumber
get() = label?.replace(Regex("""\D"""), "")?.toInt()
@@ -140,15 +133,6 @@ interface TeslaChargingGuestGraphQlApi {
get() = label?.replace(Regex("""\d"""), "")
}
@JsonClass(generateAdapter = true)
data class ChargersAvailable(val chargerDetails: List<ChargerDetail>)
@JsonClass(generateAdapter = true)
data class ChargerDetail(
val availability: ChargerAvailability,
val id: String
)
companion object {
fun create(
client: OkHttpClient,

View File

@@ -452,7 +452,10 @@ class GoingElectricApiWrapper(
if (responses.map { it.isSuccessful }.all { it }
&& plugsResponse.body()!!.status == STATUS_OK
&& chargeCardsResponse.body()!!.status == STATUS_OK
&& networksResponse.body()!!.status == STATUS_OK) {
&& networksResponse.body()!!.status == STATUS_OK
&& plugsResponse.body()!!.result != null
&& chargeCardsResponse.body()!!.result != null
&& networksResponse.body()!!.result != null) {
Resource.success(
GEReferenceData(
plugsResponse.body()!!.result!!,

View File

@@ -254,7 +254,7 @@ data class OCMUserComment(
@Json(name = "ID") val id: Long,
@Json(name = "CommentTypeID") val commentTypeId: Long,
@Json(name = "Comment") val comment: String?,
@Json(name = "UserName") val userName: String,
@Json(name = "UserName") val userName: String?,
@Json(name = "DateCreated") val dateCreated: ZonedDateTime
)

View File

@@ -11,8 +11,10 @@ import android.net.Uri
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.util.Log
import androidx.car.app.CarContext
import androidx.car.app.CarToast
import androidx.car.app.HostException
import androidx.car.app.Screen
import androidx.car.app.constraints.ConstraintManager
import androidx.car.app.model.Action
@@ -56,6 +58,7 @@ import net.vonforst.evmap.api.iconForPlugType
import net.vonforst.evmap.api.nameForPlugType
import net.vonforst.evmap.api.stringProvider
import net.vonforst.evmap.model.ChargeLocation
import net.vonforst.evmap.model.Coordinate
import net.vonforst.evmap.model.Cost
import net.vonforst.evmap.model.FaultReport
import net.vonforst.evmap.model.Favorite
@@ -74,6 +77,7 @@ import java.time.format.FormatStyle
import kotlin.math.floor
import kotlin.math.roundToInt
private const val TAG = "ChargerDetailScreen"
class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) : Screen(ctx) {
var charger: ChargeLocation? = null
@@ -543,6 +547,14 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
}
private fun navigateToCharger(charger: ChargeLocation) {
val success = navigateCarApp(charger)
if (!success && BuildConfig.FLAVOR_automotive == "automotive") {
// on AAOS, some OEMs' navigation apps might not support
navigateRegularApp(charger)
}
}
private fun navigateCarApp(charger: ChargeLocation): Boolean {
val coord = charger.coordinates
val intent =
Intent(
@@ -551,9 +563,35 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
)
try {
carContext.startCarApp(intent)
} catch (e: UnsupportedOperationException) {
CarToast.makeText(carContext, R.string.no_maps_app_found, CarToast.LENGTH_SHORT).show()
return true
} catch (e: HostException) {
Log.w(TAG, "Could not start navigation using car app intent")
Log.w(TAG, intent.toString())
e.printStackTrace()
} catch (e: SecurityException) {
Log.w(TAG, "Could not start navigation using car app intent")
Log.w(TAG, intent.toString())
e.printStackTrace()
}
return false
}
private fun navigateRegularApp(charger: ChargeLocation): Boolean {
val coord = charger.coordinates
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse(
"geo:${coord.lat},${coord.lng}?q=${coord.lat},${coord.lng}(${
Uri.encode(charger.name)
})"
)
if (intent.resolveActivity(carContext.packageManager) != null) {
carContext.startActivity(intent)
return true
} else {
Log.w(TAG, "Could not start navigation using regular intent")
Log.w(TAG, intent.toString())
}
return false
}
private fun loadCharger() {

View File

@@ -43,6 +43,7 @@ import net.vonforst.evmap.api.availability.tesla.TeslaOwnerApi
import net.vonforst.evmap.api.chargeprice.ChargepriceApi
import net.vonforst.evmap.api.chargeprice.ChargepriceCar
import net.vonforst.evmap.api.chargeprice.ChargepriceTariff
import net.vonforst.evmap.currencyDisplayName
import net.vonforst.evmap.fragment.oauth.OAuthLoginFragment
import net.vonforst.evmap.fragment.oauth.OAuthLoginFragmentArgs
import net.vonforst.evmap.getPackageInfoCompat
@@ -486,10 +487,9 @@ class ChargepriceSettingsScreen(ctx: CarContext) : Screen(ctx) {
addItem(Row.Builder().apply {
setTitle(carContext.getString(R.string.pref_chargeprice_currency))
val names =
carContext.resources.getStringArray(R.array.pref_chargeprice_currency_names)
val values =
carContext.resources.getStringArray(R.array.pref_chargeprice_currency_values)
carContext.resources.getStringArray(R.array.pref_chargeprice_currencies)
val names = values.map(::currencyDisplayName)
val index = values.indexOf(prefs.chargepriceCurrency)
addText(if (index >= 0) names[index] else "")
@@ -629,8 +629,8 @@ class SelectCurrencyScreen(ctx: CarContext) : MultiSelectSearchScreen<Pair<Strin
override fun getLabel(it: Pair<String, String>): String = it.first
override suspend fun loadData(): List<Pair<String, String>> {
val names = carContext.resources.getStringArray(R.array.pref_chargeprice_currency_names)
val values = carContext.resources.getStringArray(R.array.pref_chargeprice_currency_values)
val values = carContext.resources.getStringArray(R.array.pref_chargeprice_currencies)
val names = values.map(::currencyDisplayName)
return names.zip(values)
}
}

View File

@@ -16,6 +16,7 @@ import com.mapbox.api.geocoding.v5.models.CarmenFeature
import com.mapbox.geojson.BoundingBox
import com.mapbox.geojson.Point
import net.vonforst.evmap.R
import retrofit2.HttpException
import java.io.IOException
class MapboxAutocompleteProvider(val context: Context) : AutocompleteProvider {
@@ -25,7 +26,7 @@ class MapboxAutocompleteProvider(val context: Context) : AutocompleteProvider {
override val id = "mapbox"
override fun autocomplete(query: String, location: LatLng?): List<AutocompletePlace> {
val result = MapboxGeocoding.builder().apply {
val request = MapboxGeocoding.builder().apply {
location?.let {
proximity(Point.fromLngLat(location.longitude, location.latitude))
}
@@ -33,7 +34,12 @@ class MapboxAutocompleteProvider(val context: Context) : AutocompleteProvider {
accessToken(context.getString(R.string.mapbox_key))
autocomplete(true)
this.query(query)
}.build().executeCall()
}
val result = try {
request.build().executeCall()
} catch (e: HttpException) {
throw IOException(e)
}
if (!result.isSuccessful) {
throw IOException(result.message())
}

View File

@@ -297,6 +297,10 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
get() = resources.getBoolean(R.bool.bottom_sheet_collapsible)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
if (!prefs.welcomeDialogShown || !prefs.dataSourceSet || !prefs.privacyAccepted) {
findNavController().navigate(R.id.onboarding)
}
requireActivity().addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED)
mapFragment!!.getMapAsync(this)
@@ -1051,6 +1055,8 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
this.map = map
vm.mapProjection = map.projection
val context = this.context ?: return
view ?: return
chargerIconGenerator = ChargerIconGenerator(context, map.bitmapDescriptorFactory)
vm.mapTrafficSupported.value =

View File

@@ -8,7 +8,9 @@ import android.text.style.RelativeSizeSpan
import android.view.View
import androidx.fragment.app.viewModels
import androidx.preference.CheckBoxPreference
import androidx.preference.ListPreference
import net.vonforst.evmap.R
import net.vonforst.evmap.currencyDisplayName
import net.vonforst.evmap.ui.MultiSelectDialogPreference
import net.vonforst.evmap.viewmodel.SettingsViewModel
import net.vonforst.evmap.viewmodel.viewModelFactory
@@ -73,6 +75,11 @@ class ChargepriceSettingsFragment : BaseSettingsFragment() {
}
}
updateNativeIntegrationState()
val currencyPreference = findPreference<ListPreference>("chargeprice_currency")!!
currencyPreference.entries = currencyPreference.entryValues.map {
currencyDisplayName(it.toString()).replaceFirstChar { it.uppercase() }
}.toTypedArray()
}
private fun updateNativeIntegrationState() {

View File

@@ -9,9 +9,11 @@ import android.provider.Settings
import androidx.preference.CheckBoxPreference
import androidx.preference.ListPreference
import androidx.preference.Preference
import com.github.erfansn.localeconfigx.configuredLocales
import net.vonforst.evmap.R
import net.vonforst.evmap.isAppInstalled
import net.vonforst.evmap.ui.getAppLocale
import net.vonforst.evmap.ui.map
import net.vonforst.evmap.ui.updateAppLocale
import net.vonforst.evmap.ui.updateNightMode
@@ -23,11 +25,7 @@ class UiSettingsFragment : BaseSettingsFragment() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.settings_ui, rootKey)
langPref = findPreference("language")!!
langPref.setOnPreferenceChangeListener { _, newValue ->
updateAppLocale(newValue as String)
true
}
setupLangPref()
val appLinkPref = findPreference<Preference>("applink_associate")!!
appLinkPref.isVisible = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
@@ -36,6 +34,31 @@ class UiSettingsFragment : BaseSettingsFragment() {
immediateNavPref.isVisible = isGoogleMapsInstalled()
}
private fun setupLangPref() {
langPref = findPreference("language")!!
val configuredLocales = requireContext().configuredLocales
val numLocalesByLang = configuredLocales.map { it.language }.groupingBy { it }.eachCount()
val localeNames = configuredLocales.map {
val name = if (numLocalesByLang[it.language]!! > 1) {
it.getDisplayName(it)
} else {
it.getDisplayLanguage(it)
}
name.replaceFirstChar { c -> c.uppercase(it) }
}
val localeTags = configuredLocales.map { it.toLanguageTag() }
langPref.entries =
(listOf(getString(R.string.pref_language_device_default)) + localeNames).toTypedArray()
langPref.entryValues =
(listOf("default") + localeTags).toTypedArray()
langPref.setOnPreferenceChangeListener { _, newValue ->
updateAppLocale(newValue as String)
true
}
}
private fun isGoogleMapsInstalled() =
requireContext().packageManager.isAppInstalled("com.google.android.apps.maps")

View File

@@ -3,8 +3,9 @@ package net.vonforst.evmap.ui
import android.content.Context
import androidx.appcompat.app.AppCompatDelegate
import androidx.core.os.LocaleListCompat
import net.vonforst.evmap.R
import com.github.erfansn.localeconfigx.configuredLocales
import net.vonforst.evmap.storage.PreferenceDataSource
import java.util.Locale
fun updateNightMode(prefs: PreferenceDataSource) {
@@ -33,8 +34,11 @@ fun getAppLocale(context: Context): String? {
"default"
} else {
val arr = Array(locales.size()) { locales.get(it)!!.toLanguageTag() }
val choices =
context.resources.getStringArray(R.array.pref_language_values).joinToString(",")
LocaleListCompat.forLanguageTags(choices).getFirstMatch(arr)?.toLanguageTag()
val choices = context.configuredLocales
choices.getFirstMatch(arr)?.toLanguageTag()
}
}
inline fun <R> LocaleListCompat.map(transform: (Locale) -> R): List<R> = List(size()) {
transform(get(it)!!)
}

View File

@@ -2,6 +2,7 @@
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
app:startDestination="@id/map"
android:id="@+id/nav_graph">
<navigation

View File

@@ -199,8 +199,6 @@
<string name="autocomplete_connection_error">Nepodařilo se načíst návrhy</string>
<string name="pref_language_device_default">Podle zařízení</string>
<string name="pref_darkmode_device_default">Podle zařízení</string>
<string name="pref_chargeprice_currency_sek">Švédská koruna (SEK)</string>
<string name="pref_chargeprice_currency_usd">Americký dolar (USD)</string>
<string name="pref_provider_google_maps">Mapy Google</string>
<string name="pref_provider_osm_mapbox">OpenStreetMap (Mapbox)</string>
<string name="about_contributors">Přispěvatelé</string>
@@ -351,16 +349,6 @@
<string name="chargeprice_faq_link">https://ev-map.app/faq/#price-comparison-feature</string>
<string name="pref_darkmode_always_on">vždy zapnut</string>
<string name="pref_darkmode_always_off">vždy vypnut</string>
<string name="pref_chargeprice_currency_chf">Švýcarský frank (CHF)</string>
<string name="pref_chargeprice_currency_czk">Česká koruna (CZK)</string>
<string name="pref_chargeprice_currency_dkk">Dánská koruna (DKK)</string>
<string name="pref_chargeprice_currency_eur">Euro (EUR)</string>
<string name="pref_chargeprice_currency_gbp">Britská libra (GBP)</string>
<string name="pref_chargeprice_currency_huf">Maďarský forint (HUF)</string>
<string name="pref_chargeprice_currency_hrk">Chorvatská kuna (HRK)</string>
<string name="pref_chargeprice_currency_isk">Islandská koruna (ISK)</string>
<string name="pref_chargeprice_currency_nok">Norská koruna (NOK)</string>
<string name="pref_chargeprice_currency_pln">Polský zlotý (PLN)</string>
<string name="chargeprice_header_other_tariffs">Ostatní plány</string>
<string name="charger_website">Webové stránky</string>
<string name="compass">Kompas</string>

View File

@@ -258,18 +258,6 @@
<string name="pref_darkmode_device_default">Geräteeinstellung verwenden</string>
<string name="pref_darkmode_always_on">immer an</string>
<string name="pref_darkmode_always_off">immer aus</string>
<string name="pref_chargeprice_currency_chf">Schweizer Franken (CHF)</string>
<string name="pref_chargeprice_currency_czk">Tschechische Krone (CZK)</string>
<string name="pref_chargeprice_currency_dkk">Dänische Krone (DKK)</string>
<string name="pref_chargeprice_currency_eur">Euro (EUR)</string>
<string name="pref_chargeprice_currency_gbp">Britisches Pfund (GBP)</string>
<string name="pref_chargeprice_currency_hrk">Kroatische Kuna (HRK)</string>
<string name="pref_chargeprice_currency_huf">Ungarischer Forint (HUF)</string>
<string name="pref_chargeprice_currency_isk">Isländische Krone (ISK)</string>
<string name="pref_chargeprice_currency_nok">Norwegische Krone (NOK)</string>
<string name="pref_chargeprice_currency_pln">Polnischer Złoty (PLN)</string>
<string name="pref_chargeprice_currency_sek">Schwedische Krone (SEK)</string>
<string name="pref_chargeprice_currency_usd">US-Dollar (USD)</string>
<string name="pref_provider_google_maps">Google Maps</string>
<string name="pref_provider_osm">OpenStreetMap</string>
<string name="pref_provider_osm_mapbox">OpenStreetMap (Mapbox)</string>

View File

@@ -128,9 +128,6 @@
<string name="pref_darkmode_device_default">Utiliser le réglage de l\'appareil</string>
<string name="pref_darkmode_always_on">toujours allumé</string>
<string name="pref_darkmode_always_off">toujours éteint</string>
<string name="pref_chargeprice_currency_czk">Couronne tchèque (CZK)</string>
<string name="pref_chargeprice_currency_dkk">Couronne danoise (DKK)</string>
<string name="pref_chargeprice_currency_eur">Euro (EUR)</string>
<string name="show_more">plus…</string>
<string name="fav_remove">Retirer des favoris</string>
<string name="amenities">Commodités</string>
@@ -230,9 +227,6 @@
<item quantity="other">(seront mis en évidence dans la comparaison des prix)</item>
</plurals>
<string name="deleted_recent_search_results">Les résultats de recherche récents ont été supprimés</string>
<string name="pref_chargeprice_currency_gbp">Livre sterling (GBP)</string>
<string name="pref_chargeprice_currency_isk">Couronne islandaise (ISK)</string>
<string name="pref_chargeprice_currency_nok">Couronne norvégienne (NOK)</string>
<string name="settings_charger_data">Stations de recharge</string>
<string name="got_it">J\'ai compris</string>
<string name="powered_by_mapbox">propulsé par Mapbox</string>
@@ -246,15 +240,9 @@
<string name="settings_data_sources">Sources de données</string>
<string name="data_sources_description">Veuillez choisir une source de données pour les stations de recharge. Vous pourrez la modifier ultérieurement dans les paramètres de l\'application.</string>
<string name="pref_search_provider_info">Les données pour la recherche de lieux, en particulier celles de Google Maps, sont relativement coûteuses à récupérer. Veuillez envisager de faire un don via \"À propos\" -&gt; \"Faire un don\".</string>
<string name="pref_chargeprice_currency_hrk">Kuna croate (HRK)</string>
<string name="help">Aide</string>
<string name="pref_chargeprice_allow_unbalanced_load_summary">Autoriser la charge en courant alternatif monophasé de plus de 4,5 kW</string>
<string name="pref_chargeprice_currency_huf">Forint hongrois (HUF)</string>
<string name="pref_chargeprice_currency_pln">Złoty polonais (PLN)</string>
<string name="pref_map_rotate_gestures_on">Utilisez deux doigts pour faire pivoter la carte</string>
<string name="pref_chargeprice_currency_chf">Franc suisse (CHF)</string>
<string name="pref_chargeprice_currency_usd">Dollar américain (USD)</string>
<string name="pref_chargeprice_currency_sek">Couronne suédoise (SEK)</string>
<string name="cost_detail_charging"><b>Recharge %s</b></string>
<string name="cost_detail_parking"><b>Stationnement %s</b></string>
<string name="navigate">Naviguer vers</string>

View File

@@ -84,10 +84,6 @@
<string name="got_it">Skjønner</string>
<string name="settings_data_sources">Datakilder</string>
<string name="pref_search_delete_recent">Slett nylige søkeresultater</string>
<string name="pref_chargeprice_currency_eur">Euro (EUR)</string>
<string name="pref_chargeprice_currency_nok">Norske kroner (NOK)</string>
<string name="pref_chargeprice_currency_gbp">Britiske pund (GBP)</string>
<string name="pref_chargeprice_currency_sek">Svenske kroner (SEK)</string>
<string name="realtime_data_loading">Sjekker sanntidsstatus …</string>
<string name="realtime_data_source">Kilde for sanntidsstatus (beta): %s</string>
<string name="realtime_data_unavailable">Sanntidsstatus utilgjengelig</string>
@@ -183,16 +179,9 @@
<string name="deleted_recent_search_results">Nylige søkeresultater slettet</string>
<string name="autocomplete_connection_error">Kunne ikke laste inn forslag</string>
<string name="pref_language_device_default">Enhetsforvalg</string>
<string name="pref_chargeprice_currency_chf">Sveitserfranc (CHF)</string>
<string name="pref_chargeprice_currency_czk">Tsjekkiske kroner (CZK)</string>
<string name="pref_chargeprice_currency_dkk">Danske kroner (DKK)</string>
<string name="pref_chargeprice_currency_hrk">Kroatiske kroner (HRK)</string>
<string name="pref_map_rotate_gestures_on">Bruk to fingre for å rotere kartet</string>
<string name="pref_map_rotate_gestures_off">Rotasjon avslått (nord er alltid oppover)</string>
<string name="refresh_live_data">oppdater sanntidsstatus</string>
<string name="pref_chargeprice_currency_isk">Islandske kroner (ISK)</string>
<string name="pref_chargeprice_currency_pln">Polske zloty (PLN)</string>
<string name="pref_chargeprice_currency_usd">Amerikanske dollar (USD)</string>
<string name="filters_deactivated">Filtre deaktivert</string>
<string name="pref_navigate_use_maps_off">Navigasjonsknapp åpner kartprogrammet med laderposisjon</string>
<string name="show_more">flere …</string>
@@ -217,7 +206,6 @@
<string name="filter_exclude_faults">Utelat ladere med rapporterte feil</string>
<string name="plug_cee_blau">CEE blå</string>
<string name="filter_open_247">Døgnåpent</string>
<string name="pref_chargeprice_currency_huf">Ungarske forint (HUF)</string>
<string name="donation_dialog_detail">EVMap er fri programvare. Kodebidrag mottas med takk. Overvei å gi din støtte gjennom GitHub-sponsorer for å dekke løpende utgifter.</string>
<string name="pref_chargeprice_allow_unbalanced_load_summary">Tillat enfaselading over 4.5 kW</string>
<string name="connectors">Tilkobling</string>

View File

@@ -5,7 +5,6 @@
<string name="pref_search_provider_info">Gegevens opzoeken is duur, vooral via Google Maps. Overweeg aub om een donatie te doen via “Over” -&gt; “Doneer”.</string>
<string name="data_source_openchargemap_desc">Werelddekkend, met variabele kwaliteit. Beschrijving in Engels of lokale taal. Onderhouden door de gebruikers. Ook open overheidswege eens in sommige landen (bv. Noord-Amerika, UK, Frankrijk, Noorwegen).</string>
<string name="pref_darkmode_always_off">altijd uit</string>
<string name="pref_chargeprice_currency_eur">Euro (EUR)</string>
<string name="chargeprice_select_car_first">Kiest eerst je voertuig model in de instellingen</string>
<string name="chargeprice_no_compatible_connectors">Geen compatibele connectoren aan dit laadstation</string>
<string name="license">Licentie</string>
@@ -228,17 +227,6 @@
<string name="pref_language_device_default">Standaardtaal van toestel</string>
<string name="pref_darkmode_device_default">Standaardinstelling van toestel</string>
<string name="pref_darkmode_always_on">altijd aan</string>
<string name="pref_chargeprice_currency_chf">Zwitserse Frank (CHF)</string>
<string name="pref_chargeprice_currency_czk">Tsjechische koruna (CZK)</string>
<string name="pref_chargeprice_currency_dkk">Deense kroon (DKK)</string>
<string name="pref_chargeprice_currency_gbp">Britse Pond (GBP)</string>
<string name="pref_chargeprice_currency_hrk">Kroatische Kuna (HRK)</string>
<string name="pref_chargeprice_currency_huf">Hongaarse Forint (HUF)</string>
<string name="pref_chargeprice_currency_isk">IJslandse Kroon (ISK)</string>
<string name="pref_chargeprice_currency_nok">Noorse Kroon (NOK)</string>
<string name="pref_chargeprice_currency_pln">Poolse Złoty (PLN)</string>
<string name="pref_chargeprice_currency_sek">Zweedse Kroon (SEK)</string>
<string name="pref_chargeprice_currency_usd">Amerikaanse Dollar (USD)</string>
<string name="pref_provider_google_maps">Google Maps</string>
<string name="edit_filter_profile">“%s” editeren</string>
<string name="compass">Kompas</string>

View File

@@ -177,11 +177,6 @@
<string name="pref_language_device_default">Língua do dispositivo</string>
<string name="pref_darkmode_device_default">Padrão do dispositivo</string>
<string name="pref_darkmode_always_on">Sempre ligado</string>
<string name="pref_chargeprice_currency_chf">Franco suíço (CHF)</string>
<string name="pref_chargeprice_currency_czk">Coroa checa (CZK)</string>
<string name="pref_chargeprice_currency_dkk">Coroa dinamarquesa (DKK)</string>
<string name="pref_chargeprice_currency_eur">Euro (EUR)</string>
<string name="pref_chargeprice_currency_gbp">Libra esterlina (GBP)</string>
<string name="chargeprice_header_my_tariffs">Os meus planos</string>
<string name="chargeprice_header_other_tariffs">Outros planos</string>
<string name="developer_options">Opções de desenvolvedor</string>
@@ -287,13 +282,6 @@
<string name="welcome_1">Encontre carregadores elétricos perto de si</string>
<string name="close">Fechar</string>
<string name="edit_filter_profile">Editar “%s”</string>
<string name="pref_chargeprice_currency_hrk">Cuna croata (HRK)</string>
<string name="pref_chargeprice_currency_huf">Florim húngaro (HUF)</string>
<string name="pref_chargeprice_currency_isk">Coroa islandesa (ISK)</string>
<string name="pref_chargeprice_currency_nok">Coroa norueguesa (NOK)</string>
<string name="pref_chargeprice_currency_pln">Złoty polaco (PLN)</string>
<string name="pref_chargeprice_currency_sek">Coroa sueca (SEK)</string>
<string name="pref_chargeprice_currency_usd">Dólar americano (USD)</string>
<string name="pref_provider_google_maps">Google Maps</string>
<string name="pref_provider_osm_mapbox">OpenStreetMap (Mapbox)</string>
<string name="about_contributors">Contribuidores</string>

View File

@@ -259,18 +259,6 @@
<string name="pref_darkmode_device_default">Implicit dispozitiv</string>
<string name="pref_darkmode_always_on">permanent</string>
<string name="pref_darkmode_always_off">dezactivat</string>
<string name="pref_chargeprice_currency_chf">Franci elvetieni (CHF)</string>
<string name="pref_chargeprice_currency_czk">Coroane cehe (CZK)</string>
<string name="pref_chargeprice_currency_dkk">Coroane daneze (DKK)</string>
<string name="pref_chargeprice_currency_eur">Euro (EUR)</string>
<string name="pref_chargeprice_currency_gbp">Lire sterline (GBP)</string>
<string name="pref_chargeprice_currency_hrk">Croatian kuna (HRK)</string>
<string name="pref_chargeprice_currency_huf">Forinti maghiari (HUF)</string>
<string name="pref_chargeprice_currency_isk">Coroane islandeze (ISK)</string>
<string name="pref_chargeprice_currency_nok">Coroane norvegiene (NOK)</string>
<string name="pref_chargeprice_currency_pln">Zloti polonezi (PLN)</string>
<string name="pref_chargeprice_currency_sek">Coroane suedeze (SEK)</string>
<string name="pref_chargeprice_currency_usd">Dolari americani (USD)</string>
<string name="pref_provider_google_maps">Google Maps</string>
<string name="pref_provider_osm_mapbox">OpenStreetMap (Mapbox)</string>
<string name="about_contributors">Contribuitori</string>

View File

@@ -1,27 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="pref_language_names">
<item>@string/pref_language_device_default</item>
<item>@string/pref_language_en</item>
<item>@string/pref_language_de</item>
<item>@string/pref_language_cs</item>
<item>@string/pref_language_fr</item>
<item>@string/pref_language_nb_rNO</item>
<item>@string/pref_language_nl</item>
<item>@string/pref_language_pt</item>
<item>@string/pref_language_ro</item>
</string-array>
<string-array name="pref_language_values" translatable="false">
<item>default</item>
<item>en</item>
<item>de</item>
<item>cs</item>
<item>fr</item>
<item>nb-NO</item>
<item>nl</item>
<item>pt</item>
<item>ro</item>
</string-array>
<string-array name="pref_darkmode_names">
<item>@string/pref_darkmode_device_default</item>
<item>@string/pref_darkmode_always_on</item>
@@ -32,21 +10,7 @@
<item>on</item>
<item>off</item>
</string-array>
<string-array name="pref_chargeprice_currency_names">
<item>@string/pref_chargeprice_currency_chf</item>
<item>@string/pref_chargeprice_currency_czk</item>
<item>@string/pref_chargeprice_currency_dkk</item>
<item>@string/pref_chargeprice_currency_eur</item>
<item>@string/pref_chargeprice_currency_gbp</item>
<item>@string/pref_chargeprice_currency_hrk</item>
<item>@string/pref_chargeprice_currency_huf</item>
<item>@string/pref_chargeprice_currency_isk</item>
<item>@string/pref_chargeprice_currency_nok</item>
<item>@string/pref_chargeprice_currency_pln</item>
<item>@string/pref_chargeprice_currency_sek</item>
<item>@string/pref_chargeprice_currency_usd</item>
</string-array>
<string-array name="pref_chargeprice_currency_values" translatable="false">
<string-array name="pref_chargeprice_currencies" translatable="false">
<item>CHF</item>
<item>CZK</item>
<item>DKK</item>

View File

@@ -10,14 +10,6 @@
<string name="chargeprice_api_url">https://api.chargeprice.app/v1/</string>
<string name="fronyx_url">https://fronyx.io/</string>
<string name="website_url">https://ev-map.app</string>
<string name="pref_language_en">English</string>
<string name="pref_language_de">Deutsch</string>
<string name="pref_language_fr">Français</string>
<string name="pref_language_nb_rNO">Norsk Bokmål</string>
<string name="pref_language_nl">Nederlands</string>
<string name="pref_language_pt">Português</string>
<string name="pref_language_ro">Romana</string>
<string name="pref_language_cs">Czech</string>
<string name="about_contributors_list">
Danilo Bargen\n
Altonss\n

View File

@@ -258,18 +258,6 @@
<string name="pref_darkmode_device_default">Device default</string>
<string name="pref_darkmode_always_on">always on</string>
<string name="pref_darkmode_always_off">always off</string>
<string name="pref_chargeprice_currency_chf">Swiss franc (CHF)</string>
<string name="pref_chargeprice_currency_czk">Czech koruna (CZK)</string>
<string name="pref_chargeprice_currency_dkk">Danish krone (DKK)</string>
<string name="pref_chargeprice_currency_eur">Euro (EUR)</string>
<string name="pref_chargeprice_currency_gbp">Pound sterling (GBP)</string>
<string name="pref_chargeprice_currency_hrk">Croatian kuna (HRK)</string>
<string name="pref_chargeprice_currency_huf">Hungarian forint (HUF)</string>
<string name="pref_chargeprice_currency_isk">Icelandic króna (ISK)</string>
<string name="pref_chargeprice_currency_nok">Norwegian krone (NOK)</string>
<string name="pref_chargeprice_currency_pln">Polish złoty (PLN)</string>
<string name="pref_chargeprice_currency_sek">Swedish krona (SEK)</string>
<string name="pref_chargeprice_currency_usd">US dollar (USD)</string>
<string name="pref_provider_google_maps">Google Maps</string>
<string name="pref_provider_osm">OpenStreetMap</string>
<string name="pref_provider_osm_mapbox">OpenStreetMap (Mapbox)</string>

View File

@@ -18,8 +18,7 @@
<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:entryValues="@array/pref_chargeprice_currencies"
android:defaultValue="EUR"
app:useSimpleSummaryProvider="true" />
<CheckBoxPreference

View File

@@ -4,8 +4,6 @@
android:key="language"
android:persistent="false"
android:title="@string/pref_language"
android:entries="@array/pref_language_names"
android:entryValues="@array/pref_language_values"
android:defaultValue="default"
android:summary="%s" />
<ListPreference

View File

@@ -10,7 +10,7 @@ buildscript {
gradlePluginPortal()
}
dependencies {
classpath("com.android.tools.build:gradle:8.3.2")
classpath("com.android.tools.build:gradle:8.4.2")
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
classpath("com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:$aboutLibsVersion")
classpath("androidx.navigation:navigation-safe-args-gradle-plugin:$navVersion")
@@ -24,7 +24,6 @@ allprojects {
repositories {
google()
mavenCentral()
//noinspection JcenterRepositoryObsolete
maven { setUrl("https://jitpack.io") }
}
}

View File

@@ -101,9 +101,9 @@ to switch between the two, while the `foss` flavor only includes OSM.
### ArcGIS
[World Imagery basemap](https://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9)
*We use this for the satellite map, as [Jawg's](https://blog.jawg.io/satellite-imaging/) satellite
style does not have global coverage.*
[World Imagery basemap](https://www.arcgis.com/home/item.html?id=10df2279f9684e4a9f6a7f08febac2a9)\
*We use this for the satellite map, as [Jawg's satellite
style](https://blog.jawg.io/satellite-imaging/) does not have global coverage.*
<details>
<summary>How to obtain an API key</summary>
@@ -116,7 +116,7 @@ style does not have global coverage.*
### Mapbox
[Geocoding API](https://docs.mapbox.com/api/search/geocoding/)
[Geocoding API](https://docs.mapbox.com/api/search/geocoding/)\
*previously we also used Mapbox's Maps SDK, but this has now been switched to Jawg Maps.*
<details>

View File

@@ -0,0 +1,3 @@
Fehler behoben:
- Probleme mit OpenStreetMap behoben
- Abstürze behoben

View File

@@ -0,0 +1,2 @@
Fehler behoben:
- Abstürze behoben

View File

@@ -0,0 +1,2 @@
Fehler behoben:
- Abstürze behoben

View File

@@ -0,0 +1,2 @@
Fehler behoben:
- Abstürze behoben

View File

@@ -0,0 +1,3 @@
Bugfixes:
- Fixed problems with OpenStreetMap
- Fixed crashes

View File

@@ -0,0 +1,2 @@
Bugfixes:
- Fixed crashes

View File

@@ -0,0 +1,2 @@
Bugfixes:
- Fixed crashes

View File

@@ -0,0 +1,2 @@
Bugfixes:
- Fixed crashes

View File

@@ -1,6 +1,6 @@
#Sat Aug 06 15:33:46 CEST 2022
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME