diff --git a/app/src/main/java/com/cyb3rko/techniklogger/Utils.kt b/app/src/main/java/com/cyb3rko/techniklogger/Utils.kt index 77709be..68adfc7 100644 --- a/app/src/main/java/com/cyb3rko/techniklogger/Utils.kt +++ b/app/src/main/java/com/cyb3rko/techniklogger/Utils.kt @@ -9,7 +9,11 @@ import com.afollestad.materialdialogs.input.input internal const val CURRENT_YEAR = "current_year" internal const val CURRENT_YEAR_NAME = "current_year_name" -internal const val COLUMN_JAHR = "jahr" +internal const val COLUMN_EINSATZ_DATUM = "datum" +internal const val COLUMN_EINSATZ_DAUER = "dauer" +internal const val COLUMN_EINSATZ_JAHR = "jahr" +internal const val COLUMN_EINSATZ_NAME = "name" +internal const val COLUMN_EINSATZ_ORT = "ort" internal const val COLUMN_JAHR_NAME = "name" internal const val COLUMN_TECHNIKER_NAME = "name" internal const val SHARED_PREFERENCE = "Safe" diff --git a/app/src/main/java/com/cyb3rko/techniklogger/fragments/EinsatzPusherFragment.kt b/app/src/main/java/com/cyb3rko/techniklogger/fragments/EinsatzPusherFragment.kt index 6730aaa..e724dd9 100644 --- a/app/src/main/java/com/cyb3rko/techniklogger/fragments/EinsatzPusherFragment.kt +++ b/app/src/main/java/com/cyb3rko/techniklogger/fragments/EinsatzPusherFragment.kt @@ -170,7 +170,7 @@ class EinsatzPusherFragment : Fragment() { } private fun getArgumentInformation() { - childKey = args.childKey + childKey = args.objectId name = args.name location = args.location date = args.date diff --git a/app/src/main/java/com/cyb3rko/techniklogger/fragments/ListingFragment.kt b/app/src/main/java/com/cyb3rko/techniklogger/fragments/ListingFragment.kt index 5ec64d5..4da760e 100644 --- a/app/src/main/java/com/cyb3rko/techniklogger/fragments/ListingFragment.kt +++ b/app/src/main/java/com/cyb3rko/techniklogger/fragments/ListingFragment.kt @@ -10,27 +10,23 @@ import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController import androidx.recyclerview.widget.LinearLayoutManager import com.cyb3rko.techniklogger.* -import com.cyb3rko.techniklogger.COLUMN_JAHR -import com.cyb3rko.techniklogger.CURRENT_YEAR import com.cyb3rko.techniklogger.databinding.FragmentListingBinding -import com.cyb3rko.techniklogger.recycler.ProjectEntryViewHolder -import com.cyb3rko.techniklogger.recycler.ProjectViewState -import com.cyb3rko.techniklogger.showNameDialog +import com.cyb3rko.techniklogger.recycler.ProjectEntry +import com.cyb3rko.techniklogger.recycler.ProjectsAdapter import com.cyb3rko.techniklogger.table.ExportBuilder import com.parse.ParseObject import com.parse.ParseQuery import es.dmoral.toasty.Toasty import java.text.SimpleDateFormat import java.util.* -import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter -import me.ibrahimyilmaz.kiel.core.RecyclerViewHolder class ListingFragment : Fragment() { private var _binding: FragmentListingBinding? = null private lateinit var myContext: Context private var adminMode: Boolean? = null - private val data: MutableList = mutableListOf() + private lateinit var projectsAdapter: ProjectsAdapter + private val data: MutableList = mutableListOf() private var isFABOpen = false private lateinit var sharedPref: SharedPreferences private lateinit var sharedPrefEditor: SharedPreferences.Editor @@ -54,58 +50,36 @@ class ListingFragment : Fragment() { binding.loadingAnimation.playAnimation() - val adapter = RecyclerViewAdapter.adapterOf { - register( - layoutResource = R.layout.item_recycler_projects, - viewHolder = ::ProjectEntryViewHolder, - onBindBindViewHolder = { vh, _, text -> - vh.textView.text = text.text - vh.locationView.text = text.location - if (text.duration != "null") { - vh.dateView.text = "${SimpleDateFormat("dd.MM.yyyy", Locale.GERMANY).format(text.date)}, ${text.duration} h" - } else { - vh.dateView.text = SimpleDateFormat("dd.MM.yyyy", Locale.GERMANY).format(text.date) - } - vh.itemView.setOnClickListener { - val action = ListingFragmentDirections.navigateToProject(childKey = text.childKey) - findNavController().navigate(action) - } - vh.itemView.setOnLongClickListener { - if (adminMode != null && adminMode!!) { - val action = ListingFragmentDirections.navigateToPusher( - childKey = text.childKey, - name = text.text, - location = text.location, - date = SimpleDateFormat("dd.MM.yyyy", Locale.GERMANY).format(text.date), - time = text.time, - duration = text.duration - ) - findNavController().navigate(action) - true - } else false - } - } - ) + projectsAdapter = ProjectsAdapter({ objectId: String -> + val action = ListingFragmentDirections.navigateToProject(objectId) + findNavController().navigate(action) + }, { + if (adminMode != null && adminMode!!) { + val action = ListingFragmentDirections.navigateToPusher( + date = SimpleDateFormat("dd.MM.yyyy", Locale.GERMANY).format(it.date), + duration = it.duration, + location = it.location, + name = it.name, + objectId = it.objectId, + time = it.time + ) + findNavController().navigate(action) + true + } else false + }) + + binding.recyclerView.apply { + layoutManager = LinearLayoutManager(myContext) + adapter = projectsAdapter } - adapter.submitList(data as List?) - val linearLayoutManager = LinearLayoutManager(myContext) - linearLayoutManager.reverseLayout = true - linearLayoutManager.stackFromEnd = true - binding.recyclerView.layoutManager = linearLayoutManager - binding.recyclerView.adapter = adapter - - loadEntries(adapter) + loadEntries() binding.swipeRefreshLayout.apply { setProgressBackgroundColorSchemeResource(R.color.refreshLayoutBackground) setColorSchemeResources(R.color.refreshLayoutArrow) setOnRefreshListener { - isRefreshing = false - showAnimation(true) - data.clear() - adapter.notifyDataSetChanged() - loadEntries(adapter) + loadEntries() } } @@ -146,12 +120,13 @@ class ListingFragment : Fragment() { (requireActivity() as MainActivity).setActionBarSubtitle(null) } - private fun loadEntries(adapter: RecyclerViewAdapter>) { - data.clear() + private fun loadEntries() { val query = ParseQuery.getQuery("Einsatz") - query.limit = 100000 + query.limit = -1 + query.cachePolicy = ParseQuery.CachePolicy.CACHE_THEN_NETWORK + query.orderByDescending(COLUMN_EINSATZ_DATUM) query.whereEqualTo( - COLUMN_JAHR, + COLUMN_EINSATZ_JAHR, ParseObject.createWithoutData( "Jahr", sharedPref.getString(CURRENT_YEAR, "") @@ -161,26 +136,27 @@ class ListingFragment : Fragment() { query.findInBackground { objects, e -> if (e == null) { objects.forEach { - val dates = it["datum"].toString().split(",") + val dates = it.getString(COLUMN_EINSATZ_DATUM)!!.split(",") val time = if (dates.size > 1) dates[1] else "" - data.add(data.size, ProjectViewState.ProjectEntry( - it.objectId, - it["name"].toString(), - it["ort"].toString(), + data.add(data.size, ProjectEntry( SimpleDateFormat("yyyy.MM.dd", Locale.GERMANY).parse(dates[0])!!, - time, - it["dauer"].toString() + it.getInt(COLUMN_EINSATZ_DAUER).toString(), + it.getString(COLUMN_EINSATZ_ORT)!!, + it.getString(COLUMN_EINSATZ_NAME)!!, + it.objectId, + time )) } - data.sortBy { it.date } showAnimation(false) - adapter.notifyDataSetChanged() - binding.recyclerView.scheduleLayoutAnimation() - binding.recyclerView.scrollBy(0, -10000) + binding.swipeRefreshLayout.isRefreshing = false + projectsAdapter.submitList(data) (requireActivity() as MainActivity).setActionBarSubtitle(objects.size.toString()) } else { - showAnimation(true, false) + binding.swipeRefreshLayout.isRefreshing = false + if (data.isEmpty()) { + showAnimation(true, false) + } Toasty.error(myContext, "Abruf fehlgeschlagen", Toasty.LENGTH_SHORT).show() Log.e("TechnikLogger.EinsSuche", e.message.toString()) } 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 3677278..b379b3e 100644 --- a/app/src/main/java/com/cyb3rko/techniklogger/fragments/ProjectFragment.kt +++ b/app/src/main/java/com/cyb3rko/techniklogger/fragments/ProjectFragment.kt @@ -23,11 +23,11 @@ import com.google.android.material.timepicker.TimeFormat import com.parse.ParseObject import com.parse.ParseQuery import es.dmoral.toasty.Toasty -import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter.Companion.adapterOf -import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter -import me.ibrahimyilmaz.kiel.core.RecyclerViewHolder 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() { @@ -37,7 +37,7 @@ class ProjectFragment : Fragment() { private lateinit var adapter: RecyclerViewAdapter> private var adminMode = false - private var childKey = "" + private var objectId = "" private var dauer = "" private lateinit var einsatz: ParseObject private lateinit var sharedPref: SharedPreferences @@ -54,8 +54,8 @@ class ProjectFragment : Fragment() { sharedPref = myContext.getSharedPreferences("Safe", 0) adminMode = sharedPref.getBoolean("admin", false) - childKey = args.childKey - einsatz = ParseObject.createWithoutData("Einsatz", childKey) + objectId = args.objectId + einsatz = ParseObject.createWithoutData("Einsatz", objectId) adapter = adapterOf { register( @@ -143,7 +143,7 @@ class ProjectFragment : Fragment() { } else { val query = ParseQuery.getQuery("Teilnahme") query.whereEqualTo("von", ParseObject.createWithoutData("Techniker", clickedTechniker.key)) - query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", childKey)) + query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", objectId)) query.getFirstInBackground { obj, e -> if (e == null) { clickedTechniker.teilnahmeKey = obj.objectId @@ -178,7 +178,7 @@ class ProjectFragment : Fragment() { } else { val query = ParseQuery.getQuery("Teilnahme") query.whereEqualTo("von", ParseObject.createWithoutData("Techniker", clickedTechniker.key)) - query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", childKey)) + query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", objectId)) query.getFirstInBackground { obj, e -> if (e == null) { obj.deleteInBackground() { @@ -230,7 +230,7 @@ class ProjectFragment : Fragment() { message(text = "Möchtest du alle eingetragenen Techniker entfernen?") positiveButton(text = "Ja") { val query = ParseQuery("Teilnahme") - query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", childKey)) + query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", objectId)) query.findInBackground { objects, e -> if (e == null) { ParseObject.deleteAllInBackground(objects) @@ -265,7 +265,7 @@ class ProjectFragment : Fragment() { private fun loadData() { val query = ParseQuery.getQuery("Einsatz") - query.getInBackground(childKey) { einsatz, e -> + query.getInBackground(objectId) { einsatz, e -> if (e == null) { binding.titleView.text = einsatz["name"].toString() binding.locationView.text = einsatz["ort"].toString() @@ -278,7 +278,7 @@ class ProjectFragment : Fragment() { binding.dateView.text = date + time val query2 = ParseQuery.getQuery("Teilnahme") - query2.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", childKey)) + query2.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", objectId)) query2.include("von") query2.findInBackground { objects2, e2 -> if (e2 == null) { @@ -405,7 +405,7 @@ class ProjectFragment : Fragment() { } private fun addTechniker(newTechniker: List) { - val project = ParseObject.createWithoutData("Einsatz", childKey) + val project = ParseObject.createWithoutData("Einsatz", objectId) val entryList = mutableListOf() newTechniker.forEach { val entryObject = ParseObject("Teilnahme") diff --git a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectEntry.kt b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectEntry.kt new file mode 100644 index 0000000..d4ebdd6 --- /dev/null +++ b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectEntry.kt @@ -0,0 +1,12 @@ +package com.cyb3rko.techniklogger.recycler + +import java.util.* + +data class ProjectEntry( + val date: Date, + val duration: String, + val location: String, + val name: String, + val objectId: String, + val time: String +) diff --git a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectEntryViewHolder.kt b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectEntryViewHolder.kt deleted file mode 100644 index e94062a..0000000 --- a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectEntryViewHolder.kt +++ /dev/null @@ -1,14 +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 ProjectEntryViewHolder(view: View) : RecyclerViewHolder(view) { - val locationView: TextView = view.findViewById(R.id.item_location) - val dateView: TextView = view.findViewById(R.id.item_date) - val textView: TextView = view.findViewById(R.id.item_text) -} diff --git a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectEntryViewState.kt b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectEntryViewState.kt deleted file mode 100644 index acf40c1..0000000 --- a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectEntryViewState.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.cyb3rko.techniklogger.recycler - -import java.util.* - -sealed class ProjectViewState { - - data class ProjectEntry( - val childKey: String, - val text: String, - val location: String, - val date: Date, - val time: String, - val duration: String - ) : ProjectViewState() -} diff --git a/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectsAdapter.kt b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectsAdapter.kt new file mode 100644 index 0000000..a3fec1d --- /dev/null +++ b/app/src/main/java/com/cyb3rko/techniklogger/recycler/ProjectsAdapter.kt @@ -0,0 +1,65 @@ +package com.cyb3rko.techniklogger.recycler + +import android.annotation.SuppressLint +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 +import java.text.SimpleDateFormat +import java.util.* + +class ProjectsAdapter( + val action: (objectId: String) -> Unit, + val actionLong: (project: ProjectEntry) -> Boolean +) : ListAdapter(ProjectDiffCallback) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + val view = LayoutInflater.from(parent.context) + .inflate(R.layout.item_recycler_projects, parent, false) + + return ViewHolder(view) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val entry = getItem(position) + holder.textView.text = entry.name + holder.locationView.text = entry.location + if (entry.duration != "null") { + val date = SimpleDateFormat("dd.MM.yyyy", Locale.GERMANY).format(entry.date) + @SuppressLint("SetTextI18n") + holder.dateView.text = "${date}, ${entry.duration} h" + } else { + val date = SimpleDateFormat("dd.MM.yyyy", Locale.GERMANY).format(entry.date) + holder.dateView.text = date + } + holder.itemView.setOnClickListener { + action(entry.objectId) + } + holder.itemView.setOnLongClickListener { + return@setOnLongClickListener actionLong(entry) + } + } + + class ViewHolder(view: View) : RecyclerView.ViewHolder(view) { + val locationView: TextView = view.findViewById(R.id.item_location) + val dateView: TextView = view.findViewById(R.id.item_date) + val textView: TextView = view.findViewById(R.id.item_text) + } + + object ProjectDiffCallback : DiffUtil.ItemCallback() { + override fun areItemsTheSame(oldItem: ProjectEntry, newItem: ProjectEntry): Boolean { + return oldItem.objectId == newItem.objectId + } + + override fun areContentsTheSame(oldItem: ProjectEntry, newItem: ProjectEntry): Boolean { + return oldItem.date == newItem.date && + oldItem.duration == newItem.duration && + oldItem.location == newItem.location && + oldItem.name == newItem.name + } + } +} diff --git a/app/src/main/java/com/cyb3rko/techniklogger/table/ExportBuilder.kt b/app/src/main/java/com/cyb3rko/techniklogger/table/ExportBuilder.kt index 02f8f2e..8c69950 100644 --- a/app/src/main/java/com/cyb3rko/techniklogger/table/ExportBuilder.kt +++ b/app/src/main/java/com/cyb3rko/techniklogger/table/ExportBuilder.kt @@ -7,7 +7,7 @@ import android.util.Log import android.view.View import androidx.core.content.FileProvider import com.cyb3rko.techniklogger.databinding.FragmentListingBinding -import com.cyb3rko.techniklogger.recycler.ProjectViewState +import com.cyb3rko.techniklogger.recycler.ProjectEntry import com.itextpdf.text.* import com.itextpdf.text.pdf.PdfPTable import com.itextpdf.text.pdf.PdfWriter @@ -24,7 +24,7 @@ import java.util.* class ExportBuilder( private val myContext: Context, - data: MutableList, + data: MutableList, private val binding: FragmentListingBinding ) : Document(PageSize.A4.rotate()) { private val destination = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString() + "/" @@ -78,7 +78,7 @@ class ExportBuilder( private fun fetchTechniker(index: Int) { if (index < data.size) { val query = ParseQuery.getQuery("Teilnahme") - query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", data[index].childKey)) + query.whereEqualTo("an", ParseObject.createWithoutData("Einsatz", data[index].objectId)) query.include("von") query.findInBackground { objects, e -> if (e == null) { @@ -101,7 +101,7 @@ class ExportBuilder( data.forEachIndexed { index, projectEntry -> val information = listOf( SimpleDateFormat("dd.MM.yyyy", Locale.GERMANY).format(projectEntry.date), - projectEntry.text, + projectEntry.name, techniker[index].joinToString("\n"), projectEntry.duration) information.forEachIndexed { index2, string -> diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 4eae556..6cb8642 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -29,7 +29,7 @@ android:label="Einsatz" tools:layout="@layout/fragment_project" > + + + android:defaultValue="" /> - + android:defaultValue="" /> - + android:defaultValue="" />