diff --git a/app/build.gradle b/app/build.gradle
index 865a42e..4a1726f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,6 +4,7 @@ apply plugin: 'kotlin-android-extensions'
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.mikepenz.aboutlibraries.plugin'
+apply plugin: "androidx.navigation.safeargs.kotlin"
android {
signingConfigs {
@@ -50,6 +51,9 @@ android {
kotlinOptions {
jvmTarget = '1.8'
}
+ buildFeatures {
+ viewBinding true
+ }
packagingOptions {
pickFirst'META-INF/library_release.kotlin_module'
}
@@ -60,6 +64,9 @@ dependencies {
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.cardview:cardview:1.0.0'
implementation 'androidx.core:core-ktx:1.3.2'
+ implementation "androidx.multidex:multidex:2.0.1"
+ implementation 'androidx.navigation:navigation-fragment-ktx:2.3.4'
+ implementation 'androidx.navigation:navigation-ui-ktx:2.3.4'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.afollestad.material-dialogs:input:3.3.0'
implementation 'com.airbnb.android:lottie:3.4.2'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b57f0b9..5e38d6d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -24,14 +24,10 @@
-
-
diff --git a/app/src/main/java/com/cyb3rko/techniklogger/MainActivity.kt b/app/src/main/java/com/cyb3rko/techniklogger/MainActivity.kt
index bd3d4c4..c6b8201 100644
--- a/app/src/main/java/com/cyb3rko/techniklogger/MainActivity.kt
+++ b/app/src/main/java/com/cyb3rko/techniklogger/MainActivity.kt
@@ -7,39 +7,46 @@ import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
-import android.view.View
import androidx.appcompat.app.AppCompatActivity
-import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.navigation.findNavController
+import androidx.navigation.ui.AppBarConfiguration
+import androidx.navigation.ui.setupActionBarWithNavController
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.input.getInputField
import com.afollestad.materialdialogs.input.input
import com.androidnetworking.AndroidNetworking
import com.androidnetworking.error.ANError
import com.androidnetworking.interfaces.StringRequestListener
-import com.cyb3rko.techniklogger.recycler.ProjectEntryViewHolder
-import com.cyb3rko.techniklogger.recycler.ProjectViewState
+import com.cyb3rko.techniklogger.databinding.ActivityMainBinding
+import com.cyb3rko.techniklogger.databinding.FragmentListingBinding
+import com.cyb3rko.techniklogger.fragments.EinsatzPusherFragment
import com.cyb3rko.techniklogger.utils.About
import com.parse.ParseObject
import com.parse.ParseQuery
import es.dmoral.toasty.Toasty
-import kotlinx.android.synthetic.main.activity_main.*
-import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter
-import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter.Companion.adapterOf
-import me.ibrahimyilmaz.kiel.core.RecyclerViewHolder
-import java.text.SimpleDateFormat
import java.util.*
class MainActivity : AppCompatActivity() {
+ private var _binding: ActivityMainBinding? = null
- private var adminMode = false
- private val data: MutableList = mutableListOf()
private lateinit var sharedPref: SharedPreferences
private lateinit var sharedPrefEditor: SharedPreferences.Editor
+ // This property is only valid between onCreateView and onDestroyView.
+ private val binding get() = _binding!!
+
@SuppressLint("SetTextI18n")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
+ // This property is only valid between onCreateView and onDestroyView.
+ _binding = ActivityMainBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ val navController = findNavController(R.id.nav_host_fragment_activity_main)
+ // Passing each menu ID as a set of Ids because each
+ // menu should be considered as top level destinations.
+ val appBarConfiguration = AppBarConfiguration(setOf(R.id.navigation_listing))
+ setupActionBarWithNavController(navController, appBarConfiguration)
sharedPref = getSharedPreferences("Safe", 0)
sharedPrefEditor = sharedPref.edit()
@@ -47,56 +54,8 @@ class MainActivity : AppCompatActivity() {
if (sharedPref.getString("name", "") == "") {
showNameDialog()
- } else {
- updateAdminStatus()
}
- loading_animation.playAnimation()
-
- val adapter = 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 {
- ProjectActivityBuilder(applicationContext)
- .setKey(text.childKey)
- .start()
- }
- vh.itemView.setOnLongClickListener {
- if (adminMode) {
- val intent = Intent(applicationContext, EinsatzPusher::class.java)
- intent.putExtra("childKey", text.childKey)
- intent.putExtra("name", text.text)
- intent.putExtra("location", text.location)
- intent.putExtra("date", SimpleDateFormat("dd.MM.yyyy", Locale.GERMANY).format(text.date))
- intent.putExtra("time", text.time)
- intent.putExtra("duration", text.duration)
- intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
- startActivity(intent)
- true
- } else false
- }
- }
- )
- }
-
- adapter.submitList(data as List?)
- val linearLayoutManager = LinearLayoutManager(applicationContext)
- linearLayoutManager.reverseLayout = true
- linearLayoutManager.stackFromEnd = true
- recycler_view.layoutManager = linearLayoutManager
- recycler_view.adapter = adapter
-
- loadEntries(adapter)
-
updateCheck()
}
@@ -116,82 +75,12 @@ class MainActivity : AppCompatActivity() {
}
positiveButton(0, "Speichern") {
- sharedPref.edit().putString("name", inputName.toString()).apply()
- updateAdminStatus()
- }
- }
- }
- }
-
- private fun loadEntries(adapter: RecyclerViewAdapter>) {
- val query = ParseQuery.getQuery("Einsatz")
- query.limit = 100000
-
- query.findInBackground { objects, e ->
- if (e == null) {
- objects.forEach {
- val dates = it["datum"].toString().split(",")
- val time = if (dates.size > 1) dates[1] else ""
- data.add(data.size, ProjectViewState.ProjectEntry(
- it.objectId,
- it["name"].toString(),
- it["ort"].toString(),
- SimpleDateFormat("yyyy.MM.dd", Locale.GERMANY).parse(dates[0])!!,
- time,
- it["dauer"].toString()
- ))
- }
-
- data.sortBy { it.date }
- hideProgress()
- adapter.notifyDataSetChanged()
- recycler_view.scheduleLayoutAnimation()
- recycler_view.scrollBy(0, -10000)
- } else {
- Toasty.error(applicationContext, "Abruf fehlgeschlagen", Toasty.LENGTH_SHORT).show()
- Log.e("TechnikLogger.EinsSuche", e.message.toString())
- }
- }
- }
-
- private fun hideProgress() {
- loading_animation.visibility = View.GONE
- loading_animation.cancelAnimation()
- }
-
- private fun updateAdminStatus() {
- val query = ParseQuery.getQuery("Techniker")
- query.whereEqualTo("name", sharedPref.getString("name", ""))
- query.getFirstInBackground { techniker, e ->
- if (e == null) {
- if (techniker.getBoolean("admin")) {
- adminMode = true
- sharedPrefEditor.putBoolean("admin", adminMode)
- sharedPrefEditor.putString("technikerId", techniker.objectId).apply()
- floatingActionButton.show()
- floatingActionButton.setOnClickListener {
- startActivity(Intent(applicationContext, EinsatzPusher::class.java))
+ sharedPref.edit().putString("name", inputName.toString()).commit()
finish()
+ startActivity(Intent(applicationContext, MainActivity::class.java))
}
- } else {
- adminMode = false
- sharedPrefEditor.putBoolean("admin", adminMode).apply()
- floatingActionButton.hide()
}
- } else {
- floatingActionButton.hide()
- adminMode = false
- sharedPrefEditor.putBoolean("admin", adminMode).apply()
- Toasty.error(applicationContext, "Adminstatus unbekannt", Toasty.LENGTH_SHORT).show()
- Log.e("TechnikLogger.TechSuche", e.message.toString())
}
- }
- }
-
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- // Inflate the menu; this adds items to the action bar if it is present.
- menuInflater.inflate(R.menu.menu_main, menu)
- return true
}
private fun updateCheck() {
@@ -211,13 +100,23 @@ class MainActivity : AppCompatActivity() {
})
}
+ override fun onSupportNavigateUp(): Boolean {
+ val navController = findNavController(R.id.nav_host_fragment_activity_main)
+ return navController.navigateUp() || super.onSupportNavigateUp()
+ }
+
+ override fun onCreateOptionsMenu(menu: Menu): Boolean {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ menuInflater.inflate(R.menu.menu_main, menu)
+ return true
+ }
+
override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
when (item.itemId) {
R.id.action_rename -> showNameDialog()
- R.id.action_admin -> updateAdminStatus()
R.id.action_about -> startActivity(Intent(applicationContext, About::class.java))
// R.id.action_privacy_policy ->
// R.id.action_terms_of_use ->
diff --git a/app/src/main/java/com/cyb3rko/techniklogger/ProjectActivityBuilder.kt b/app/src/main/java/com/cyb3rko/techniklogger/ProjectActivityBuilder.kt
deleted file mode 100644
index fb38d9f..0000000
--- a/app/src/main/java/com/cyb3rko/techniklogger/ProjectActivityBuilder.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.cyb3rko.techniklogger
-
-import android.content.Context
-import android.content.Intent
-
-class ProjectActivityBuilder(private val context: Context) {
-
- private var childKey = ""
-
- fun setKey(childKey: String): ProjectActivityBuilder {
- this.childKey = childKey
- return this
- }
-
- fun start() {
- val intent = Intent(context, ProjectActivity::class.java)
- intent.putExtra("childKey", childKey)
- intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
- context.startActivity(intent)
- }
-}
diff --git a/app/src/main/java/com/cyb3rko/techniklogger/EinsatzPusher.kt b/app/src/main/java/com/cyb3rko/techniklogger/fragments/EinsatzPusherFragment.kt
similarity index 53%
rename from app/src/main/java/com/cyb3rko/techniklogger/EinsatzPusher.kt
rename to app/src/main/java/com/cyb3rko/techniklogger/fragments/EinsatzPusherFragment.kt
index b0c2dcc..5ef2a0a 100644
--- a/app/src/main/java/com/cyb3rko/techniklogger/EinsatzPusher.kt
+++ b/app/src/main/java/com/cyb3rko/techniklogger/fragments/EinsatzPusherFragment.kt
@@ -1,26 +1,33 @@
-package com.cyb3rko.techniklogger
+package com.cyb3rko.techniklogger.fragments
-import android.annotation.SuppressLint
-import android.content.Intent
+import android.content.Context
import android.os.Bundle
import android.text.Html
import android.text.SpannableStringBuilder
-import android.view.MenuItem
+import android.util.Log
+import android.view.LayoutInflater
import android.view.View
-import androidx.appcompat.app.AppCompatActivity
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.findNavController
+import androidx.navigation.fragment.navArgs
import com.afollestad.materialdialogs.MaterialDialog
+import com.cyb3rko.techniklogger.R
+import com.cyb3rko.techniklogger.databinding.FragmentEinsatzPusherBinding
import com.google.android.material.datepicker.MaterialDatePicker
import com.google.android.material.timepicker.MaterialTimePicker
import com.google.android.material.timepicker.TimeFormat
import com.parse.ParseObject
import es.dmoral.toasty.Toasty
-import kotlinx.android.synthetic.main.activity_einsatz_pusher.*
import java.sql.Time
import java.text.DecimalFormat
import java.text.SimpleDateFormat
import java.util.*
-class EinsatzPusher : AppCompatActivity() {
+class EinsatzPusherFragment : Fragment() {
+ private var _binding: FragmentEinsatzPusherBinding? = null
+ private lateinit var myContext: Context
+ private val args: EinsatzPusherFragmentArgs by navArgs()
private lateinit var childKey: String
private var date = ""
@@ -31,28 +38,29 @@ class EinsatzPusher : AppCompatActivity() {
private var duration = ""
private lateinit var location: String
private lateinit var name: String
- private val simpleDateFormat = SimpleDateFormat("dd.MM.yyyy", Locale.GERMANY)
+ private val simpleDateFormat = SimpleDateFormat("dd.MM.yyyy")
- @SuppressLint("SetTextI18n")
- override fun onCreate(savedInstanceState: Bundle?) {
- getBundleInformation()
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_einsatz_pusher)
+ // This property is only valid between onCreateView and onDestroyView.
+ private val binding get() = _binding!!
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ _binding = FragmentEinsatzPusherBinding.inflate(inflater, container, false)
+ val root = binding.root
+ myContext = requireContext()
+
+ getArgumentInformation()
restoreInformation()
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
-
val builder = MaterialDatePicker.Builder.datePicker().setTitleText("Datum")
val builder2 = MaterialTimePicker.Builder().setTimeFormat(TimeFormat.CLOCK_24H).setTitleText("Von")
val builder3 = MaterialTimePicker.Builder().setTimeFormat(TimeFormat.CLOCK_24H).setTitleText("Bis")
- date_button.setOnClickListener {
- if (date != "null") {
+ binding.dateButton.setOnClickListener {
+ if (date != "") {
val dateInMillis = simpleDateFormat.parse(date)!!.time
- builder.setSelection(dateInMillis + 3600000)
+ builder.setSelection(dateInMillis + 7200000)
}
- if (time != "null") {
+ if (time != "") {
val times = time.split(" - ")
builder2.setHour(times[0].split(":")[0].toInt())
.setMinute(times[0].split(":")[1].toInt())
@@ -69,8 +77,8 @@ class EinsatzPusher : AppCompatActivity() {
var minutesInMillis: Long
picker.addOnPositiveButtonClickListener {
date = simpleDateFormat.format(Date(it))
- date_view.text = Html.fromHtml("Datum:
${date}")
- picker2.show(supportFragmentManager, picker2.tag)
+ binding.dateView.text = Html.fromHtml("Datum:
${date}")
+ activity?.let { it1 -> picker2.show(it1.supportFragmentManager, picker2.tag) }
}
picker2.addOnPositiveButtonClickListener {
hour = picker2.hour.toString()
@@ -81,7 +89,7 @@ class EinsatzPusher : AppCompatActivity() {
minutesInMillis = picker2.minute.toLong() * 60000
time1 = Time(hoursInMillis + minutesInMillis)
tempTime += "${hour}:${minute} - "
- picker3.show(supportFragmentManager, picker3.tag)
+ activity?.let { it1 -> picker3.show(it1.supportFragmentManager, picker3.tag) }
}
picker3.addOnPositiveButtonClickListener {
hour = picker3.hour.toString()
@@ -95,30 +103,38 @@ class EinsatzPusher : AppCompatActivity() {
time = tempTime
duration = DecimalFormat("#.#").format((time2.time - time1.time) / 3600 / 1000.toFloat())
duration = duration.replace(",", ".")
- duration_view.text = Html.fromHtml("Dauer: $time Uhr, $duration Stunden")
+ binding.durationView.text = Html.fromHtml("Dauer: $time Uhr, $duration Stunden")
}
- picker.show(supportFragmentManager, picker.tag)
+ activity?.let { it1 -> picker.show(it1.supportFragmentManager, picker.tag) }
}
- if (childKey != "null") {
- delete_button.visibility = View.VISIBLE
- delete_button.setOnClickListener {
- MaterialDialog(this)
+ if (childKey != "") {
+ binding.deleteButton.visibility = View.VISIBLE
+ binding.deleteButton.setOnClickListener {
+ MaterialDialog(myContext)
.show {
message(0, "Möchtest du diesen Einsatz entfernen?")
positiveButton(0, "Ja") {
- entry.deleteInBackground()
+ entry.deleteInBackground {
+ if (it == null) {
+ findNavController().navigate(R.id.navigation_listing)
+ } else {
+ Toasty.error(myContext, "Fehler bei Löschung").show()
+ Log.e("TechnikLogger.Einsätze", it.message.toString())
+ }
+ }
+
}
negativeButton(0, "Abbrechen")
}
}
}
- finished_button.setOnClickListener {
- val name = nameEditText.text.toString()
- val location = locationEditText.text.toString()
+ binding.finishedButton.setOnClickListener {
+ val name = binding.nameEditText.text.toString()
+ val location = binding.locationEditText.text.toString()
- if (name != "" && location != "" && time != "null") {
+ if (name != "" && location != "" && time != "") {
entry.put("name", name)
entry.put("ort", location)
val dateTimes = date.split(".")
@@ -126,66 +142,54 @@ class EinsatzPusher : AppCompatActivity() {
if (time != "") dateTime += ",$time"
entry.put("datum", dateTime)
entry.put("dauer", duration.toFloat())
- if (childKey == "null") {
+ if (childKey == "") {
entry.put("techniker", listOf())
}
- entry.saveInBackground()
- finish()
- startActivity(Intent(applicationContext, MainActivity::class.java))
+ entry.saveInBackground() {
+ if (it == null) {
+ findNavController().navigate(R.id.navigation_listing)
+ } else {
+ Toasty.error(myContext, "Fehler bei Speicherung").show()
+ Log.e("TechnikLogger.Einsätze", it.message.toString())
+ }
+ }
} else {
- Toasty.error(applicationContext, "Fülle zuerst alle Felder aus").show()
+ Toasty.error(myContext, "Fülle zuerst alle Felder aus").show()
}
}
+
+ return root
}
- private fun getBundleInformation() {
- childKey = intent.extras?.getString("childKey").toString()
- name = intent.extras?.getString("name").toString()
- location = intent.extras?.getString("location").toString()
- date = intent.extras?.getString("date").toString()
- time = intent.extras?.getString("time").toString()
- duration = intent.extras?.getString("duration").toString()
+ private fun getArgumentInformation() {
+ childKey = args.childKey
+ name = args.name
+ location = args.location
+ date = args.date
+ time = args.time
+ duration = args.duration
}
private fun restoreInformation() {
- if (name != "null") {
- nameEditText.text = SpannableStringBuilder(name)
+ if (name != "") {
+ binding.nameEditText.text = SpannableStringBuilder(name)
}
- if (location != "null") {
- locationEditText.text = SpannableStringBuilder(location)
+ if (location != "") {
+ binding.locationEditText.text = SpannableStringBuilder(location)
}
- if (date != "null") {
- date_view.text = Html.fromHtml("Datum:
${date}")
+ if (date != "") {
+ binding.dateView.text = Html.fromHtml("Datum:
${date}")
}
- if (time != "null") {
- duration_view.text = Html.fromHtml("Dauer: $time Uhr, $duration Stunden")
- } else if (duration != "null") {
- duration_view.text = Html.fromHtml("Dauer: $duration Stunden")
+ if (time != "") {
+ binding.durationView.text = Html.fromHtml("Dauer: $time Uhr, $duration Stunden")
+ } else if (duration != "") {
+ binding.durationView.text = Html.fromHtml("Dauer: $duration Stunden")
}
- if (childKey == "null") {
+ if (childKey == "") {
entry = ParseObject("Einsatz")
} else {
entry = ParseObject.createWithoutData("Einsatz", childKey)
}
}
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- when (item.itemId) {
- android.R.id.home -> {
- finish()
- startActivity(Intent(applicationContext, MainActivity::class.java))
- }
- }
-
- return super.onOptionsItemSelected(item)
- }
-
- override fun onBackPressed() {
- finish()
- startActivity(Intent(applicationContext, MainActivity::class.java))
- }
}
diff --git a/app/src/main/java/com/cyb3rko/techniklogger/fragments/ListingFragment.kt b/app/src/main/java/com/cyb3rko/techniklogger/fragments/ListingFragment.kt
new file mode 100644
index 0000000..34e8571
--- /dev/null
+++ b/app/src/main/java/com/cyb3rko/techniklogger/fragments/ListingFragment.kt
@@ -0,0 +1,165 @@
+package com.cyb3rko.techniklogger.fragments
+
+import android.content.Context
+import android.content.Intent
+import android.content.SharedPreferences
+import android.os.Bundle
+import android.util.Log
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.findNavController
+import androidx.recyclerview.widget.LinearLayoutManager
+import com.cyb3rko.techniklogger.R
+import com.cyb3rko.techniklogger.databinding.FragmentListingBinding
+import com.cyb3rko.techniklogger.recycler.ProjectEntryViewHolder
+import com.cyb3rko.techniklogger.recycler.ProjectViewState
+import com.parse.ParseObject
+import com.parse.ParseQuery
+import es.dmoral.toasty.Toasty
+import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter
+import me.ibrahimyilmaz.kiel.core.RecyclerViewHolder
+import java.text.SimpleDateFormat
+import java.util.*
+
+class ListingFragment : Fragment() {
+ private var _binding: FragmentListingBinding? = null
+ private lateinit var myContext: Context
+
+ private var adminMode = false
+ private val data: MutableList = mutableListOf()
+ private lateinit var sharedPref: SharedPreferences
+ private lateinit var sharedPrefEditor: SharedPreferences.Editor
+
+ // This property is only valid between onCreateView and onDestroyView.
+ private val binding get() = _binding!!
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ _binding = FragmentListingBinding.inflate(inflater, container, false)
+ val root = binding.root
+ myContext = requireContext()
+
+ sharedPref = myContext.getSharedPreferences("Safe", 0)
+ sharedPrefEditor = sharedPref.edit()
+ sharedPrefEditor.apply()
+
+ 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) {
+ 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
+ }
+ }
+ )
+ }
+
+ 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)
+
+ return root
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ updateAdminStatus()
+ }
+
+ private fun loadEntries(adapter: RecyclerViewAdapter>) {
+ data.clear()
+ val query = ParseQuery.getQuery("Einsatz")
+ query.limit = 100000
+
+ query.findInBackground { objects, e ->
+ if (e == null) {
+ objects.forEach {
+ val dates = it["datum"].toString().split(",")
+ val time = if (dates.size > 1) dates[1] else ""
+ data.add(data.size, ProjectViewState.ProjectEntry(
+ it.objectId,
+ it["name"].toString(),
+ it["ort"].toString(),
+ SimpleDateFormat("yyyy.MM.dd", Locale.GERMANY).parse(dates[0])!!,
+ time,
+ it["dauer"].toString()
+ ))
+ }
+
+ data.sortBy { it.date }
+ hideProgress()
+ adapter.notifyDataSetChanged()
+ binding.recyclerView.scheduleLayoutAnimation()
+ binding.recyclerView.scrollBy(0, -10000)
+ } else {
+ Toasty.error(myContext, "Abruf fehlgeschlagen", Toasty.LENGTH_SHORT).show()
+ Log.e("TechnikLogger.EinsSuche", e.message.toString())
+ }
+ }
+ }
+
+ private fun hideProgress() {
+ binding.loadingAnimation.visibility = View.GONE
+ binding.loadingAnimation.cancelAnimation()
+ }
+
+ private fun updateAdminStatus() {
+ val query = ParseQuery.getQuery("Techniker")
+ query.whereEqualTo("name", sharedPref.getString("name", ""))
+ query.getFirstInBackground { techniker, e ->
+ if (e == null) {
+ if (techniker.getBoolean("admin")) {
+ adminMode = true
+ sharedPrefEditor.putBoolean("admin", adminMode)
+ sharedPrefEditor.putString("technikerId", techniker.objectId).apply()
+ binding.floatingActionButton.show()
+ binding.floatingActionButton.setOnClickListener {
+ val action = ListingFragmentDirections.navigateToPusher()
+ findNavController().navigate(action)
+ }
+ } else {
+ adminMode = false
+ sharedPrefEditor.putBoolean("admin", adminMode).apply()
+ binding.floatingActionButton.hide()
+ }
+ } else {
+ binding.floatingActionButton.hide()
+ adminMode = false
+ sharedPrefEditor.putBoolean("admin", adminMode).apply()
+ Toasty.error(myContext, "Adminstatus unbekannt", Toasty.LENGTH_SHORT).show()
+ Log.e("TechnikLogger.TechSuche", e.message.toString())
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/cyb3rko/techniklogger/ProjectActivity.kt b/app/src/main/java/com/cyb3rko/techniklogger/fragments/ProjectFragment.kt
similarity index 71%
rename from app/src/main/java/com/cyb3rko/techniklogger/ProjectActivity.kt
rename to app/src/main/java/com/cyb3rko/techniklogger/fragments/ProjectFragment.kt
index e73abc6..3a04e1d 100644
--- a/app/src/main/java/com/cyb3rko/techniklogger/ProjectActivity.kt
+++ b/app/src/main/java/com/cyb3rko/techniklogger/fragments/ProjectFragment.kt
@@ -1,13 +1,13 @@
-package com.cyb3rko.techniklogger
+package com.cyb3rko.techniklogger.fragments
import android.annotation.SuppressLint
+import android.content.Context
import android.content.SharedPreferences
import android.os.Bundle
import android.util.Log
-import android.view.Menu
-import android.view.MenuItem
-import android.view.View
-import androidx.appcompat.app.AppCompatActivity
+import android.view.*
+import androidx.fragment.app.Fragment
+import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.LinearLayoutManager
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.input.getInputField
@@ -15,21 +15,23 @@ import com.afollestad.materialdialogs.input.input
import com.afollestad.materialdialogs.list.isItemChecked
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.parse.ParseObject
import com.parse.ParseQuery
import es.dmoral.toasty.Toasty
-import kotlinx.android.synthetic.main.activity_main.*
import java.lang.IndexOutOfBoundsException
import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter.Companion.adapterOf
-import kotlinx.android.synthetic.main.activity_project.*
-import kotlinx.android.synthetic.main.activity_project.recycler_view
import me.ibrahimyilmaz.kiel.adapter.RecyclerViewAdapter
import me.ibrahimyilmaz.kiel.core.RecyclerViewHolder
@SuppressLint("SetTextI18n")
-class ProjectActivity : AppCompatActivity() {
+class ProjectFragment : Fragment() {
+ private var _binding: FragmentProjectBinding? = null
+ private lateinit var myContext: Context
+ private val args: ProjectFragmentArgs by navArgs()
private lateinit var adapter: RecyclerViewAdapter>
private var adminMode = false
@@ -38,16 +40,19 @@ class ProjectActivity : AppCompatActivity() {
private lateinit var sharedPref: SharedPreferences
private val techniker: MutableList = mutableListOf()
- override fun onCreate(savedInstanceState: Bundle?) {
- childKey = intent.extras?.getString("childKey").toString()
- einsatz = ParseObject.createWithoutData("Einsatz", childKey)
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_project)
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ private val binding get() = _binding!!
- sharedPref = getSharedPreferences("Safe", 0)
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ _binding = FragmentProjectBinding.inflate(inflater, container, false)
+ val root = binding.root
+ myContext = requireContext()
+
+ sharedPref = myContext.getSharedPreferences("Safe", 0)
adminMode = sharedPref.getBoolean("admin", false)
+ childKey = args.childKey
+ einsatz = ParseObject.createWithoutData("Einsatz", childKey)
+
adapter = adapterOf {
register(
layoutResource = R.layout.item_recycler_techniker,
@@ -56,7 +61,7 @@ class ProjectActivity : AppCompatActivity() {
vh.textView.text = text.name
vh.itemView.setOnClickListener {
if (adminMode) {
- MaterialDialog(this@ProjectActivity)
+ MaterialDialog(myContext)
.show {
message(text = "Möchtest du \'${text.name}\' entfernen?")
positiveButton(text = "Ja") {
@@ -64,8 +69,8 @@ class ProjectActivity : AppCompatActivity() {
einsatz.put("techniker", techniker)
einsatz.saveInBackground()
adapter.notifyDataSetChanged()
- this@ProjectActivity.recycler_view.scheduleLayoutAnimation()
- this@ProjectActivity.techniker_view.text = "Techniker: ${techniker.size}"
+ binding.recyclerView.scheduleLayoutAnimation()
+ binding.technikerView.text = "Techniker: ${techniker.size}"
if (techniker.size == 0) showDivider(false)
}
negativeButton(text = "Abbrechen")
@@ -96,35 +101,35 @@ class ProjectActivity : AppCompatActivity() {
techniker.add(ProjectTechnikerViewState.ProjectTechniker(it.getString("name")!!, it.objectId))
}
techniker.sortBy { it.name }
- recycler_view.scheduleLayoutAnimation()
+ binding.recyclerView.scheduleLayoutAnimation()
adapter.notifyDataSetChanged()
- techniker_view.text = "Techniker: ${techniker.size}"
+ binding.technikerView.text = "Techniker: ${techniker.size}"
showDivider()
} else {
- Toasty.error(applicationContext, "Fehler bei Id-Abfrage", Toasty.LENGTH_SHORT).show()
+ Toasty.error(myContext, "Fehler bei Id-Abfrage", Toasty.LENGTH_SHORT).show()
Log.e("TechnikLogger.TechSuche", e2.message.toString())
}
}
}
- title_view.text = einsatz["name"].toString()
- location_view.text = einsatz["ort"].toString()
+ binding.titleView.text = einsatz["name"].toString()
+ binding.locationView.text = einsatz["ort"].toString()
val dates = einsatz["datum"].toString().split(",")
val dateParts = dates[0].split(".")
val date = "${dateParts[2]}.${dateParts[1]}.${dateParts[0]}"
val time = if (dates.size > 1) ", ${dates[1]}" else ""
- date_view.text = date + time
+ binding.dateView.text = date + time
} else {
- Toasty.error(applicationContext, "Abruf fehlgeschlagen", Toasty.LENGTH_SHORT).show()
+ Toasty.error(myContext, "Abruf fehlgeschlagen", Toasty.LENGTH_SHORT).show()
Log.e("TechnikLogger.TechSuche", e.message.toString())
}
}
adapter.submitList(techniker as List?)
- recycler_view.layoutManager = LinearLayoutManager(applicationContext)
- recycler_view.adapter = adapter
+ binding.recyclerView.layoutManager = LinearLayoutManager(myContext)
+ binding.recyclerView.adapter = adapter
- add_button.setOnClickListener {
+ binding.addButton.setOnClickListener {
val name = sharedPref.getString("name", "invalid")!!
if (!adminMode) selfAdd(name) else bothAdd(name)
}
@@ -132,9 +137,9 @@ class ProjectActivity : AppCompatActivity() {
emptyCheck()
if (adminMode) {
- reset_button.visibility = View.VISIBLE
- reset_button.setOnClickListener {
- MaterialDialog(this).show {
+ binding.resetButton.visibility = View.VISIBLE
+ binding.resetButton.setOnClickListener {
+ MaterialDialog(myContext).show {
message(text = "Möchtest du alle eingetragenen Techniker entfernen?")
positiveButton(text = "Ja") {
einsatz.put("techniker", listOf())
@@ -142,12 +147,14 @@ class ProjectActivity : AppCompatActivity() {
techniker.clear()
adapter.notifyDataSetChanged()
showDivider(false)
- this@ProjectActivity.techniker_view.text = "Techniker: ${techniker.size}"
+ binding.technikerView.text = "Techniker: ${techniker.size}"
}
negativeButton(text = "Abbrechen")
}
}
}
+
+ return root
}
private fun technikerExists(name: String): Boolean {
@@ -160,7 +167,7 @@ class ProjectActivity : AppCompatActivity() {
}
private fun bothAdd(name: String) {
- MaterialDialog(this)
+ MaterialDialog(myContext)
.show {
message(text = "Möchtest du nur dich oder auch andere Techniker eintragen?")
positiveButton(text = "Mich") {
@@ -175,7 +182,7 @@ class ProjectActivity : AppCompatActivity() {
private fun selfAdd(name: String, skip: Boolean = false) {
if (!technikerExists(name)) {
if (!skip) {
- MaterialDialog(this).show {
+ MaterialDialog(myContext).show {
message(text = "Möchtest du dich als involvierter Techniker eintragen?")
positiveButton(text = "Ja") {
val entry = ParseObject.createWithoutData("Einsatz", childKey)
@@ -185,8 +192,8 @@ class ProjectActivity : AppCompatActivity() {
techniker.sortBy { it.name }
adapter.notifyDataSetChanged()
showDivider(true)
- this@ProjectActivity.recycler_view.scheduleLayoutAnimation()
- this@ProjectActivity.techniker_view.text = "Techniker: ${techniker.size}"
+ binding.recyclerView.scheduleLayoutAnimation()
+ binding.technikerView.text = "Techniker: ${techniker.size}"
}
negativeButton(text = "Abbrechen")
}
@@ -198,11 +205,11 @@ class ProjectActivity : AppCompatActivity() {
techniker.sortBy { it.name }
adapter.notifyDataSetChanged()
showDivider(true)
- this@ProjectActivity.recycler_view.scheduleLayoutAnimation()
- this@ProjectActivity.techniker_view.text = "Techniker: ${techniker.size}"
+ binding.recyclerView.scheduleLayoutAnimation()
+ binding.technikerView.text = "Techniker: ${techniker.size}"
}
} else {
- MaterialDialog(this)
+ MaterialDialog(myContext)
.show {
message(text = "Du bist bereits eingetragen.")
positiveButton(text = "Ok")
@@ -231,7 +238,7 @@ class ProjectActivity : AppCompatActivity() {
}
}
val intArray = currentSelection.toIntArray()
- MaterialDialog(this@ProjectActivity).show {
+ MaterialDialog(myContext).show {
listItemsMultiChoice(items = names, initialSelection = intArray, disabledIndices = intArray)
positiveButton(text = "Hinzufügen") {
it.uncheckItems(intArray)
@@ -248,34 +255,34 @@ class ProjectActivity : AppCompatActivity() {
techniker.sortBy { it.name }
adapter.notifyDataSetChanged()
showDivider(true)
- this@ProjectActivity.recycler_view.scheduleLayoutAnimation()
- this@ProjectActivity.techniker_view.text = "Techniker: ${techniker.size}"
+ binding.recyclerView.scheduleLayoutAnimation()
+ binding.technikerView.text = "Techniker: ${techniker.size}"
}
negativeButton(text = "Abbrechen") {
addTechniker.clear()
}
}
} else {
- Toasty.error(applicationContext, "Fehler bei Id-Abfrage", Toasty.LENGTH_SHORT).show()
+ Toasty.error(myContext, "Fehler bei Id-Abfrage", Toasty.LENGTH_SHORT).show()
Log.e("TechnikLogger.TechSuche", e.message.toString())
}
}
}
private fun showDivider(show: Boolean = true) {
- divider.visibility = if (show) View.VISIBLE else View.GONE
+ binding.divider.visibility = if (show) View.VISIBLE else View.GONE
}
private fun emptyCheck() {
if (techniker.isEmpty()) {
- divider.visibility = View.GONE
+ binding.divider.visibility = View.GONE
}
}
private fun showNameDialog() {
- val currentName = getSharedPreferences("Safe", 0).getString("name", "")
+ val currentName = myContext.getSharedPreferences("Safe", 0).getString("name", "")
- MaterialDialog(this)
+ MaterialDialog(myContext)
.cancelable(false)
.title(0, "Bitte gebe deinen Namen ein")
.show {
@@ -288,32 +295,10 @@ class ProjectActivity : AppCompatActivity() {
}
positiveButton {
- getSharedPreferences("Safe", 0).edit().putString("name", inputName.toString()).apply()
+ myContext.getSharedPreferences("Safe", 0).edit().putString("name", inputName.toString()).apply()
}
}
positiveButton(0, "Speichern")
}
}
-
- override fun onCreateOptionsMenu(menu: Menu): Boolean {
- // Inflate the menu; this adds items to the action bar if it is present.
- menuInflater.inflate(R.menu.menu_main, menu)
- return true
- }
-
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- // Handle action bar item clicks here. The action bar will
- // automatically handle clicks on the Home/Up button, so long
- // as you specify a parent activity in AndroidManifest.xml.
- when (item.itemId) {
- android.R.id.home -> finish()
- R.id.action_rename -> showNameDialog()
-// R.id.action_icons -> setContentView(AboutIcons(applicationContext, R.drawable::class.java).setTitle("Benutzte Icons").get())
-// R.id.action_libraries -> LibsBuilder().start(this)
-// R.id.action_privacy_policy ->
-// R.id.action_terms_of_use ->
- }
-
- return super.onOptionsItemSelected(item)
- }
}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 49771cc..2a72667 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,59 +1,17 @@
-
+ android:layout_height="match_parent">
-
+ android:layout_height="match_parent"
+ app:defaultNavHost="true"
+ app:navGraph="@navigation/mobile_navigation" />
-
-
-
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_einsatz_pusher.xml b/app/src/main/res/layout/fragment_einsatz_pusher.xml
similarity index 96%
rename from app/src/main/res/layout/activity_einsatz_pusher.xml
rename to app/src/main/res/layout/fragment_einsatz_pusher.xml
index 9e5d841..b64f177 100644
--- a/app/src/main/res/layout/activity_einsatz_pusher.xml
+++ b/app/src/main/res/layout/fragment_einsatz_pusher.xml
@@ -1,6 +1,7 @@
@@ -80,7 +81,7 @@
android:layout_height="wrap_content"
android:text="Datum:\n---"
android:textAlignment="center"
- android:layout_gravity="center_vertical"
+ android:layout_gravity="center"
android:foregroundGravity="center_vertical"
android:layout_marginStart="20dp"
android:textSize="16sp"/>
@@ -123,7 +124,7 @@
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:textAlignment="center"
- android:layout_gravity="center_vertical"
+ android:layout_gravity="center"
android:foregroundGravity="center_vertical"
android:layout_marginStart="20dp"
android:textSize="16sp"/>
@@ -155,6 +156,7 @@
android:visibility="gone"
style="@style/Widget.MaterialComponents.Button"
android:textSize="12sp"
- android:text="Einsatz entfernen" />
+ android:text="Einsatz entfernen"
+ tools:visibility="visible" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_listing.xml b/app/src/main/res/layout/fragment_listing.xml
new file mode 100644
index 0000000..49771cc
--- /dev/null
+++ b/app/src/main/res/layout/fragment_listing.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_project.xml b/app/src/main/res/layout/fragment_project.xml
similarity index 100%
rename from app/src/main/res/layout/activity_project.xml
rename to app/src/main/res/layout/fragment_project.xml
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
index 39cfb68..cc9d304 100644
--- a/app/src/main/res/menu/menu_main.xml
+++ b/app/src/main/res/menu/menu_main.xml
@@ -7,11 +7,6 @@
android:title="Namen ändern"
app:showAsAction="never" />
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 5013399..7cafb1d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -12,6 +12,7 @@ buildscript {
classpath 'com.google.gms:google-services:4.3.4'
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:$about_libraries_version"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ classpath "androidx.navigation:navigation-safe-args-gradle-plugin:2.3.4"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files