mirror of
https://github.com/ev-map/EVMap.git
synced 2025-12-25 08:07:46 -05:00
Compare commits
1 Commits
openstreet
...
chargepric
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a22b347edc |
@@ -0,0 +1,74 @@
|
||||
package net.vonforst.evmap.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ArrayAdapter
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import androidx.navigation.ui.setupWithNavController
|
||||
import net.vonforst.evmap.MapsActivity
|
||||
import net.vonforst.evmap.R
|
||||
import net.vonforst.evmap.databinding.FragmentChargepriceFeedbackBinding
|
||||
import net.vonforst.evmap.viewmodel.ChargepriceFeedbackViewModel
|
||||
import net.vonforst.evmap.viewmodel.viewModelFactory
|
||||
|
||||
class ChargepriceFeedbackFragment : Fragment() {
|
||||
|
||||
private lateinit var binding: FragmentChargepriceFeedbackBinding
|
||||
private val vm: ChargepriceFeedbackViewModel by viewModels(factoryProducer = {
|
||||
viewModelFactory {
|
||||
ChargepriceFeedbackViewModel(
|
||||
requireActivity().application,
|
||||
getString(R.string.chargeprice_key),
|
||||
getString(R.string.chargeprice_api_url)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val fragmentArgs: ChargepriceFeedbackFragmentArgs by navArgs()
|
||||
vm.feedbackType.value = fragmentArgs.feedbackType
|
||||
vm.charger.value = fragmentArgs.charger
|
||||
vm.vehicle.value = fragmentArgs.vehicle
|
||||
vm.chargePrices.value = fragmentArgs.chargePrices?.toList()
|
||||
vm.batteryRange.value = fragmentArgs.batteryRange?.toList()
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View {
|
||||
binding = DataBindingUtil.inflate(
|
||||
inflater,
|
||||
R.layout.fragment_chargeprice_feedback, container, false
|
||||
)
|
||||
binding.lifecycleOwner = this
|
||||
binding.vm = vm
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.toolbar.setupWithNavController(
|
||||
findNavController(),
|
||||
(requireActivity() as MapsActivity).appBarConfiguration
|
||||
)
|
||||
binding.tariffSpinner.setAdapter(
|
||||
ArrayAdapter<String>(
|
||||
requireContext(),
|
||||
R.layout.item_simple_multiline,
|
||||
R.id.text,
|
||||
mutableListOf()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import net.vonforst.evmap.api.equivalentPlugTypes
|
||||
import net.vonforst.evmap.databinding.FragmentChargepriceBinding
|
||||
import net.vonforst.evmap.model.Chargepoint
|
||||
import net.vonforst.evmap.storage.PreferenceDataSource
|
||||
import net.vonforst.evmap.viewmodel.ChargepriceFeedbackType
|
||||
import net.vonforst.evmap.viewmodel.ChargepriceViewModel
|
||||
import net.vonforst.evmap.viewmodel.Status
|
||||
import net.vonforst.evmap.viewmodel.savedStateViewModelFactory
|
||||
@@ -182,6 +183,9 @@ class ChargepriceFragment : Fragment() {
|
||||
binding.btnSettings.setOnClickListener {
|
||||
findNavController().navigate(R.id.action_chargeprice_to_chargepriceSettingsFragment)
|
||||
}
|
||||
binding.btnFeedbackMissingPrice.setOnClickListener {
|
||||
feedbackMissingPrice()
|
||||
}
|
||||
|
||||
binding.batteryRange.setLabelFormatter { value: Float ->
|
||||
val fmt = NumberFormat.getNumberInstance()
|
||||
@@ -202,6 +206,14 @@ class ChargepriceFragment : Fragment() {
|
||||
(activity as? MapsActivity)?.openUrl(getString(R.string.chargeprice_faq_link))
|
||||
true
|
||||
}
|
||||
R.id.menu_feedback_missing_price -> {
|
||||
feedbackMissingPrice()
|
||||
true
|
||||
}
|
||||
R.id.menu_feedback_wrong_price -> {
|
||||
feedbackWrongPrice()
|
||||
true
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
@@ -235,4 +247,30 @@ class ChargepriceFragment : Fragment() {
|
||||
view.setBackgroundColor(MaterialColors.getColor(view, android.R.attr.windowBackground))
|
||||
}
|
||||
|
||||
private fun feedbackMissingPrice() {
|
||||
findNavController().navigate(
|
||||
R.id.action_chargeprice_to_chargepriceFeedbackFragment,
|
||||
ChargepriceFeedbackFragmentArgs(
|
||||
ChargepriceFeedbackType.MISSING_PRICE,
|
||||
vm.charger.value,
|
||||
vm.vehicle.value,
|
||||
vm.chargePricesForChargepoint.value?.data?.toTypedArray(),
|
||||
vm.batteryRange.value?.toFloatArray()
|
||||
).toBundle()
|
||||
)
|
||||
}
|
||||
|
||||
private fun feedbackWrongPrice() {
|
||||
findNavController().navigate(
|
||||
R.id.action_chargeprice_to_chargepriceFeedbackFragment,
|
||||
ChargepriceFeedbackFragmentArgs(
|
||||
ChargepriceFeedbackType.WRONG_PRICE,
|
||||
vm.charger.value,
|
||||
vm.vehicle.value,
|
||||
vm.chargePricesForChargepoint.value?.data?.toTypedArray(),
|
||||
vm.batteryRange.value?.toFloatArray()
|
||||
).toBundle()
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ import android.graphics.drawable.LayerDrawable
|
||||
import android.text.SpannableString
|
||||
import android.view.View
|
||||
import android.view.ViewGroup.MarginLayoutParams
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.AutoCompleteTextView
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.ColorInt
|
||||
@@ -128,9 +130,18 @@ fun <T> setRecyclerViewData(recyclerView: RecyclerView, items: List<T>?) {
|
||||
}
|
||||
|
||||
@BindingAdapter("data")
|
||||
fun <T> setRecyclerViewData(recyclerView: ViewPager2, items: List<T>?) {
|
||||
if (recyclerView.adapter is ListAdapter<*, *>) {
|
||||
(recyclerView.adapter as ListAdapter<T, *>).submitList(items)
|
||||
fun <T> setViewPager2Data(viewPager: ViewPager2, items: List<T>?) {
|
||||
if (viewPager.adapter is ListAdapter<*, *>) {
|
||||
(viewPager.adapter as ListAdapter<T, *>).submitList(items)
|
||||
}
|
||||
}
|
||||
|
||||
@BindingAdapter("data")
|
||||
fun <T> setAutoCompleteTextViewData(atv: AutoCompleteTextView, items: List<T>?) {
|
||||
if (atv.adapter is ArrayAdapter<*>) {
|
||||
val arrayAdapter = atv.adapter as ArrayAdapter<T>
|
||||
arrayAdapter.clear()
|
||||
items?.let { arrayAdapter.addAll(it) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
package net.vonforst.evmap.viewmodel
|
||||
|
||||
import android.app.Application
|
||||
import androidx.lifecycle.*
|
||||
import kotlinx.coroutines.launch
|
||||
import net.vonforst.evmap.R
|
||||
import net.vonforst.evmap.api.chargeprice.*
|
||||
import net.vonforst.evmap.model.ChargeLocation
|
||||
import net.vonforst.evmap.model.Chargepoint
|
||||
import net.vonforst.evmap.storage.PreferenceDataSource
|
||||
import net.vonforst.evmap.ui.currency
|
||||
import java.io.IOException
|
||||
|
||||
enum class ChargepriceFeedbackType {
|
||||
MISSING_PRICE, WRONG_PRICE, MISSING_VEHICLE
|
||||
}
|
||||
|
||||
class ChargepriceFeedbackViewModel(
|
||||
application: Application,
|
||||
chargepriceApiKey: String,
|
||||
chargepriceApiUrl: String
|
||||
) :
|
||||
AndroidViewModel(application) {
|
||||
private var api = ChargepriceApi.create(chargepriceApiKey, chargepriceApiUrl)
|
||||
private var prefs = PreferenceDataSource(application)
|
||||
|
||||
// data supplied through fragment args
|
||||
val feedbackType = MutableLiveData<ChargepriceFeedbackType>()
|
||||
val charger = MutableLiveData<ChargeLocation>()
|
||||
val chargepoint = MutableLiveData<Chargepoint>()
|
||||
val vehicle = MutableLiveData<ChargepriceCar>()
|
||||
val chargePrices = MutableLiveData<List<ChargePrice>>()
|
||||
val batteryRange = MutableLiveData<List<Float>>()
|
||||
|
||||
// data input by user
|
||||
val tariff = MutableLiveData<String>()
|
||||
val price = MutableLiveData<String>()
|
||||
val notes = MutableLiveData<String>()
|
||||
val email = MutableLiveData<String>()
|
||||
|
||||
val loading = MutableLiveData<Boolean>().apply { value = false }
|
||||
|
||||
val chargePricesStrings = chargePrices.map {
|
||||
it.map {
|
||||
val name = if (!it.tariffName.lowercase().startsWith(it.provider.lowercase())) {
|
||||
"${it.provider} ${it.tariffName}"
|
||||
} else it.tariffName
|
||||
val price = application.getString(
|
||||
R.string.charge_price_format,
|
||||
it.chargepointPrices[0].price,
|
||||
currency(it.currency)
|
||||
)
|
||||
"$name: $price"
|
||||
}.toList()
|
||||
}
|
||||
|
||||
private val feedback = MediatorLiveData<ChargepriceUserFeedback>().apply {
|
||||
listOf(
|
||||
feedbackType,
|
||||
charger,
|
||||
chargepoint,
|
||||
vehicle,
|
||||
chargePrices,
|
||||
tariff,
|
||||
price,
|
||||
notes,
|
||||
email
|
||||
).forEach {
|
||||
addSource(it) {
|
||||
try {
|
||||
value = when (feedbackType.value!!) {
|
||||
ChargepriceFeedbackType.MISSING_PRICE -> {
|
||||
ChargepriceMissingPriceFeedback(
|
||||
tariff.value ?: "",
|
||||
charger.value?.network?.take(200) ?: "",
|
||||
price.value ?: "",
|
||||
charger.value?.let { ChargepriceApi.getPoiUrl(it) } ?: "",
|
||||
notes.value ?: "",
|
||||
email.value ?: "",
|
||||
getChargepriceContext(),
|
||||
ChargepriceApi.getChargepriceLanguage()
|
||||
)
|
||||
}
|
||||
ChargepriceFeedbackType.WRONG_PRICE -> {
|
||||
ChargepriceWrongPriceFeedback(
|
||||
"", // TODO: dropdown value
|
||||
charger.value?.network?.take(200) ?: "",
|
||||
"", // TODO: dropdown value
|
||||
price.value ?: "",
|
||||
charger.value?.let { ChargepriceApi.getPoiUrl(it) } ?: "",
|
||||
notes.value ?: "",
|
||||
email.value ?: "",
|
||||
getChargepriceContext(),
|
||||
ChargepriceApi.getChargepriceLanguage()
|
||||
)
|
||||
}
|
||||
ChargepriceFeedbackType.MISSING_VEHICLE -> {
|
||||
TODO()
|
||||
}
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
value = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val formValid = feedback.map { it != null }
|
||||
|
||||
fun sendFeedback() {
|
||||
val feedback = feedback.value ?: return
|
||||
viewModelScope.launch {
|
||||
loading.value = true
|
||||
try {
|
||||
api.userFeedback(feedback)
|
||||
} catch (e: IOException) {
|
||||
|
||||
}
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun getChargepriceContext(): String {
|
||||
val result = StringBuilder()
|
||||
vehicle.value?.let { result.append("Vehicle: ${it.brand} ${it.name}\n") }
|
||||
batteryRange.value?.let { result.append("Battery SOC: ${it[0]} to ${it[1]}\n") }
|
||||
return result.toString()
|
||||
}
|
||||
}
|
||||
@@ -168,7 +168,8 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/battery_range"
|
||||
tools:itemCount="3"
|
||||
tools:listitem="@layout/item_chargeprice" />
|
||||
tools:listitem="@layout/item_chargeprice"
|
||||
tools:visibility="invisible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView8"
|
||||
@@ -179,10 +180,11 @@
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/chargeprice_no_tariffs_found"
|
||||
app:goneUnless="@{vm.chargePricesForChargepoint.status == Status.SUCCESS && vm.chargePricesForChargepoint.data.size() == 0}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btnFeedbackMissingPrice"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/charge_prices_list"
|
||||
app:layout_constraintTop_toTopOf="@+id/charge_prices_list" />
|
||||
app:layout_constraintTop_toTopOf="@+id/charge_prices_list"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView9"
|
||||
@@ -237,6 +239,20 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView3" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnFeedbackMissingPrice"
|
||||
style="@style/Widget.Material3.Button.TonalButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/chargeprice_feedback_missing_price"
|
||||
app:goneUnless="@{vm.chargePricesForChargepoint.status == Status.SUCCESS && vm.chargePricesForChargepoint.data.size() == 0}"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/textView8" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
209
app/src/main/res/layout/fragment_chargeprice_feedback.xml
Normal file
209
app/src/main/res/layout/fragment_chargeprice_feedback.xml
Normal file
@@ -0,0 +1,209 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layout xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<data>
|
||||
|
||||
<import type="net.vonforst.evmap.viewmodel.ChargepriceFeedbackViewModel" />
|
||||
|
||||
<import type="net.vonforst.evmap.viewmodel.ChargepriceFeedbackType" />
|
||||
|
||||
<variable
|
||||
name="vm"
|
||||
type="ChargepriceFeedbackViewModel" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:goneUnless="@{vm.loading}" />
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/toolbar_container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:fitsSystemWindows="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:liftOnScroll="true">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:fillViewport="true"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/toolbar_container"
|
||||
app:goneUnless="@{!vm.loading}">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/mainLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtCPO"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:text="@{@string/chargeprice_feedback_cpo(vm.charger.network)}"
|
||||
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
|
||||
app:goneUnless="@{vm.charger.network != null && vm.feedbackType == ChargepriceFeedbackType.MISSING_PRICE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/chargeprice_feedback_cpo" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/input_tariff"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:counterEnabled="true"
|
||||
app:counterMaxLength="100"
|
||||
app:goneUnless="@{vm.feedbackType == ChargepriceFeedbackType.MISSING_PRICE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/txtCPO">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/chargeprice_feedback_tariff"
|
||||
android:maxLength="100"
|
||||
android:text="@={vm.tariff}" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/input_tariff_spinner"
|
||||
style="@style/Widget.Material3.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:goneUnless="@{vm.feedbackType == ChargepriceFeedbackType.WRONG_PRICE}"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/input_tariff">
|
||||
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:id="@+id/tariff_spinner"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/chargeprice_feedback_tariff"
|
||||
android:inputType="none"
|
||||
app:data="@{vm.chargePricesStrings}" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/input_price"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:counterEnabled="true"
|
||||
app:counterMaxLength="100"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/input_tariff_spinner">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/chargeprice_feedback_price"
|
||||
android:maxLength="100"
|
||||
android:text="@={vm.price}" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/input_comment"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:counterEnabled="true"
|
||||
app:counterMaxLength="1000"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/input_price">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="160dp"
|
||||
android:gravity="top"
|
||||
android:hint="@string/chargeprice_feedback_comment"
|
||||
android:inputType="textMultiLine"
|
||||
android:maxLength="1000"
|
||||
android:text="@={vm.notes}" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/input_email"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:counterEnabled="true"
|
||||
app:counterMaxLength="100"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/input_comment">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/chargeprice_feedback_email"
|
||||
android:inputType="textEmailAddress"
|
||||
android:maxLength="100"
|
||||
android:text="@={vm.email}" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btnSend"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:onClick="@{(view) -> vm.sendFeedback()}"
|
||||
android:enabled="@{vm.formValid}"
|
||||
android:text="@string/chargeprice_feedback_send"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/input_email" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
19
app/src/main/res/layout/item_simple_multiline.xml
Normal file
19
app/src/main/res/layout/item_simple_multiline.xml
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="13dp"
|
||||
android:paddingTop="13dp"
|
||||
android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="3"
|
||||
android:textAppearance="?attr/textAppearanceBodyLarge"
|
||||
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam" />
|
||||
</FrameLayout>
|
||||
@@ -6,6 +6,16 @@
|
||||
android:id="@+id/menu_help"
|
||||
android:icon="@drawable/ic_help"
|
||||
android:title="@string/help"
|
||||
app:showAsAction="always" />
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_feedback_missing_price"
|
||||
android:title="@string/chargeprice_feedback_missing_price"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_feedback_wrong_price"
|
||||
android:title="@string/chargeprice_feedback_wrong_price"
|
||||
app:showAsAction="never" />
|
||||
|
||||
</menu>
|
||||
|
||||
@@ -124,6 +124,13 @@
|
||||
app:enterAnim="@animator/nav_default_enter_anim"
|
||||
app:popEnterAnim="@animator/nav_default_enter_anim"
|
||||
app:popExitAnim="@animator/nav_default_exit_anim" />
|
||||
<action
|
||||
android:id="@+id/action_chargeprice_to_chargepriceFeedbackFragment"
|
||||
app:destination="@id/chargeprice_feedback"
|
||||
app:exitAnim="@animator/nav_default_exit_anim"
|
||||
app:enterAnim="@animator/nav_default_enter_anim"
|
||||
app:popEnterAnim="@animator/nav_default_enter_anim"
|
||||
app:popExitAnim="@animator/nav_default_exit_anim" />
|
||||
<action
|
||||
android:id="@+id/action_chargeprice_to_donateFragment"
|
||||
app:destination="@id/donate" />
|
||||
@@ -131,6 +138,31 @@
|
||||
android:name="charger"
|
||||
app:argType="net.vonforst.evmap.model.ChargeLocation" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/chargeprice_feedback"
|
||||
android:name="net.vonforst.evmap.fragment.ChargepriceFeedbackFragment"
|
||||
android:label="@string/chargeprice_feedback"
|
||||
tools:layout="@layout/fragment_chargeprice_feedback">
|
||||
<argument
|
||||
android:name="feedbackType"
|
||||
app:argType="net.vonforst.evmap.viewmodel.ChargepriceFeedbackType" />
|
||||
<argument
|
||||
android:name="charger"
|
||||
app:argType="net.vonforst.evmap.model.ChargeLocation"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="vehicle"
|
||||
app:argType="net.vonforst.evmap.api.chargeprice.ChargepriceCar"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="chargePrices"
|
||||
app:argType="net.vonforst.evmap.api.chargeprice.ChargePrice[]"
|
||||
app:nullable="true" />
|
||||
<argument
|
||||
android:name="batteryRange"
|
||||
app:argType="float[]"
|
||||
app:nullable="true" />
|
||||
</fragment>
|
||||
<fragment
|
||||
android:id="@+id/donate"
|
||||
android:name="net.vonforst.evmap.fragment.DonateFragment"
|
||||
|
||||
@@ -270,4 +270,13 @@
|
||||
<string name="pref_provider_osm_mapbox">OpenStreetMap (Mapbox)</string>
|
||||
<string name="about_contributors">Mitwirkende</string>
|
||||
<string name="about_contributors_text">Dank an alle Mitwirkenden für ihre Beiträge von Code und Übersetzungen für EVMap:</string>
|
||||
<string name="chargeprice_feedback">Feedback</string>
|
||||
<string name="chargeprice_feedback_missing_price">Fehlenden Preis melden</string>
|
||||
<string name="chargeprice_feedback_wrong_price">Falschen Preis melden</string>
|
||||
<string name="chargeprice_feedback_email">E-Mail-Adresse für Rückfragen</string>
|
||||
<string name="chargeprice_feedback_comment">Weitere Infos</string>
|
||||
<string name="chargeprice_feedback_price">Preis (pro kWh, Minute, etc.)</string>
|
||||
<string name="chargeprice_feedback_cpo">Betreiber der Station (CPO): %s</string>
|
||||
<string name="chargeprice_feedback_tariff">Anbieter bzw. Tarif</string>
|
||||
<string name="chargeprice_feedback_send">Absenden</string>
|
||||
</resources>
|
||||
@@ -269,4 +269,13 @@
|
||||
<string name="pref_provider_osm_mapbox">OpenStreetMap (Mapbox)</string>
|
||||
<string name="about_contributors">Contributors</string>
|
||||
<string name="about_contributors_text">Thanks to all contributors for their coding and translation contributions to EVMap:</string>
|
||||
<string name="chargeprice_feedback">Feedback</string>
|
||||
<string name="chargeprice_feedback_missing_price">Report missing price</string>
|
||||
<string name="chargeprice_feedback_wrong_price">Report incorrect price</string>
|
||||
<string name="chargeprice_feedback_email">Email address for further questions</string>
|
||||
<string name="chargeprice_feedback_comment">Other details</string>
|
||||
<string name="chargeprice_feedback_price">Price (per kWh, minute, etc.)</string>
|
||||
<string name="chargeprice_feedback_cpo">Station operator (CPO): %s</string>
|
||||
<string name="chargeprice_feedback_tariff">Provider / plan</string>
|
||||
<string name="chargeprice_feedback_send">Submit</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user