diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/CustomField.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/CustomField.kt index 8f31431b..0a6f59e4 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/CustomField.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/CustomField.kt @@ -11,12 +11,14 @@ import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.interfaces.SaveValidityStatus import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.CustomFieldRow import net.pokeranalytics.android.ui.view.rowrepresentable.CustomizableRowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow import timber.log.Timber import java.util.* +import kotlin.collections.ArrayList open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDataSource, RowRepresentable { @@ -35,10 +37,10 @@ open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDa // Migration var type: Int = Type.LIST.ordinal - set(value) { - field = value - this.updateRowRepresentation() - } + set(value) { + field = value + this.updateRowRepresentation() + } var duplicateValue: Boolean = false var entries: RealmList = RealmList() @@ -57,7 +59,6 @@ open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDa private var rowRepresentation: List = mutableListOf() override fun adapterRows(): List? { - Timber.d("adapterRows: ${rowRepresentation.size}") return rowRepresentation } @@ -93,6 +94,16 @@ open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDa return R.string.relationship_error } + override fun editDescriptors(row: RowRepresentable): ArrayList? { + return when (row) { + is CustomFieldEntry -> row.editingDescriptors( + mapOf( + "defaultValue" to row.value + ) + ) + else -> null + } + } private fun updatedRowRepresentationForCurrentState(): List { val rows = ArrayList() @@ -101,11 +112,14 @@ open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDa if (type == Type.LIST.ordinal && entries.size >= 0) { rows.add(CustomizableRowRepresentable(RowViewType.HEADER_TITLE, R.string.items_list)) - entries.forEach {entry -> - rows.add(CustomizableRowRepresentable(RowViewType.TITLE, title = entry.value)) + if (entries.isNotEmpty()) { + Timber.d("entries: ${entries.size}") + entries.sortBy { it.order } + rows.addAll(entries) } } + Timber.d("rows: ${rows.size}") return rows } @@ -113,4 +127,21 @@ open class CustomField : RealmObject(), NameManageable, StaticRowRepresentableDa this.rowRepresentation = this.updatedRowRepresentationForCurrentState() } + /** + * Add entry + */ + fun addEntry() { + val entry = CustomFieldEntry() + entry.order = (entries.lastOrNull()?.order ?: 0) + 1 + entries.add(entry) + updateRowRepresentation() + } + + /** + * + */ + fun deleteEntry() { + + } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/CustomFieldEntry.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/CustomFieldEntry.kt index 767d0f4a..fed2340d 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/CustomFieldEntry.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/CustomFieldEntry.kt @@ -1,15 +1,45 @@ package net.pokeranalytics.android.model.realm +import android.content.Context +import android.text.InputType import io.realm.RealmObject +import io.realm.annotations.Ignore import io.realm.annotations.PrimaryKey +import net.pokeranalytics.android.R +import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType +import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor +import net.pokeranalytics.android.ui.view.RowViewType +import net.pokeranalytics.android.util.NULL_TEXT import java.util.* -open class CustomFieldEntry : RealmObject() { +open class CustomFieldEntry : RealmObject(), RowRepresentable { @PrimaryKey var id = UUID.randomUUID().toString() var value: String = "" var order: Int = 0 + @Ignore + override val viewType: Int = RowViewType.TITLE.ordinal + + @Ignore + override val bottomSheetType: BottomSheetType = BottomSheetType.EDIT_TEXT + + override fun localizedTitle(context: Context): String { + return context.getString(R.string.value) + } + + override fun getDisplayName(): String { + return if (value.isNotEmpty()) value else NULL_TEXT + } + + override fun editingDescriptors(map: Map): ArrayList? { + val defaultValue: Any? by map + return arrayListOf( + RowRepresentableEditDescriptor(defaultValue, R.string.value, InputType.TYPE_CLASS_TEXT) + ) + } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/CustomFieldDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/CustomFieldDataFragment.kt index d379d96d..10786d0f 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/CustomFieldDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/CustomFieldDataFragment.kt @@ -5,15 +5,17 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.interpolator.view.animation.FastOutSlowInInterpolator -import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.fragment_custom_view.* import net.pokeranalytics.android.R import net.pokeranalytics.android.model.realm.CustomField +import net.pokeranalytics.android.model.realm.CustomFieldEntry import net.pokeranalytics.android.ui.adapter.RowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.extensions.px +import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment import net.pokeranalytics.android.ui.view.RowRepresentable -import net.pokeranalytics.android.ui.view.RowRepresentableDiffCallback import net.pokeranalytics.android.ui.view.RowRepresentableEditDescriptor import net.pokeranalytics.android.ui.view.rowrepresentable.CustomFieldRow import net.pokeranalytics.android.ui.view.rowrepresentable.SimpleRow @@ -34,6 +36,71 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa private val oldRows: ArrayList = ArrayList() + + private val itemTouchHelper = ItemTouchHelper(object : ItemTouchHelper.Callback() { + + var dragFrom = -1 + var dragTo = -1 + + override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int { + return if (viewHolder.adapterPosition <= 2) { + return 0 + } else { + makeFlag( + ItemTouchHelper.ACTION_STATE_DRAG, ItemTouchHelper.DOWN + or ItemTouchHelper.UP or ItemTouchHelper.START or ItemTouchHelper.END + ) + } + } + + override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean { + if (target.adapterPosition <= 2) { + return false + } + + val fromPosition = viewHolder.adapterPosition + val toPosition = target.adapterPosition + + if (dragFrom == -1) { + dragFrom = viewHolder.adapterPosition - 1 // Header + } + dragTo = target.adapterPosition - 1 // Header + + rowRepresentableAdapter.notifyItemMoved(fromPosition, toPosition) + + /* + adapterRows()?.filter { it is CustomFieldEntry }?.forEachIndexed { index, rowRepresentable -> + val entry = rowRepresentable as CustomFieldEntry + Timber.d("$index ${entry.value} ${entry.order}") + } + */ + + + return true + } + + override fun onMoved(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, fromPos: Int, target: RecyclerView.ViewHolder, toPos: Int, x: Int, y: Int) { + super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y) + + Collections.swap(customField.entries, fromPos - (CustomFieldRow.values().size + 1), toPos - (CustomFieldRow.values().size + 1)) + customField.entries.forEachIndexed { index, rowRepresentable -> + val entry = rowRepresentable as CustomFieldEntry + entry.order = index + } + + } + + override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) { + super.clearView(recyclerView, viewHolder) + dragFrom = -1 + dragTo = -1 + } + + override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { + } + }) + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.fragment_custom_view, container, false) @@ -69,7 +136,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa } override fun intForRow(row: RowRepresentable): Int { - return when(row) { + return when (row) { CustomFieldRow.TYPE -> customField.type else -> super.intForRow(row) } @@ -78,22 +145,36 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa override fun editDescriptors(row: RowRepresentable): ArrayList? { return when (row) { SimpleRow.NAME -> row.editingDescriptors(mapOf("defaultValue" to this.customField.name)) + is CustomFieldEntry -> row.editingDescriptors(mapOf("defaultValue" to row.value)) else -> null } } override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { when (row) { + is CustomFieldEntry -> { + val data = customField.editDescriptors(row) + Timber.d("data: $data") + BottomSheetFragment.create(fragmentManager, row, this, data, false) + } else -> super.onRowSelected(position, row, fromAction) } } override fun onRowValueChanged(value: Any?, row: RowRepresentable) { - //super.onRowValueChanged(value, row) Timber.d("onRowValueChanged: $row => $value") - customField.updateValue(value, row) - updateUI() - updateAdapterUI() + when (row) { + is CustomFieldEntry -> { + row.value = value as String? ?: "" + rowRepresentableAdapter.refreshRow(row) + } + CustomFieldRow.TYPE -> { + customField.updateValue(value, row) + updateUI() + updateAdapterUI() + } + } + } /** @@ -104,8 +185,11 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa bottomBar.translationY = 72f.px bottomBar.visibility = View.VISIBLE + itemTouchHelper.attachToRecyclerView(recyclerView) + addItem.setOnClickListener { - Timber.d("Click on add item") + customField.addEntry() + updateAdapterUI() } updateUI() @@ -123,7 +207,6 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa } else { bottomBar.animate().translationY(72f.px) .setInterpolator(FastOutSlowInInterpolator()) - .withEndAction { } .start() } } @@ -132,6 +215,15 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa * Update adapter UI */ private fun updateAdapterUI() { + rowRepresentableAdapter.notifyDataSetChanged() + /* + //TODO: Code to animate changes + + // Test: + // not really, i agree with your part about performance but notifyDataSetChanged() does not kill animations, + // to animate using notifyDataSetChanged(), a) call setHasStableIds(true) on your RecyclerView.Adapter object and b) + // override getItemId inside your Adapter to return a unique long value for each row and check it out, the animations do work + customField.adapterRows()?.let { val diffResult = DiffUtil.calculateDiff(RowRepresentableDiffCallback(it, oldRows)) rowRepresentableAdapter.updateRows(diffResult) @@ -139,6 +231,7 @@ class CustomFieldDataFragment : EditableDataFragment(), StaticRowRepresentableDa oldRows.clear() oldRows.addAll(it) } + */ } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt index 58784f62..5d3d6148 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/data/EditableDataFragment.kt @@ -70,6 +70,7 @@ open class EditableDataFragment : RealmFragment(), RowRepresentableDelegate { } override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { + BottomSheetFragment.create(fragmentManager, row, this, getDataSource().editDescriptors(row)) }