diff --git a/app/src/main/java/net/vonforst/evmap/adapter/DataBindingAdapters.kt b/app/src/main/java/net/vonforst/evmap/adapter/DataBindingAdapters.kt index 13c6ba98..15d1306c 100644 --- a/app/src/main/java/net/vonforst/evmap/adapter/DataBindingAdapters.kt +++ b/app/src/main/java/net/vonforst/evmap/adapter/DataBindingAdapters.kt @@ -94,6 +94,17 @@ class ConnectorAdapter : DataBindingAdapter() { + 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() { diff --git a/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt b/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt index 02acb8f2..593b9bf7 100644 --- a/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt +++ b/app/src/main/java/net/vonforst/evmap/api/availability/AvailabilityDetector.kt @@ -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 } diff --git a/app/src/main/java/net/vonforst/evmap/fragment/ConnectorDetailsDialog.kt b/app/src/main/java/net/vonforst/evmap/fragment/ConnectorDetailsDialog.kt new file mode 100644 index 00000000..33ed0d8b --- /dev/null +++ b/app/src/main/java/net/vonforst/evmap/fragment/ConnectorDetailsDialog.kt @@ -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, + evseIds: List? = 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() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt b/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt index 48c19d7c..8cc781b3 100644 --- a/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt +++ b/app/src/main/java/net/vonforst/evmap/fragment/MapFragment.kt @@ -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) diff --git a/app/src/main/java/net/vonforst/evmap/ui/BindingAdapters.kt b/app/src/main/java/net/vonforst/evmap/ui/BindingAdapters.kt index ed41e6c0..90f80e96 100644 --- a/app/src/main/java/net/vonforst/evmap/ui/BindingAdapters.kt +++ b/app/src/main/java/net/vonforst/evmap/ui/BindingAdapters.kt @@ -156,11 +156,21 @@ fun setImageTintAvailability(view: ImageView, available: List 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?) { 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?) { 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?): String? { if (status == null) return null @@ -281,6 +310,18 @@ fun availabilityText(status: List?): 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>?): List? { return it?.flatten() } diff --git a/app/src/main/res/layout/dialog_connector_details.xml b/app/src/main/res/layout/dialog_connector_details.xml new file mode 100644 index 00000000..ccc35d5c --- /dev/null +++ b/app/src/main/res/layout/dialog_connector_details.xml @@ -0,0 +1,34 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_connector_details_item.xml b/app/src/main/res/layout/dialog_connector_details_item.xml new file mode 100644 index 00000000..4e29ee70 --- /dev/null +++ b/app/src/main/res/layout/dialog_connector_details_item.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_connector.xml b/app/src/main/res/layout/item_connector.xml index 7a318809..ea285710 100644 --- a/app/src/main/res/layout/item_connector.xml +++ b/app/src/main/res/layout/item_connector.xml @@ -14,7 +14,8 @@ + android:layout_height="wrap_content" + android:background="?selectableItemBackgroundBorderless"> Tesla Daten konnten nicht geladen werden In Zwischenablage kopiert + Verfügbar + Besetzt + Lädt + Defekt + Status unbekannt Ladestationsname \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6808bf1d..c0c308d2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -368,5 +368,10 @@ Tesla Could not load data Copied to clipboard + Available + Occupied + Charging + Out of order + Status Unknown Charger name \ No newline at end of file