Compare commits

...

39 Commits
1.1.3 ... 1.2.0

Author SHA1 Message Date
Johan von Forstner
385aa46686 Release 1.2.0 2022-01-02 15:41:14 +01:00
Johan von Forstner
3c9a0b3a50 improve performance of layers menu opening/closing 2022-01-02 13:40:20 +01:00
Johan von Forstner
761a690d76 Remove unneeded close button from Chargeprice view 2022-01-01 21:22:37 +01:00
Johan von Forstner
7356b8a1be Remove unneeded close button from Chargeprice view 2022-01-01 21:21:29 +01:00
Johan von Forstner
0c0a1f59a6 add option to set Chargeprice range for Android Auto
fixes #131
2022-01-01 20:07:40 +01:00
Johan von Forstner
876d2759dd fix imports for foss build flavor 2022-01-01 20:06:39 +01:00
Johan von Forstner
ae489aa6ef add app shortcut for favorites view
fixes #152
2022-01-01 15:43:20 +01:00
Johan von Forstner
d21ac0a781 CheckableConnectorAdapter: avoid IndexOutOfBoundsException 2022-01-01 15:33:54 +01:00
Johan von Forstner
b4baa87e10 reuse AnyMaps fragment instance when MapFragment is recreated 2021-12-31 17:50:45 +01:00
Johan von Forstner
05ffe1c265 make ChargepriceFragment a regular full-screen view, not dialog 2021-12-31 17:49:35 +01:00
Johan von Forstner
8d68dd5366 add some fragment transitions 2021-12-31 15:50:39 +01:00
Johan von Forstner
dbcde7cf7a fix build warnings regarding string formatting 2021-12-30 16:38:08 +01:00
Johan von Forstner
4ea37ee10d update Android Gradle plugin 2021-12-30 16:25:19 +01:00
Johan von Forstner
ec7b08338c fix crash when Geocoder has no internet connection 2021-12-30 14:12:59 +01:00
Johan von Forstner
dc4c2394f9 slightly improve performance of layers menu open/close 2021-12-26 19:57:30 +01:00
Johan von Forstner
4b4ee807b0 update Google Maps library 2021-12-26 19:49:02 +01:00
Johan von Forstner
c55720edc7 fix #149: pasting text into search bar did not work 2021-12-26 19:46:45 +01:00
Johan von Forstner
57ba8db799 "start navigation immediately" intent is specific to Google Maps
fallback to normal geo intent if not available
2021-12-26 18:17:33 +01:00
johan12345
3151d74d1a decrease width of search bar on large tablets
#133
2021-12-26 18:14:53 +01:00
johan12345
af0fb6762d fix maxWidth implementation for dialogs
#133
2021-12-26 18:14:53 +01:00
johan12345
5571c33ebe new layout for onboarding on large tablets
#133
2021-12-26 18:14:53 +01:00
johan12345
388952ae28 add landscape layout for Android Auto onboarding card
missed in 7eeb10f
2021-12-26 18:14:53 +01:00
johan12345
94934aa130 update buttons in onboarding landscape layout 2021-12-26 18:14:52 +01:00
johan12345
63eddde837 add logo animation in search bar on app start 2021-12-26 18:14:52 +01:00
johan12345
a9f735d783 Update Material Components library, switch to Material3 theme 2021-12-26 17:54:35 +01:00
Johan von Forstner
2dcd04c86e improve compatibility of geo intent
now also works with Waze
2021-12-26 17:38:53 +01:00
Johan von Forstner
9ed23c7000 fix typo 2021-12-25 18:21:48 +01:00
Johan von Forstner
79a7200f7b remove unnecessary @ExperimentalCoroutinesApi 2021-12-25 18:21:47 +01:00
Johan von Forstner
0c315079ca upgrade Room, Moshi 2021-12-25 18:21:46 +01:00
Johan von Forstner
7943d6669c adjust large image size in Android Auto
as discussed in
https://issuetracker.google.com/issues/211012779#comment2
2021-12-23 16:56:16 +01:00
Johan von Forstner
a781591510 add manual mapping for Android Auto vehicle models 2021-12-18 17:13:26 +01:00
Johan von Forstner
b8ba06bab1 ChargepriceScreen: more sophisticated vehicle matching
first try to match by manufacturer only, then manufacturer + model
2021-12-18 16:55:29 +01:00
Johan von Forstner
955b64ec66 ChargepriceScreen: adaptive maxRows 2021-12-18 16:41:31 +01:00
Johan von Forstner
117ab0f159 if available, use additional rows in ChargerDetailScreen
#145
2021-12-18 16:39:59 +01:00
Johan von Forstner
bac3fd1048 fix parking emoji on Android Auto 2021-12-18 16:04:16 +01:00
Johan von Forstner
7cc07ca511 ChargerDetailScreen: show large photo if supported
#145
2021-12-18 15:34:59 +01:00
Johan von Forstner
80743fab7d update car app library to 1.2.0-beta02
#145
2021-12-18 13:41:47 +01:00
Johan von Forstner
c423974ffd check if car location is valid before using it (#148) 2021-12-18 13:18:36 +01:00
Johan von Forstner
b2d365755f remove .gitattributes 2021-12-18 13:17:30 +01:00
134 changed files with 1924 additions and 555 deletions

2
.gitattributes vendored
View File

@@ -1,2 +0,0 @@
_img/screenshots/**/*.png filter=lfs diff=lfs merge=lfs -text
fastlane/metadata/android/**/images/**/*.png filter=lfs diff=lfs merge=lfs -text

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 972 KiB

After

Width:  |  Height:  |  Size: 844 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 352 KiB

After

Width:  |  Height:  |  Size: 200 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 93 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 131 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 837 KiB

After

Width:  |  Height:  |  Size: 844 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 341 KiB

After

Width:  |  Height:  |  Size: 200 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 93 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 131 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

After

Width:  |  Height:  |  Size: 1.0 MiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 972 KiB

After

Width:  |  Height:  |  Size: 841 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 KiB

After

Width:  |  Height:  |  Size: 199 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 95 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 837 KiB

After

Width:  |  Height:  |  Size: 841 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 330 KiB

After

Width:  |  Height:  |  Size: 199 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

After

Width:  |  Height:  |  Size: 95 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 124 KiB

View File

@@ -13,8 +13,8 @@ android {
applicationId "net.vonforst.evmap"
minSdkVersion 21
targetSdkVersion 31
versionCode 67
versionName "1.1.3"
versionCode 68
versionName "1.2.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -111,14 +111,14 @@ android {
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.appcompat:appcompat:1.4.0'
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.core:core-splashscreen:1.0.0-alpha02'
implementation "androidx.activity:activity-ktx:1.4.0"
implementation "androidx.fragment:fragment-ktx:1.3.6"
implementation "androidx.fragment:fragment-ktx:1.4.0"
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.preference:preference-ktx:1.1.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'com.google.android.material:material:1.5.0-rc01'
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
implementation 'androidx.recyclerview:recyclerview:1.2.1'
implementation 'androidx.browser:browser:1.4.0'
@@ -127,8 +127,8 @@ dependencies {
implementation 'com.squareup.retrofit2:converter-moshi:2.9.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.squareup.okhttp3:okhttp-urlconnection:4.9.0'
implementation 'com.squareup.moshi:moshi-kotlin:1.12.0'
implementation 'com.squareup.moshi:moshi-adapters:1.12.0'
implementation 'com.squareup.moshi:moshi-kotlin:1.13.0'
implementation 'com.squareup.moshi:moshi-adapters:1.13.0'
implementation 'moe.banana:moshi-jsonapi:3.5.0'
implementation 'moe.banana:moshi-jsonapi-retrofit-converter:3.5.0'
implementation 'io.coil-kt:coil:1.1.0'
@@ -143,14 +143,14 @@ dependencies {
implementation 'com.github.romandanylyk:PageIndicatorView:b1bad589b5'
// Android Auto
googleImplementation 'androidx.car.app:app:1.1.0-rc01'
googleImplementation 'androidx.car.app:app-projected:1.1.0-rc01'
googleImplementation 'androidx.car.app:app:1.2.0-alpha02'
googleImplementation 'androidx.car.app:app-projected:1.2.0-alpha02'
// AnyMaps
def anyMapsVersion = '751daec281'
implementation "com.github.johan12345.AnyMaps:anymaps-base:$anyMapsVersion"
googleImplementation "com.github.johan12345.AnyMaps:anymaps-google:$anyMapsVersion"
googleImplementation 'com.google.android.gms:play-services-maps:18.0.0'
googleImplementation 'com.google.android.gms:play-services-maps:18.0.1'
implementation "com.github.johan12345.AnyMaps:anymaps-mapbox:$anyMapsVersion"
// Google Places
@@ -170,7 +170,7 @@ dependencies {
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"
// room library
def room_version = "2.3.0"
def room_version = "2.4.0"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version"
implementation "androidx.room:room-ktx:$room_version"
@@ -196,7 +196,7 @@ dependencies {
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.12.0"
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.13.0"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.1.5'
}

View File

@@ -8,6 +8,7 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController
import com.google.android.material.transition.MaterialSharedAxis
import net.vonforst.evmap.MapsActivity
import net.vonforst.evmap.R
import net.vonforst.evmap.databinding.FragmentDonateBinding
@@ -15,11 +16,17 @@ import net.vonforst.evmap.databinding.FragmentDonateBinding
class DonateFragment : Fragment() {
private lateinit var binding: FragmentDonateBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
): View {
binding = FragmentDonateBinding.inflate(inflater, container, false)
return binding.root
}
@@ -27,16 +34,13 @@ class DonateFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
(requireActivity() as AppCompatActivity).setSupportActionBar(binding.toolbar)
binding.btnDonate.setOnClickListener {
(activity as? MapsActivity)?.openUrl(getString(R.string.paypal_link))
}
}
override fun onResume() {
super.onResume()
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
binding.btnDonate.setOnClickListener {
(activity as? MapsActivity)?.openUrl(getString(R.string.paypal_link))
}
}
}

View File

@@ -23,7 +23,7 @@
<Button
android:id="@+id/btnDonate"
style="@style/Widget.MaterialComponents.Button.Icon"
style="@style/Widget.Material3.Button.Icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen>
</PreferenceScreen>

View File

@@ -8,6 +8,7 @@ import androidx.car.app.CarContext
import androidx.car.app.Screen
import androidx.car.app.Session
import androidx.car.app.hardware.CarHardwareManager
import androidx.car.app.hardware.common.CarValue
import androidx.car.app.hardware.info.CarHardwareLocation
import androidx.car.app.hardware.info.CarSensors
import androidx.car.app.validation.HostValidator
@@ -90,11 +91,13 @@ class EVMapSession(val cas: CarAppService) : Session(), LifecycleObserver {
}
private fun onCarHardwareLocationReceived(loc: CarHardwareLocation) {
updateLocation(loc.location.value)
if (loc.location.status == CarValue.STATUS_SUCCESS && loc.location.value != null) {
updateLocation(loc.location.value)
// we successfully received a location from the car hardware,
// so we don't need the smartphone location anymore.
unbindLocationService()
// we successfully received a location from the car hardware,
// so we don't need the smartphone location anymore.
unbindLocationService()
}
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)

View File

@@ -0,0 +1,19 @@
package net.vonforst.evmap.auto
/**
* This file lists known mappings between the vehicle model provided by Android Auto's CarInfo API
* and human-readable vehicle models as listed by Chargeprice in their vehicle database.
*/
private val models = mapOf(
"Audi" to mapOf(
"516 (G4x)" to "e-tron"
)
)
fun getVehicleModel(manufacturer: String?, model: String?) =
if (manufacturer != null && model != null) {
models[manufacturer]?.get(model) ?: model
} else {
null
}

View File

@@ -8,6 +8,7 @@ import androidx.browser.customtabs.CustomTabsIntent
import androidx.car.app.CarContext
import androidx.car.app.CarToast
import androidx.car.app.Screen
import androidx.car.app.constraints.ConstraintManager
import androidx.car.app.hardware.CarHardwareManager
import androidx.car.app.hardware.info.Model
import androidx.car.app.model.*
@@ -37,9 +38,11 @@ class ChargepriceScreen(ctx: CarContext, val charger: ChargeLocation) : Screen(c
}
private var prices: List<ChargePrice>? = null
private var meta: ChargepriceChargepointMeta? = null
private val maxRows = 6
private val maxRows = if (ctx.carAppApiLevel >= 2) {
ctx.constraintManager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_LIST)
} else 6
private var errorMessage: String? = null
private val batteryRange = listOf(20.0, 80.0)
private val batteryRange = prefs.chargepriceBatteryRangeAndroidAuto
override fun onGetTemplate(): Template {
if (prices == null) loadData()
@@ -168,47 +171,10 @@ class ChargepriceScreen(ctx: CarContext, val charger: ChargeLocation) : Screen(c
private fun loadPrices(model: Model?) {
val dataAdapter = getDataAdapter() ?: return
val manufacturer = model?.manufacturer?.value
val modelName = model?.name?.value
val modelName = getVehicleModel(model?.manufacturer?.value, model?.name?.value)
lifecycleScope.launch {
try {
var vehicles = api.getVehicles().filter {
it.id in prefs.chargepriceMyVehicles
}
if (vehicles.isEmpty()) {
errorMessage = carContext.getString(R.string.chargeprice_select_car_first)
invalidate()
return@launch
} else if (vehicles.size > 1) {
if (manufacturer != null && modelName != null) {
vehicles = vehicles.filter {
it.brand == manufacturer && it.name.startsWith(modelName)
}
if (vehicles.isEmpty()) {
errorMessage = carContext.getString(
R.string.auto_chargeprice_vehicle_unknown,
manufacturer,
modelName
)
invalidate()
return@launch
} else if (vehicles.size > 1) {
errorMessage = carContext.getString(
R.string.auto_chargeprice_vehicle_ambiguous,
manufacturer,
modelName
)
invalidate()
return@launch
}
} else {
errorMessage =
carContext.getString(R.string.auto_chargeprice_vehicle_unavailable)
invalidate()
return@launch
}
}
val car = vehicles[0]
val car = determineVehicle(manufacturer, modelName)
val cpStation = ChargepriceStation.fromEvmap(charger, car.compatibleEvmapConnectors)
val result = api.getChargePrices(ChargepriceRequest().apply {
this.dataAdapter = dataAdapter
@@ -229,7 +195,7 @@ class ChargepriceScreen(ctx: CarContext, val charger: ChargeLocation) : Screen(c
}
} else null
options = ChargepriceOptions(
batteryRange = batteryRange,
batteryRange = batteryRange.map { it.toDouble() },
providerCustomerTariffs = prefs.chargepriceShowProviderCustomerTariffs,
maxMonthlyFees = if (prefs.chargepriceNoBaseFee) 0.0 else null,
currency = prefs.chargepriceCurrency
@@ -283,10 +249,73 @@ class ChargepriceScreen(ctx: CarContext, val charger: ChargeLocation) : Screen(c
)
.show()
}
} catch (e: NoVehicleSelectedException) {
errorMessage = carContext.getString(R.string.chargeprice_select_car_first)
invalidate()
} catch (e: VehicleUnknownException) {
errorMessage = carContext.getString(
R.string.auto_chargeprice_vehicle_unknown,
manufacturer,
modelName
)
invalidate()
} catch (e: VehicleAmbiguousException) {
errorMessage = carContext.getString(
R.string.auto_chargeprice_vehicle_ambiguous,
manufacturer,
modelName
)
invalidate()
} catch (e: VehicleUnavailableException) {
errorMessage =
carContext.getString(R.string.auto_chargeprice_vehicle_unavailable)
invalidate()
}
}
}
private class NoVehicleSelectedException : Exception()
private class VehicleUnknownException : Exception()
private class VehicleAmbiguousException : Exception()
private class VehicleUnavailableException : Exception()
private suspend fun determineVehicle(
manufacturer: String?,
modelName: String?
): ChargepriceCar {
var vehicles = api.getVehicles().filter {
it.id in prefs.chargepriceMyVehicles
}
if (vehicles.isEmpty()) {
throw NoVehicleSelectedException()
} else if (vehicles.size > 1) {
if (manufacturer != null) {
vehicles = vehicles.filter {
it.brand == manufacturer
}
if (vehicles.isEmpty()) {
throw VehicleUnknownException()
} else if (vehicles.size > 1) {
if (modelName != null) {
vehicles = vehicles.filter {
it.name.startsWith(modelName)
}
if (vehicles.isEmpty()) {
throw VehicleUnknownException()
} else if (vehicles.size > 1) {
throw VehicleAmbiguousException()
}
} else {
throw VehicleAmbiguousException()
}
}
} else {
throw VehicleUnavailableException()
}
}
return vehicles[0]
}
private fun getDataAdapter(): String? = when (charger.dataSource) {
"goingelectric" -> ChargepriceApi.DATA_SOURCE_GOINGELECTRIC
"openchargemap" -> ChargepriceApi.DATA_SOURCE_OPENCHARGEMAP

View File

@@ -2,6 +2,7 @@ package net.vonforst.evmap.auto
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import android.text.SpannableStringBuilder
@@ -9,8 +10,11 @@ import android.text.Spanned
import androidx.car.app.CarContext
import androidx.car.app.CarToast
import androidx.car.app.Screen
import androidx.car.app.constraints.ConstraintManager
import androidx.car.app.model.*
import androidx.core.graphics.drawable.IconCompat
import androidx.core.graphics.scale
import androidx.core.text.HtmlCompat
import androidx.lifecycle.lifecycleScope
import coil.imageLoader
import coil.request.ImageRequest
@@ -50,10 +54,18 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
private val referenceData = api.getReferenceData(lifecycleScope, carContext)
private val imageSize = 128 // images should be 128dp according to docs
private val imageHeightLarge = 480 // images should be 480 x 854 dp according to docs
private val imageWidthLarge = 854
private val iconGen =
ChargerIconGenerator(carContext, null, oversize = 1.4f, height = imageSize)
private val maxRows = if (ctx.carAppApiLevel >= 2) {
ctx.constraintManager.getContentLimit(ConstraintManager.CONTENT_LIMIT_TYPE_PANE)
} else 2
private val largeImageSupported =
ctx.carAppApiLevel >= 4 // since API 4, Row.setImage is supported
init {
referenceData.observe(this) {
loadCharger()
@@ -66,86 +78,21 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
return PaneTemplate.Builder(
Pane.Builder().apply {
charger?.let { charger ->
addRow(Row.Builder().apply {
setTitle(charger.address.toString())
val icon = iconGen.getBitmap(
tint = getMarkerTint(charger),
fault = charger.faultReport != null,
multi = charger.isMulti()
)
setImage(
CarIcon.Builder(IconCompat.createWithBitmap(icon)).build(),
Row.IMAGE_TYPE_LARGE
)
val chargepointsText = SpannableStringBuilder()
charger.chargepointsMerged.forEachIndexed { i, cp ->
if (i > 0) chargepointsText.append(" · ")
chargepointsText.append(
"${cp.count}× ${
nameForPlugType(
carContext.stringProvider(),
cp.type
if (largeImageSupported && photo != null) {
setImage(CarIcon.Builder(IconCompat.createWithBitmap(photo)).build())
}
generateRows(charger).forEach { addRow(it) }
addAction(
Action.Builder()
.setIcon(
CarIcon.Builder(
IconCompat.createWithResource(
carContext,
R.drawable.ic_navigation
)
} ${cp.formatPower()}"
).build()
)
availability?.status?.get(cp)?.let { status ->
chargepointsText.append(
" (${availabilityText(status)}/${cp.count})",
ForegroundCarColorSpan.create(carAvailabilityColor(status)),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
addText(chargepointsText)
}.build())
addRow(Row.Builder().apply {
photo?.let {
setImage(
CarIcon.Builder(IconCompat.createWithBitmap(photo)).build(),
Row.IMAGE_TYPE_LARGE
)
}
val operatorText = StringBuilder().apply {
charger.operator?.let { append(it) }
charger.network?.let {
if (isNotEmpty()) append(" · ")
append(it)
}
}.ifEmpty {
carContext.getString(R.string.unknown_operator)
}
setTitle(operatorText)
charger.cost?.let { addText(it.getStatusText(carContext, emoji = true)) }
charger.faultReport?.created?.let {
addText(
carContext.getString(
R.string.auto_fault_report_date,
it.atZone(ZoneId.systemDefault())
.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))
)
)
}
/*val types = charger.chargepoints.map { it.type }.distinct()
if (types.size == 1) {
setImage(
CarIcon.of(IconCompat.createWithResource(carContext, iconForPlugType(types[0]))),
Row.IMAGE_TYPE_ICON)
}*/
}.build())
addAction(Action.Builder()
.setIcon(
CarIcon.Builder(
IconCompat.createWithResource(
carContext,
R.drawable.ic_navigation
)
).build()
)
.setTitle(carContext.getString(R.string.navigate))
.setTitle(carContext.getString(R.string.navigate))
.setBackgroundColor(CarColor.PRIMARY)
.setOnClickListener {
navigateToCharger(charger)
@@ -197,6 +144,144 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
}.build()
}
private fun generateRows(charger: ChargeLocation): List<Row> {
val rows = mutableListOf<Row>()
// Row 1: address + chargepoints
rows.add(Row.Builder().apply {
setTitle(charger.address.toString())
if (photo == null) {
// show just the icon
val icon = iconGen.getBitmap(
tint = getMarkerTint(charger),
fault = charger.faultReport != null,
multi = charger.isMulti()
)
setImage(
CarIcon.Builder(IconCompat.createWithBitmap(icon)).build(),
Row.IMAGE_TYPE_LARGE
)
} else if (!largeImageSupported) {
// show the photo with icon
setImage(
CarIcon.Builder(IconCompat.createWithBitmap(photo)).build(),
Row.IMAGE_TYPE_LARGE
)
}
addText(generateChargepointsText(charger))
}.build())
if (maxRows <= 3) {
// row 2: operator + cost + fault report
rows.add(Row.Builder().apply {
if (photo != null && !largeImageSupported) {
setImage(
CarIcon.Builder(IconCompat.createWithBitmap(photo)).build(),
Row.IMAGE_TYPE_LARGE
)
}
val operatorText = generateOperatorText(charger)
setTitle(operatorText)
charger.cost?.let { addText(it.getStatusText(carContext, emoji = true)) }
charger.faultReport?.let { fault ->
addText(
carContext.getString(
R.string.auto_fault_report_date,
fault.created?.atZone(ZoneId.systemDefault())
?.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))
)
)
}
}.build())
} else {
// row 2: operator + cost + cost description
rows.add(Row.Builder().apply {
if (photo != null && !largeImageSupported) {
setImage(
CarIcon.Builder(IconCompat.createWithBitmap(photo)).build(),
Row.IMAGE_TYPE_LARGE
)
}
val operatorText = generateOperatorText(charger)
setTitle(operatorText)
charger.cost?.let {
addText(it.getStatusText(carContext, emoji = true))
(it.descriptionShort ?: it.descriptionLong)?.let { addText(it) }
}
}.build())
// row 3: fault report (if exists)
charger.faultReport?.let { fault ->
rows.add(Row.Builder().apply {
setTitle(
carContext.getString(
R.string.auto_fault_report_date,
fault.created?.atZone(ZoneId.systemDefault())
?.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT))
)
)
fault.description?.let {
addText(
HtmlCompat.fromHtml(
it.replace("\n", " · "),
HtmlCompat.FROM_HTML_MODE_LEGACY
)
)
}
}.build())
}
// row 4: opening hours + location description
charger.openinghours?.let { hours ->
rows.add(Row.Builder().apply {
setTitle(hours.getStatusText(carContext))
hours.description?.let { addText(it) }
charger.locationDescription?.let { addText(it) }
}.build())
}
}
return rows
}
private fun generateChargepointsText(charger: ChargeLocation): SpannableStringBuilder {
val chargepointsText = SpannableStringBuilder()
charger.chargepointsMerged.forEachIndexed { i, cp ->
if (i > 0) chargepointsText.append(" · ")
chargepointsText.append(
"${cp.count}× ${
nameForPlugType(
carContext.stringProvider(),
cp.type
)
} ${cp.formatPower()}"
)
availability?.status?.get(cp)?.let { status ->
chargepointsText.append(
" (${availabilityText(status)}/${cp.count})",
ForegroundCarColorSpan.create(carAvailabilityColor(status)),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
}
}
return chargepointsText
}
private fun generateOperatorText(charger: ChargeLocation) =
if (charger.operator != null && charger.network != null) {
if (charger.operator.contains(charger.network)) {
charger.operator
} else if (charger.network.contains(charger.operator)) {
charger.network
} else {
"${charger.operator} · ${charger.network}"
}
} else if (charger.operator != null) {
charger.operator
} else if (charger.network != null) {
charger.network
} else {
carContext.getString(R.string.unknown_operator)
}
private fun navigateToCharger(charger: ChargeLocation) {
val coord = charger.coordinates
val intent =
@@ -212,18 +297,47 @@ class ChargerDetailScreen(ctx: CarContext, val chargerSparse: ChargeLocation) :
lifecycleScope.launch {
val response = api.getChargepointDetail(referenceData, chargerSparse.id)
if (response.status == Status.SUCCESS) {
charger = response.data!!
val charger = response.data!!
val photo = charger?.photos?.firstOrNull()
val photo = charger.photos?.firstOrNull()
photo?.let {
val size = (carContext.resources.displayMetrics.density * 64).roundToInt()
val url = photo.getUrl(size = size)
val density = carContext.resources.displayMetrics.density
val url = if (largeImageSupported) {
photo.getUrl(
width = (imageWidthLarge * density).roundToInt(),
height = (imageHeightLarge * density).roundToInt()
)
} else {
photo.getUrl(size = (imageSize * density).roundToInt())
}
val request = ImageRequest.Builder(carContext).data(url).build()
this@ChargerDetailScreen.photo =
var img =
(carContext.imageLoader.execute(request).drawable as BitmapDrawable).bitmap
}
availability = charger?.let { getAvailability(it).data }
// draw icon on top of image
val icon = iconGen.getBitmap(
tint = getMarkerTint(charger),
fault = charger.faultReport != null,
multi = charger.isMulti()
)
img = img.copy(Bitmap.Config.ARGB_8888, true)
val iconSmall = icon.scale(
(img.height * 0.4 / icon.height * icon.width).roundToInt(),
(img.height * 0.4).roundToInt()
)
val canvas = Canvas(img)
canvas.drawBitmap(
iconSmall,
0f,
(img.height - iconSmall.height * 1.1).toFloat(),
null
)
this@ChargerDetailScreen.photo = img
}
this@ChargerDetailScreen.charger = charger
availability = getAvailability(charger).data
invalidate()
} else {

View File

@@ -59,7 +59,12 @@ class VehicleDataScreen(ctx: CarContext) : Screen(ctx), LifecycleObserver {
return GridTemplate.Builder().apply {
setTitle(
if (model != null && model.manufacturer.value != null && model.name.value != null) {
"${model.manufacturer.value} ${model.name.value}"
"${model.manufacturer.value} ${
getVehicleModel(
model.manufacturer.value,
model.name.value
)
}"
} else {
carContext.getString(R.string.auto_vehicle_data)
}

View File

@@ -12,7 +12,9 @@ import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.color.MaterialColors
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialSharedAxis
import net.vonforst.evmap.MapsActivity
import net.vonforst.evmap.R
import net.vonforst.evmap.adapter.DonationAdapter
@@ -23,6 +25,12 @@ class DonateFragment : Fragment() {
private lateinit var binding: FragmentDonateBinding
private val vm: DonateViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -31,12 +39,18 @@ class DonateFragment : Fragment() {
binding = DataBindingUtil.inflate(inflater, R.layout.fragment_donate, container, false)
binding.lifecycleOwner = this
binding.vm = vm
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
(requireActivity() as AppCompatActivity).setSupportActionBar(binding.toolbar)
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
binding.productsList.apply {
adapter = DonationAdapter().apply {
onClickListener = {
@@ -56,13 +70,8 @@ class DonateFragment : Fragment() {
vm.purchaseFailed.observe(viewLifecycleOwner, Observer {
Snackbar.make(view, R.string.donation_failed, Snackbar.LENGTH_LONG).show()
})
}
override fun onResume() {
super.onResume()
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
// Workaround for AndroidX bug: https://github.com/material-components/material-components-android/issues/1984
view.setBackgroundColor(MaterialColors.getColor(view, android.R.attr.windowBackground))
}
}

View File

@@ -0,0 +1,47 @@
package net.vonforst.evmap.fragment.preference
import android.content.SharedPreferences
import android.os.Bundle
import android.view.View
import androidx.fragment.app.viewModels
import androidx.preference.MultiSelectListPreference
import net.vonforst.evmap.R
import net.vonforst.evmap.ui.RangeSliderPreference
import net.vonforst.evmap.viewmodel.SettingsViewModel
import net.vonforst.evmap.viewmodel.viewModelFactory
import java.text.NumberFormat
class AndroidAutoSettingsFragment : BaseSettingsFragment() {
override val isTopLevel = false
private lateinit var rangePreference: RangeSliderPreference
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
rangePreference = findPreference("chargeprice_battery_range_android_auto")!!
rangePreference.labelFormatter = { value: Float ->
val fmt = NumberFormat.getNumberInstance()
fmt.maximumFractionDigits = 0
fmt.format(value.toDouble()) + "%"
}
updateRangePreferenceSummary()
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.settings_android_auto, rootKey)
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {
when (key) {
"chargeprice_battery_range_android_auto_min", "chargeprice_battery_range_android_auto_max" -> {
updateRangePreferenceSummary()
}
}
}
private fun updateRangePreferenceSummary() {
val range = prefs.chargepriceBatteryRangeAndroidAuto
rangePreference.summary = getString(R.string.chargeprice_battery_range, range[0], range[1])
}
}

View File

@@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FF000000"
android:pathData="m22.78,17.91c0.16,0.25 0.22,0.51 0.22,0.79 0,0.38 -0.13,0.69 -0.43,0.94s-0.63,0.36 -1.01,0.36h-2.48l-6.66,-12h-0.84l-6.66,12h-2.53c-0.47,0 -0.86,-0.2 -1.17,-0.62s-0.33,-0.88 -0.05,-1.38l9.61,-16.31c0.31,-0.47 0.72,-0.69 1.22,-0.69 0.53,0 0.92,0.22 1.17,0.69zM4.78,22.31 L12,9.38 19.22,22.31 18.5,23 12,20.34 5.44,23z" />
</vector>

View File

@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/welcomeTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="72dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="16dp"
android:text="@string/welcome_android_auto"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/img_android_auto" />
<TextView
android:id="@+id/welcomeText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:layout_marginBottom="56dp"
android:breakStrategy="balanced"
android:text="@string/welcome_android_auto_detail"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/welcomeTitle" />
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="@string/sounds_cool"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/welcomeText" />
<ImageView
android:id="@+id/img_android_auto"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_marginStart="72dp"
android:layout_marginBottom="28dp"
android:background="@drawable/circle_bg_logo"
android:backgroundTint="@color/android_auto_accent"
android:scaleType="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.65"
app:srcCompat="@drawable/android_auto" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,66 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/welcomeTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="16dp"
android:gravity="center"
android:text="@string/welcome_android_auto"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/welcomeText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="56dp"
android:breakStrategy="balanced"
android:gravity="center"
android:text="@string/welcome_android_auto_detail"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="@string/sounds_cool"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<ImageView
android:id="@+id/img_android_auto"
android:layout_width="72dp"
android:layout_height="72dp"
android:layout_marginTop="28dp"
android:layout_marginBottom="28dp"
android:background="@drawable/circle_bg_logo"
android:backgroundTint="@color/android_auto_accent"
android:scaleType="center"
app:layout_constraintBottom_toTopOf="@+id/welcomeTitle"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.7"
app:srcCompat="@drawable/android_auto" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -13,7 +13,7 @@
android:layout_marginBottom="16dp"
android:gravity="center"
android:text="@string/welcome_android_auto"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
@@ -29,7 +29,7 @@
android:breakStrategy="balanced"
android:gravity="center"
android:text="@string/welcome_android_auto_detail"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
app:layout_constraintEnd_toEndOf="parent"
@@ -38,7 +38,7 @@
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"

View File

@@ -29,7 +29,7 @@
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:text="@{item.sku.title}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/textView21"
app:layout_constraintHorizontal_bias="0.0"
@@ -42,7 +42,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{item.sku.price}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"

View File

@@ -31,6 +31,7 @@
<string name="welcome_android_auto_detail">Auf unterstützen Autos kannst du EVMap auch mit Android Auto nutzen. Öffne dazu einfach die EVMap-App aus dem Menü von Android Auto.</string>
<string name="sounds_cool">klingt cool</string>
<string name="auto_chargeprice_vehicle_unavailable">EVMap konnte das Fahrzeugmodell nicht erkennen.</string>
<string name="auto_chargeprice_vehicle_unknown">Keins der in der App ausgewählten Fahrzeuge passt zu diesem Fahrzeug (%s %s).</string>
<string name="auto_chargeprice_vehicle_ambiguous">Mehrere der in der App ausgewählten Fahrzeuge passen zu diesem Fahrzeug (%s %s).</string>
<string name="auto_chargeprice_vehicle_unknown">Keins der in der App ausgewählten Fahrzeuge passt zu diesem Fahrzeug (%1$s %2$s).</string>
<string name="auto_chargeprice_vehicle_ambiguous">Mehrere der in der App ausgewählten Fahrzeuge passen zu diesem Fahrzeug (%1$s %2$s).</string>
<string name="settings_android_auto_chargeprice_range">Ladebereich für Preisvergleich</string>
</resources>

View File

@@ -3,8 +3,8 @@
<style name="CarAppTheme">
<item name="carColorPrimary">@color/colorPrimary</item>
<item name="carColorPrimaryDark">@color/colorPrimaryVariant</item>
<item name="carColorPrimaryDark">@color/colorPrimaryDark</item>
<item name="carColorSecondary">@color/colorSecondary</item>
<item name="carColorSecondaryDark">@color/colorSecondaryVariant</item>
<item name="carColorSecondaryDark">@color/colorSecondaryDark</item>
</style>
</resources>

View File

@@ -41,6 +41,7 @@
<string name="welcome_android_auto_detail">You can also use EVMap from within Android Auto on supported cars. Simply select the EVMap app in the Android Auto menu.</string>
<string name="sounds_cool">sounds cool</string>
<string name="auto_chargeprice_vehicle_unavailable">EVMap could not determine your vehicle model.</string>
<string name="auto_chargeprice_vehicle_unknown">None of the vehicles selected in the app matches this vehicle (%s %s).</string>
<string name="auto_chargeprice_vehicle_ambiguous">Mehrere der in der App ausgewählten Fahrzeuge passen zu diesem Fahrzeug (%s %s).</string>
<string name="auto_chargeprice_vehicle_unknown">None of the vehicles selected in the app matches this vehicle (%1$s %2$s).</string>
<string name="auto_chargeprice_vehicle_ambiguous">Mehrere der in der App ausgewählten Fahrzeuge passen zu diesem Fahrzeug (%1$s %2$s).</string>
<string name="settings_android_auto_chargeprice_range">Charging range for price comparison</string>
</resources>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto">
<net.vonforst.evmap.ui.RangeSliderPreference
android:key="chargeprice_battery_range_android_auto"
android:title="@string/settings_android_auto_chargeprice_range"
android:valueFrom="0.0"
android:valueTo="100.0"
app:updatesContinuously="true"
android:defaultValue="20.0,80.0"
android:layout="@layout/preference_widget_rangeslider"
tools:summary="@string/chargeprice_battery_range" />
</PreferenceScreen>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:fragment="net.vonforst.evmap.fragment.preference.AndroidAutoSettingsFragment"
android:title="@string/settings_android_auto"
android:icon="@drawable/ic_android_auto" />
</PreferenceScreen>

View File

@@ -256,6 +256,10 @@
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
</intent-filter>
<meta-data
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity>
<!-- Override services of the com.mapzen.android.lost library with exported:false

View File

@@ -1,5 +1,6 @@
package net.vonforst.evmap
import android.app.PendingIntent
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
@@ -18,7 +19,6 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.NavController
import androidx.navigation.findNavController
import androidx.navigation.fragment.FragmentNavigator
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupWithNavController
@@ -27,8 +27,10 @@ import androidx.preference.PreferenceFragmentCompat
import com.car2go.maps.model.LatLng
import com.google.android.material.navigation.NavigationView
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialSharedAxis
import net.vonforst.evmap.fragment.MapFragmentArgs
import net.vonforst.evmap.model.ChargeLocation
import net.vonforst.evmap.navigation.NavHostFragment
import net.vonforst.evmap.storage.PreferenceDataSource
import net.vonforst.evmap.utils.LocaleContextWrapper
import net.vonforst.evmap.utils.getLocationFromIntent
@@ -38,6 +40,7 @@ const val REQUEST_LOCATION_PERMISSION = 1
const val EXTRA_CHARGER_ID = "chargerId"
const val EXTRA_LAT = "lat"
const val EXTRA_LON = "lon"
const val EXTRA_FAVORITES = "favorites"
class MapsActivity : AppCompatActivity(),
PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
@@ -65,8 +68,6 @@ class MapsActivity : AppCompatActivity(),
setContentView(R.layout.activity_maps)
navController = findNavController(R.id.nav_host_fragment)
val navGraph = navController.navInflater.inflate(R.navigation.nav_graph)
appBarConfiguration = AppBarConfiguration(
setOf(
R.id.map,
@@ -76,6 +77,10 @@ class MapsActivity : AppCompatActivity(),
),
findViewById<DrawerLayout>(R.id.drawer_layout)
)
val navHostFragment =
supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as NavHostFragment
navController = navHostFragment.navController
val navGraph = navController.navInflater.inflate(R.navigation.nav_graph)
val navView = findViewById<NavigationView>(R.id.nav_view)
navView.setupWithNavController(navController)
@@ -112,55 +117,57 @@ class MapsActivity : AppCompatActivity(),
return
} else {
navGraph.setStartDestination(R.id.map)
navController.graph = navGraph
}
navController.setGraph(navGraph, MapFragmentArgs(appStart = true).toBundle())
var deepLink: PendingIntent? = null
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]
val deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
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 != null && query.isNotEmpty()) {
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) {
deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(chargerId = id).toBundle())
.createPendingIntent()
}
} else if (intent.hasExtra(EXTRA_CHARGER_ID)) {
deepLink = navController.createDeepLink()
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(latLng = LatLng(lat, lon)).toBundle())
.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()
deepLink.send()
} else if (query != null && query.isNotEmpty()) {
val deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(locationName = query).toBundle())
} else if (intent.hasExtra(EXTRA_FAVORITES)) {
deepLink = navController.createDeepLink()
.setDestination(R.id.favs)
.createPendingIntent()
deepLink.send()
}
} else if (intent?.scheme == "https" && intent?.data?.host == "www.goingelectric.de") {
val id = intent.data?.pathSegments?.last()?.toLongOrNull()
if (id != null) {
val deepLink = navController.createDeepLink()
.setGraph(R.navigation.nav_graph)
.setDestination(R.id.map)
.setArguments(MapFragmentArgs(chargerId = id).toBundle())
.createPendingIntent()
deepLink.send()
}
} else if (intent.hasExtra(EXTRA_CHARGER_ID)) {
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()
.send()
deepLink?.send()
}
}
@@ -169,6 +176,7 @@ class MapsActivity : AppCompatActivity(),
val coord = charger.coordinates
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse("google.navigation:q=${coord.lat},${coord.lng}")
intent.`package` = "com.google.android.apps.maps"
if (prefs.navigateUseMaps && intent.resolveActivity(packageManager) != null) {
startActivity(intent);
} else {
@@ -180,7 +188,11 @@ class MapsActivity : AppCompatActivity(),
fun showLocation(charger: ChargeLocation) {
val coord = charger.coordinates
val intent = Intent(Intent.ACTION_VIEW)
intent.data = Uri.parse("geo:0,0?q=${coord.lat},${coord.lng}(${charger.name})")
intent.data = Uri.parse(
"geo:${coord.lat},${coord.lng}?q=${coord.lat},${coord.lng}(${
Uri.encode(charger.name)
})"
)
if (intent.resolveActivity(packageManager) != null) {
startActivity(intent);
} else {
@@ -225,6 +237,9 @@ class MapsActivity : AppCompatActivity(),
caller: PreferenceFragmentCompat,
pref: Preference
): Boolean {
caller.exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
caller.reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
// Identify the Navigation Destination
val navDestination = navController.graph
.find { target -> target is FragmentNavigator.Destination && pref.fragment == target.className }

View File

@@ -144,10 +144,9 @@ class CheckableConnectorAdapter : DataBindingAdapter<Chargepoint>() {
field = value
checkedItem?.let {
if (value != null && getItem(it).type !in value) {
val index = currentList.indexOfFirst {
checkedItem = currentList.indexOfFirst {
it.type in value
}
checkedItem = if (index == -1) null else index
}.takeIf { it != -1 }
onCheckedItemChangedListener?.invoke(getCheckedItem())
}
}
@@ -168,7 +167,7 @@ class CheckableConnectorAdapter : DataBindingAdapter<Chargepoint>() {
}
root.setOnCheckedChangeListener { v: View, checked: Boolean ->
if (checked) {
checkedItem = holder.bindingAdapterPosition
checkedItem = holder.bindingAdapterPosition.takeIf { it != -1 }
root.post {
notifyDataSetChanged()
}
@@ -180,7 +179,7 @@ class CheckableConnectorAdapter : DataBindingAdapter<Chargepoint>() {
fun getCheckedItem(): Chargepoint? = checkedItem?.let { getItem(it) }
fun setCheckedItem(item: Chargepoint?) {
checkedItem = item?.let { currentList.indexOf(item) }
checkedItem = item?.let { currentList.indexOf(item) }.takeIf { it != -1 }
}
var onCheckedItemChangedListener: ((Chargepoint?) -> Unit)? = null

View File

@@ -73,7 +73,7 @@ fun buildDetails(
)
} ?: "",
loc.faultReport.description?.let {
HtmlCompat.fromHtml(it, HtmlCompat.FROM_HTML_MODE_LEGACY)
HtmlCompat.fromHtml(it.replace("\n", "<br>"), HtmlCompat.FROM_HTML_MODE_LEGACY)
} ?: "",
clickable = true
) else null,

View File

@@ -2,7 +2,6 @@ package net.vonforst.evmap.api.availability
import com.facebook.stetho.okhttp3.StethoInterceptor
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.withContext
import net.vonforst.evmap.api.RateLimitInterceptor
import net.vonforst.evmap.api.await
@@ -24,7 +23,6 @@ interface AvailabilityDetector {
suspend fun getAvailability(location: ChargeLocation): ChargeLocationStatus
}
@ExperimentalCoroutinesApi
abstract class BaseAvailabilityDetector(private val client: OkHttpClient) : AvailabilityDetector {
protected val radius = 150 // max radius in meters

View File

@@ -1,6 +1,5 @@
package net.vonforst.evmap.api.availability
import kotlinx.coroutines.ExperimentalCoroutinesApi
import net.vonforst.evmap.api.iterator
import net.vonforst.evmap.model.ChargeLocation
import net.vonforst.evmap.model.Chargepoint
@@ -8,12 +7,10 @@ import okhttp3.OkHttpClient
import org.json.JSONObject
import java.io.IOException
@ExperimentalCoroutinesApi
class ChargecloudAvailabilityDetector(
client: OkHttpClient,
private val operatorId: String
) : BaseAvailabilityDetector(client) {
@ExperimentalCoroutinesApi
override suspend fun getAvailability(location: ChargeLocation): ChargeLocationStatus {
val url =
"https://app.chargecloud.de/emobility:ocpi/$operatorId/app/2.0/locations?latitude=${location.coordinates.lat}&longitude=${location.coordinates.lng}&radius=$radius&offset=0&limit=10"

View File

@@ -2,12 +2,9 @@ package net.vonforst.evmap.fragment
import android.annotation.SuppressLint
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.*
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
@@ -15,7 +12,9 @@ import androidx.navigation.fragment.navArgs
import androidx.navigation.ui.setupWithNavController
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.color.MaterialColors
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialContainerTransform
import net.vonforst.evmap.MapsActivity
import net.vonforst.evmap.R
import net.vonforst.evmap.adapter.ChargepriceAdapter
@@ -30,7 +29,7 @@ import net.vonforst.evmap.viewmodel.Status
import net.vonforst.evmap.viewmodel.viewModelFactory
import java.text.NumberFormat
class ChargepriceFragment : DialogFragment() {
class ChargepriceFragment : Fragment() {
private lateinit var binding: FragmentChargepriceBinding
private var connectionErrorSnackbar: Snackbar? = null
@@ -43,9 +42,9 @@ class ChargepriceFragment : DialogFragment() {
}
})
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
dialog?.window?.attributes?.windowAnimations = R.style.ChargepriceDialogAnimation
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
sharedElementEnterTransition = MaterialContainerTransform()
}
override fun onCreateView(
@@ -66,20 +65,15 @@ class ChargepriceFragment : DialogFragment() {
return binding.root
}
override fun onStart() {
super.onStart()
// dialog with 95% screen height
dialog?.window?.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
(resources.displayMetrics.heightPixels * 0.95).toInt()
)
}
@SuppressLint("ClickableViewAccessibility")
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
val fragmentArgs: ChargepriceFragmentArgs by navArgs()
val charger = fragmentArgs.charger
val dataSource = fragmentArgs.dataSource
@@ -171,10 +165,6 @@ class ChargepriceFragment : DialogFragment() {
binding.toolbar.setOnMenuItemClickListener {
when (it.itemId) {
R.id.menu_close -> {
dismiss()
true
}
R.id.menu_help -> {
(activity as? MapsActivity)?.openUrl(getString(R.string.chargeprice_faq_link))
true
@@ -207,14 +197,9 @@ class ChargepriceFragment : DialogFragment() {
}
}
}
// Workaround for AndroidX bug: https://github.com/material-components/material-components-android/issues/1984
view.setBackgroundColor(MaterialColors.getColor(view, android.R.attr.windowBackground))
}
override fun onResume() {
super.onResume()
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
}
}
}

View File

@@ -17,7 +17,9 @@ import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.car2go.maps.model.LatLng
import com.google.android.material.color.MaterialColors
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialFadeThrough
import com.mapzen.android.lost.api.LocationServices
import com.mapzen.android.lost.api.LostApiClient
import net.vonforst.evmap.MapsActivity
@@ -51,6 +53,9 @@ class FavoritesFragment : Fragment(), LostApiClient.ConnectionCallbacks {
super.onCreate(savedInstanceState)
locationClient = LostApiClient.Builder(requireContext())
.addConnectionCallbacks(this).build()
enterTransition = MaterialFadeThrough()
exitTransition = MaterialFadeThrough()
}
override fun onCreateView(
@@ -70,6 +75,13 @@ class FavoritesFragment : Fragment(), LostApiClient.ConnectionCallbacks {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Workaround for AndroidX bug: https://github.com/material-components/material-components-android/issues/1984
view.setBackgroundColor(MaterialColors.getColor(view, android.R.attr.windowBackground))
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
adapter = FavoritesAdapter(onDelete = {
delete(it.charger)
@@ -254,9 +266,5 @@ class FavoritesFragment : Fragment(), LostApiClient.ConnectionCallbacks {
override fun onResume() {
super.onResume()
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
}
}

View File

@@ -11,6 +11,8 @@ import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.color.MaterialColors
import com.google.android.material.transition.MaterialSharedAxis
import kotlinx.coroutines.launch
import net.vonforst.evmap.MapsActivity
import net.vonforst.evmap.R
@@ -24,6 +26,12 @@ class FilterFragment : Fragment() {
private lateinit var binding: FragmentFilterBinding
private val vm: FilterViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -43,6 +51,17 @@ class FilterFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
(requireActivity() as AppCompatActivity).setSupportActionBar(binding.toolbar)
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
vm.filterProfile.observe(viewLifecycleOwner) {
if (it != null) {
binding.toolbar.title = getString(R.string.edit_filter_profile, it.name)
}
}
binding.filtersList.apply {
adapter = FiltersAdapter()
layoutManager =
@@ -57,6 +76,9 @@ class FilterFragment : Fragment() {
binding.toolbar.setNavigationOnClickListener {
findNavController().popBackStack()
}
// Workaround for AndroidX bug: https://github.com/material-components/material-components-android/issues/1984
view.setBackgroundColor(MaterialColors.getColor(view, android.R.attr.windowBackground))
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
@@ -108,18 +130,4 @@ class FilterFragment : Fragment() {
}
}
}
override fun onResume() {
super.onResume()
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
vm.filterProfile.observe(viewLifecycleOwner) {
if (it != null) {
binding.toolbar.title = getString(R.string.edit_filter_profile, it.name)
}
}
}
}

View File

@@ -17,7 +17,9 @@ import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.color.MaterialColors
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialSharedAxis
import kotlinx.coroutines.launch
import net.vonforst.evmap.MapsActivity
import net.vonforst.evmap.R
@@ -43,6 +45,12 @@ class FilterProfilesFragment : Fragment() {
private var deleteSnackbar: Snackbar? = null
private var toDelete: FilterProfile? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -58,6 +66,11 @@ class FilterProfilesFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
(requireActivity() as AppCompatActivity).setSupportActionBar(binding.toolbar)
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
touchHelper = ItemTouchHelper(object : ItemTouchHelper.SimpleCallback(
ItemTouchHelper.UP or ItemTouchHelper.DOWN,
ItemTouchHelper.RIGHT or ItemTouchHelper.LEFT
@@ -201,14 +214,9 @@ class FilterProfilesFragment : Fragment() {
binding.toolbar.setNavigationOnClickListener {
findNavController().popBackStack()
}
}
override fun onResume() {
super.onResume()
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
// Workaround for AndroidX bug: https://github.com/material-components/material-components-android/issues/1984
view.setBackgroundColor(MaterialColors.getColor(view, android.R.attr.windowBackground))
}
fun delete(fp: FilterProfile) {

View File

@@ -32,6 +32,7 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.navigation.findNavController
import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.navigation.ui.setupWithNavController
@@ -53,6 +54,8 @@ import com.car2go.maps.model.MarkerOptions
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.transition.MaterialArcMotion
import com.google.android.material.transition.MaterialContainerTransform
import com.google.android.material.transition.MaterialFadeThrough
import com.google.android.material.transition.MaterialSharedAxis
import com.mahc.custombottomsheetbehavior.BottomSheetBehaviorGoogleMapsLike
import com.mahc.custombottomsheetbehavior.BottomSheetBehaviorGoogleMapsLike.STATE_COLLAPSED
import com.mahc.custombottomsheetbehavior.BottomSheetBehaviorGoogleMapsLike.STATE_HIDDEN
@@ -147,8 +150,13 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
.build()
locationClient.connect()
clusterIconGenerator = ClusterIconGenerator(requireContext())
enterTransition = MaterialFadeThrough()
exitTransition = MaterialFadeThrough()
}
private val mapFragmentTag = "map"
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
@@ -159,6 +167,10 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
binding.vm = vm
val provider = prefs.mapProvider
if (mapFragment == null) {
mapFragment =
requireActivity().supportFragmentManager.findFragmentByTag(mapFragmentTag) as MapFragment?
}
if (mapFragment == null || mapFragment!!.priority[0] != provider) {
mapFragment = MapFragment()
mapFragment!!.priority = arrayOf(
@@ -172,7 +184,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
)
requireActivity().supportFragmentManager
.beginTransaction()
.replace(R.id.map, mapFragment!!)
.replace(R.id.map, mapFragment!!, mapFragmentTag)
.commit()
// reset map-related stuff (map provider may have changed)
@@ -194,7 +206,11 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
val density = resources.displayMetrics.density
// status bar height + toolbar height + margin
val margin =
insets.systemWindowInsetTop + (48 * density).toInt() + (24 * density).toInt()
if (binding.toolbarContainer.layoutParams.width == ViewGroup.LayoutParams.MATCH_PARENT) {
insets.systemWindowInsetTop + (48 * density).toInt() + (28 * density).toInt()
} else {
insets.systemWindowInsetTop + (12 * density).toInt()
}
binding.fabLayers.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = margin
}
@@ -234,6 +250,11 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
setupAdapters()
(activity as? MapsActivity)?.setSupportActionBar(binding.toolbar)
binding.toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
if (prefs.appStartCounter > 5 && !prefs.opensourceDonationsDialogShown) {
try {
findNavController().navigate(R.id.action_map_to_opensource_donations)
@@ -250,6 +271,32 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
// when there is already another navigation going on
}
}*/
val fragmentArgs: MapFragmentArgs by navArgs()
if (savedInstanceState == null && fragmentArgs.appStart) {
// logo animation after starting the app
binding.appLogo.root.visibility = View.VISIBLE
binding.appLogo.root.alpha = 0f
binding.search.visibility = View.GONE
binding.appLogo.root.animate().alpha(1f)
.withEndAction {
binding.appLogo.root.animate().alpha(0f).apply {
startDelay = 1000
}.withEndAction {
binding.appLogo.root.visibility = View.GONE
binding.search.visibility = View.VISIBLE
binding.search.alpha = 0f
binding.search.animate().alpha(1f).start()
}.start()
}.apply {
startDelay = 100
}.start()
arguments = fragmentArgs.copy(appStart = false).toBundle()
} else {
binding.appLogo.root.visibility = View.GONE
binding.search.visibility = View.VISIBLE
}
}
override fun onResume() {
@@ -257,12 +304,6 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
val hostActivity = activity as? MapsActivity ?: return
hostActivity.fragmentCallback = this
val navController = findNavController()
binding.toolbar.setupWithNavController(
navController,
(requireActivity() as MapsActivity).appBarConfiguration
)
vm.reloadPrefs()
if (requestingLocationUpdates && requireContext().checkAnyLocationPermission()
&& locationClient.isConnected
@@ -311,9 +352,12 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
OpenChargeMapApiWrapper::class.java -> "open_charge_map"
else -> throw IllegalArgumentException("unsupported data source")
}
val extras =
FragmentNavigatorExtras(binding.detailView.btnChargeprice to getString(R.string.shared_element_chargeprice))
findNavController().navigate(
R.id.action_map_to_chargepriceFragment,
ChargepriceFragmentArgs(charger, dataSource).toBundle()
ChargepriceFragmentArgs(charger, dataSource).toBundle(),
null, extras
)
}
binding.detailView.topPart.setOnClickListener {
@@ -392,6 +436,7 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
binding.search.onFocusChangeListener = View.OnFocusChangeListener { v, hasFocus ->
if (hasFocus) {
binding.search.keyListener = searchKeyListener
binding.search.text = binding.search.text // workaround to fix copy/paste
} else {
binding.search.keyListener = null
}
@@ -417,28 +462,38 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
private fun openLayersMenu() {
binding.fabLayers.tag = false
val materialTransform = MaterialContainerTransform().apply {
startView = binding.fabLayers
endView = binding.layersSheet
setPathMotion(MaterialArcMotion())
duration = 250
scrimColor = Color.TRANSPARENT
}
TransitionManager.beginDelayedTransition(binding.root, materialTransform)
vm.layersMenuOpen.value = true
binding.fabLayers.postDelayed({
val materialTransform = MaterialContainerTransform().apply {
startView = binding.fabLayers
endView = binding.layersSheet
setPathMotion(MaterialArcMotion())
duration = 250
scrimColor = Color.TRANSPARENT
addTarget(binding.layersSheet)
isElevationShadowEnabled = false
}
TransitionManager.beginDelayedTransition(binding.root, materialTransform)
vm.layersMenuOpen.value = true
}, 100)
}
private fun closeLayersMenu() {
binding.fabLayers.tag = true
val materialTransform = MaterialContainerTransform().apply {
startView = binding.layersSheet
endView = binding.fabLayers
setPathMotion(MaterialArcMotion())
duration = 200
scrimColor = Color.TRANSPARENT
}
TransitionManager.beginDelayedTransition(binding.root, materialTransform)
vm.layersMenuOpen.value = false
binding.fabLayers.postDelayed({
val materialTransform = MaterialContainerTransform().apply {
startView = binding.layersSheet
endView = binding.fabLayers
setPathMotion(MaterialArcMotion())
duration = 200
scrimColor = Color.TRANSPARENT
addTarget(binding.fabLayers)
isElevationShadowEnabled = false
}
TransitionManager.beginDelayedTransition(binding.root, materialTransform)
vm.layersMenuOpen.value = false
}, 100)
}
private fun toggleFavorite() {
@@ -557,8 +612,8 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
updateBackPressedCallback()
})
vm.layersMenuOpen.observe(viewLifecycleOwner, Observer { open ->
binding.fabLayers.visibility = if (open) View.GONE else View.VISIBLE
binding.layersSheet.visibility = if (open) View.VISIBLE else View.GONE
binding.fabLayers.visibility = if (open) View.INVISIBLE else View.VISIBLE
binding.layersSheet.visibility = if (open) View.VISIBLE else View.INVISIBLE
updateBackPressedCallback()
})
vm.mapType.observe(viewLifecycleOwner, Observer {
@@ -877,7 +932,11 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
} else if (locationName != null) {
lifecycleScope.launch {
val address = withContext(Dispatchers.IO) {
Geocoder(requireContext()).getFromLocationName(locationName, 1).getOrNull(0)
try {
Geocoder(requireContext()).getFromLocationName(locationName, 1).getOrNull(0)
} catch (e: IOException) {
null
}
}
address?.let {
val latLng = LatLng(it.latitude, it.longitude)
@@ -1070,12 +1129,18 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
filterView?.setOnClickListener {
var profilesMap: MutableBiMap<Long, MenuItem> = HashBiMap()
val popup = PopupMenu(requireContext(), it, Gravity.END)
val popup = PopupMenu(
ContextThemeWrapper(requireContext(), R.style.RoundedPopup),
it,
Gravity.END
)
popup.menuInflater.inflate(R.menu.popup_filter, popup.menu)
MenuCompat.setGroupDividerEnabled(popup.menu, true)
popup.setOnMenuItemClickListener {
when (it.itemId) {
R.id.menu_edit_filters -> {
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
lifecycleScope.launch {
vm.copyFiltersToCustom()
requireView().findNavController().navigate(
@@ -1085,6 +1150,8 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
true
}
R.id.menu_manage_filter_profiles -> {
exitTransition = MaterialSharedAxis(MaterialSharedAxis.Z, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.Z, false)
requireView().findNavController().navigate(
R.id.action_map_to_filterProfilesFragment
)

View File

@@ -4,6 +4,7 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.appcompat.app.AppCompatDialogFragment
import androidx.core.widget.doAfterTextChanged
import androidx.recyclerview.widget.LinearLayoutManager
@@ -14,6 +15,7 @@ import net.vonforst.evmap.databinding.DialogMultiSelectBinding
import java.util.*
import kotlin.collections.HashMap
import kotlin.collections.HashSet
import kotlin.math.roundToInt
class MultiSelectDialog : AppCompatDialogFragment() {
companion object {
@@ -53,9 +55,13 @@ class MultiSelectDialog : AppCompatDialogFragment() {
override fun onStart() {
super.onStart()
val density = resources.displayMetrics.density
val width = resources.displayMetrics.widthPixels
val maxWidth = (500 * density).roundToInt()
// dialog with 95% screen height
dialog?.window?.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
if (width < maxWidth) WindowManager.LayoutParams.MATCH_PARENT else maxWidth,
(resources.displayMetrics.heightPixels * 0.95).toInt()
)
}

View File

@@ -52,8 +52,17 @@ class OnboardingFragment : Fragment() {
override fun onPageSelected(position: Int) {
binding.pageIndicatorView.selection = position
binding.forward?.visibility =
if (position == adapter.itemCount - 1) View.INVISIBLE else View.VISIBLE
binding.backward?.visibility = if (position == 0) View.INVISIBLE else View.VISIBLE
}
})
binding.forward?.setOnClickListener {
binding.viewPager.setCurrentItem(binding.viewPager.currentItem + 1, true)
}
binding.backward?.setOnClickListener {
binding.viewPager.setCurrentItem(binding.viewPager.currentItem - 1, true)
}
return binding.root
}

View File

@@ -1,11 +1,15 @@
package net.vonforst.evmap.fragment.preference
import android.os.Bundle
import android.view.View
import androidx.appcompat.widget.Toolbar
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.color.MaterialColors
import com.google.android.material.transition.MaterialFadeThrough
import com.google.android.material.transition.MaterialSharedAxis
import com.mikepenz.aboutlibraries.LibsBuilder
import net.vonforst.evmap.BuildConfig
import net.vonforst.evmap.MapsActivity
@@ -13,14 +17,23 @@ import net.vonforst.evmap.R
class AboutFragment : PreferenceFragmentCompat() {
override fun onResume() {
super.onResume()
val toolbar = requireView().findViewById(R.id.toolbar) as Toolbar
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enterTransition = MaterialFadeThrough()
exitTransition = MaterialFadeThrough()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
// Workaround for AndroidX bug: https://github.com/material-components/material-components-android/issues/1984
view.setBackgroundColor(MaterialColors.getColor(view, android.R.attr.windowBackground))
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
@@ -54,6 +67,8 @@ class AboutFragment : PreferenceFragmentCompat() {
true
}
"donate" -> {
exitTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
reenterTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
findNavController().navigate(R.id.action_about_to_donateFragment)
true
}

View File

@@ -7,6 +7,9 @@ import androidx.appcompat.widget.Toolbar
import androidx.navigation.fragment.findNavController
import androidx.navigation.ui.setupWithNavController
import androidx.preference.PreferenceFragmentCompat
import com.google.android.material.color.MaterialColors
import com.google.android.material.transition.MaterialFadeThrough
import com.google.android.material.transition.MaterialSharedAxis
import net.vonforst.evmap.MapsActivity
import net.vonforst.evmap.R
import net.vonforst.evmap.storage.PreferenceDataSource
@@ -14,22 +17,38 @@ import net.vonforst.evmap.storage.PreferenceDataSource
abstract class BaseSettingsFragment : PreferenceFragmentCompat(),
SharedPreferences.OnSharedPreferenceChangeListener {
protected lateinit var prefs: PreferenceDataSource
protected abstract val isTopLevel: Boolean
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (isTopLevel) {
enterTransition = MaterialFadeThrough()
exitTransition = MaterialFadeThrough()
} else {
enterTransition = MaterialSharedAxis(MaterialSharedAxis.X, true)
returnTransition = MaterialSharedAxis(MaterialSharedAxis.X, false)
}
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val toolbar = view.findViewById<Toolbar>(R.id.toolbar)
toolbar.setupWithNavController(
findNavController(),
(requireActivity() as MapsActivity).appBarConfiguration
)
prefs = PreferenceDataSource(requireContext())
// Workaround for AndroidX bug: https://github.com/material-components/material-components-android/issues/1984
view.setBackgroundColor(MaterialColors.getColor(view, android.R.attr.windowBackground))
}
override fun onResume() {
super.onResume()
preferenceManager.sharedPreferences.registerOnSharedPreferenceChangeListener(this)
val navController = findNavController()
val toolbar = requireView().findViewById(R.id.toolbar) as Toolbar
toolbar.setupWithNavController(
navController,
(requireActivity() as MapsActivity).appBarConfiguration
)
}
override fun onPause() {

View File

@@ -10,6 +10,8 @@ import net.vonforst.evmap.viewmodel.SettingsViewModel
import net.vonforst.evmap.viewmodel.viewModelFactory
class ChargepriceSettingsFragment : BaseSettingsFragment() {
override val isTopLevel = false
private val vm: SettingsViewModel by viewModels(factoryProducer = {
viewModelFactory {
SettingsViewModel(

View File

@@ -11,6 +11,8 @@ import net.vonforst.evmap.viewmodel.SettingsViewModel
import net.vonforst.evmap.viewmodel.viewModelFactory
class DataSettingsFragment : BaseSettingsFragment() {
override val isTopLevel = false
private val vm: SettingsViewModel by viewModels(factoryProducer = {
viewModelFactory {
SettingsViewModel(

View File

@@ -7,13 +7,15 @@ import net.vonforst.evmap.R
class SettingsFragment : BaseSettingsFragment() {
override val isTopLevel = true
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.settings, rootKey)
addPreferencesFromResource(R.xml.settings)
addPreferencesFromResource(R.xml.settings_variantspecific)
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String) {

View File

@@ -6,6 +6,8 @@ import net.vonforst.evmap.R
import net.vonforst.evmap.ui.updateNightMode
class UiSettingsFragment : BaseSettingsFragment() {
override val isTopLevel = false
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.settings_ui, rootKey)
}

View File

@@ -10,6 +10,7 @@ import androidx.navigation.fragment.findNavController
import net.vonforst.evmap.R
import net.vonforst.evmap.databinding.DialogOpensourceDonationsBinding
import net.vonforst.evmap.storage.PreferenceDataSource
import kotlin.math.roundToInt
class OpensourceDonationsDialogFramgent : AppCompatDialogFragment() {
private lateinit var binding: DialogOpensourceDonationsBinding
@@ -43,8 +44,13 @@ class OpensourceDonationsDialogFramgent : AppCompatDialogFragment() {
override fun onStart() {
super.onStart()
val density = resources.displayMetrics.density
val width = resources.displayMetrics.widthPixels
val maxWidth = (500 * density).roundToInt()
dialog?.window?.setLayout(
WindowManager.LayoutParams.MATCH_PARENT,
if (width < maxWidth) WindowManager.LayoutParams.MATCH_PARENT else maxWidth,
WindowManager.LayoutParams.WRAP_CONTENT
)
}

View File

@@ -152,7 +152,7 @@ data class Cost(
val parking =
if (freeparking) ctx.getString(R.string.free) else ctx.getString(R.string.paid)
return if (emoji) {
" $parking"
"\uD83C\uDD7F $parking"
} else {
HtmlCompat.fromHtml(ctx.getString(R.string.cost_detail_parking, parking), 0)
}

View File

@@ -168,6 +168,17 @@ class PreferenceDataSource(val context: Context) {
.apply()
}
var chargepriceBatteryRangeAndroidAuto: List<Float>
get() = listOf(
sp.getFloat("chargeprice_battery_range_android_auto_min", 20f),
sp.getFloat("chargeprice_battery_range_android_auto_max", 80f),
)
set(value) {
sp.edit().putFloat("chargeprice_battery_range_android_auto_min", value[0])
.putFloat("chargeprice_battery_range_android_auto_max", value[1])
.apply()
}
/** App start counter, introduced with Version 1.0.0 */
var appStartCounter: Long
get() = sp.getLong("app_start_counter", 0)

View File

@@ -0,0 +1,117 @@
package net.vonforst.evmap.ui
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.preference.Preference
import androidx.preference.PreferenceViewHolder
import com.google.android.material.slider.RangeSlider
import net.vonforst.evmap.R
class RangeSliderPreference(context: Context, attrs: AttributeSet) : Preference(context, attrs) {
var valueFrom: Float = 0f
set(value) {
val v = if (value > valueTo) valueTo else value
if (v != valueFrom) {
field = v
notifyChanged()
}
}
var valueTo: Float = 100f
set(value) {
val v = if (value < valueFrom) valueFrom else value
if (v != valueTo) {
field = v
notifyChanged()
}
}
var stepSize: Float? = null
set(value) {
if (value != stepSize) {
field = value
notifyChanged()
}
}
var updatesContinuously: Boolean
var defaultValue: List<Float>
var labelFormatter: ((Float) -> String)? = null
set(value) {
if (value != labelFormatter) {
field = value
notifyChanged()
}
}
private lateinit var slider: RangeSlider
private var dragging = false
var values: List<Float>
get() = if ((sharedPreferences.contains(key + "_min") && sharedPreferences.contains(key + "_max"))) {
listOf(
sharedPreferences.getFloat(key + "_min", 0f),
sharedPreferences.getFloat(key + "_max", 0f)
)
} else defaultValue
set(value) {
sharedPreferences.edit()
.putFloat(key + "_min", value[0])
.putFloat(key + "_max", value[1])
.apply()
}
init {
val a = context.obtainStyledAttributes(
attrs, R.styleable.RangeSliderPreference
)
// The ordering of these two statements are important. If we want to set max first, we need
// to perform the same steps by changing min/max to max/min as following:
// mMax = a.getInt(...) and setMin(...).
valueFrom = a.getFloat(R.styleable.RangeSliderPreference_android_valueFrom, 0f)
valueTo = a.getFloat(R.styleable.RangeSliderPreference_android_valueTo, 100f)
stepSize =
a.getFloat(R.styleable.RangeSliderPreference_android_stepSize, -1f).takeIf { it != -1f }
updatesContinuously = a.getBoolean(
R.styleable.RangeSliderPreference_updatesContinuously,
false
)
defaultValue =
a.getString(R.styleable.RangeSliderPreference_android_defaultValue)?.split(",")
?.map { it.toFloat() } ?: listOf(valueFrom, valueTo)
a.recycle()
}
override fun onBindViewHolder(holder: PreferenceViewHolder) {
super.onBindViewHolder(holder)
slider = holder.findViewById(R.id.rangeSlider) as RangeSlider
slider.valueFrom = valueFrom
slider.valueTo = valueTo
stepSize?.let { slider.stepSize = it }
slider.addOnChangeListener { slider, value, fromUser ->
if (fromUser && (updatesContinuously || !dragging)) {
syncValueInternal(slider)
}
}
slider.setOnTouchListener { v, event ->
when (event.actionMasked) {
MotionEvent.ACTION_DOWN -> dragging = true
MotionEvent.ACTION_UP -> dragging = false
}
false
}
slider.values = values
slider.isEnabled = isEnabled
slider.setLabelFormatter(labelFormatter)
}
private fun syncValueInternal(slider: RangeSlider) {
val newValues = slider.values
if (callChangeListener(newValues)) {
values = newValues
} else {
slider.values = values
}
}
}

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:color="?android:attr/textColorSecondary" android:alpha="0.38" />
<item android:state_focused="false" android:color="?android:attr/textColorPrimary" />
</selector>

View File

@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z" />
</vector>

View File

@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal"
android:autoMirrored="true">
<path
android:fillColor="@android:color/white"
android:pathData="M12,4l-1.41,1.41L16.17,11H4v2h12.17l-5.58,5.59L12,20l8,-8z" />
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@color/colorSecondary"
android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z" />
</vector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?colorSurface" />
<corners android:radius="24dp" />
</shape>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?android:colorBackground" />
<corners android:radius="8dp" />
</shape>

View File

@@ -31,7 +31,7 @@
android:layout_marginEnd="32dp"
android:layout_marginBottom="16dp"
android:text="@string/pref_data_source"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
@@ -46,7 +46,7 @@
android:layout_marginBottom="28dp"
android:breakStrategy="balanced"
android:text="@string/data_sources_description"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
app:layout_constraintEnd_toEndOf="parent"
@@ -54,7 +54,7 @@
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.MaterialComponents.Button"
style="@style/Widget.Material3.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"

View File

@@ -26,7 +26,7 @@
android:layout_marginStart="72dp"
android:layout_marginTop="4dp"
android:text="&lt; 11 kW"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toTopOf="@id/icon4"
app:layout_constraintEnd_toStartOf="@+id/iconLabel2"
app:layout_constraintHorizontal_bias="0.5"
@@ -51,7 +51,7 @@
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:text="≥ 11 kW"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/iconLabel3"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iconLabel1"
@@ -75,7 +75,7 @@
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:text="≥ 20 kW"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/iconLabel4"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iconLabel2"
@@ -100,7 +100,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="≥ 43 kW"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/iconLabel5"
app:layout_constraintHorizontal_chainStyle="packed"
@@ -126,7 +126,7 @@
android:layout_marginStart="16dp"
android:layout_marginTop="4dp"
android:text="≥ 100 kW"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toEndOf="@id/iconLabel3"
app:layout_constraintStart_toEndOf="@+id/iconLabel4"
app:layout_constraintTop_toBottomOf="@+id/icon5" />
@@ -139,7 +139,7 @@
android:layout_marginEnd="32dp"
android:layout_marginBottom="16dp"
android:text="@string/welcome_2_title"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/iconLabel3"
@@ -154,7 +154,7 @@
android:layout_marginBottom="42dp"
android:breakStrategy="balanced"
android:text="@string/welcome_2"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
app:layout_constraintEnd_toEndOf="parent"
@@ -163,7 +163,7 @@
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="72dp"

View File

@@ -24,7 +24,7 @@
android:layout_marginEnd="32dp"
android:layout_marginBottom="16dp"
android:text="@string/welcome_to_evmap"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
@@ -39,7 +39,7 @@
android:layout_marginBottom="56dp"
android:breakStrategy="balanced"
android:text="@string/welcome_1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
app:layout_constraintEnd_toEndOf="parent"
@@ -48,7 +48,7 @@
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
style="@style/Widget.Material3.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:background="?colorPrimaryContainer">
<androidx.cardview.widget.CardView
android:id="@+id/card"
android:layout_width="0dp"
android:layout_height="540dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/forward"
app:layout_constraintStart_toEndOf="@id/backward"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="540dp">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:overScrollMode="never">
</androidx.viewpager2.widget.ViewPager2>
</androidx.cardview.widget.CardView>
<com.rd.PageIndicatorView
android:id="@+id/pageIndicatorView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/card"
app:piv_animationType="worm"
app:piv_dynamicCount="true"
app:piv_interactiveAnimation="true"
app:piv_padding="8dp"
app:piv_radius="6dp"
app:piv_selectedColor="@color/colorPrimary"
app:piv_unselectedColor="@color/pager_unselected"
app:piv_viewPager="@id/viewPager" />
<Button
android:id="@+id/forward"
style="@style/Widget.App.Button.ElevatedButton.IconOnly"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
app:icon="@drawable/ic_arrow_forward"
app:layout_constraintBottom_toBottomOf="@+id/card"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/card"
app:layout_constraintTop_toTopOf="@+id/card" />
<Button
android:id="@+id/backward"
style="@style/Widget.App.Button.ElevatedButton.IconOnly"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="48dp"
android:layout_marginEnd="48dp"
app:icon="@drawable/ic_arrow_back"
app:layout_constraintBottom_toBottomOf="@+id/card"
app:layout_constraintEnd_toStartOf="@+id/card"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/card" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="@+id/rg_data_source"
layout="@layout/data_source_select"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="56dp"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/welcomeTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="16dp"
android:gravity="center"
android:text="@string/pref_data_source"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/welcomeText2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="32dp"
android:gravity="center"
android:text="@string/data_sources_description"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
android:breakStrategy="balanced"
app:layout_constraintBottom_toTopOf="@+id/rg_data_source"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.Material3.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="@string/lets_go"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View File

@@ -0,0 +1,189 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/icon1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="28dp"
app:layout_constraintBottom_toTopOf="@+id/iconLabel1"
app:layout_constraintEnd_toEndOf="@+id/iconLabel1"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="@+id/iconLabel1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.7"
app:layout_constraintVertical_chainStyle="packed"
app:srcCompat="@drawable/ic_map_marker_charging"
app:tint="@color/charger_low"
app:tintMode="multiply" />
<TextView
android:id="@+id/iconLabel1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginBottom="28dp"
android:text="&lt; 11 kW"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeTitle"
app:layout_constraintEnd_toStartOf="@+id/iconLabel2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/icon1" />
<ImageView
android:id="@+id/icon2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="@+id/iconLabel2"
app:layout_constraintStart_toStartOf="@+id/iconLabel2"
app:layout_constraintTop_toTopOf="@id/icon1"
app:srcCompat="@drawable/ic_map_marker_charging"
app:tint="@color/charger_11kw"
app:tintMode="multiply" />
<TextView
android:id="@+id/iconLabel2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="≥ 11 kW"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/iconLabel3"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iconLabel1"
app:layout_constraintTop_toBottomOf="@+id/icon2" />
<ImageView
android:id="@+id/icon3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="@+id/iconLabel3"
app:layout_constraintStart_toStartOf="@+id/iconLabel3"
app:layout_constraintTop_toTopOf="@id/icon1"
app:srcCompat="@drawable/ic_map_marker_charging"
app:tint="@color/charger_20kw"
app:tintMode="multiply" />
<TextView
android:id="@+id/iconLabel3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="≥ 20 kW"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/iconLabel4"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iconLabel2"
app:layout_constraintTop_toBottomOf="@+id/icon3" />
<ImageView
android:id="@+id/icon4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="@+id/iconLabel4"
app:layout_constraintStart_toStartOf="@+id/iconLabel4"
app:layout_constraintTop_toTopOf="@id/icon1"
app:srcCompat="@drawable/ic_map_marker_charging"
app:tint="@color/charger_43kw"
app:tintMode="multiply" />
<TextView
android:id="@+id/iconLabel4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="≥ 43 kW"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/iconLabel5"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iconLabel3"
app:layout_constraintTop_toBottomOf="@+id/icon4" />
<ImageView
android:id="@+id/icon5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="@+id/iconLabel5"
app:layout_constraintStart_toStartOf="@+id/iconLabel5"
app:layout_constraintTop_toTopOf="@id/icon1"
app:srcCompat="@drawable/ic_map_marker_charging"
app:tint="@color/charger_100kw"
app:tintMode="multiply" />
<TextView
android:id="@+id/iconLabel5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="≥ 100 kW"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iconLabel4"
app:layout_constraintTop_toBottomOf="@+id/icon5" />
<TextView
android:id="@+id/welcomeTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="16dp"
android:gravity="center"
android:text="@string/welcome_2_title"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/welcomeText2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="8dp"
android:gravity="center"
android:text="@string/welcome_2_detail"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
android:textColor="?android:textColorSecondary"
android:breakStrategy="balanced"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/welcomeText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="8dp"
android:breakStrategy="balanced"
android:gravity="center"
android:text="@string/welcome_2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toTopOf="@+id/welcomeText2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="@string/got_it"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/animation_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="32dp"
android:layout_marginTop="28dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="28dp"
app:layout_constraintBottom_toTopOf="@+id/welcomeTitle"
app:layout_constraintDimensionRatio="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_max="256dp"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.85"
app:layout_constraintWidth_max="256dp"
app:srcCompat="@drawable/intro_anim_onboarding"
android:contentDescription="@string/app_name" />
<TextView
android:id="@+id/welcomeTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="16dp"
android:gravity="center"
android:text="@string/welcome_to_evmap"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/welcomeText1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="56dp"
android:gravity="center"
android:text="@string/welcome_1"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
android:breakStrategy="balanced"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.Material3.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
android:text="@string/get_started"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -5,7 +5,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="net.vonforst.evmap.navigation.NavHostFragment"
android:layout_height="match_parent"

View File

@@ -18,7 +18,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline4"
android:textAppearance="@style/TextAppearance.Material3.HeadlineLarge"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:visibility="gone"
tools:visibility="visible">
<ImageView
android:id="@+id/imageView2"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="-4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/textView14"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_launcher_foreground" />
<TextView
android:id="@+id/textView14"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:text="@string/app_name"
android:textAppearance="@style/TextAppearance.Material3.TitleLarge"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@id/imageView2"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<RadioButton
android:id="@+id/rbGoingElectric"
@@ -9,7 +10,7 @@
android:layout_height="wrap_content"
android:text="@string/data_source_goingelectric"
android:textColor="#098ac7"
android:buttonTint="#098ac7"
app:buttonTint="#098ac7"
android:textSize="16sp"
android:textStyle="bold" />
@@ -28,7 +29,7 @@
android:layout_height="wrap_content"
android:text="@string/data_source_openchargemap"
android:textColor="#587e25"
android:buttonTint="#587e25"
app:buttonTint="#587e25"
android:textSize="16sp"
android:textStyle="bold" />

View File

@@ -84,7 +84,7 @@
android:ellipsize="end"
android:maxLines="@{expanded ? 3 : 1}"
android:text="@{charger.data.name}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@+id/txtAvailability"
app:layout_constraintHorizontal_bias="0.0"
@@ -99,7 +99,7 @@
android:ellipsize="end"
android:maxLines="1"
android:text="@{charger.data.address.toString()}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/txtName"
@@ -115,7 +115,7 @@
android:maxLines="1"
android:minWidth="50dp"
android:text="@{BindingAdaptersKt.distance(distance)}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toBottomOf="@+id/txtConnectors"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
tools:text="10 km" />
@@ -131,7 +131,7 @@
android:maxLines="1"
android:padding="2dp"
android:text="@{String.format(&quot;%s/%d&quot;, BindingAdaptersKt.availabilityText(BindingAdaptersKt.flatten(filteredAvailability.data.status.values())), filteredAvailability.data.totalChargepoints)}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
android:textColor="@android:color/white"
app:backgroundTintAvailability="@{BindingAdaptersKt.flatten(availability.data.status.values())}"
app:invisibleUnlessAnimated="@{availability.data != null &amp;&amp; !expanded}"
@@ -149,7 +149,7 @@
android:ellipsize="end"
android:maxLines="1"
android:text="@{charger.data.formatChargepoints(ChargepointApiKt.stringProvider(context))}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/txtDistance"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/textView2"
@@ -174,7 +174,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/connectors"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
android:textAppearance="@style/TextAppearance.Material3.TitleSmall"
android:textColor="?colorPrimary"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="@+id/guideline"
@@ -186,7 +186,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/amenities"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
android:textAppearance="@style/TextAppearance.Material3.TitleSmall"
android:textColor="?colorPrimary"
app:goneUnless="@{charger.data.amenities != null}"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
@@ -200,7 +200,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@{charger.data.amenities}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:autoLink="web"
android:linksClickable="true"
app:goneUnless="@{charger.data.amenities != null}"
@@ -216,7 +216,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/general_info"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
android:textAppearance="@style/TextAppearance.Material3.TitleSmall"
android:textColor="?colorPrimary"
app:goneUnless="@{charger.data.generalInformation != null}"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
@@ -230,7 +230,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:text="@{charger.data.generalInformation}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:autoLink="web"
android:linksClickable="true"
app:goneUnless="@{charger.data.generalInformation != null}"
@@ -277,7 +277,7 @@
<Button
android:id="@+id/sourceButton"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
style="@style/Widget.Material3.Button.TextButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
@@ -293,7 +293,7 @@
android:layout_height="wrap_content"
android:gravity="right|end"
android:text="@{availability.status == Status.SUCCESS ? @string/realtime_data_source(availability.data.source) : availability.status == Status.LOADING ? @string/realtime_data_loading : @string/realtime_data_unavailable}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
app:layout_constraintStart_toStartOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@+id/connectors"
@@ -312,11 +312,12 @@
<Button
android:id="@+id/btnChargeprice"
style="@style/Widget.MaterialComponents.Button.OutlinedButton.Icon"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/go_to_chargeprice"
android:transitionName="@string/shared_element_chargeprice"
app:goneUnless="@{charger.data != null &amp;&amp; charger.data.chargepriceData != null &amp;&amp; charger.data.chargepriceData.country != null &amp;&amp; ChargepriceApi.isCountrySupported(charger.data.chargepriceData.country, charger.data.dataSource)}"
app:icon="@drawable/ic_chargeprice"
app:layout_constraintEnd_toStartOf="@+id/guideline2"
@@ -362,7 +363,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textAlignment="center"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
android:textStyle="italic"
android:text="@{charger.data.license}"
android:breakStrategy="balanced"

View File

@@ -12,7 +12,7 @@
android:layout_marginTop="18dp"
android:layout_marginEnd="16dp"
android:text="@string/pref_data_source"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@@ -41,7 +41,7 @@
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:text="@string/data_sources_description"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
@@ -60,7 +60,7 @@
<Button
android:id="@+id/btnOK"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
@@ -72,7 +72,7 @@
<Button
android:id="@+id/btnCancel"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"

View File

@@ -7,7 +7,7 @@
<TextView
android:id="@+id/dialogTitle"
style="@style/MaterialAlertDialog.MaterialComponents.Title.Text"
style="@style/MaterialAlertDialog.Material3.Title.Text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
@@ -31,7 +31,7 @@
<Button
android:id="@+id/btnAll"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/all"
@@ -40,7 +40,7 @@
<Button
android:id="@+id/btnOK"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
@@ -51,7 +51,7 @@
<Button
android:id="@+id/btnCancel"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
@@ -61,7 +61,7 @@
<Button
android:id="@+id/btnNone"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
@@ -71,7 +71,7 @@
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/tilSearch"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.Dense"
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.Dense"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"

View File

@@ -3,7 +3,6 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:maxWidth="200dp"
android:orientation="vertical">
<ScrollView
@@ -44,7 +43,7 @@
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:text="@string/donation_dialog_title"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/topPanel" />
@@ -57,7 +56,7 @@
android:layout_marginTop="8dp"
android:layout_marginEnd="16dp"
android:text="@string/donation_dialog_detail"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/welcomeTitle" />
@@ -76,7 +75,7 @@
<Button
android:id="@+id/btnGithubSponsors"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
@@ -90,7 +89,7 @@
<Button
android:id="@+id/btnDonate"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/donate"
@@ -100,7 +99,7 @@
<Button
android:id="@+id/btnOk"
style="@style/Widget.MaterialComponents.Button.TextButton.Dialog"
style="@style/Widget.Material3.Button.TextButton.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/ok"

View File

@@ -18,7 +18,8 @@
android:id="@+id/linearLayout5"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:orientation="vertical"
android:transitionName="@string/shared_element_chargeprice">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/toolbar_container"
@@ -27,9 +28,10 @@
android:fitsSystemWindows="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
app:layout_constraintTop_toTopOf="parent"
app:liftOnScroll="true">
<androidx.appcompat.widget.Toolbar
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize">
@@ -48,7 +50,7 @@
app:srcCompat="@drawable/ic_powered_by_chargeprice"
app:tint="?android:textColorPrimary"
tools:ignore="RtlSymmetry" />
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout>
@@ -68,7 +70,7 @@
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="@string/chargeprice_select_connector"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
android:textAppearance="@style/TextAppearance.Material3.TitleSmall"
android:textColor="?colorPrimary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/vehicle_selection" />
@@ -94,7 +96,7 @@
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="@{String.format(@string/chargeprice_battery_range, vm.batteryRange[0], vm.batteryRange[1])}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
android:textAppearance="@style/TextAppearance.Material3.TitleSmall"
android:textColor="?colorPrimary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/connectors_list"
@@ -107,7 +109,7 @@
android:layout_marginStart="4dp"
android:layout_marginTop="8dp"
android:text="@{@string/chargeprice_duration(BindingAdaptersKt.time((int) Math.round(vm.chargepriceMetaForChargepoint.data.duration)))}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
android:textAppearance="@style/TextAppearance.Material3.TitleSmall"
android:textColor="?colorPrimary"
app:invisibleUnlessAnimated="@{!vm.batteryRangeSliderDragging &amp;&amp; vm.chargepriceMetaForChargepoint.status == Status.SUCCESS}"
app:layout_constraintStart_toEndOf="@+id/textView2"
@@ -122,7 +124,7 @@
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="@string/chargeprice_vehicle"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle2"
android:textAppearance="@style/TextAppearance.Material3.TitleSmall"
android:textColor="?colorPrimary"
app:goneUnless="@{vm.vehicles.data != null &amp;&amp; vm.vehicles.data.size() > 1}"
app:layout_constraintStart_toStartOf="parent"
@@ -226,7 +228,7 @@
<Button
android:id="@+id/btnSettings"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"

View File

@@ -23,9 +23,10 @@
android:fitsSystemWindows="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
app:layout_constraintTop_toTopOf="parent"
app:liftOnScroll="true">
<androidx.appcompat.widget.Toolbar
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
@@ -70,7 +71,7 @@
android:breakStrategy="balanced"
android:gravity="center_horizontal"
android:text="@string/favorites_empty_state"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
android:textColor="?android:textColorSecondary"
app:goneUnless="@{vm.listData.size() == 0}"
app:layout_constraintBottom_toBottomOf="parent"

View File

@@ -21,9 +21,10 @@
android:id="@+id/toolbar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
app:liftOnScroll="true">
<androidx.appcompat.widget.Toolbar
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize" />

View File

@@ -29,7 +29,7 @@
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="wrap_content"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.appbar.AppBarLayout>
@@ -56,7 +56,7 @@
android:breakStrategy="balanced"
android:gravity="center_horizontal"
android:text="@string/filterprofiles_empty_state"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
android:textColor="?android:textColorSecondary"
app:goneUnless="@{vm.filterProfiles.size() == 0}"
app:layout_constraintBottom_toBottomOf="parent"

View File

@@ -42,78 +42,101 @@
<FrameLayout
android:id="@+id/toolbar_container"
android:layout_width="match_parent"
android:layout_width="@dimen/map_toolbar_width"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:layout_behavior="@string/ScrollingAppBarLayoutBehavior">
<com.google.android.material.appbar.AppBarLayout
<com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewElevatedStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:elevation="8dp"
android:background="@drawable/rounded_rect_4dp"
android:backgroundTint="?android:colorBackground">
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:cardElevation="4dp"
app:cardCornerRadius="24dp"
android:theme="@style/NoElevationOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="48dp"
app:contentInsetStartWithNavigation="70dp">
android:layout_height="wrap_content">
<LinearLayout
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="center_vertical"
android:focusable="true"
android:focusableInTouchMode="true">
android:layout_height="48dp"
app:contentInsetStartWithNavigation="70dp">
<net.vonforst.evmap.ui.AutocompleteTextViewWithSuggestions
android:id="@+id/search"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:singleLine="true"
android:scrollHorizontally="true"
android:ellipsize="end"
android:background="@null"
android:gravity="center_vertical"
android:hint="@string/search"
android:textAppearance="@style/TextAppearance.MaterialComponents.Subtitle1"
android:textColor="?android:textColorSecondary"
android:dropDownVerticalOffset="8dp"
android:popupBackground="@drawable/rounded_rect_4dp" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="@+id/clearSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:background="?attr/selectableItemBackgroundBorderless"
app:invisibleUnless="@{search.text.length() > 0}"
app:tint="?colorControlNormal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/handle"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_close"
android:contentDescription="@string/delete" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="center_vertical"
android:focusable="true"
android:focusableInTouchMode="true">
</androidx.appcompat.widget.Toolbar>
<net.vonforst.evmap.ui.AutocompleteTextViewWithSuggestions
android:id="@+id/search"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:singleLine="true"
android:scrollHorizontally="true"
android:ellipsize="end"
android:background="@null"
android:gravity="center_vertical"
android:hint="@string/search"
android:textSize="18sp"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
android:textColorHint="@color/hint_text_color"
android:dropDownVerticalOffset="8dp"
android:popupElevation="2dp"
android:popupBackground="@drawable/rounded_rect_24dp" />
<ProgressBar
android:id="@+id/progressBar2"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-10dp"
android:layout_marginBottom="-7dp"
android:indeterminate="true"
android:visibility="visible"
app:goneUnless="@{ vm.chargepoints.status == Status.LOADING }" />
<ImageButton
android:id="@+id/clearSearch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:background="?attr/selectableItemBackgroundBorderless"
app:invisibleUnless="@{search.text.length() > 0}"
app:tint="?colorControlNormal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/handle"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_close"
android:contentDescription="@string/delete" />
</LinearLayout>
</com.google.android.material.appbar.AppBarLayout>
<include
layout="@layout/app_logo_small"
android:id="@+id/app_logo"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</com.google.android.material.appbar.MaterialToolbar>
<ProgressBar
android:id="@+id/progressBar2"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="-10dp"
android:layout_marginBottom="-7dp"
android:indeterminate="true"
android:visibility="visible"
app:goneUnless="@{ vm.chargepoints.status == Status.LOADING }" />
</com.google.android.material.appbar.AppBarLayout>
</com.google.android.material.card.MaterialCardView>
</FrameLayout>
@@ -190,14 +213,15 @@
android:src="@drawable/ic_directions"
app:layout_anchor="@id/bottom_sheet"
app:layout_anchorGravity="top|right|end"
app:layout_behavior="@string/ScrollAwareFABBehavior" />
app:layout_behavior="@string/ScrollAwareFABBehavior"
android:theme="@style/NoElevationOverlay" />
<com.mahc.custombottomsheetbehavior.MergedAppBarLayout
android:id="@+id/detail_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/MergedAppBarLayoutBehavior"
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar" />
android:theme="@style/ThemeOverlay.Material3.Dark.ActionBar" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_layers"
@@ -206,25 +230,25 @@
android:clickable="true"
android:focusable="true"
android:layout_gravity="top|end"
android:layout_marginEnd="12dp"
android:layout_marginTop="96dp"
android:elevation="-1dp"
android:layout_marginEnd="20dp"
android:layout_marginTop="@dimen/layers_fab_top_padding"
app:tint="?android:colorControlNormal"
app:backgroundTint="?android:colorBackground"
app:borderWidth="0dp"
app:fabSize="mini"
app:srcCompat="@drawable/ic_layers"
app:layout_behavior="net.vonforst.evmap.ui.HideOnExpandFabBehavior"/>
app:layout_behavior="net.vonforst.evmap.ui.HideOnExpandFabBehavior"
android:theme="@style/NoElevationOverlay" />
<androidx.cardview.widget.CardView
android:id="@+id/layers_sheet"
android:layout_height="wrap_content"
android:layout_width="200dp"
android:layout_gravity="top|end"
android:layout_marginEnd="8dp"
android:layout_marginTop="96dp"
android:elevation="-1dp"
android:visibility="gone"
android:layout_marginEnd="16dp"
android:layout_marginTop="@dimen/layers_fab_top_padding"
android:visibility="invisible"
app:cardCornerRadius="16dp"
tools:visibility="visible">
<include

View File

@@ -2,7 +2,6 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:id="@+id/rl_create_account"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
@@ -26,7 +25,7 @@
app:piv_dynamicCount="true"
app:piv_interactiveAnimation="true"
app:piv_selectedColor="@color/colorPrimary"
app:piv_unselectedColor="@color/colorPrimaryTransparent"
app:piv_unselectedColor="@color/colorPrimaryContainer"
app:piv_viewPager="@id/viewPager"
app:piv_padding="8dp"
app:piv_radius="6dp" />

View File

@@ -31,7 +31,7 @@
android:layout_marginBottom="16dp"
android:gravity="center"
android:text="@string/pref_data_source"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
@@ -46,7 +46,7 @@
android:layout_marginBottom="32dp"
android:gravity="center"
android:text="@string/data_sources_description"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
android:breakStrategy="balanced"
app:layout_constraintBottom_toTopOf="@+id/rg_data_source"
@@ -56,7 +56,7 @@
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.MaterialComponents.Button"
style="@style/Widget.Material3.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"

View File

@@ -27,7 +27,7 @@
android:layout_marginTop="4dp"
android:layout_marginBottom="28dp"
android:text="&lt; 11 kW"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeTitle"
app:layout_constraintEnd_toStartOf="@+id/iconLabel2"
app:layout_constraintHorizontal_bias="0.5"
@@ -51,7 +51,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="≥ 11 kW"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/iconLabel3"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iconLabel1"
@@ -74,7 +74,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="≥ 20 kW"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/iconLabel4"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iconLabel2"
@@ -97,7 +97,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="≥ 43 kW"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toStartOf="@+id/iconLabel5"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iconLabel3"
@@ -120,7 +120,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="≥ 100 kW"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iconLabel4"
@@ -135,7 +135,7 @@
android:layout_marginBottom="16dp"
android:gravity="center"
android:text="@string/welcome_2_title"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
@@ -150,7 +150,7 @@
android:layout_marginBottom="8dp"
android:gravity="center"
android:text="@string/welcome_2_detail"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
android:textColor="?android:textColorSecondary"
android:breakStrategy="balanced"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
@@ -168,7 +168,7 @@
android:breakStrategy="balanced"
android:gravity="center"
android:text="@string/welcome_2"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
app:layout_constraintBottom_toTopOf="@+id/welcomeText2"
app:layout_constraintEnd_toEndOf="parent"
@@ -177,7 +177,7 @@
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"

View File

@@ -33,7 +33,7 @@
android:layout_marginBottom="16dp"
android:gravity="center"
android:text="@string/welcome_to_evmap"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline6"
android:textAppearance="@style/TextAppearance.Material3.HeadlineSmall"
app:layout_constraintBottom_toTopOf="@+id/welcomeText1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
@@ -48,7 +48,7 @@
android:layout_marginBottom="56dp"
android:gravity="center"
android:text="@string/welcome_1"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
android:textColor="?android:textColorSecondary"
android:breakStrategy="balanced"
app:layout_constraintBottom_toTopOf="@+id/btnGetStarted"
@@ -58,7 +58,7 @@
<Button
android:id="@+id/btnGetStarted"
style="@style/Widget.MaterialComponents.Button.OutlinedButton"
style="@style/Widget.Material3.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"

View File

@@ -3,15 +3,17 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/toolbar_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true">
android:fitsSystemWindows="true"
app:liftOnScroll="true">
<androidx.appcompat.widget.Toolbar
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize" />

View File

@@ -30,7 +30,7 @@
android:ellipsize="end"
android:singleLine="true"
android:text="@{item.primaryText}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/icon"
@@ -63,7 +63,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@{BindingAdaptersKt.distance(item.distanceMeters)}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:goneUnless="@{item.distanceMeters != null}"
app:layout_constraintEnd_toEndOf="@+id/icon"
app:layout_constraintStart_toStartOf="@+id/icon"
@@ -80,7 +80,7 @@
android:ellipsize="end"
android:singleLine="true"
android:text="@{item.secondaryText}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/title"

View File

@@ -44,7 +44,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{item.tariffName}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body2"
android:textAppearance="@style/TextAppearance.Material3.BodyMedium"
app:layout_constraintBottom_toTopOf="@+id/txtProvider"
app:layout_constraintEnd_toStartOf="@+id/ivLogo"
app:layout_constraintStart_toStartOf="parent"
@@ -57,7 +57,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{item.provider}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:goneUnless="@{!item.tariffName.toLowerCase().startsWith(item.provider.toLowerCase())}"
app:layout_constraintBottom_toTopOf="@+id/rvTags"
app:layout_constraintEnd_toStartOf="@+id/ivLogo"
@@ -83,7 +83,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/chargeprice_provider_customer_tariff"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:goneUnless="@{item.providerCustomerTariff}"
app:layout_constraintBottom_toTopOf="@id/txtMonthlyFee"
app:layout_constraintEnd_toStartOf="@+id/ivLogo"
@@ -96,7 +96,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@{item.formatMonthlyFees(context)}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:goneUnless="@{item.totalMonthlyFee > 0 || item.monthlyMinSales > 0}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/ivLogo"
@@ -127,7 +127,7 @@
android:gravity="end"
android:text="@{String.format(item.chargepointPrices.get(0).priceDistribution.isOnlyKwh ? @string/charge_price_kwh_format : @string/charge_price_average_format, item.chargepointPrices.get(0).price / meta.energy, BindingAdaptersKt.currency(item.currency))}"
app:goneUnless="@{item.chargepointPrices.get(0).price > 0}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toTopOf="@id/txtPriceDetails"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline5"
@@ -142,7 +142,7 @@
android:gravity="end"
android:text="@{item.chargepointPrices.get(0).formatDistribution(context)}"
app:goneUnless="@{!item.chargepointPrices.get(0).formatDistribution(context).empty}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/guideline5"

View File

@@ -21,9 +21,9 @@
android:background="@drawable/rounded_rect_16dp"
android:maxLines="3"
android:text="@{item.text}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
android:textColor="?android:textColorPrimary"
android:theme="@style/ThemeOverlay.MaterialComponents.Dark"
android:theme="@style/ThemeOverlay.Material3.Dark"
android:gravity="center_vertical"
android:drawablePadding="4dp"
android:paddingEnd="8dp"

View File

@@ -16,7 +16,7 @@
</data>
<com.google.android.material.chip.Chip
style="@style/Widget.MaterialComponents.Chip.Choice"
style="@style/Widget.Material3.Chip.Filter"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="4dp"

View File

@@ -41,7 +41,7 @@
android:layout_marginStart="38dp"
android:layout_marginTop="38dp"
android:text="@{String.format(&quot;× %d&quot;, item.chargepoint.count)}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintStart_toStartOf="@+id/imageView"
app:layout_constraintTop_toTopOf="@+id/imageView"
app:goneUnless="@{item.status == null}"
@@ -55,7 +55,7 @@
android:layout_marginStart="30dp"
android:layout_marginTop="30dp"
android:text="@{String.format(&quot;%s/%d&quot;, BindingAdaptersKt.availabilityText(item.status), item.chargepoint.count)}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
android:background="@drawable/rounded_rect"
android:padding="2dp"
android:textColor="@android:color/white"
@@ -73,7 +73,7 @@
android:layout_marginTop="4dp"
android:layout_marginBottom="8dp"
android:text="@{item.chargepoint.formatPower()}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

View File

@@ -52,7 +52,7 @@
android:layout_marginTop="38dp"
android:layout_marginEnd="4dp"
android:text="@{String.format(&quot;× %d&quot;, item.count)}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
android:textColor="@{BindingAdaptersKt.colorEnabled(context, enabled)}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/imageView"
@@ -66,7 +66,7 @@
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:text="@{item.formatPower()}"
android:textAppearance="@style/TextAppearance.MaterialComponents.Caption"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
android:textColor="@{BindingAdaptersKt.colorEnabled(context, enabled)}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"

Some files were not shown because too many files have changed in this diff Show More