add connector details dialog

relevant for #275 and #151
This commit is contained in:
johan12345
2023-12-17 16:46:56 +01:00
parent d8e8475666
commit 22d24f3bd0
10 changed files with 280 additions and 3 deletions

View File

@@ -94,6 +94,17 @@ class ConnectorAdapter : DataBindingAdapter<ConnectorAdapter.ChargepointWithAvai
override fun getItemViewType(position: Int): Int = R.layout.item_connector
}
class ConnectorDetailsAdapter : DataBindingAdapter<ConnectorDetailsAdapter.ConnectorDetails>() {
data class ConnectorDetails(
val chargepoint: Chargepoint,
val status: ChargepointStatus?,
val evseId: String?
) :
Equatable
override fun getItemViewType(position: Int): Int = R.layout.dialog_connector_details_item
}
class ChargepriceAdapter() :
DataBindingAdapter<ChargePrice>() {

View File

@@ -1,8 +1,10 @@
package net.vonforst.evmap.api.availability
import android.content.Context
import android.os.Parcelable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.parcelize.Parcelize
import net.vonforst.evmap.addDebugInterceptors
import net.vonforst.evmap.api.RateLimitInterceptor
import net.vonforst.evmap.api.await
@@ -154,7 +156,8 @@ data class ChargeLocationStatus(
val totalChargepoints = status.map { it.key.count }.sum()
}
enum class ChargepointStatus {
@Parcelize
enum class ChargepointStatus : Parcelable {
AVAILABLE, UNKNOWN, CHARGING, OCCUPIED, FAULTED
}

View File

@@ -0,0 +1,75 @@
package net.vonforst.evmap.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.os.BundleCompat
import androidx.recyclerview.widget.LinearLayoutManager
import net.vonforst.evmap.adapter.ConnectorDetailsAdapter
import net.vonforst.evmap.api.availability.ChargeLocationStatus
import net.vonforst.evmap.api.availability.ChargepointStatus
import net.vonforst.evmap.databinding.DialogConnectorDetailsBinding
import net.vonforst.evmap.databinding.DialogDataSourceSelectBinding
import net.vonforst.evmap.model.Chargepoint
import net.vonforst.evmap.model.FILTERS_DISABLED
import net.vonforst.evmap.storage.PreferenceDataSource
import net.vonforst.evmap.ui.MaterialDialogFragment
class ConnectorDetailsDialog : MaterialDialogFragment() {
private lateinit var binding: DialogConnectorDetailsBinding
companion object {
fun getInstance(
chargepoint: Chargepoint,
status: List<ChargepointStatus>,
evseIds: List<String>? = null
): ConnectorDetailsDialog {
val dialog = ConnectorDetailsDialog()
dialog.arguments = Bundle().apply {
putParcelable("chargepoint", chargepoint)
putParcelableArrayList("status", ArrayList(status))
putStringArrayList("evseIds", evseIds?.let { ArrayList(it) })
}
return dialog
}
}
override fun createView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = DialogConnectorDetailsBinding.inflate(inflater, container, false)
prefs = PreferenceDataSource(requireContext())
return binding.root
}
private lateinit var prefs: PreferenceDataSource
override fun initView(view: View, savedInstanceState: Bundle?) {
val args = requireArguments()
val chargepoint = BundleCompat.getParcelable(args, "chargepoint", Chargepoint::class.java)!!
val status =
BundleCompat.getParcelableArrayList(args, "status", ChargepointStatus::class.java)
val evseIds = args.getStringArrayList("evseIds")
val items = List(chargepoint.count) { i ->
ConnectorDetailsAdapter.ConnectorDetails(chargepoint, status?.get(i), evseIds?.get(i))
}.sortedBy { it.evseId }
binding.list.apply {
adapter = ConnectorDetailsAdapter().apply {
submitList(items)
}
itemAnimator = null
layoutManager =
LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false)
}
binding.btnClose.setOnClickListener {
dismiss()
}
}
}

View File

@@ -814,7 +814,20 @@ class MapFragment : Fragment(), OnMapReadyCallback, MapsActivity.FragmentCallbac
}
binding.detailView.connectors.apply {
adapter = ConnectorAdapter()
adapter = ConnectorAdapter().apply {
onClickListener = { item ->
vm.availability.value?.data?.let {
item.status?.let { status ->
val dialog = ConnectorDetailsDialog.getInstance(
item.chargepoint,
status,
it.evseIds?.get(item.chargepoint)
)
dialog.show(parentFragmentManager, null)
}
}
}
}
itemAnimator = null
layoutManager =
LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)

View File

