mirror of
https://github.com/ev-map/EVMap.git
synced 2025-12-28 17:47:44 -05:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9222dec613 | ||
|
|
71c36fbc8f | ||
|
|
830477e664 | ||
|
|
3ce91a9c50 | ||
|
|
a3b2b94b25 | ||
|
|
a7770e1c1b | ||
|
|
fcd51307cb | ||
|
|
ba4a9c29b2 | ||
|
|
3463177ad2 | ||
|
|
09deaf5080 |
1
.github/workflows/release.yml
vendored
1
.github/workflows/release.yml
vendored
@@ -32,6 +32,7 @@ jobs:
|
||||
MAPBOX_API_KEY: ${{ secrets.MAPBOX_API_KEY }}
|
||||
GOOGLE_MAPS_API_KEY: ${{ secrets.GOOGLE_MAPS_API_KEY }}
|
||||
FRONYX_API_KEY: ${{ secrets.FRONYX_API_KEY }}
|
||||
ACRA_CRASHREPORT_CREDENTIALS: ${{ secrets.ACRA_CRASHREPORT_CREDENTIALS }}
|
||||
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
|
||||
KEYSTORE_ALIAS: ${{ secrets.KEYSTORE_ALIAS }}
|
||||
KEYSTORE_ALIAS_PASSWORD: ${{ secrets.KEYSTORE_ALIAS_PASSWORD }}
|
||||
|
||||
@@ -19,8 +19,8 @@ android {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 34
|
||||
// NOTE: always increase versionCode by 2 since automotive flavor uses versionCode + 1
|
||||
versionCode 194
|
||||
versionName "1.6.7"
|
||||
versionCode 200
|
||||
versionName "1.6.9"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
resConfigs supportedLocales.split(',')
|
||||
@@ -253,7 +253,6 @@ dependencies {
|
||||
|
||||
// ACRA (crash reporting)
|
||||
def acraVersion = "5.11.1"
|
||||
implementation("ch.acra:acra-mail:$acraVersion")
|
||||
implementation("ch.acra:acra-http:$acraVersion")
|
||||
implementation("ch.acra:acra-dialog:$acraVersion")
|
||||
implementation("ch.acra:acra-limiter:$acraVersion")
|
||||
|
||||
@@ -11,7 +11,6 @@ import net.vonforst.evmap.ui.updateNightMode
|
||||
import org.acra.config.dialog
|
||||
import org.acra.config.httpSender
|
||||
import org.acra.config.limiter
|
||||
import org.acra.config.mailSender
|
||||
import org.acra.data.StringFormat
|
||||
import org.acra.ktx.initAcra
|
||||
import org.acra.sender.HttpSender
|
||||
@@ -37,21 +36,14 @@ class EvMapApplication : Application(), Configuration.Provider {
|
||||
initAcra {
|
||||
buildConfigClass = BuildConfig::class.java
|
||||
|
||||
// Vehicles often don't have an email app, so use HTTP to send instead
|
||||
reportFormat = StringFormat.JSON
|
||||
|
||||
if (BuildConfig.FLAVOR_automotive == "automotive") {
|
||||
// Vehicles often don't have an email app, so use HTTP to send instead
|
||||
httpSender {
|
||||
uri = getString(R.string.acra_backend_url)
|
||||
val creds = getString(R.string.acra_credentials).split(":")
|
||||
basicAuthLogin = creds[0]
|
||||
basicAuthPassword = creds[1]
|
||||
httpMethod = HttpSender.Method.POST
|
||||
}
|
||||
} else {
|
||||
mailSender {
|
||||
mailTo = "evmap+crashreport@vonforst.net"
|
||||
}
|
||||
httpSender {
|
||||
uri = getString(R.string.acra_backend_url)
|
||||
val creds = getString(R.string.acra_credentials).split(":")
|
||||
basicAuthLogin = creds[0]
|
||||
basicAuthPassword = creds[1]
|
||||
httpMethod = HttpSender.Method.POST
|
||||
}
|
||||
|
||||
dialog {
|
||||
|
||||
@@ -105,20 +105,19 @@ class EnBwAvailabilityDetector(client: OkHttpClient, baseUrl: String? = null) :
|
||||
var markers =
|
||||
api.getMarkers(lng - coordRange, lng + coordRange, lat - coordRange, lat + coordRange)
|
||||
|
||||
while (markers.any { it.grouped }) {
|
||||
markers = markers.flatMap {
|
||||
if (it.grouped) {
|
||||
api.getMarkers(
|
||||
it.viewPort.lowerLeftLon,
|
||||
it.viewPort.upperRightLon,
|
||||
it.viewPort.lowerLeftLat,
|
||||
it.viewPort.upperRightLat
|
||||
)
|
||||
} else {
|
||||
listOf(it)
|
||||
}
|
||||
markers = markers.flatMap {
|
||||
if (it.grouped) {
|
||||
api.getMarkers(
|
||||
it.viewPort.lowerLeftLon,
|
||||
it.viewPort.upperRightLon,
|
||||
it.viewPort.lowerLeftLat,
|
||||
it.viewPort.upperRightLat
|
||||
)
|
||||
} else {
|
||||
listOf(it)
|
||||
}
|
||||
}
|
||||
if (markers.any { it.grouped }) throw AvailabilityDetectorException("markers still grouped")
|
||||
|
||||
val nearest = markers.minByOrNull { marker ->
|
||||
distanceBetween(marker.lat, marker.lon, lat, lng)
|
||||
|
||||
@@ -10,10 +10,8 @@ import android.text.Spanned
|
||||
import androidx.car.app.CarContext
|
||||
import androidx.car.app.CarToast
|
||||
import androidx.car.app.Screen
|
||||
import androidx.car.app.annotations.ExperimentalCarApi
|
||||
import androidx.car.app.constraints.ConstraintManager
|
||||
import androidx.car.app.model.*
|
||||
import androidx.car.app.model.TabTemplate.TabCallback
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import androidx.core.graphics.scale
|
||||
import androidx.core.text.HtmlCompat
|
||||
@@ -50,10 +48,7 @@ import java.time.format.FormatStyle
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
||||
@ExperimentalCarApi
|
||||
class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) : Screen(ctx) {
|
||||
private val TAB_MAIN = "main"
|
||||
|
||||
var charger: ChargeLocation? = null
|
||||
var photo: Bitmap? = null
|
||||
private var availability: ChargeLocationStatus? = null
|
||||
@@ -73,8 +68,6 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
|
||||
private val maxRows = ctx.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_PANE)
|
||||
private val largeImageSupported =
|
||||
ctx.carAppApiLevel >= 4 // since API 4, Row.setImage is supported
|
||||
private val tabsSupported = ctx.carAppApiLevel >= 6
|
||||
private var currentTab = TAB_MAIN
|
||||
|
||||
private var favorite: Favorite? = null
|
||||
private var favoriteUpdateJob: Job? = null
|
||||
@@ -86,45 +79,6 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
|
||||
override fun onGetTemplate(): Template {
|
||||
if (charger == null) loadCharger()
|
||||
|
||||
if (tabsSupported) {
|
||||
return generateTabs()
|
||||
} else {
|
||||
return generateMainPane()
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateTabs(): TabTemplate {
|
||||
return TabTemplate.Builder(object : TabCallback {
|
||||
override fun onTabSelected(tabContentId: String) {
|
||||
currentTab = tabContentId
|
||||
invalidate()
|
||||
}
|
||||
}).apply {
|
||||
charger?.let {
|
||||
addTab(
|
||||
Tab.Builder()
|
||||
.setTitle(carContext.getString(R.string.general_info))
|
||||
.setIcon(CarIcon.APP_ICON)
|
||||
.setContentId(TAB_MAIN).build()
|
||||
)
|
||||
addTab(
|
||||
Tab.Builder()
|
||||
.setTitle("bla")
|
||||
.setIcon(CarIcon.APP_ICON)
|
||||
.setContentId("bla").build()
|
||||
)
|
||||
val contents = when (currentTab) {
|
||||
TAB_MAIN -> generateMainPane()
|
||||
else -> throw IllegalArgumentException("invalid tab")
|
||||
}
|
||||
setTabContents(TabContents.Builder(contents).build())
|
||||
setActiveTabContentId(currentTab)
|
||||
} ?: setLoading(true)
|
||||
setHeaderAction(Action.APP_ICON)
|
||||
}.build()
|
||||
}
|
||||
|
||||
private fun generateMainPane(): PaneTemplate {
|
||||
return PaneTemplate.Builder(
|
||||
Pane.Builder().apply {
|
||||
charger?.let { charger ->
|
||||
@@ -146,28 +100,28 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
|
||||
)
|
||||
.setTitle(carContext.getString(R.string.navigate))
|
||||
.setFlags(Action.FLAG_PRIMARY)
|
||||
.setBackgroundColor(CarColor.PRIMARY)
|
||||
.setOnClickListener {
|
||||
navigateToCharger(charger)
|
||||
}
|
||||
.build())
|
||||
if (ChargepriceApi.isChargerSupported(charger)) {
|
||||
addAction(
|
||||
Action.Builder()
|
||||
.setIcon(
|
||||
CarIcon.Builder(
|
||||
IconCompat.createWithResource(
|
||||
carContext,
|
||||
R.drawable.ic_chargeprice
|
||||
)
|
||||
).build()
|
||||
)
|
||||
.setTitle(carContext.getString(R.string.auto_prices))
|
||||
.setBackgroundColor(CarColor.PRIMARY)
|
||||
.setOnClickListener {
|
||||
navigateToCharger(charger)
|
||||
}
|
||||
.build())
|
||||
if (ChargepriceApi.isChargerSupported(charger)) {
|
||||
addAction(
|
||||
Action.Builder()
|
||||
.setIcon(
|
||||
CarIcon.Builder(
|
||||
IconCompat.createWithResource(
|
||||
carContext,
|
||||
R.drawable.ic_chargeprice
|
||||
)
|
||||
).build()
|
||||
)
|
||||
.setTitle(carContext.getString(R.string.auto_prices))
|
||||
.setOnClickListener {
|
||||
screenManager.push(ChargepriceScreen(carContext, charger))
|
||||
}
|
||||
.build())
|
||||
}
|
||||
}
|
||||
} ?: setLoading(true)
|
||||
}.build()
|
||||
).apply {
|
||||
@@ -336,6 +290,18 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
|
||||
}.build())
|
||||
}
|
||||
}
|
||||
if (rows.count() < maxRows && charger.generalInformation != null) {
|
||||
rows.add(Row.Builder().apply {
|
||||
setTitle(carContext.getString(R.string.general_info))
|
||||
addText(charger.generalInformation)
|
||||
}.build())
|
||||
}
|
||||
if (rows.count() < maxRows && charger.amenities != null) {
|
||||
rows.add(Row.Builder().apply {
|
||||
setTitle(carContext.getString(R.string.amenities))
|
||||
addText(charger.amenities)
|
||||
}.build())
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
@@ -417,8 +383,10 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
|
||||
} else {
|
||||
append(nameForPlugType(carContext.stringProvider(), cp.type))
|
||||
}
|
||||
append(" ")
|
||||
append(cp.formatPower())
|
||||
cp.formatPower()?.let {
|
||||
append(" ")
|
||||
append(it)
|
||||
}
|
||||
}
|
||||
availability?.status?.get(cp)?.let { status ->
|
||||
chargepointsText.append(
|
||||
|
||||
@@ -41,7 +41,9 @@ class FilterScreen(ctx: CarContext, val session: EVMapSession) : Screen(ctx) {
|
||||
if (filterStatus in listOf(FILTERS_DISABLED, FILTERS_FAVORITES, FILTERS_CUSTOM)) {
|
||||
page = 0
|
||||
} else {
|
||||
page = paginateProfiles(it).indexOfFirst { it.any { it.id == filterStatus } }
|
||||
val index =
|
||||
paginateProfiles(it).indexOfFirst { it.any { it.id == filterStatus } }
|
||||
page = index.takeUnless { it == -1 } ?: 0
|
||||
}
|
||||
invalidate()
|
||||
}
|
||||
|
||||
@@ -1043,7 +1043,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
binding.search.requestFocus()
|
||||
binding.search.setSelection(locationName.length)
|
||||
}
|
||||
if (context.checkAnyLocationPermission()) {
|
||||
if (context.checkAnyLocationPermission() && prefs.currentMapMyLocationEnabled) {
|
||||
enableLocation(!positionSet, false)
|
||||
positionSet = true
|
||||
}
|
||||
@@ -1400,6 +1400,9 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
|
||||
prefs.currentMapLocation = it.bounds.center
|
||||
prefs.currentMapZoom = it.zoom
|
||||
}
|
||||
vm.myLocationEnabled.value?.let {
|
||||
prefs.currentMapMyLocationEnabled = it
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
|
||||
@@ -291,6 +291,12 @@ class PreferenceDataSource(val context: Context) {
|
||||
sp.edit().putFloat("current_map_zoom", value).apply()
|
||||
}
|
||||
|
||||
var currentMapMyLocationEnabled: Boolean
|
||||
get() = sp.getBoolean("current_map_my_location_enabled", false)
|
||||
set(value) {
|
||||
sp.edit().putBoolean("current_map_my_location_enabled", value).apply()
|
||||
}
|
||||
|
||||
var privacyAccepted: Boolean
|
||||
get() = sp.getBoolean("privacy_accepted", false)
|
||||
set(value) {
|
||||
|
||||
8
fastlane/metadata/android/de-DE/changelogs/196.txt
Normal file
8
fastlane/metadata/android/de-DE/changelogs/196.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Verbesserungen:
|
||||
- Neue Einstellung für Maßeinheiten
|
||||
- Anpassungen für Android 14
|
||||
- Android Auto: Weitere Detailbeschreibungen zu den Ladestationen
|
||||
- Android Auto: Löschbutton in der Filterliste
|
||||
|
||||
Fehler behoben:
|
||||
- Fehler beim Laden der EnBW Echtzeitdaten
|
||||
5
fastlane/metadata/android/de-DE/changelogs/200.txt
Normal file
5
fastlane/metadata/android/de-DE/changelogs/200.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Verbesserungen:
|
||||
- Beim Start der App wird nun der zuletzt gesehene Kartenausschnitt gezeigt
|
||||
|
||||
Fehler behoben:
|
||||
- Abstürze behoben
|
||||
8
fastlane/metadata/android/en-US/changelogs/196.txt
Normal file
8
fastlane/metadata/android/en-US/changelogs/196.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
Improvements:
|
||||
- New setting for units of measurement
|
||||
- Adjustments for Android 14
|
||||
- Android Auto: More detailed descriptions of chargers
|
||||
- Android Auto: Delete button in filter list
|
||||
|
||||
Bugfixes:
|
||||
- Errors loading realtime data from EnBW
|
||||
5
fastlane/metadata/android/en-US/changelogs/200.txt
Normal file
5
fastlane/metadata/android/en-US/changelogs/200.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
Improvements:
|
||||
- When starting the app, the last viewed map area will be shown
|
||||
|
||||
Bugfixes:
|
||||
- Fixed crashes
|
||||
Reference in New Issue
Block a user