From 85a38071be496dd5201fe01b5fc59077695473bb Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Fri, 24 May 2019 11:22:51 +0200 Subject: [PATCH] Improve filters list --- .../android/model/realm/Filter.kt | 159 ++++++++++-------- .../android/ui/activity/DataListActivity.kt | 29 ++-- .../android/ui/extensions/UIExtensions.kt | 6 + .../android/ui/fragment/DataListFragment.kt | 54 ++++-- .../android/ui/fragment/FiltersFragment.kt | 2 +- .../android/ui/view/RowRepresentable.kt | 10 +- .../android/ui/view/RowViewType.kt | 9 + .../res/layout/row_title_value_action.xml | 8 +- 8 files changed, 162 insertions(+), 115 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt index df148089..a7576a40 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/Filter.kt @@ -12,7 +12,9 @@ import net.pokeranalytics.android.model.interfaces.Deletable import net.pokeranalytics.android.model.interfaces.DeleteValidityStatus import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.ui.interfaces.FilterableType +import net.pokeranalytics.android.ui.view.ImageDecorator import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import java.util.* @@ -21,14 +23,14 @@ import java.util.* * It contains a list of [FilterCondition] describing the complete query to launch * The [Filter] is working closely with a [Filterable] interface providing the entity we want the query being launched on */ -open class Filter : RealmObject(), RowRepresentable, Identifiable, Deletable { +open class Filter : RealmObject(), RowRepresentable, Identifiable, Deletable, ImageDecorator { companion object { // Create a new instance - fun newInstance(realm: Realm, filterableType:Int): Filter { + fun newInstance(realm: Realm, filterableType: Int): Filter { val filter = Filter() - filter.filterableTypeOrdinal = filterableType + filter.filterableTypeOrdinal = filterableType return filter //return realm.copyToRealm(filter) } @@ -38,26 +40,26 @@ open class Filter : RealmObject(), RowRepresentable, Identifiable, Deletable { return realm.where().equalTo("id", filterId).findFirst() } - inline fun queryOn(realm: Realm, query: Query, sortField: String? = null): RealmResults { - val realmQuery = realm.where() - sortField?.let { - return query.queryWith(realmQuery).sort(it).findAll() - } ?: run { - return query.queryWith(realmQuery).findAll() - } - } + inline fun queryOn(realm: Realm, query: Query, sortField: String? = null): RealmResults { + val realmQuery = realm.where() + sortField?.let { + return query.queryWith(realmQuery).sort(it).findAll() + } ?: run { + return query.queryWith(realmQuery).findAll() + } + } fun sortedByUsage(realm: Realm): RealmResults { return realm.where(Filter::class.java).findAll().sort("usageCount") } - } + } @PrimaryKey - override var id = UUID.randomUUID().toString() + override var id = UUID.randomUUID().toString() // the queryWith name - var name: String = "" + var name: String = "" // the number of use of the queryWith, // for MutableRealmInteger, see https://realm.io/docs/java/latest/#counters @@ -66,106 +68,115 @@ open class Filter : RealmObject(), RowRepresentable, Identifiable, Deletable { var filterConditions: RealmList = RealmList() private set - private var filterableTypeOrdinal: Int? = null - - val filterableType: FilterableType - get() { - this.filterableTypeOrdinal?.let { - return FilterableType.values()[it] - } - return FilterableType.ALL - } + private var filterableTypeOrdinal: Int? = null + + override val viewType: Int + get() = RowViewType.TITLE_VALUE_ACTION.ordinal + override val imageRes: Int? + get() = R.drawable.ic_outline_settings + override val imageTint: Int? + get() = R.color.green + override val imageClickable: Boolean? + get() = true + + val filterableType: FilterableType + get() { + this.filterableTypeOrdinal?.let { + return FilterableType.values()[it] + } + return FilterableType.ALL + } fun createOrUpdateFilterConditions(filterConditionRows: ArrayList) { - println("list of querys saving: ${filterConditionRows.map { it.id }}") - println("list of querys previous: ${this.filterConditions.map { it.queryCondition.id }}") - filterConditionRows + println("list of querys saving: ${filterConditionRows.map { it.id }}") + println("list of querys previous: ${this.filterConditions.map { it.queryCondition.id }}") + filterConditionRows .map { it.groupId } .distinct() - .forEach { groupId-> + .forEach { groupId -> filterConditionRows .filter { it.groupId == groupId } .apply { - println("list of querys: ${this.map { it.id }}") - val casted = arrayListOf() - casted.addAll(this) - val newFilterCondition = FilterCondition(casted) - val previousCondition = filterConditions.filter { - it.filterName == newFilterCondition.filterName && it.operator == newFilterCondition.operator - } - filterConditions.removeAll(previousCondition) - filterConditions.add(newFilterCondition) - } + println("list of querys: ${this.map { it.id }}") + val casted = arrayListOf() + casted.addAll(this) + val newFilterCondition = FilterCondition(casted) + val previousCondition = filterConditions.filter { + it.filterName == newFilterCondition.filterName && it.operator == newFilterCondition.operator + } + filterConditions.removeAll(previousCondition) + filterConditions.add(newFilterCondition) + } } } - fun remove(filterCategoryRow: FilterCategoryRow) { - val sections = filterCategoryRow.filterSectionRows.map { it.name } - val savedSections = filterConditions.filter { sections.contains(it.sectionName) } - this.filterConditions.removeAll(savedSections) - } + fun remove(filterCategoryRow: FilterCategoryRow) { + val sections = filterCategoryRow.filterSectionRows.map { it.name } + val savedSections = filterConditions.filter { sections.contains(it.sectionName) } + this.filterConditions.removeAll(savedSections) + } fun countBy(filterCategoryRow: FilterCategoryRow): Int { val sections = filterCategoryRow.filterSectionRows.map { it.name } - println("list of sections $sections") - val savedSections = filterConditions.filter { sections.contains(it.sectionName) }.flatMap { it.queryCondition.id } - println("list of savedSections $savedSections") - return savedSections.size + println("list of sections $sections") + val savedSections = filterConditions.filter { sections.contains(it.sectionName) }.flatMap { it.queryCondition.id } + println("list of savedSections $savedSections") + return savedSections.size } fun contains(filterElementRow: QueryCondition): Boolean { - println("list of saved queries ${filterConditions.map { it.queryCondition.id }}") - println("list of contains ${filterElementRow.id}") - val contained = filterConditions.flatMap{ it.queryCondition.id }.contains(filterElementRow.id.first()) - println("list of : $contained") - return contained + println("list of saved queries ${filterConditions.map { it.queryCondition.id }}") + println("list of contains ${filterElementRow.id}") + val contained = filterConditions.flatMap { it.queryCondition.id }.contains(filterElementRow.id.first()) + println("list of : $contained") + return contained } /** * Get the saved value for the given [filterElementRow] */ - fun loadValueForElement(filterElementRow: QueryCondition) { + fun loadValueForElement(filterElementRow: QueryCondition) { val filtered = filterConditions.filter { it.queryCondition.id == filterElementRow.id } if (filtered.isNotEmpty()) { - return filterElementRow.updateValueBy(filtered.first()) + return filterElementRow.updateValueBy(filtered.first()) } } inline fun results(firstField: String? = null, secondField: String? = null): RealmResults { - val realmQuery = realm.where() + val realmQuery = realm.where() - if (firstField != null && secondField != null) { - return this.query.queryWith(realmQuery).distinct(firstField, secondField).findAll() - } + if (firstField != null && secondField != null) { + return this.query.queryWith(realmQuery).distinct(firstField, secondField).findAll() + } - if (firstField != null) { - return this.query.queryWith(realmQuery).distinct(firstField).findAll() - } + if (firstField != null) { + return this.query.queryWith(realmQuery).distinct(firstField).findAll() + } - return this.query.queryWith(realmQuery).findAll() - } + return this.query.queryWith(realmQuery).findAll() + } - val query: Query - get() { - val query = Query() - this.filterConditions.forEach { - query.add(it.queryCondition) - } - return query - } + val query: Query + get() { + val query = Query() + this.filterConditions.forEach { + query.add(it.queryCondition) + } + return query + } - override fun getDisplayName(context: Context): String { - if (name.isNotEmpty()) return name - return this.query.getName(context) - } + override fun getDisplayName(context: Context): String { + if (name.isNotEmpty()) return name + return this.query.getName(context) + } override fun isValidForDelete(realm: Realm): Boolean { return true diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/DataListActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/DataListActivity.kt index 11b92ce6..846a901b 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/DataListActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/DataListActivity.kt @@ -14,8 +14,9 @@ class DataListActivity : PokerAnalyticsActivity() { enum class IntentKey(val keyName: String) { DATA_TYPE("DATA_TYPE"), - LIVE_DATA_TYPE("LIVE_DATA_TYPE"), - ITEM_DELETED("ITEM_DELETED") + LIVE_DATA_TYPE("LIVE_DATA_TYPE"), + ITEM_DELETED("ITEM_DELETED"), + SHOW_ADD_BUTTON("SHOW_ADD_BUTTON"), } companion object { @@ -23,17 +24,18 @@ class DataListActivity : PokerAnalyticsActivity() { context.startActivity(getIntent(context, dataType)) } - fun newSelectInstance(fragment: Fragment, dataType: Int) { - val context = fragment.requireContext() - fragment.startActivityForResult(getIntent(context, dataType), FilterActivityRequestCode.SELECT_FILTER.ordinal) - } + fun newSelectInstance(fragment: Fragment, dataType: Int, showAddButton: Boolean = true) { + val context = fragment.requireContext() + fragment.startActivityForResult(getIntent(context, dataType, showAddButton), FilterActivityRequestCode.SELECT_FILTER.ordinal) + } - private fun getIntent(context:Context, dataType:Int) : Intent { - val intent = Intent(context, DataListActivity::class.java) - intent.putExtra(IntentKey.DATA_TYPE.keyName, dataType) - return intent - } - } + private fun getIntent(context: Context, dataType: Int, showAddButton: Boolean = true): Intent { + val intent = Intent(context, DataListActivity::class.java) + intent.putExtra(IntentKey.DATA_TYPE.keyName, dataType) + intent.putExtra(IntentKey.SHOW_ADD_BUTTON.keyName, showAddButton) + return intent + } + } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -46,10 +48,11 @@ class DataListActivity : PokerAnalyticsActivity() { * Init UI */ private fun initUI() { - val dataType = intent.getIntExtra(IntentKey.DATA_TYPE.keyName, 0) + val showAddButton = intent.getBooleanExtra(IntentKey.SHOW_ADD_BUTTON.keyName, true) val fragment = dataListFragment as DataListFragment fragment.setData(dataType) + fragment.updateUI(showAddButton) } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/extensions/UIExtensions.kt b/app/src/main/java/net/pokeranalytics/android/ui/extensions/UIExtensions.kt index ce769da5..2b1ff140 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/extensions/UIExtensions.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/extensions/UIExtensions.kt @@ -5,6 +5,7 @@ import android.content.Context import android.content.Intent import android.content.res.Resources import android.net.Uri +import android.util.TypedValue import android.view.View import android.widget.Toast import androidx.appcompat.app.AlertDialog @@ -149,4 +150,9 @@ fun View.showWithAnimation() { isVisible = true animate().cancel() animate().alpha(1f).start() +} + +fun View.addCircleRipple() = with(TypedValue()) { + context.theme.resolveAttribute(android.R.attr.selectableItemBackgroundBorderless, this, true) + setBackgroundResource(resourceId) } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt index ac4d5f01..dfa4a081 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt @@ -19,6 +19,7 @@ import net.pokeranalytics.android.ui.activity.FiltersActivity import net.pokeranalytics.android.ui.adapter.LiveRowRepresentableDataSource import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate +import net.pokeranalytics.android.ui.extensions.toast import net.pokeranalytics.android.ui.fragment.components.DeletableItemFragment import net.pokeranalytics.android.ui.helpers.SwipeToDeleteCallback import net.pokeranalytics.android.ui.view.RowRepresentable @@ -41,20 +42,6 @@ class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource return this.items } - /** - * Set fragment data - */ - fun setData(dataType: Int) { - - this.dataType = LiveData.values()[dataType] - this.identifiableClass = this.dataType.relatedEntity - setToolbarTitle(this.dataType.localizedTitle(requireContext())) - - val realm = getRealm() - this.items = realm.sorted(this.identifiableClass) - - } - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.fragment_data_list, container, false) @@ -124,10 +111,16 @@ class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource when (this.dataType) { LiveData.FILTER -> { - val intent = Intent() - intent.putExtra(FiltersActivity.IntentKey.FILTER_ID.keyName, (row as Filter).id) - activity?.setResult(Activity.RESULT_OK, intent) - activity?.finish() + if (fromAction) { + // Open filter params + toast("Hey") + } else { + // Select filter + val intent = Intent() + intent.putExtra(FiltersActivity.IntentKey.FILTER_ID.keyName, (row as Filter).id) + activity?.setResult(Activity.RESULT_OK, intent) + activity?.finish() + } } else -> { val identifier = (row as Identifiable).id @@ -136,4 +129,29 @@ class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource } } + /** + * Set fragment data + */ + fun setData(dataType: Int) { + + this.dataType = LiveData.values()[dataType] + this.identifiableClass = this.dataType.relatedEntity + setToolbarTitle(this.dataType.localizedTitle(requireContext())) + + val realm = getRealm() + this.items = realm.sorted(this.identifiableClass) + + } + + /** + * Update UI + */ + fun updateUI(showAddButton: Boolean) { + if (showAddButton) { + this.addButton.show() + } else { + this.addButton.hide() + } + } + } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt index ad66cd84..7bed87d8 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt @@ -156,7 +156,7 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, } moreFilters.setOnClickListener { - DataListActivity.newSelectInstance(this, LiveData.FILTER.ordinal) + DataListActivity.newSelectInstance(this, LiveData.FILTER.ordinal, false) } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/RowRepresentable.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/RowRepresentable.kt index 15212620..1f6ce50f 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/RowRepresentable.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/RowRepresentable.kt @@ -34,15 +34,13 @@ interface DefaultEditDataSource : EditDataSource, Localizable { interface ImageDecorator { val imageRes: Int? - get() { - return null - } + get() = null val imageTint: Int? - get() { - return null - } + get() = null + val imageClickable: Boolean? + get() = false } /** diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt index efa3a5c2..ed8dfffd 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/RowViewType.kt @@ -31,6 +31,7 @@ import net.pokeranalytics.android.model.realm.Session import net.pokeranalytics.android.model.realm.Transaction import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.extensions.ChipGroupExtension +import net.pokeranalytics.android.ui.extensions.addCircleRipple import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.extensions.setTextFormat import net.pokeranalytics.android.ui.graph.AxisFormatting @@ -204,6 +205,14 @@ enum class RowViewType(private var layoutRes: Int) { row.imageTint?.let { color -> imageView.setColorFilter(ContextCompat.getColor(imageView.context, color)) } + if (row.imageClickable == true) { + imageView.addCircleRipple() + imageView.setOnClickListener { + adapter.delegate?.onRowSelected(position, row, true) + } + } else { + imageView.setBackgroundResource(0) + } } // Listener diff --git a/app/src/main/res/layout/row_title_value_action.xml b/app/src/main/res/layout/row_title_value_action.xml index b0e98b29..2b3e7f62 100644 --- a/app/src/main/res/layout/row_title_value_action.xml +++ b/app/src/main/res/layout/row_title_value_action.xml @@ -25,6 +25,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginStart="16dp" + android:layout_marginEnd="8dp" android:ellipsize="end" android:gravity="end|center_vertical" android:maxLines="1" @@ -39,14 +40,15 @@ android:id="@+id/action" android:layout_width="32dp" android:layout_height="32dp" - android:layout_marginStart="16dp" + android:background="?selectableItemBackgroundBorderless" android:padding="4dp" android:visibility="gone" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="@+id/guidelineEnd" app:layout_constraintStart_toEndOf="@+id/value" app:layout_constraintTop_toTopOf="parent" - tools:src="@drawable/ic_close" /> + tools:src="@drawable/ic_close" + tools:visibility="visible" /> + app:layout_constraintGuide_end="8dp" /> \ No newline at end of file