@@ -156,11 +156,21 @@ fun setImageTintAvailability(view: ImageView, available: List<ChargepointStatus>
view.imageTintList = ColorStateList.valueOf(availabilityColor(available, view.context))
}
@BindingAdapter("tintAvailability")
fun setImageTintAvailability(view: ImageView, available: ChargepointStatus?) {
view.imageTintList = ColorStateList.valueOf(availabilityColor(available, view.context))
}
@BindingAdapter("textColorAvailability")
fun setTextColorAvailability(view: TextView, available: List<ChargepointStatus>?) {
view.setTextColor(availabilityColor(available, view.context))
}
@BindingAdapter("textColorAvailability")
fun setTextColorAvailability(view: TextView, available: ChargepointStatus?) {
view.setTextColor(availabilityColor(available, view.context))
}
@BindingAdapter("backgroundTintAvailability")
fun setBackgroundTintAvailability(view: View, available: List<ChargepointStatus>?) {
view.backgroundTintList = ColorStateList.valueOf(availabilityColor(available, view.context))
@@ -269,6 +279,25 @@ private fun availabilityColor(
ta.getColor(0, 0)
}
private fun availabilityColor(
status: ChargepointStatus?,
context: Context
): Int = when (status) {
ChargepointStatus.UNKNOWN -> ContextCompat.getColor(context, R.color.unknown)
ChargepointStatus.AVAILABLE -> ContextCompat.getColor(context, R.color.available)
ChargepointStatus.FAULTED -> ContextCompat.getColor(context, R.color.unavailable)
ChargepointStatus.OCCUPIED, ChargepointStatus.CHARGING -> ContextCompat.getColor(
context,
R.color.charging
)
null -> {
val ta =
context.theme.obtainStyledAttributes(intArrayOf(androidx.appcompat.R.attr.colorControlNormal))
ta.getColor(0, 0)
}
}
fun availabilityText(status: List<ChargepointStatus>?): String? {
if (status == null) return null
@@ -281,6 +310,18 @@ fun availabilityText(status: List<ChargepointStatus>?): String? {
} else available.toString()
}
fun availabilityText(status: ChargepointStatus?, context: Context): String? {
if (status == null) return null
return when (status) {
ChargepointStatus.UNKNOWN -> context.getString(R.string.status_unknown)
ChargepointStatus.AVAILABLE -> context.getString(R.string.status_available)
ChargepointStatus.CHARGING -> context.getString(R.string.status_charging)
ChargepointStatus.OCCUPIED -> context.getString(R.string.status_occupied)
ChargepointStatus.FAULTED -> context.getString(R.string.status_faulted)
}
}
fun flatten(it: Iterable<Iterable<ChargepointStatus>>?): List<ChargepointStatus>? {
return it?.flatten()
}

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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="8dp"
android:paddingBottom="8dp">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/list"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/dialog_connector_details_item" />
<ImageButton
android:id="@+id/btnClose"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="0dp"
android:layout_marginEnd="12dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:contentDescription="@string/close"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@drawable/ic_close"
app:tint="?colorControlNormal" />
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<data>
<import type="net.vonforst.evmap.adapter.ConnectorDetailsAdapter.ConnectorDetails" />
<import type="net.vonforst.evmap.ui.BindingAdaptersKt" />
<variable
name="item"
type="ConnectorDetails" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/listPreferredItemHeightSmall"
android:layout_marginStart="?attr/dialogPreferredPadding"
android:layout_marginEnd="?attr/dialogPreferredPadding">
<ImageView
android:id="@+id/imageView"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:tintMode="src_in"
android:contentDescription="@{item.chargepoint.type}"
app:connectorIcon="@{item.chargepoint.type}"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:tintAvailability="@{item.status}"
tools:tint="@color/available"
tools:srcCompat="@drawable/ic_connector_typ2" />
<TextView
android:id="@+id/textView6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginBottom="8dp"
android:text="@{item.chargepoint.formatPower()}"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:goneUnless="@{item.chargepoint.hasKnownPower()}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/imageView"
app:layout_constraintStart_toStartOf="@+id/imageView"
app:layout_constraintTop_toBottomOf="@+id/imageView"
app:textColorAvailability="@{item.status}"
tools:text="350 kW"
tools:textColor="@color/available" />
<TextView
android:id="@+id/txtEvseid"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="18dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="14dp"
android:text="@{item.evseId}"
app:layout_constraintBottom_toBottomOf="@+id/imageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintTop_toTopOf="parent"
tools:text="SK*IOY*E222901" />
<TextView
android:id="@+id/txtStatus"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="14dp"
android:text="@{BindingAdaptersKt.availabilityText(item.status, context)}"
android:textAppearance="@style/TextAppearance.Material3.BodySmall"
app:goneUnless="@{item.status != null}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="@+id/txtEvseid"
app:layout_constraintTop_toBottomOf="@+id/txtEvseid"
tools:text="Available" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@@ -14,7 +14,8 @@
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless">
<ImageView
android:id="@+id/imageView"

View File

@@ -368,5 +368,10 @@
<string name="referral_tesla">Tesla</string>
<string name="generic_connection_error">Daten konnten nicht geladen werden</string>
<string name="copied">In Zwischenablage kopiert</string>
<string name="status_available">Verfügbar</string>
<string name="status_occupied">Besetzt</string>
<string name="status_charging">Lädt</string>
<string name="status_faulted">Defekt</string>
<string name="status_unknown">Status unbekannt</string>
<string name="charger_name">Ladestationsname</string>
</resources>

View File

@@ -368,5 +368,10 @@
<string name="referral_tesla">Tesla</string>
<string name="generic_connection_error">Could not load data</string>
<string name="copied">Copied to clipboard</string>
<string name="status_available">Available</string>
<string name="status_occupied">Occupied</string>
<string name="status_charging">Charging</string>
<string name="status_faulted">Out of order</string>
<string name="status_unknown">Status Unknown</string>
<string name="charger_name">Charger name</string>
</resources>