From 751b304a9bff7fb6e61ebc91825dc31d32bcf7ae Mon Sep 17 00:00:00 2001 From: Niko Diamadis Date: Mon, 30 May 2022 23:28:37 +0200 Subject: [PATCH] =?UTF-8?q?Benutze=20ListAdapter=20statt=20Kiel=20f=C3=BCr?= =?UTF-8?q?=20Projects?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fragments/ProjectFragment.kt | 321 +++++++++--------- .../recycler/ProjectTechniker.kt | 9 + .../recycler/ProjectTechnikerAdapter.kt | 48 +++ .../recycler/ProjectTechnikerViewHolder.kt | 12 - .../recycler/ProjectTechnikerViewState.kt | 12 - 5 files changed, 214 insertions(+), 188 deletions(-) create mode 100644 app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechniker.kt create mode 100644 app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerAdapter.kt delete mode 100644 app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerViewHolder.kt delete mode 100644 app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerViewState.kt diff --git a/app/src/main/java/com/cyb3rko/techniklogger/fragments/ProjectFragment.kt b/app/src/main/java/com/cyb3rko/techniklogger/fragments/ProjectFragment.kt index b379b3e..0998051 100644 --- a/app/src/main/java/com/cyb3rko/techniklogger/fragments/ProjectFragment.kt +++ b/app/src/main/java/com/cyb3rko/techniklogger/fragments/ProjectFragment.kt @@ -16,8 +16,8 @@ import com.afollestad.materialdialogs.list.listItemsMultiChoice import com.afollestad.materialdialogs.list.uncheckItems import com.cyb3rko.techniklogger.R import com.cyb3rko.techniklogger.databinding.FragmentProjectBinding -import com.cyb3rko.techniklogger.recycler.ProjectTechnikerViewHolder -import com.cyb3rko.techniklogger.recycler.ProjectTechnikerViewState +import com.cyb3rko.techniklogger.recycler.ProjectTechniker +import com.cyb3rko.techniklogger.recycler.ProjectTechnikerAdapter import com.google.android.material.timepicker.MaterialTimePicker import com.google.android.material.timepicker.TimeFormat import com.parse.ParseObject @@ -25,9 +25,6 @@ import com.parse.ParseQuery import es.dmoral.toasty.Toasty import java.sql.Time import java.text.DecimalFormat -import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter -import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter.Companion.adapterOf -import me.ibrahimyilmaz.kiel.core.RecyclerViewHolder @SuppressLint("SetTextI18n") class ProjectFragment : Fragment() { @@ -35,13 +32,13 @@ class ProjectFragment : Fragment() { private lateinit var myContext: Context private val args: ProjectFragmentArgs by navArgs() - private lateinit var adapter: RecyclerViewAdapter> + private lateinit var technikerAdapter: ProjectTechnikerAdapter private var adminMode = false private var objectId = "" private var dauer = "" private lateinit var einsatz: ParseObject private lateinit var sharedPref: SharedPreferences - private val techniker: MutableList = mutableListOf() + private val techniker: MutableList = mutableListOf() private var time = "" private val binding get() = _binding!! @@ -57,160 +54,148 @@ class ProjectFragment : Fragment() { objectId = args.objectId einsatz = ParseObject.createWithoutData("Einsatz", objectId) - adapter = adapterOf { - register( - layoutResource = R.layout.item_recycler_techniker, - viewHolder = ::ProjectTechnikerViewHolder, - onBindBindViewHolder = { vh, _, clickedTechniker -> - vh.textView.text = "${clickedTechniker.name}, ${clickedTechniker.dauer} h" - vh.itemView.setOnClickListener { - if (adminMode || clickedTechniker.name == sharedPref.getString("name", "")) { - MaterialDialog(myContext) - .show { - title(text = clickedTechniker.name) - val uhrzeit = if (clickedTechniker.uhrzeit == "0") time else clickedTechniker.uhrzeit - message(text = Html.fromHtml("Arbeitszeit:
$uhrzeit Uhr

Wie möchtest du " + - "diesen Eintrag bearbeiten?")) - positiveButton(text = "Arbeitszeit ändern") { - var tempTime = "" - var time1 = Time(0) - var time2 = Time(0) - val builder = MaterialTimePicker.Builder().setTimeFormat(TimeFormat.CLOCK_24H).setTitleText("Von") - val builder2 = MaterialTimePicker.Builder().setTimeFormat(TimeFormat.CLOCK_24H).setTitleText("Bis") - val picker = builder.build() - val picker2 = builder2.build() - var hour: String - var minute: String - var hoursInMillis: Long - var minutesInMillis: Long - if (clickedTechniker.uhrzeit != "0") { - val times = clickedTechniker.uhrzeit.split(" - ") - builder.setHour(times[0].split(":")[0].toInt()) - .setMinute(times[0].split(":")[1].toInt()) - builder2.setHour(times[1].split(":")[0].toInt()) - .setMinute(times[1].split(":")[1].toInt()) - } - picker.addOnPositiveButtonClickListener { - hour = picker.hour.toString() - hour = if (hour.length != 1) hour else "0$hour" - minute = picker.minute.toString() - minute = if (minute.length != 1) minute else "0$minute" - hoursInMillis = picker.hour.toLong() * 3600000 - minutesInMillis = picker.minute.toLong() * 60000 - time1 = Time(hoursInMillis + minutesInMillis) - val testTime = time.split(" ")[0] - val testHour = testTime.split(":")[0] - val testMinutes = testTime.split(":")[1] - if (testHour > hour) { - Toasty.warning(myContext, "Zeitpunkt nicht im Zeitraum des Einsatzes", Toasty.LENGTH_LONG).show() - } else if (testHour == hour && testMinutes > minute) { - Toasty.warning(myContext, "Zeitpunkt nicht im Zeitraum des Einsatzes", Toasty.LENGTH_LONG).show() - } else { - tempTime += "${hour}:${minute} - " - activity?.let { it1 -> picker2.show(it1.supportFragmentManager, picker2.tag) } - } - } - picker2.addOnPositiveButtonClickListener { - hour = picker2.hour.toString() - hour = if (hour.length != 1) hour else "0$hour" - minute = picker2.minute.toString() - minute = if (minute.length != 1) minute else "0$minute" - hoursInMillis = hour.toLong() * 3600000 - minutesInMillis = minute.toLong() * 60000 - time2 = Time(hoursInMillis + minutesInMillis) - val testTime = time.split(" ")[2] - val testHour = testTime.split(":")[0] - val testMinutes = testTime.split(":")[1] - if (testHour < hour) { - Toasty.warning(myContext, "Zeitpunkt nicht im Zeitraum des Einsatzes", Toasty.LENGTH_LONG).show() - return@addOnPositiveButtonClickListener - } else if (testHour == hour && testMinutes < minute) { - Toasty.warning(myContext, "Zeitpunkt nicht im Zeitraum des Einsatzes", Toasty.LENGTH_LONG).show() - return@addOnPositiveButtonClickListener - } - tempTime += "${hour}:${minute}" - clickedTechniker.uhrzeit = tempTime - val tempDauer = DecimalFormat("#.#").format((time2.time - time1.time) / 3600 / 1000.toFloat()) - clickedTechniker.dauer = tempDauer.replace(",", ".") + technikerAdapter = ProjectTechnikerAdapter { + if (adminMode || it.name == sharedPref.getString("name", "")) { + MaterialDialog(myContext) + .show { + title(text = it.name) + val uhrzeit = if (it.uhrzeit == "0") time else it.uhrzeit + message(text = Html.fromHtml("Arbeitszeit:
$uhrzeit Uhr

Wie möchtest du " + + "diesen Eintrag bearbeiten?")) + positiveButton(text = "Arbeitszeit ändern") { _ -> + var tempTime = "" + var time1 = Time(0) + var time2 = Time(0) + val builder = MaterialTimePicker.Builder().setTimeFormat( + TimeFormat.CLOCK_24H).setTitleText("Von") + val builder2 = MaterialTimePicker.Builder().setTimeFormat(TimeFormat.CLOCK_24H).setTitleText("Bis") + val picker = builder.build() + val picker2 = builder2.build() + var hour: String + var minute: String + var hoursInMillis: Long + var minutesInMillis: Long + if (it.uhrzeit != "0") { + val times = it.uhrzeit.split(" - ") + builder.setHour(times[0].split(":")[0].toInt()) + .setMinute(times[0].split(":")[1].toInt()) + builder2.setHour(times[1].split(":")[0].toInt()) + .setMinute(times[1].split(":")[1].toInt()) + } + picker.addOnPositiveButtonClickListener { + hour = picker.hour.toString() + hour = if (hour.length != 1) hour else "0$hour" + minute = picker.minute.toString() + minute = if (minute.length != 1) minute else "0$minute" + hoursInMillis = picker.hour.toLong() * 3600000 + minutesInMillis = picker.minute.toLong() * 60000 + time1 = Time(hoursInMillis + minutesInMillis) + val testTime = time.split(" ")[0] + val testHour = testTime.split(":")[0] + val testMinutes = testTime.split(":")[1] + if (testHour > hour) { + Toasty.warning(myContext, "Zeitpunkt nicht im Zeitraum des Einsatzes", Toasty.LENGTH_LONG).show() + } else if (testHour == hour && testMinutes > minute) { + Toasty.warning(myContext, "Zeitpunkt nicht im Zeitraum des Einsatzes", Toasty.LENGTH_LONG).show() + } else { + tempTime += "${hour}:${minute} - " + activity?.let { it1 -> picker2.show(it1.supportFragmentManager, picker2.tag) } + } + } + picker2.addOnPositiveButtonClickListener { _ -> + hour = picker2.hour.toString() + hour = if (hour.length != 1) hour else "0$hour" + minute = picker2.minute.toString() + minute = if (minute.length != 1) minute else "0$minute" + hoursInMillis = hour.toLong() * 3600000 + minutesInMillis = minute.toLong() * 60000 + time2 = Time(hoursInMillis + minutesInMillis) + val testTime = time.split(" ")[2] + val testHour = testTime.split(":")[0] + val testMinutes = testTime.split(":")[1] + if (testHour < hour) { + Toasty.warning(myContext, "Zeitpunkt nicht im Zeitraum des Einsatzes", Toasty.LENGTH_LONG).show() + return@addOnPositiveButtonClickListener + } else if (testHour == hour && testMinutes < minute) { + Toasty.warning(myContext, "Zeitpunkt nicht im Zeitraum des Einsatzes", Toasty.LENGTH_LONG).show() + return@addOnPositiveButtonClickListener + } + tempTime += "${hour}:${minute}" + it.uhrzeit = tempTime + val tempDauer = DecimalFormat("#.#").format((time2.time - time1.time) / 3600 / 1000.toFloat()) + it.dauer = tempDauer.replace(",", ".") - if (clickedTechniker.teilnahmeKey != "0") { - val dauerFloat = clickedTechniker.dauer.toFloat() - ParseObject.createWithoutData("Teilnahme", clickedTechniker.teilnahmeKey).apply { - put("dauer", dauerFloat) - put("uhrzeit", clickedTechniker.uhrzeit) - saveInBackground() - } - } else { - val query = ParseQuery.getQuery("Teilnahme") - query.whereEqualTo("von", ParseObject.createWithoutData("Techniker", clickedTechniker.key)) - query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", objectId)) - query.getFirstInBackground { obj, e -> - if (e == null) { - clickedTechniker.teilnahmeKey = obj.objectId - val dauerFloat = clickedTechniker.dauer.toFloat() - ParseObject.createWithoutData("Teilnahme", clickedTechniker.teilnahmeKey).apply { - put("dauer", dauerFloat) - put("uhrzeit", clickedTechniker.uhrzeit) - saveInBackground() - } - adapter.notifyDataSetChanged() - binding.recyclerView.scheduleLayoutAnimation() - } else { - Toasty.error(myContext, "Fehler bei Techniker-Abfrage").show() - Log.e("TechnikLogger.TechSuche", e.message.toString()) - } - } - } - - adapter.notifyDataSetChanged() - binding.recyclerView.scheduleLayoutAnimation() - } - activity?.let { it1 -> picker.show(it1.supportFragmentManager, picker.tag) } + if (it.teilnahmeKey != "0") { + val dauerFloat = it.dauer.toFloat() + ParseObject.createWithoutData("Teilnahme", it.teilnahmeKey).apply { + put("dauer", dauerFloat) + put("uhrzeit", it.uhrzeit) + saveInBackground() } - negativeButton(text = "Entfernen") { - techniker.remove(clickedTechniker) - if (clickedTechniker.teilnahmeKey != "0") { - ParseObject.createWithoutData ("Teilnahme", clickedTechniker.teilnahmeKey).deleteInBackground() { - adapter.notifyDataSetChanged() - binding.recyclerView.scheduleLayoutAnimation() - binding.technikerView.text = "Techniker: ${techniker.size}" + } else { + val query = ParseQuery.getQuery("Teilnahme") + query.whereEqualTo("von", ParseObject.createWithoutData("Techniker", it.objectId)) + query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", objectId)) + query.getFirstInBackground { obj, e -> + if (e == null) { + it.teilnahmeKey = obj.objectId + val dauerFloat = it.dauer.toFloat() + ParseObject.createWithoutData("Teilnahme", it.teilnahmeKey).apply { + put("dauer", dauerFloat) + put("uhrzeit", it.uhrzeit) + saveInBackground() } + technikerAdapter.submitList(techniker) } else { - val query = ParseQuery.getQuery("Teilnahme") - query.whereEqualTo("von", ParseObject.createWithoutData("Techniker", clickedTechniker.key)) - query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", objectId)) - query.getFirstInBackground { obj, e -> - if (e == null) { - obj.deleteInBackground() { - if (it == null) { - adapter.notifyDataSetChanged() - binding.recyclerView.scheduleLayoutAnimation() - binding.technikerView.text = "Techniker: ${techniker.size}" - } else { - Toasty.error(myContext, "Fehler bei Techniker-Löschung").show() - Log.e("TechnikLogger.TechLösch", it.message.toString()) - } - } - } else { - Toasty.error(myContext, "Fehler bei Techniker-Abfrage").show() - Log.e("TechnikLogger.TechSuche", e.message.toString()) - } - } + Toasty.error(myContext, "Fehler bei Techniker-Abfrage").show() + Log.e("TechnikLogger.TechSuche", e.message.toString()) } - if (techniker.size == 0) showDivider(false) } } + + technikerAdapter.submitList(techniker) + } + activity?.let { it1 -> picker.show(it1.supportFragmentManager, picker.tag) } + } + negativeButton(text = "Entfernen") { _ -> + techniker.remove(it) + if (it.teilnahmeKey != "0") { + ParseObject.createWithoutData ("Teilnahme", it.teilnahmeKey).deleteInBackground() { + technikerAdapter.submitList(techniker) + binding.technikerView.text = "Techniker: ${techniker.size}" + } + } else { + val query = ParseQuery.getQuery("Teilnahme") + query.whereEqualTo("von", ParseObject.createWithoutData("Techniker", it.objectId)) + query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", objectId)) + query.getFirstInBackground { obj, e -> + if (e == null) { + obj.deleteInBackground { + if (it == null) { + technikerAdapter.submitList(techniker) + binding.technikerView.text = "Techniker: ${techniker.size}" + } else { + Toasty.error(myContext, "Fehler bei Techniker-Löschung").show() + Log.e("TechnikLogger.TechLösch", it.message.toString()) + } + } + } else { + Toasty.error(myContext, "Fehler bei Techniker-Abfrage").show() + Log.e("TechnikLogger.TechSuche", e.message.toString()) + } + } + } + if (techniker.size == 0) showDivider(false) } } - } - ) + } } loadData() - adapter.submitList(techniker as List?) + technikerAdapter.submitList(techniker as List?) binding.recyclerView.layoutManager = LinearLayoutManager(myContext) - binding.recyclerView.adapter = adapter + binding.recyclerView.adapter = technikerAdapter binding.addButton.setOnClickListener { val name = sharedPref.getString("name", "invalid")!! @@ -235,7 +220,7 @@ class ProjectFragment : Fragment() { if (e == null) { ParseObject.deleteAllInBackground(objects) techniker.clear() - adapter.notifyDataSetChanged() + technikerAdapter.submitList(techniker) showDivider(false) binding.technikerView.text = "Techniker: 0" } else { @@ -249,15 +234,19 @@ class ProjectFragment : Fragment() { } } - binding.swipeRefreshLayout.setOnRefreshListener { - binding.titleView.text = "" - binding.dateView.text = "" - binding.locationView.text = "" - techniker.clear() - adapter.notifyDataSetChanged() - showDivider(false) - binding.technikerView.text = "Techniker: 0" - loadData() + binding.swipeRefreshLayout.apply { + setProgressBackgroundColorSchemeResource(R.color.refreshLayoutBackground) + setColorSchemeResources(R.color.refreshLayoutArrow) + setOnRefreshListener { + binding.titleView.text = "" + binding.dateView.text = "" + binding.locationView.text = "" + techniker.clear() + technikerAdapter.submitList(techniker) + showDivider(false) + binding.technikerView.text = "Techniker: 0" + loadData() + } } return root @@ -288,17 +277,16 @@ class ProjectFragment : Fragment() { val dauerEntry = it.getNumber("dauer")!! val dauer = if (dauerEntry == 0) einsatz.getNumber("dauer")!!.toString() else dauerEntry.toString() val time = it.getString("uhrzeit")!! - techniker.add(ProjectTechnikerViewState.ProjectTechniker( + techniker.add(ProjectTechniker( + dauer, teilnehmenderTechniker.getString("name")!!, teilnehmenderTechniker.objectId, it.objectId, - dauer, time )) } techniker.sortBy { it.name } - binding.recyclerView.scheduleLayoutAnimation() - adapter.notifyDataSetChanged() + technikerAdapter.submitList(techniker) binding.technikerView.text = "Techniker: ${techniker.size}" showDivider() } @@ -412,14 +400,19 @@ class ProjectFragment : Fragment() { entryObject.put("von", it) entryObject.put("an", project) entryList.add(entryObject) - techniker.add(ProjectTechnikerViewState.ProjectTechniker(it.getString("name")!!, it.objectId, "0", dauer, time)) + techniker.add(ProjectTechniker( + dauer, + it.getString("name")!!, + it.objectId, + "0", + time + )) } ParseObject.saveAllInBackground(entryList) { if (it == null) { techniker.sortBy { it.name } - adapter.notifyDataSetChanged() + technikerAdapter.submitList(techniker) showDivider(true) - binding.recyclerView.scheduleLayoutAnimation() binding.technikerView.text = "Techniker: ${techniker.size}" } else { Toasty.error(myContext, "Fehler bei Techniker-Suche").show() diff --git a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechniker.kt b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechniker.kt new file mode 100644 index 0000000..9898821 --- /dev/null +++ b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechniker.kt @@ -0,0 +1,9 @@ +package com.cyb3rko.techniklogger.recycler + +data class ProjectTechniker( + var dauer: String, + val name: String, + val objectId: String, + var teilnahmeKey: String, + var uhrzeit: String +) diff --git a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerAdapter.kt b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerAdapter.kt new file mode 100644 index 0000000..abdf54d --- /dev/null +++ b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerAdapter.kt @@ -0,0 +1,48 @@ +package com.cyb3rko.techniklogger.recycler + +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.cyb3rko.techniklogger.R + +class ProjectTechnikerAdapter( + val action: (techniker: ProjectTechniker) -> Unit +) : ListAdapter(ProjectTechnikerDiffCallback) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_recycler_techniker, parent, false) + + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val entry = getItem(position) + val title = "${entry.name}, ${entry.dauer} h" + holder.titleView.text = title + holder.titleView.setOnClickListener { + action(entry) + } + } + + class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val titleView: TextView = view.findViewById(R.id.title) + } + + object ProjectTechnikerDiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: ProjectTechniker, newItem: ProjectTechniker): Boolean { + return oldItem.objectId == newItem.objectId + } + + override fun areContentsTheSame(oldItem: ProjectTechniker, newItem: ProjectTechniker): Boolean { + return oldItem.dauer == newItem.dauer && + oldItem.name == newItem.name && + oldItem.teilnahmeKey == newItem.teilnahmeKey && + oldItem.uhrzeit == newItem.uhrzeit + } + } +} diff --git a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerViewHolder.kt b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerViewHolder.kt deleted file mode 100644 index b8bae68..0000000 --- a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerViewHolder.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.cyb3rko.techniklogger.recycler - -import android.view.View -import android.widget.TextView - -import com.cyb3rko.techniklogger.R - -import me.ibrahimyilmaz.kiel.core.RecyclerViewHolder - -class ProjectTechnikerViewHolder(view: View) : RecyclerViewHolder(view) { - val textView: TextView = view.findViewById(R.id.title) -} diff --git a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerViewState.kt b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerViewState.kt deleted file mode 100644 index 7e8d57b..0000000 --- a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectTechnikerViewState.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.cyb3rko.techniklogger.recycler - -sealed class ProjectTechnikerViewState { - - data class ProjectTechniker( - val name: String, - val key: String, - var teilnahmeKey: String, - var dauer: String, - var uhrzeit: String - ) : ProjectTechnikerViewState() -}