From 7924e19fe3bbdab283deb855fe6424532b6693a2 Mon Sep 17 00:00:00 2001 From: Laurent Date: Thu, 24 Sep 2020 17:05:19 +0200 Subject: [PATCH 01/11] Changed QueryCondition single values from optional to mandatory + Details ViewModel creation and refactoring --- .../filter/RealmFilterInstrumentedUnitTest.kt | 4 +- .../calculus/bankroll/BankrollReport.kt | 8 +- .../android/exceptions/Exceptions.kt | 18 +- .../android/model/filter/Query.kt | 16 +- .../android/model/filter/QueryCondition.kt | 277 +++++++--------- .../android/model/realm/Filter.kt | 40 +-- .../android/model/realm/FilterCondition.kt | 10 +- .../modules/filter/FilterDetailsFragment.kt | 302 ++++++++++-------- .../modules/filter/FilterDetailsViewModel.kt | 116 +++++++ .../ui/modules/filter/FilterViewModel.kt | 14 +- .../ui/modules/filter/FiltersActivity.kt | 6 +- .../ui/modules/filter/FiltersFragment.kt | 8 +- .../rowrepresentable/FilterCategoryRow.kt | 8 +- .../view/rowrepresentable/FilterElementRow.kt | 112 ++++++- .../view/rowrepresentable/FilterSectionRow.kt | 182 ++++++----- 15 files changed, 681 insertions(+), 440 deletions(-) create mode 100644 app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt index f52f3e2e..022b63ec 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt @@ -24,8 +24,8 @@ class RealmFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { filter.name = "testSaveLoadCashFilter" val filterElement = QueryCondition.IsCash - filterElement.filterSectionRow = FilterSectionRow.CashOrTournament - filter.createOrUpdateFilterConditions(arrayListOf(filterElement)) +// filterElement.filterSectionRow = FilterSectionRow.CashOrTournament + filter.createOrUpdateFilterConditions(arrayListOf(filterElement), FilterSectionRow.CashOrTournament) val useCount = filter.countBy(FilterCategoryRow.GENERAL) Assert.assertEquals(1, useCount) diff --git a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt index ce66fe36..56f0be1d 100644 --- a/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt +++ b/app/src/main/java/net/pokeranalytics/android/calculus/bankroll/BankrollReport.kt @@ -220,14 +220,10 @@ class BankrollReportSetup(val bankrollId: String? = null, val from: Date? = null query.add(bankrollCondition) } this.from?.let { - val fromCondition = QueryCondition.StartedFromDate() - fromCondition.singleValue = it - query.add(fromCondition) + query.add(QueryCondition.StartedFromDate(it)) } this.to?.let { - val toCondition = QueryCondition.StartedToDate() - toCondition.singleValue = it - query.add(toCondition) + query.add(QueryCondition.StartedToDate(it)) } return query } diff --git a/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt b/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt index b12a9342..ce70fd9c 100644 --- a/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt +++ b/app/src/main/java/net/pokeranalytics/android/exceptions/Exceptions.kt @@ -1,7 +1,5 @@ package net.pokeranalytics.android.exceptions -import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow - class ModelException(message: String) : Exception(message) class FormattingException(message: String) : Exception(message) class RowRepresentableEditDescriptorException(message: String) : Exception(message) @@ -14,16 +12,16 @@ class PAIllegalStateException(message: String) : Exception(message) sealed class PokerAnalyticsException(message: String) : Exception(message) { object FilterElementUnknownName : PokerAnalyticsException(message = "No filterElement name was found to identify the queryCondition") - object FilterElementUnknownSectionName: PokerAnalyticsException(message = "No filterElement section name was found to identify the queryCondition") - object FilterMissingEntity: PokerAnalyticsException(message = "This queryWith has no entity initialized") - object FilterUnhandledEntity : PokerAnalyticsException(message = "This entity is not filterable") +// object FilterElementUnknownSectionName: PokerAnalyticsException(message = "No filterElement section name was found to identify the queryCondition") +// object FilterMissingEntity: PokerAnalyticsException(message = "This queryWith has no entity initialized") +// object FilterUnhandledEntity : PokerAnalyticsException(message = "This entity is not filterable") object QueryValueMapUnknown: PokerAnalyticsException(message = "fieldName is missing") object QueryTypeUnhandled: PokerAnalyticsException(message = "queryWith type not handled") object QueryValueMapUnexpectedValue: PokerAnalyticsException(message = "valueMap null not expected") object FilterElementExpectedValueMissing : PokerAnalyticsException(message = "queryWith is empty or null") - data class FilterElementTypeMissing(val filterElementRow: FilterElementRow) : PokerAnalyticsException(message = "queryWith element '$filterElementRow' type is missing") - data class QueryValueMapMissingKeys(val missingKeys: List) : PokerAnalyticsException(message = "valueMap does not contain $missingKeys") - data class UnknownQueryTypeForRow(val filterElementRow: FilterElementRow) : PokerAnalyticsException(message = "no queryWith type for $filterElementRow") - data class MissingFieldNameForQueryCondition(val name: String) : PokerAnalyticsException(message = "Missing fieldname for QueryCondition ${name}") - object InputFragmentException : PokerAnalyticsException(message = "RowEditableDelegate must be a Fragment") +// data class FilterElementTypeMissing(val filterElementRow: FilterElementRow) : PokerAnalyticsException(message = "queryWith element '$filterElementRow' type is missing") +// data class QueryValueMapMissingKeys(val missingKeys: List) : PokerAnalyticsException(message = "valueMap does not contain $missingKeys") +// data class UnknownQueryTypeForRow(val filterElementRow: FilterElementRow) : PokerAnalyticsException(message = "no queryWith type for $filterElementRow") +// data class MissingFieldNameForQueryCondition(val name: String) : PokerAnalyticsException(message = "Missing fieldname for QueryCondition ${name}") +// object InputFragmentException : PokerAnalyticsException(message = "RowEditableDelegate must be a Fragment") } diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt index d56f03a4..c90b16c0 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/Query.kt @@ -84,14 +84,14 @@ class Query { } // println("<<<<<< ${realmQuery.description}") - val queryLast = this.conditions.firstOrNull { - it is QueryCondition.Last - } - queryLast?.let {qc -> - (qc as QueryCondition.Last).singleValue?.let { - return realmQuery.limit(it.toLong()) - } - } +// val queryLast = this.conditions.firstOrNull { +// it is QueryCondition.Last +// } +// queryLast?.let {qc -> +// (qc as QueryCondition.Last).singleValue?.let { +// return realmQuery.limit(it.toLong()) +// } +// } return realmQuery } diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt index df26b424..f513f38d 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt @@ -16,23 +16,25 @@ import net.pokeranalytics.android.model.interfaces.Identifiable import net.pokeranalytics.android.model.interfaces.NameManageable import net.pokeranalytics.android.model.realm.* import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType +import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType -import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow -import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow +import net.pokeranalytics.android.ui.view.rowrepresentable.* import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.UserDefaults import net.pokeranalytics.android.util.extensions.* +import java.lang.Exception import java.text.DateFormatSymbols import java.text.NumberFormat import java.util.* import kotlin.collections.ArrayList +import kotlin.reflect.full.primaryConstructor /** * Enum describing the way a query should be handled * Some queries requires a value to be checked upon through equals, in, more, less, between */ -sealed class QueryCondition : FilterElementRow { +sealed class QueryCondition : RowRepresentable { companion object { inline fun more(): T { @@ -49,7 +51,15 @@ sealed class QueryCondition : FilterElementRow { fun valueOf(name: String): T { val kClass = Class.forName("${QueryCondition::class.qualifiedName}$$name").kotlin - val instance = kClass.objectInstance ?: kClass.java.newInstance() + val instance = try { + kClass.objectInstance ?: kClass.java.newInstance() + } catch (e: Exception) { + // some object instance can fail due to: java.lang.Class has no zero argument constructor + // We should have just one constructor with a single parameter + val primaryConstructor = kClass.java.declaredConstructors.first() + val param = primaryConstructor.parameterTypes.first() + primaryConstructor.newInstance(param.newInstance()) + } return instance as T } @@ -125,25 +135,29 @@ sealed class QueryCondition : FilterElementRow { abstract class ListOfValues : QueryCondition(), Comparable> where T : Comparable { - abstract var listOfValues: ArrayList + abstract var listOfValues: MutableList abstract fun labelForValue(value: T, context: Context): String open fun entityName(context: Context): String { return getDisplayName(context) } - override fun getDisplayName(context: Context): String { + fun getDisplayName(context: Context, values: List): String { val prefix = this.resId?.let { context.getString(it) + " " } ?: "" - return when (listOfValues.size) { + return when (values.size) { 0 -> return NULL_TEXT - 1, 2 -> prefix + listOfValues.map { labelForValue(it, context) }.joinToString(", ") - else -> "${listOfValues.size} $prefix ${entityName(context)}" + 1, 2 -> prefix + values.joinToString(", ") { labelForValue(it, context) } + else -> "${values.size} $prefix ${entityName(context)}" } } + override fun getDisplayName(context: Context): String { + return getDisplayName(context, this.listOfValues) + } + override fun compareTo(other: ListOfValues): Int { return listOfValues.sorted().first().compareTo(other.listOfValues.sorted().first()) } @@ -151,17 +165,18 @@ sealed class QueryCondition : FilterElementRow { fun firstValue(context: Context): String? { return this.listOfValues.firstOrNull()?.let { this.labelForValue(it, context) } } + } - abstract class SingleValue : ListOfValues() where T : Comparable { - override var listOfValues = ArrayList() - abstract var singleValue: T? + abstract class SingleValue(value: T) : ListOfValues() where T : Comparable { + override var listOfValues = mutableListOf() + var singleValue: T = value } abstract class ListOfDouble : ListOfValues() { open var sign: Int = 1 override var operator: Operator = Operator.ANY - override var listOfValues: ArrayList = arrayListOf() + override var listOfValues = mutableListOf() override fun updateValueBy(filterCondition: FilterCondition) { super.updateValueBy(filterCondition) listOfValues = filterCondition.getValues() @@ -170,11 +185,15 @@ sealed class QueryCondition : FilterElementRow { override fun labelForValue(value: Double, context: Context): String { return value.toCurrency(UserDefaults.currency) } + + override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { + return DoubleValueListFilterItemRow(this, filterSectionRow) + } } abstract class ListOfInt : ListOfValues() { override var operator: Operator = Operator.ANY - override var listOfValues: ArrayList = arrayListOf() + override var listOfValues = mutableListOf() override fun updateValueBy(filterCondition: FilterCondition) { super.updateValueBy(filterCondition) listOfValues = filterCondition.getValues() @@ -183,11 +202,15 @@ sealed class QueryCondition : FilterElementRow { override fun labelForValue(value: Int, context: Context): String { return value.toString() } + + override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { + return IntValueListFilterItemRow(this, filterSectionRow) + } } abstract class ListOfString : ListOfValues() { override var operator: Operator = Operator.ANY - override var listOfValues = ArrayList() + override var listOfValues = mutableListOf() override fun labelForValue(value: String, context: Context): String { return value } @@ -196,48 +219,42 @@ sealed class QueryCondition : FilterElementRow { super.updateValueBy(filterCondition) listOfValues = filterCondition.getValues() } + + override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { + return StringValueListFilterItemRow(this, filterSectionRow) + } } - abstract class SingleDate : SingleValue() { + abstract class SingleDate(date: Date) : SingleValue(date) { override fun labelForValue(value: Date, context: Context): String { return value.shortDate() } - override var listOfValues = ArrayList() - - override var singleValue: Date? - get() { - return listOfValues.firstOrNull() - } - set(value) { - listOfValues.removeAll(this.listOfValues) - value?.let { listOfValues.add(it) } - } + override var listOfValues = mutableListOf() override fun updateValueBy(filterCondition: FilterCondition) { super.updateValueBy(filterCondition) singleValue = filterCondition.getValue() } + + override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { + return DateFilterItemRow(this, filterSectionRow) + } } - abstract class SingleInt : SingleValue() { + abstract class SingleInt(value: Int) : SingleValue(value) { override fun labelForValue(value: Int, context: Context): String { return value.toString() } - override var singleValue: Int? - get() { - return listOfValues.firstOrNull() - } - set(value) { - listOfValues.removeAll(this.listOfValues) - value?.let { listOfValues.add(it) } - } - override fun updateValueBy(filterCondition: FilterCondition) { super.updateValueBy(filterCondition) singleValue = filterCondition.getValue() } + + override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { + return IntFilterItemRow(this, filterSectionRow) + } } override fun getDisplayName(context: Context): String { @@ -247,7 +264,7 @@ sealed class QueryCondition : FilterElementRow { return baseId } - override var filterSectionRow: FilterSectionRow = FilterSectionRow.CashOrTournament +// override var filterSectionRow: FilterSectionRow = FilterSectionRow.CashOrTournament abstract class QueryDataCondition : ListOfString() { fun setObject(dataObject: T) { @@ -263,7 +280,7 @@ sealed class QueryCondition : FilterElementRow { val completeLabel = when (listOfValues.size) { 0 -> NULL_TEXT 1, 2 -> { - listOfValues.map { labelForValue(realm, it) }.joinToString(", ") + listOfValues.joinToString(", ") { labelForValue(realm, it) } } else -> "${listOfValues.size} $entityName" } @@ -286,21 +303,19 @@ sealed class QueryCondition : FilterElementRow { val showTime: Boolean } - abstract class DateQuery : SingleDate(), DateTime { + abstract class DateQuery(date: Date) : SingleDate(date), DateTime { override val showTime: Boolean = false override fun labelForValue(value: Date, context: Context): String { - return singleValue?.let { - if (showTime) { - it.shortTime() - } else { - it.shortDate() - } - } ?: NULL_TEXT + return if (showTime) { + singleValue.shortTime() + } else { + singleValue.shortDate() + } } } - abstract class TimeQuery : DateQuery() { + abstract class TimeQuery(date: Date) : DateQuery(date) { override val showTime: Boolean = true } @@ -343,50 +358,34 @@ sealed class QueryCondition : FilterElementRow { } } - class AnyTournamentName() : QueryDataCondition() { + class AnyTournamentName : QueryDataCondition() { override val entity: Class = TournamentName::class.java - constructor(tournamentName: TournamentName) : this() { - this.setObject(tournamentName) - } - override fun entityName(context: Context): String { return context.getString(R.string.tournament_names) } } - class AnyTournamentFeature() : QueryDataCondition() { + class AnyTournamentFeature : QueryDataCondition() { override val entity: Class = TournamentFeature::class.java - constructor(tournamentFeature: TournamentFeature) : this() { - this.setObject(tournamentFeature) - } - override fun entityName(context: Context): String { return context.getString(R.string.tournament_features) } } - class AllTournamentFeature() : QueryDataCondition() { + class AllTournamentFeature : QueryDataCondition() { override var operator = Operator.ALL override val entity: Class = TournamentFeature::class.java - constructor(tournamentFeature: TournamentFeature) : this() { - this.setObject(tournamentFeature) - } - override fun entityName(context: Context): String { return context.getString(R.string.tournament_features) } } - class AnyLocation() : QueryDataCondition() { + class AnyLocation : QueryDataCondition() { override val entity: Class = Location::class.java - constructor(location: Location) : this() { - this.setObject(location) - } - override fun entityName(context: Context): String { return context.getString(R.string.locations) } @@ -440,13 +439,13 @@ sealed class QueryCondition : FilterElementRow { } } - object Last : SingleInt() { - override var operator = Operator.EQUALS - override fun getDisplayName(context: Context): String { - //TODO update string "last %i" - return "${context.getString(R.string.last_i_records)} $singleValue" - } - } +// object Last : SingleInt() { +// override var operator = Operator.EQUALS +// override fun getDisplayName(context: Context): String { +// //TODO update string "last %i" +// return "${context.getString(R.string.last_i_records)} $singleValue" +// } +// } class NumberOfTable : ListOfInt() { override fun labelForValue(value: Int, context: Context): String { @@ -507,19 +506,19 @@ sealed class QueryCondition : FilterElementRow { } } - class StartedFromDate : DateQuery() { + class StartedFromDate(date: Date) : DateQuery(date) { override var operator = Operator.MORE } - class StartedToDate : DateQuery() { + class StartedToDate(date: Date) : DateQuery(date) { override var operator = Operator.LESS } - class EndedFromDate : DateQuery() { + class EndedFromDate(date: Date) : DateQuery(date) { override var operator = Operator.MORE } - class EndedToDate : DateQuery() { + class EndedToDate(date: Date) : DateQuery(date) { override var operator = Operator.LESS } @@ -564,7 +563,7 @@ sealed class QueryCondition : FilterElementRow { } } - class PastDay : SingleInt() { + class PastDay(value: Int) : SingleInt(value) { override var operator = Operator.EQUALS override val viewType: Int = RowViewType.TITLE_VALUE_CHECK.ordinal @@ -579,9 +578,10 @@ sealed class QueryCondition : FilterElementRow { } } - class Duration : SingleInt() { + class Duration(value: Int) : SingleInt(value) { override var operator = Operator.EQUALS - var minutes: Int? + + var minutes: Int get() { return singleValue } @@ -589,12 +589,9 @@ sealed class QueryCondition : FilterElementRow { singleValue = value } - val netDuration: Long? + val netDuration: Long get() { - minutes?.let { - return (it * 60 * 1000).toLong() - } - return null + return (singleValue * 60 * 1000).toLong() } override val viewType: Int = RowViewType.TITLE_VALUE_CHECK.ordinal @@ -609,21 +606,21 @@ sealed class QueryCondition : FilterElementRow { object EndDateNotNull : NotNullQueryCondition() object BigBlindNotNull : NotNullQueryCondition() - class StartedFromTime() : TimeQuery() { + class StartedFromTime(date: Date) : TimeQuery(date) { override var operator = Operator.MORE - constructor(date: Date) : this() { - singleValue = date - } +// constructor(date: Date) : this() { +// singleValue = date +// } } - class EndedToTime() : TimeQuery() { + class EndedToTime(date: Date) : TimeQuery(date) { override var operator = Operator.LESS - constructor(date: Date) : this() { - singleValue = date - } +// constructor(date: Date) : this() { +// singleValue = date +// } } @@ -641,10 +638,6 @@ sealed class QueryCondition : FilterElementRow { class CustomFieldQuery() : QueryDataCondition() { override var entity: Class = CustomField::class.java - - constructor(customField: CustomField) : this() { - this.setObject(customField) - } } open class CustomFieldNumberQuery() : ListOfDouble(), CustomFieldRelated { @@ -712,6 +705,10 @@ sealed class QueryCondition : FilterElementRow { } } + open fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { + return BaseFilterItemRow(this, filterSectionRow) + } + /** * main method of the enum * providing a base RealmQuery [realmQuery], the method is able to attached the corresponding query and returns the newly formed [RealmQuery] @@ -762,15 +759,12 @@ sealed class QueryCondition : FilterElementRow { .lessThanOrEqualTo(fieldName, calendar.time.endOfDay()) } is PastDay -> { - singleValue?.let { - val startDate = Date() - val calendar = Calendar.getInstance() - calendar.time = startDate - calendar.add(Calendar.DAY_OF_YEAR, -it) - return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and() - .lessThanOrEqualTo(fieldName, startDate.endOfDay()) - } - return realmQuery + val startDate = Date() + val calendar = Calendar.getInstance() + calendar.time = startDate + calendar.add(Calendar.DAY_OF_YEAR, -singleValue) + return realmQuery.greaterThanOrEqualTo(fieldName, calendar.time.startOfDay()).and() + .lessThanOrEqualTo(fieldName, startDate.endOfDay()) } is DuringThisWeek -> { val calendar = Calendar.getInstance() @@ -800,29 +794,21 @@ sealed class QueryCondition : FilterElementRow { } is StartedFromTime -> { val calendar = Calendar.getInstance() - singleValue?.let { - calendar.time = it - realmQuery.greaterThanOrEqualTo(fieldName, calendar.hourMinute()) - if (otherQueryCondition is EndedToTime) { - otherQueryCondition.singleValue?.let { endTime -> - calendar.time = endTime - realmQuery.lessThanOrEqualTo(fieldName, calendar.hourMinute()) - } - } + calendar.time = singleValue + realmQuery.greaterThanOrEqualTo(fieldName, calendar.hourMinute()) + if (otherQueryCondition is EndedToTime) { + calendar.time = otherQueryCondition.singleValue + realmQuery.lessThanOrEqualTo(fieldName, calendar.hourMinute()) } return realmQuery } is EndedToTime -> { val calendar = Calendar.getInstance() - singleValue?.let { date -> - calendar.time = date - realmQuery.lessThanOrEqualTo(fieldName, calendar.hourMinute()) - if (otherQueryCondition is StartedFromTime) { - otherQueryCondition.singleValue?.let { startTime -> - calendar.time = startTime - realmQuery.greaterThanOrEqualTo(fieldName, calendar.hourMinute()) - } - } + calendar.time = singleValue + realmQuery.lessThanOrEqualTo(fieldName, calendar.hourMinute()) + if (otherQueryCondition is StartedFromTime) { + calendar.time = otherQueryCondition.singleValue + realmQuery.greaterThanOrEqualTo(fieldName, calendar.hourMinute()) } return realmQuery } @@ -846,14 +832,8 @@ sealed class QueryCondition : FilterElementRow { return when (operator) { Operator.EQUALS -> { when (this) { - is SingleDate -> realmQuery.equalTo( - fieldName, - singleValue ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing - ) - is SingleInt -> realmQuery.equalTo( - fieldName, - singleValue ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing - ) + is SingleDate -> realmQuery.equalTo(fieldName, singleValue) + is SingleInt -> realmQuery.equalTo(fieldName, singleValue) is ListOfInt -> realmQuery.equalTo(fieldName, listOfValues.first()) is ListOfDouble -> realmQuery.equalTo(fieldName, listOfValues.first() * sign) is ListOfString -> realmQuery.equalTo(fieldName, listOfValues.first()) @@ -862,20 +842,11 @@ sealed class QueryCondition : FilterElementRow { } Operator.MORE -> { when (this) { - is SingleDate -> realmQuery.greaterThanOrEqualTo( - fieldName, - singleValue?.startOfDay() ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing - ) - is Duration -> realmQuery.greaterThan( - fieldName, - netDuration ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing - ) + is SingleDate -> realmQuery.greaterThanOrEqualTo(fieldName, singleValue.startOfDay()) + is Duration -> realmQuery.greaterThan(fieldName, netDuration) is TournamentFinalPosition -> realmQuery.greaterThanOrEqualTo(fieldName, listOfValues.first()) is TournamentNumberOfPlayer -> realmQuery.greaterThanOrEqualTo(fieldName, listOfValues.first()) - is SingleInt -> realmQuery.greaterThan( - fieldName, - singleValue ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing - ) + is SingleInt -> realmQuery.greaterThan(fieldName, singleValue) is ListOfInt -> realmQuery.greaterThan(fieldName, listOfValues.first()) is NetAmountLost -> realmQuery.lessThan(fieldName, listOfValues.first() * -1) is ListOfDouble -> realmQuery.greaterThan(fieldName, listOfValues.first() * sign) @@ -884,20 +855,11 @@ sealed class QueryCondition : FilterElementRow { } Operator.LESS -> { when (this) { - is SingleDate -> realmQuery.lessThanOrEqualTo( - fieldName, - singleValue?.endOfDay() ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing - ) - is Duration -> realmQuery.lessThan( - fieldName, - netDuration ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing - ) + is SingleDate -> realmQuery.lessThanOrEqualTo(fieldName, singleValue.endOfDay()) + is Duration -> realmQuery.lessThan(fieldName, netDuration) is TournamentFinalPosition -> realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first()) is TournamentNumberOfPlayer -> realmQuery.lessThanOrEqualTo(fieldName, listOfValues.first()) - is SingleInt -> realmQuery.lessThan( - fieldName, - singleValue ?: throw PokerAnalyticsException.FilterElementExpectedValueMissing - ) + is SingleInt -> realmQuery.lessThan(fieldName, singleValue) is ListOfInt -> realmQuery.lessThan(fieldName, listOfValues.first()) is NetAmountLost -> { realmQuery.greaterThan(fieldName, listOfValues.first() * -1) @@ -947,6 +909,7 @@ sealed class QueryCondition : FilterElementRow { } } + override val viewType: Int get() { return when (this) { 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 f23db5bd..5dc1487c 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 @@ -17,6 +17,7 @@ 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.FilterCategoryRow +import net.pokeranalytics.android.ui.view.rowrepresentable.FilterItemRow import timber.log.Timber import java.util.* @@ -89,22 +90,25 @@ open class Filter : RealmObject(), RowRepresentable, Editable, Deletable, Counta return FilterableType.ALL } - fun createOrUpdateFilterConditions(filterConditionRows: ArrayList) { - Timber.d("list of querys saving: ${filterConditionRows.map { it.id }}") + fun createOrUpdateFilterConditions(filterConditionRows: List) { + + Timber.d("list of querys saving: ${filterConditionRows.map { it.queryCondition?.id }}") Timber.d("list of querys previous: ${this.filterConditions.map { it.queryCondition.id }}") + filterConditionRows - .map { - it.groupId + .mapNotNull { + it.queryCondition?.groupId } .distinct() .forEach { groupId -> filterConditionRows .filter { - it.groupId == groupId + it.queryCondition?.groupId == groupId } .apply { - Timber.d("list of querys: ${this.map { it.id }}") - val newFilterCondition = FilterCondition(this) + val conditions = this.mapNotNull { it.queryCondition } + Timber.d("list of querys: ${conditions.map { it.id }}") + val newFilterCondition = FilterCondition(conditions, this.first().filterSectionRow) val previousCondition = filterConditions.filter { it.filterName == newFilterCondition.filterName && it.operator == newFilterCondition.operator } @@ -136,17 +140,17 @@ open class Filter : RealmObject(), RowRepresentable, Editable, Deletable, Counta return contained } - /** - * Get the saved value for the given [filterElementRow] - */ - fun loadValueForElement(filterElementRow: QueryCondition) { - val filtered = filterConditions.filter { - it.queryCondition.id == filterElementRow.id - } - if (filtered.isNotEmpty()) { - return filterElementRow.updateValueBy(filtered.first()) - } - } +// /** +// * Get the saved value for the given [filterElementRow] +// */ +// fun loadValueForElement(filterElementRow: QueryCondition) { +// val filtered = filterConditions.filter { +// it.queryCondition.id == filterElementRow.id +// } +// if (filtered.isNotEmpty()) { +// return filterElementRow.updateValueBy(filtered.first()) +// } +// } inline fun query(firstField: String? = null, vararg remainingFields: String): RealmQuery { val realmQuery = realm.where() diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt index 3a4f1538..7bf65944 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt @@ -4,17 +4,18 @@ import io.realm.RealmList import io.realm.RealmObject import net.pokeranalytics.android.exceptions.PokerAnalyticsException import net.pokeranalytics.android.model.filter.QueryCondition +import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow import java.util.* import kotlin.collections.ArrayList open class FilterCondition() : RealmObject() { - private constructor(filterName:String, sectionName:String) : this() { + private constructor(filterName: String, sectionName: String) : this() { this.filterName = filterName this.sectionName = sectionName } - constructor(filterElementRows: List) : this(filterElementRows.first().baseId, filterElementRows.first().filterSectionRow.name) { + constructor(filterElementRows: List, section: FilterSectionRow) : this(filterElementRows.first().baseId, section.name) { val row = filterElementRows.first() this.filterName ?: throw PokerAnalyticsException.FilterElementUnknownName this.operator = row.operator.ordinal @@ -22,8 +23,8 @@ open class FilterCondition() : RealmObject() { this.stringValue = row.customFieldId } when (row) { - is QueryCondition.SingleInt -> this.setValue(row.singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) - is QueryCondition.SingleDate -> this.setValue(row.singleValue?:throw PokerAnalyticsException.FilterElementExpectedValueMissing) + is QueryCondition.SingleInt -> this.setValue(row.singleValue) + is QueryCondition.SingleDate -> this.setValue(row.singleValue) is QueryCondition.ListOfDouble -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfDouble).listOfValues }) is QueryCondition.ListOfInt -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfInt).listOfValues }) is QueryCondition.ListOfString -> this.setValues(filterElementRows.flatMap { (it as QueryCondition.ListOfString).listOfValues }) @@ -91,4 +92,5 @@ open class FilterCondition() : RealmObject() { fun setValue(value:String) { stringValue = value } + } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt index 5e5794a7..4d6ef051 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt @@ -1,6 +1,5 @@ package net.pokeranalytics.android.ui.modules.filter -import android.content.Context import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -10,34 +9,38 @@ import androidx.recyclerview.widget.LinearLayoutManager import kotlinx.android.synthetic.main.fragment_filter_details.* import kotlinx.android.synthetic.main.fragment_filter_details.view.* import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate -import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.helpers.DateTimePickerManager import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType -import net.pokeranalytics.android.ui.view.rowrepresentable.FilterElementRow -import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow -import net.pokeranalytics.android.util.NULL_TEXT +import net.pokeranalytics.android.ui.view.rowrepresentable.* import timber.log.Timber import java.util.* -import kotlin.collections.ArrayList -open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { +open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { - val model: FilterViewModel by lazy { + private val activityModel: FilterViewModel by lazy { ViewModelProvider(requireActivity()).get(FilterViewModel::class.java) } + private lateinit var model: FilterDetailsViewModel private lateinit var rowRepresentableAdapter: RowRepresentableAdapter -// private var currentFilter: Filter? = null - private var rows: ArrayList = ArrayList() - private var rowsForFilterSubcategoryRow: HashMap> = HashMap() + companion object { - private val selectedRows = ArrayList() + fun newInstance(categoryRow: FilterCategoryRow): FilterDetailsFragment { + val fragment = FilterDetailsFragment() + val bundle = Bundle() + bundle.putInt(BundleKey.DATA_TYPE.value, categoryRow.ordinal) + fragment.arguments = bundle + return fragment + } + + } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) @@ -57,7 +60,6 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSo // requireFragmentManager().popBackStackImmediate() } - /** * Init UI */ @@ -80,39 +82,27 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSo */ private fun initData() { -// this.arguments?.let { bundle -> -// -// bundle.getString(BundleKey.PRIMARY_KEY.value)?.let { filterId -> -// this.currentFilter = getRealm().findById(filterId) -// } -// -// val category = bundle.getInt(BundleKey.DATA_TYPE.value) -// this.filterCategoryRow = FilterCategoryRow.values()[category] -// -// } ?: throw PAIllegalStateException("Missing bundle") + this.arguments?.let { bundle -> - //currentFilter = Filter.getFilterBydId(getRealm(), primaryKey) -// currentFilter = FiltersFragment.currentFilter + val filter = this.activityModel.currentFilter ?: throw PAIllegalStateException("Filter is null") + val category = bundle.getInt(BundleKey.DATA_TYPE.value) + val categoryRow = FilterCategoryRow.values()[category] + Timber.d("Category row = $categoryRow") - Timber.d(">> Filter = ${this.model.currentFilter}") - Timber.d("selectedRow = ${this.model.selectedCategoryRow}") + val factory = FilterDetailsViewModelFactory(filter, categoryRow) + this.model = ViewModelProvider(this, factory).get(FilterDetailsViewModel::class.java) - val filterCategoryRow = this.model.filterCategoryRow + } ?: throw PAIllegalStateException("Missing bundle") - this.appBar.toolbar.title = filterCategoryRow.localizedTitle(requireContext()) + //currentFilter = Filter.getFilterBydId(getRealm(), primaryKey) +// currentFilter = FiltersFragment.currentFilter - this.rows.clear() - this.rowsForFilterSubcategoryRow.clear() - this.rows.addAll(filterCategoryRow.filterElements) + Timber.d(">> Filter = ${this.activityModel.currentFilter}") + Timber.d("selectedRow = ${this.activityModel.selectedCategoryRow}") - this.rows.forEach { element -> - if (element is QueryCondition && this.model.currentFilter?.contains(element) == true) { - this.model.currentFilter?.loadValueForElement(element) - this.selectedRows.add(element) - } - } + this.appBar.toolbar.title = this.activityModel.selectedCategoryRow?.localizedTitle(requireContext()) - this.rowRepresentableAdapter = RowRepresentableAdapter(this, this) + this.rowRepresentableAdapter = RowRepresentableAdapter(this.model, this) this.recyclerView.adapter = rowRepresentableAdapter } @@ -125,48 +115,78 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSo } when (row) { - is QueryCondition.DateQuery -> DateTimePickerManager.create( - requireContext(), - row, - this, - row.singleValue, - onlyDate = !row.showTime, - onlyTime = row.showTime - ) - is QueryCondition.Duration -> { - var hours: String? = null - var minutes: String? = null - row.minutes?.let { - hours = if (it / 60 > 0) (it / 60).toString() else null - minutes = if (it % 60 > 0) (it % 60).toString() else null + is DateFilterItemRow -> { + when (val condition = row.rawCondition) { + is QueryCondition.DateQuery -> DateTimePickerManager.create( + requireContext(), + row, + this, + row.value, + onlyDate = !condition.showTime, + onlyTime = condition.showTime + ) + } + } + is IntFilterItemRow -> { + when (val condition = row.rawCondition) { + is QueryCondition.Duration -> { + val hours: String? = (condition.minutes / 60).toString() + val minutes: String? = (condition.minutes % 60).toString() + val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) + showBottomSheet(row, this, data, true) + } } - val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) - showBottomSheet(row, this, data, true) } - is QueryCondition.ListOfValues<*> -> { - var valueAsString: String? = null - row.listOfValues.firstOrNull()?.let { - valueAsString = row.listOfValues.firstOrNull()?.toString() + is ValueListFilterItemRow<*> -> { + when (row.rawCondition) { + is QueryCondition.ListOfValues<*> -> { + var valueAsString: String? = null + row.list.firstOrNull()?.let { + valueAsString = row.list.firstOrNull()?.toString() + } + val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) + showBottomSheet(row, this, data, true) + } } - val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) - showBottomSheet(row, this, data, true) } } - } - override fun charSequenceForRow(row: RowRepresentable, context: Context): CharSequence { - return when (row) { - is QueryCondition.ListOfValues<*> -> row.firstValue(context) - else -> super.charSequenceForRow(row, context, 0) - } ?: NULL_TEXT - } - override fun isSelected( - position: Int, - row: RowRepresentable, - tag: Int - ): Boolean { - return selectedRows.contains(row) +// (row as? BaseFilterItemRow)?.let { filterItemRow -> +// val rawCondition = filterItemRow.rawCondition +// when (rawCondition) { +// is QueryCondition.DateQuery -> DateTimePickerManager.create( +// requireContext(), +// row, +// this, +// filterItemRow.value, +// onlyDate = !row.showTime, +// onlyTime = row.showTime +// ) +// is QueryCondition.Duration -> { +// val hours: String? = (row.minutes / 60).toString() +// val minutes: String? = (row.minutes % 60).toString() +//// row.minutes?.let { +//// hours = if (it / 60 > 0) (it / 60).toString() else null +//// minutes = if (it % 60 > 0) (it % 60).toString() else null +//// } +// val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) +// showBottomSheet(row, this, data, true) +// } +// is QueryCondition.ListOfValues<*> -> { +// var valueAsString: String? = null +// row.listOfValues.firstOrNull()?.let { +// valueAsString = row.listOfValues.firstOrNull()?.toString() +// } +// val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) +// showBottomSheet(row, this, data, true) +// } +// else -> { } +// } +// +// } + + } override fun onRowValueChanged(value: Any?, row: RowRepresentable) { @@ -174,80 +194,89 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSo Timber.d("onRowValueChanged: $row $value") when (row) { - is QueryCondition.DateQuery -> row.singleValue = if (value != null && value is Date) value else null - is QueryCondition.Duration -> { - if (value is ArrayList<*>) { - val hours: Int? = try { - (value[0] as String?)?.toInt() - } catch (e: Exception) { - null - } - val minutes = try { - (value[1] as String?)?.toInt() - } catch (e: Exception) { - null + is DateFilterItemRow -> { + row.value = value as Date + } + is IntFilterItemRow -> { + when (value) { + is Int -> { + row.value = value } - if (hours != null && minutes != null) { - row.minutes = hours * 60 + minutes - } else if (hours != null) { - row.minutes = hours * 60 - } else if (minutes != null) { - row.minutes = minutes + is ArrayList<*> -> { + val hours: Int? = try { + (value[0] as String?)?.toInt() + } catch (e: Exception) { + null + } + val minutes = try { + (value[1] as String?)?.toInt() + } catch (e: Exception) { + null + } + if (hours != null && minutes != null) { + row.value = hours * 60 + minutes + } else if (hours != null) { + row.value = hours * 60 + } else if (minutes != null) { + row.value = minutes + } } - } else { - row.minutes = null } } - is QueryCondition.SingleInt -> row.singleValue = if (value != null && value is String) value.toInt() else null - is QueryCondition.ListOfDouble -> row.listOfValues = arrayListOf().apply { - if (value != null && value is String) this.add(value.toDouble()) + is DoubleValueListFilterItemRow -> { + val string = value as String + row.add(string.toDouble()) } - is QueryCondition.ListOfInt -> row.listOfValues = arrayListOf().apply { - if (value != null && value is String) this.add(value.toInt()) + is IntValueListFilterItemRow -> { + val string = value as String + row.add(string.toInt()) } - is QueryCondition.ListOfString -> row.listOfValues = arrayListOf().apply { - if (value != null && value is String) this.add(value) + is StringValueListFilterItemRow -> { + row.add(value as String) } } +// when (row) { +// is QueryCondition.DateQuery -> { +// if (value != null && value is Date) { +// row.singleValue = value +// } +// } +// is QueryCondition.Duration -> { +// if (value is ArrayList<*>) { +// +// } +// } +// is QueryCondition.SingleInt -> { +// if (value != null && value is String) { +// row.singleValue = value.toInt() +// } +// } +// is QueryCondition.ListOfDouble -> row.listOfValues = arrayListOf().apply { +// if (value != null && value is String) this.add(value.toDouble()) +// } +// is QueryCondition.ListOfInt -> row.listOfValues = arrayListOf().apply { +// if (value != null && value is String) this.add(value.toInt()) +// } +// is QueryCondition.ListOfString -> row.listOfValues = arrayListOf().apply { +// if (value != null && value is String) this.add(value) +// } +// } + // Remove the row before updating the selected rows list - selectedRows.remove(row as FilterElementRow) + this.model.selectedRows.remove(row as FilterItemRow) updateRowsSelection(row, value == null) } - override fun adapterRows(): List? { - return rows - } - - override fun viewTypeForPosition(position: Int): Int { - val rowViewType = rowRepresentableForPosition(position)?.viewType ?: -1 - return if (rowViewType != -1) rowViewType else RowViewType.TITLE_CHECK.ordinal - } - /** * Update rows selection */ private fun updateRowsSelection(row: RowRepresentable, forceDeselection: Boolean = false) { - if (selectedRows.contains(row) || forceDeselection) { - selectedRows.remove(row) - } else { - if (row is FilterElementRow) { - row.sectionToExclude?.let { filterSectionToExclude -> - val excludedFilters = selectedRows.filter { - filterSectionToExclude.contains(it.filterSectionRow) - } - excludedFilters.forEach { - selectedRows.remove(it) - rowRepresentableAdapter.refreshRow(it) - } - } - selectedRows.add(row as QueryCondition) - } - } + this.model.updateRowsSelection(this.rowRepresentableAdapter, row, forceDeselection) - println("list of selected rows : $selectedRows") +// println("list of selected rows : $selectedRows") // Update UI this.rowRepresentableAdapter.refreshRow(row) @@ -258,18 +287,23 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSo */ private fun saveData() { - val currentFilter = this.model.currentFilter + val currentFilter = this.activityModel.currentFilter //TODO: Save currentFilter details data Timber.d("Save data for queryWith: ${currentFilter?.id}") - this.selectedRows.forEach { + this.model.selectedRows.forEach { Timber.d("Selected rows: $it") } - getRealm().executeTransaction { - currentFilter?.remove(this.model.filterCategoryRow) - currentFilter?.createOrUpdateFilterConditions(this.selectedRows) - } + this.activityModel.selectedCategoryRow?.let { category -> + + getRealm().executeTransaction { + currentFilter?.remove(category) + val validConditions = this.model.selectedRows.filter { it.queryCondition != null } + currentFilter?.createOrUpdateFilterConditions(validConditions) + } + } + currentFilter?.filterConditions?.forEach { Timber.d("Condition: $it") } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt new file mode 100644 index 00000000..ba9885b0 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt @@ -0,0 +1,116 @@ +package net.pokeranalytics.android.ui.modules.filter + +import android.content.Context +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import net.pokeranalytics.android.model.filter.QueryCondition +import net.pokeranalytics.android.model.realm.Filter +import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter +import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource +import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.ui.view.RowViewType +import net.pokeranalytics.android.ui.view.rowrepresentable.BaseFilterItemRow +import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow +import net.pokeranalytics.android.ui.view.rowrepresentable.FilterItemRow +import net.pokeranalytics.android.ui.view.rowrepresentable.ValueListFilterItemRow +import net.pokeranalytics.android.util.NULL_TEXT +import timber.log.Timber + +class FilterDetailsViewModelFactory(var filter: Filter, var categoryRow: FilterCategoryRow): ViewModelProvider.Factory { + + override fun create(modelClass: Class): T { + return FilterDetailsViewModel(categoryRow, filter) as T + } + +} + +class FilterDetailsViewModel(categoryRow: FilterCategoryRow, var filter: Filter) : ViewModel(), StaticRowRepresentableDataSource { + + private var rows: ArrayList = ArrayList() + val selectedRows = ArrayList() + +// private var rowsForFilterSubcategoryRow: HashMap> = +// HashMap() + + init { + this.rows.addAll(categoryRow.filterElements) + this.defineSelectedItems() + } + + override fun adapterRows(): List? { + return this.rows + } + + override fun charSequenceForRow(row: RowRepresentable, context: Context): CharSequence { + + val filterItemRow = row as? BaseFilterItemRow + filterItemRow?.let { + return when (val condition = it.rawCondition) { + is QueryCondition.ListOfValues<*> -> condition.firstValue(context) ?: NULL_TEXT + else -> super.charSequenceForRow(row, context, 0) + } + } + return NULL_TEXT + +// return when (row) { +// is BaseFilterItemRow -> { +// +// } +// is QueryCondition.ListOfValues<*> -> row.firstValue(context) +// else -> super.charSequenceForRow(row, context, 0) +// } ?: NULL_TEXT + } + + override fun isSelected(position: Int, row: RowRepresentable, tag: Int): Boolean { + return this.selectedRows.contains(row) + } + + override fun viewTypeForPosition(position: Int): Int { + val rowRepresentable = rowRepresentableForPosition(position) + val rowViewType = rowRepresentable?.viewType ?: -1 +// Timber.d("found viewtype = $rowViewType, rr = $rowRepresentable") + return if (rowViewType != -1) rowViewType else RowViewType.TITLE_CHECK.ordinal + } + + private fun defineSelectedItems() { + this.rows.filterIsInstance().forEach { item -> + + val condition = item.queryCondition + if (condition != null && this.filter.contains(condition)) { + + // Load items with appropriate value + this.filter.filterConditions.firstOrNull { + it.queryCondition.id == condition.id + }?.let { + item.updateValue(it) +// item.queryCondition?.updateValueBy(it) + this.selectedRows.add(item) + } + } + + } + + } + + fun updateRowsSelection(adapter: RowRepresentableAdapter, row: RowRepresentable, forceDeselection: Boolean = false) { + + if (this.selectedRows.contains(row) || forceDeselection) { + this.selectedRows.remove(row) + } else { + if (row is FilterItemRow) { + row.sectionToExclude?.let { filterSectionToExclude -> + val excludedFilters = this.selectedRows.filter { + filterSectionToExclude.contains(it.filterSectionRow) + } + excludedFilters.forEach { + this.selectedRows.remove(it) + adapter.refreshRow(it) + } + } + this.selectedRows.add(row) + } + } + + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterViewModel.kt index 450c633a..b3e4661d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterViewModel.kt @@ -20,14 +20,16 @@ class FilterViewModel : ViewModel(), StaticRowRepresentableDataSource { var filterCopy: Filter? = null private var categoryRows: ArrayList = ArrayList() var primaryKey: String? = null - var selectedCategoryRow: RowRepresentable? = null + + var selectedCategoryRow: FilterCategoryRow? = null + var isUpdating = false - // Details - val filterCategoryRow: FilterCategoryRow - get() { - return this.selectedCategoryRow as FilterCategoryRow - } + +// val filterCategoryRow: FilterCategoryRow +// get() { +// return this.selectedCategoryRow as FilterCategoryRow +// } fun init(realm: Realm) { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersActivity.kt index 8bb9d5a8..b4ff29bd 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersActivity.kt @@ -6,8 +6,10 @@ import android.os.Bundle import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.ui.activity.components.BaseActivity import net.pokeranalytics.android.ui.fragment.components.BaseFragment +import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow class FiltersActivity : BaseActivity() { @@ -102,9 +104,9 @@ class FiltersActivity : BaseActivity() { } - fun showDetailsFragment() { + fun showDetailsFragment(categoryRow: FilterCategoryRow) { - val detailsFragment = FilterDetailsFragment() + val detailsFragment = FilterDetailsFragment.newInstance(categoryRow) val fragmentTransaction = this.supportFragmentManager.beginTransaction() fragmentTransaction.replace(R.id.container, detailsFragment) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt index 88b5894a..57e610b3 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt @@ -21,6 +21,7 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.view.RowRepresentable +import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.extensions.sorted import timber.log.Timber @@ -148,10 +149,11 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate { override fun onRowSelected(position: Int, row: RowRepresentable, tag: Int) { super.onRowSelected(position, row, tag) - this.model.selectedCategoryRow = row - this.model.currentFilter?.id?.let { _ -> + val categoryRow = row as FilterCategoryRow + this.model.selectedCategoryRow = categoryRow + this.model.currentFilter?.let { _ -> - (activity as FiltersActivity).showDetailsFragment() + (activity as FiltersActivity).showDetailsFragment(categoryRow) // this.model.filterCategoryRow = row as FilterCategoryRow diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterCategoryRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterCategoryRow.kt index 362001bc..362c09a5 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterCategoryRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterCategoryRow.kt @@ -63,7 +63,13 @@ enum class FilterCategoryRow(override val resId: Int?, override val viewType: In val filterElements: List get() { return filterSectionRows.flatMap { - it.filterElements + val items = it.filterItems + val list = mutableListOf() + if (items.isNotEmpty()) { + list.add(it) + list.addAll(it.filterItems) + } + list } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt index 43860b3a..dc6cc88d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt @@ -1,17 +1,22 @@ package net.pokeranalytics.android.ui.view.rowrepresentable +import android.content.Context import android.text.InputType import net.pokeranalytics.android.R import net.pokeranalytics.android.model.filter.QueryCondition +import net.pokeranalytics.android.model.realm.FilterCondition 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 java.util.* -interface FilterElementRow : RowRepresentable { +interface FilterItemRow : RowRepresentable { + + val queryCondition: QueryCondition? + var filterSectionRow: FilterSectionRow + override fun editingDescriptors(map: Map): ArrayList? { - return when (this) { + return when (this.queryCondition) { is QueryCondition.Duration -> { val hours: String? by map val minutes: String? by map @@ -22,9 +27,9 @@ interface FilterElementRow : RowRepresentable { } is QueryCondition.ListOfValues<*> -> { val valueAsString: String? by map - val hint = when (this.operator) { + val hint = when (this.queryCondition?.operator) { QueryCondition.Operator.MORE, QueryCondition.Operator.LESS -> { - when (this) { + when (this.queryCondition) { is QueryCondition.CustomFieldNumberQuery -> R.string.value is QueryCondition.CustomFieldAmountQuery -> R.string.amount else -> this.filterSectionRow.resId @@ -41,7 +46,7 @@ interface FilterElementRow : RowRepresentable { } } - var filterSectionRow: FilterSectionRow + fun updateValue(it: FilterCondition) { } val sectionToExclude: List? get() { @@ -58,4 +63,97 @@ interface FilterElementRow : RowRepresentable { } return null } -} \ No newline at end of file +} + +open class BaseFilterItemRow(queryCondition: QueryCondition, override var filterSectionRow: FilterSectionRow) : FilterItemRow { + + var rawCondition: QueryCondition = queryCondition + private set + + override val queryCondition: QueryCondition? + get() { return rawCondition } + + // Row Representable + + override fun getDisplayName(context: Context): String { + return this.rawCondition.getDisplayName(context) + } + + override val viewType: Int + get() { return this.rawCondition.viewType } + + override val bottomSheetType: BottomSheetType + get() { return this.rawCondition.bottomSheetType } + +} + + +abstract class ValueFilterItemRow>(queryCondition: QueryCondition.SingleValue, filterSectionRow: FilterSectionRow): BaseFilterItemRow(queryCondition, filterSectionRow) { + + private var valueCondition: QueryCondition.SingleValue = queryCondition + + var value: T? = null + + override val queryCondition: QueryCondition? + get() { + value?.let { + valueCondition.singleValue = it + return valueCondition + } + return null + } + + override fun updateValue(fc: FilterCondition) { + + // TODO + +// this.value = fc.queryCondition. + + } + +} + +abstract class ValueListFilterItemRow>(queryCondition: QueryCondition.ListOfValues, filterSectionRow: FilterSectionRow): BaseFilterItemRow(queryCondition, filterSectionRow) { + + private var listCondition: QueryCondition.ListOfValues = queryCondition + + var list: MutableList = mutableListOf() + private set + + fun add(value: T) { + this.list.add(value) + } + + override val queryCondition: QueryCondition? + get() { + return if (list.isNotEmpty()) { + listCondition.listOfValues = list + listCondition + } else { + null + } + } + +// override fun getDisplayName(context: Context): String { +// return this.listCondition.getDisplayName(context, this.list) +// } + + override fun updateValue(fc: FilterCondition) { + + // TODO + +// this.value = fc.queryCondition. + + } +} + +class DateFilterItemRow(queryCondition: QueryCondition.SingleDate, filterSectionRow: FilterSectionRow): ValueFilterItemRow(queryCondition, filterSectionRow) +class IntFilterItemRow(queryCondition: QueryCondition.SingleInt, filterSectionRow: FilterSectionRow): ValueFilterItemRow(queryCondition, filterSectionRow) + +class IntValueListFilterItemRow(queryCondition: QueryCondition.ListOfInt, filterSectionRow: FilterSectionRow): ValueListFilterItemRow(queryCondition, filterSectionRow) +class DoubleValueListFilterItemRow(queryCondition: QueryCondition.ListOfDouble, filterSectionRow: FilterSectionRow): ValueListFilterItemRow(queryCondition, filterSectionRow) +class StringValueListFilterItemRow(queryCondition: QueryCondition.ListOfString, filterSectionRow: FilterSectionRow): ValueListFilterItemRow(queryCondition, filterSectionRow) + +//interface FilterElementRow : RowRepresentable { +// +//} \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt index 319eee8d..b058aeaf 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterSectionRow.kt @@ -8,6 +8,7 @@ import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.filter.mapFirstCondition import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType +import java.util.* sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable { object CashOrTournament: FilterSectionRow(R.string.cash_or_tournament) @@ -69,101 +70,118 @@ sealed class FilterSectionRow(override val resId: Int?) : RowRepresentable { val allowMultiSelection: Boolean get() = (this.selectionType == SelectionType.MULTIPLE) - val filterElements: List + val filterItems: List get() { + return this.queryConditions.map { + it.toRowWrapper(this@FilterSectionRow) + } + } + + private val queryConditions: List + get() { + return when (this@FilterSectionRow) { + // General + CashOrTournament -> Criteria.SessionTypes.queryConditions.mapFirstCondition() + LiveOrOnline -> Criteria.BankrollTypes.queryConditions.mapFirstCondition() + Game -> Criteria.Games.queryConditions.mapFirstCondition() + LimitType -> Criteria.Limits.queryConditions.mapFirstCondition() + TableSize -> Criteria.TableSizes.queryConditions.mapFirstCondition() + // Date + DynamicDate -> arrayListOf( + QueryCondition.IsToday, + QueryCondition.WasYesterday, + QueryCondition.WasTodayAndYesterday, + QueryCondition.DuringThisWeek, + QueryCondition.DuringThisMonth, + QueryCondition.DuringThisYear + ) + WeekdayOrWeekend -> arrayListOf(QueryCondition.IsWeekDay, QueryCondition.IsWeekEnd) + Year -> Criteria.Years.queryConditions.mapFirstCondition() + DayOfWeek -> Criteria.DaysOfWeek.queryConditions.mapFirstCondition() + MonthOfYear -> Criteria.MonthsOfYear.queryConditions.mapFirstCondition() + + // Duration + SessionDuration -> QueryCondition.moreOrLess() + + FixedDate -> arrayListOf(QueryCondition.StartedFromDate(Date()), QueryCondition.EndedToDate(Date())) // dummy constructor values + Duration -> arrayListOf(QueryCondition.PastDay(0)) // dummy constructor values + TimeFrameRange -> arrayListOf(QueryCondition.StartedFromTime(Date()), QueryCondition.EndedToTime(Date())) // dummy constructor values - val data = arrayListOf().apply { - this.addAll( - when (this@FilterSectionRow) { - - // General - CashOrTournament -> Criteria.SessionTypes.queryConditions.mapFirstCondition() - LiveOrOnline -> Criteria.BankrollTypes.queryConditions.mapFirstCondition() - Game -> Criteria.Games.queryConditions.mapFirstCondition() - LimitType -> Criteria.Limits.queryConditions.mapFirstCondition() - TableSize -> Criteria.TableSizes.queryConditions.mapFirstCondition() - // Date - DynamicDate -> arrayListOf( - QueryCondition.IsToday, - QueryCondition.WasYesterday, - QueryCondition.WasTodayAndYesterday, - QueryCondition.DuringThisWeek, - QueryCondition.DuringThisMonth, - QueryCondition.DuringThisYear - ) - FixedDate -> arrayListOf(QueryCondition.StartedFromDate(), QueryCondition.EndedToDate()) - Duration -> arrayListOf(QueryCondition.PastDay()) - WeekdayOrWeekend -> arrayListOf(QueryCondition.IsWeekDay, QueryCondition.IsWeekEnd) - Year -> Criteria.Years.queryConditions.mapFirstCondition() - DayOfWeek -> Criteria.DaysOfWeek.queryConditions.mapFirstCondition() - MonthOfYear -> Criteria.MonthsOfYear.queryConditions.mapFirstCondition() - - // Duration - SessionDuration -> QueryCondition.moreOrLess() - TimeFrameRange -> arrayListOf(QueryCondition.StartedFromTime(), QueryCondition.EndedToTime()) - - // Sessions - //Sessions -> arrayListOf(QueryCondition.LastGame(), QueryCondition.LastSession()) - - // Cash - Blind -> Criteria.Blinds.queryConditions.mapFirstCondition() + // Sessions + //Sessions -> arrayListOf(QueryCondition.LastGame(), QueryCondition.LastSession()) + + // Cash + Blind -> Criteria.Blinds.queryConditions.mapFirstCondition() // CashRebuyCount -> QueryCondition.moreOrLess() - // Tournament - TournamentType -> Criteria.TournamentTypes.queryConditions.mapFirstCondition() + // Tournament + TournamentType -> Criteria.TournamentTypes.queryConditions.mapFirstCondition() // CompletionPercentage -> arrayListOf() - TournamentFinalPosition -> QueryCondition.moreOrLess() - TournamentNumberOfPlayer -> QueryCondition.moreOrLess() - TournamentEntryFee -> Criteria.TournamentFees.queryConditions.mapFirstCondition() - TournamentName -> Criteria.TournamentNames.queryConditions.mapFirstCondition() - TournamentFeature -> Criteria.TournamentFeatures.queryConditions.mapFirstCondition() - Location -> Criteria.Locations.queryConditions.mapFirstCondition() - Bankroll -> Criteria.Bankrolls.queryConditions.mapFirstCondition() - MultiTabling -> QueryCondition.moreOrLess() - //NumberOfPlayers -> QueryCondition.moreOrLess() - NumberOfRebuy -> QueryCondition.moreOrLess() + TournamentFinalPosition -> QueryCondition.moreOrLess() + TournamentNumberOfPlayer -> QueryCondition.moreOrLess() + TournamentEntryFee -> Criteria.TournamentFees.queryConditions.mapFirstCondition() + TournamentName -> Criteria.TournamentNames.queryConditions.mapFirstCondition() + TournamentFeature -> Criteria.TournamentFeatures.queryConditions.mapFirstCondition() + Location -> Criteria.Locations.queryConditions.mapFirstCondition() + Bankroll -> Criteria.Bankrolls.queryConditions.mapFirstCondition() + MultiTabling -> QueryCondition.moreOrLess() + //NumberOfPlayers -> QueryCondition.moreOrLess() + NumberOfRebuy -> QueryCondition.moreOrLess() // MultiPlayer -> arrayListOf() - Value -> arrayListOf().apply { - addAll(QueryCondition.moreOrLess()) - addAll(QueryCondition.moreOrLess()) - } - TransactionType -> Criteria.TransactionTypes.queryConditions.mapFirstCondition() - is CustomField -> { - val cf = this@FilterSectionRow.customField - if (cf.isListType) { - Criteria.ListCustomFields(cf.id).queryConditions.mapFirstCondition() - } else if (cf.isAmountType) { - QueryCondition.moreOrLess().apply { - this.forEach { - it.customFieldId = cf.id - } - } - } else { - QueryCondition.moreOrLess().apply { - this.forEach { - it.customFieldId = cf.id - } - } - } - } - else -> arrayListOf() - }.apply { - this.forEach { - it.filterSectionRow = this@FilterSectionRow + Value -> arrayListOf().apply { + addAll(QueryCondition.moreOrLess()) + addAll(QueryCondition.moreOrLess()) + } + TransactionType -> Criteria.TransactionTypes.queryConditions.mapFirstCondition() + is CustomField -> { + val cf = this@FilterSectionRow.customField + when { + cf.isListType -> { + Criteria.ListCustomFields(cf.id).queryConditions.mapFirstCondition() + } + cf.isAmountType -> { + QueryCondition.moreOrLess().apply { + this.forEach { + it.customFieldId = cf.id + } + } + } + else -> { + QueryCondition.moreOrLess().apply { + this.forEach { + it.customFieldId = cf.id + } + } } } - ) + } + else -> arrayListOf() } + } - // Add the section row only if we have data for this section - if (data.isNotEmpty()) { - data.add(0, this@FilterSectionRow) - } - return data - } +// val filterElements: List +// get() { +// +// val data = arrayListOf().apply { +// this.addAll( +// filterItems.apply { +// this.forEach { +// it.filterSectionRow = this@FilterSectionRow +// } +// } +// ) +// } +// +// // Add the section row only if we have data for this section +// if (data.isNotEmpty()) { +// data.add(0, this@FilterSectionRow) +// } +// +// return data +// } private val selectionType: SelectionType get() { From fb0c5f79334354f8b4f7c689145b3e9172981110 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 25 Sep 2020 12:29:13 +0200 Subject: [PATCH 02/11] More fixes --- .../android/model/filter/QueryCondition.kt | 3 -- .../modules/filter/FilterDetailsFragment.kt | 7 +++-- .../modules/filter/FilterDetailsViewModel.kt | 29 ++++++++++++------- .../view/rowrepresentable/FilterElementRow.kt | 28 ++++++++++++++++-- 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt index f513f38d..308b8695 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt @@ -22,12 +22,9 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.* import net.pokeranalytics.android.util.NULL_TEXT import net.pokeranalytics.android.util.UserDefaults import net.pokeranalytics.android.util.extensions.* -import java.lang.Exception import java.text.DateFormatSymbols import java.text.NumberFormat import java.util.* -import kotlin.collections.ArrayList -import kotlin.reflect.full.primaryConstructor /** * Enum describing the way a query should be handled diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt index 4d6ef051..a7b9b90e 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt @@ -130,8 +130,8 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { is IntFilterItemRow -> { when (val condition = row.rawCondition) { is QueryCondition.Duration -> { - val hours: String? = (condition.minutes / 60).toString() - val minutes: String? = (condition.minutes % 60).toString() + val hours = (condition.minutes / 60).toString() + val minutes = (condition.minutes % 60).toString() val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) showBottomSheet(row, this, data, true) } @@ -195,7 +195,7 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { when (row) { is DateFilterItemRow -> { - row.value = value as Date + row.value = value as? Date } is IntFilterItemRow -> { when (value) { @@ -221,6 +221,7 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { row.value = minutes } } + else -> { row.value = null } } } is DoubleValueListFilterItemRow -> { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt index ba9885b0..b9c98cec 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt @@ -3,18 +3,15 @@ package net.pokeranalytics.android.ui.modules.filter import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider -import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType -import net.pokeranalytics.android.ui.view.rowrepresentable.BaseFilterItemRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterItemRow -import net.pokeranalytics.android.ui.view.rowrepresentable.ValueListFilterItemRow +import net.pokeranalytics.android.ui.view.rowrepresentable.FilterValueHolder import net.pokeranalytics.android.util.NULL_TEXT -import timber.log.Timber class FilterDetailsViewModelFactory(var filter: Filter, var categoryRow: FilterCategoryRow): ViewModelProvider.Factory { @@ -43,14 +40,24 @@ class FilterDetailsViewModel(categoryRow: FilterCategoryRow, var filter: Filter) override fun charSequenceForRow(row: RowRepresentable, context: Context): CharSequence { - val filterItemRow = row as? BaseFilterItemRow - filterItemRow?.let { - return when (val condition = it.rawCondition) { - is QueryCondition.ListOfValues<*> -> condition.firstValue(context) ?: NULL_TEXT - else -> super.charSequenceForRow(row, context, 0) + return when (row) { + is FilterValueHolder -> { + row.valueFormatted(context) } - } - return NULL_TEXT + else -> super.charSequenceForRow(row, context, 0) + } ?: NULL_TEXT + +// val filterItemRow = row as? BaseFilterItemRow +// filterItemRow?.let { +// return when (val condition = it.rawCondition) { +//// is QueryCondition.SingleValue<*> -> filter +// is QueryCondition.ListOfValues<*> -> { +// condition.firstValue(context) ?: NULL_TEXT +// } +// else -> super.charSequenceForRow(row, context, 0) +// } +// } +// return NULL_TEXT // return when (row) { // is BaseFilterItemRow -> { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt index dc6cc88d..cdf99d06 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt @@ -8,6 +8,7 @@ import net.pokeranalytics.android.model.realm.FilterCondition 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.util.NULL_TEXT import java.util.* interface FilterItemRow : RowRepresentable { @@ -65,6 +66,10 @@ interface FilterItemRow : RowRepresentable { } } +interface FilterValueHolder { + fun valueFormatted(context: Context): CharSequence? +} + open class BaseFilterItemRow(queryCondition: QueryCondition, override var filterSectionRow: FilterSectionRow) : FilterItemRow { var rawCondition: QueryCondition = queryCondition @@ -79,6 +84,9 @@ open class BaseFilterItemRow(queryCondition: QueryCondition, override var filter return this.rawCondition.getDisplayName(context) } + override val resId: Int? + get() { return this.rawCondition.resId } + override val viewType: Int get() { return this.rawCondition.viewType } @@ -88,7 +96,7 @@ open class BaseFilterItemRow(queryCondition: QueryCondition, override var filter } -abstract class ValueFilterItemRow>(queryCondition: QueryCondition.SingleValue, filterSectionRow: FilterSectionRow): BaseFilterItemRow(queryCondition, filterSectionRow) { +abstract class ValueFilterItemRow>(queryCondition: QueryCondition.SingleValue, filterSectionRow: FilterSectionRow): BaseFilterItemRow(queryCondition, filterSectionRow), FilterValueHolder { private var valueCondition: QueryCondition.SingleValue = queryCondition @@ -103,6 +111,13 @@ abstract class ValueFilterItemRow>(queryCondition: QueryConditi return null } + override fun valueFormatted(context: Context): CharSequence? { + this.value?.let { + return this.valueCondition.labelForValue(it, context) + } + return NULL_TEXT + } + override fun updateValue(fc: FilterCondition) { // TODO @@ -113,7 +128,7 @@ abstract class ValueFilterItemRow>(queryCondition: QueryConditi } -abstract class ValueListFilterItemRow>(queryCondition: QueryCondition.ListOfValues, filterSectionRow: FilterSectionRow): BaseFilterItemRow(queryCondition, filterSectionRow) { +abstract class ValueListFilterItemRow>(queryCondition: QueryCondition.ListOfValues, filterSectionRow: FilterSectionRow): BaseFilterItemRow(queryCondition, filterSectionRow), FilterValueHolder { private var listCondition: QueryCondition.ListOfValues = queryCondition @@ -134,6 +149,15 @@ abstract class ValueListFilterItemRow>(queryCondition: QueryCon } } + + override fun valueFormatted(context: Context): CharSequence? { + this.list.firstOrNull()?.let { + return this.listCondition.labelForValue(it, context) + } + return NULL_TEXT + } + + // override fun getDisplayName(context: Context): String { // return this.listCondition.getDisplayName(context, this.list) // } From 457ef13c2fd5ecfa4ba51aaac8d871e94b6d329e Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 25 Sep 2020 14:05:45 +0200 Subject: [PATCH 03/11] More fixes and amazing improvements --- .../BottomSheetEditTextFragment.kt | 2 +- .../modules/filter/FilterDetailsFragment.kt | 73 +++++++++++-------- .../view/rowrepresentable/FilterElementRow.kt | 12 +++ 3 files changed, 54 insertions(+), 33 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetEditTextFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetEditTextFragment.kt index 68270e60..cf69a603 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetEditTextFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetEditTextFragment.kt @@ -29,7 +29,7 @@ class BottomSheetEditTextFragment : BottomSheetFragment() { */ private fun initUI() { - val data = getDescriptors() ?: throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found") + val data = getDescriptors() ?: throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor not found for $this") if (data.size != 1) { throw RowRepresentableEditDescriptorException("RowRepresentableEditDescriptor inconsistency") } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt index a7b9b90e..b5b9da1a 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt @@ -114,43 +114,52 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { return } - when (row) { - is DateFilterItemRow -> { - when (val condition = row.rawCondition) { - is QueryCondition.DateQuery -> DateTimePickerManager.create( - requireContext(), - row, - this, - row.value, - onlyDate = !condition.showTime, - onlyTime = condition.showTime - ) - } - } - is IntFilterItemRow -> { - when (val condition = row.rawCondition) { - is QueryCondition.Duration -> { - val hours = (condition.minutes / 60).toString() - val minutes = (condition.minutes % 60).toString() - val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) - showBottomSheet(row, this, data, true) - } + (row as? BaseFilterItemRow)?.let { + when (val condition = it.rawCondition) { + is QueryCondition.DateQuery -> DateTimePickerManager.create( + requireContext(), + row, + this, + (row as DateFilterItemRow).value, + onlyDate = !condition.showTime, + onlyTime = condition.showTime + ) + is QueryCondition.Duration -> { + val hours = (condition.minutes / 60).toString() + val minutes = (condition.minutes % 60).toString() + val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) + showBottomSheet(row, this, data, true) } - } - is ValueListFilterItemRow<*> -> { - when (row.rawCondition) { - is QueryCondition.ListOfValues<*> -> { - var valueAsString: String? = null - row.list.firstOrNull()?.let { - valueAsString = row.list.firstOrNull()?.toString() - } - val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) - showBottomSheet(row, this, data, true) - } + is QueryCondition.ListOfValues<*> -> { + val valueAsString: String? = (row as FilterValueHolder).singleValue?.toString() +// row.list.firstOrNull()?.let { +// valueAsString = row.list.firstOrNull()?.toString() +// } + val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) + showBottomSheet(row, this, data, true) } + else -> { } } } +// when (row) { +// is DateFilterItemRow -> { +// when (val condition = row.rawCondition) { +// +// } +// } +// is IntFilterItemRow -> { +// when (val condition = row.rawCondition) { +// +// } +// } +// is ValueListFilterItemRow<*> -> { +// when (row.rawCondition) { +// +// } +// } +// } + // (row as? BaseFilterItemRow)?.let { filterItemRow -> // val rawCondition = filterItemRow.rawCondition diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt index cdf99d06..36952dcf 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt @@ -68,6 +68,7 @@ interface FilterItemRow : RowRepresentable { interface FilterValueHolder { fun valueFormatted(context: Context): CharSequence? + val singleValue: Any? } open class BaseFilterItemRow(queryCondition: QueryCondition, override var filterSectionRow: FilterSectionRow) : FilterItemRow { @@ -93,6 +94,8 @@ open class BaseFilterItemRow(queryCondition: QueryCondition, override var filter override val bottomSheetType: BottomSheetType get() { return this.rawCondition.bottomSheetType } + + } @@ -118,6 +121,11 @@ abstract class ValueFilterItemRow>(queryCondition: QueryConditi return NULL_TEXT } + override val singleValue: Any? + get() { + return this.value + } + override fun updateValue(fc: FilterCondition) { // TODO @@ -157,6 +165,10 @@ abstract class ValueListFilterItemRow>(queryCondition: QueryCon return NULL_TEXT } + override val singleValue: Any? + get() { + return this.list.firstOrNull() + } // override fun getDisplayName(context: Context): String { // return this.listCondition.getDisplayName(context, this.list) From b7613644c6f4405da8e2e3de83bcd842f1832801 Mon Sep 17 00:00:00 2001 From: Laurent Date: Fri, 25 Sep 2020 16:56:19 +0200 Subject: [PATCH 04/11] Fixes important bugs --- .../filter/BlindFilterInstrumentedTest.kt | 18 ++-- .../filter/DateFilterInstrumentedUnitTest.kt | 37 ++++---- .../filter/RealmFilterInstrumentedUnitTest.kt | 6 +- .../SessionFilterInstrumentedUnitTest.kt | 64 +++++--------- .../android/model/filter/QueryCondition.kt | 42 ++++++---- .../android/model/realm/FilterCondition.kt | 14 +++- .../calendar/CalendarDetailsActivity.kt | 4 +- .../modules/filter/FilterDetailsFragment.kt | 4 +- .../modules/filter/FilterDetailsViewModel.kt | 4 +- .../view/rowrepresentable/FilterElementRow.kt | 84 +++++++++---------- .../android/InstantiationTest.kt | 27 ++++++ 11 files changed, 157 insertions(+), 147 deletions(-) create mode 100644 app/src/test/java/net/pokeranalytics/android/InstantiationTest.kt diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/BlindFilterInstrumentedTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/BlindFilterInstrumentedTest.kt index 6260a833..883816ce 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/BlindFilterInstrumentedTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/BlindFilterInstrumentedTest.kt @@ -47,9 +47,9 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() { listOfValues = arrayListOf(s1.blinds!!) } - blind.filterSectionRow = FilterSectionRow.Blind +// blind.filterSectionRow = FilterSectionRow.Blind - val filterElement = FilterCondition(filterElementRows = arrayListOf(blind)) + val filterElement = FilterCondition(arrayListOf(blind), FilterSectionRow.Blind) filter.updateValueBy(filterElement) val sessions = Filter.queryOn(realm, Query(filter)) @@ -97,10 +97,7 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() { listOfValues = arrayListOf(s2.blinds!!) } - blind1.filterSectionRow = FilterSectionRow.Blind - blind2.filterSectionRow = FilterSectionRow.Blind - - val filterElements = FilterCondition(filterElementRows = arrayListOf(blind1, blind2)) + val filterElements = FilterCondition(arrayListOf(blind1, blind2), FilterSectionRow.Blind) filter.updateValueBy(filterElements) val sessions = Filter.queryOn(realm, Query(filter)) @@ -146,9 +143,7 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() { listOfValues = arrayListOf(s3.blinds!!) } - blind.filterSectionRow = FilterSectionRow.Blind - - val filterElement = FilterCondition(filterElementRows = arrayListOf(blind)) + val filterElement = FilterCondition(arrayListOf(blind), FilterSectionRow.Blind) filter.updateValueBy(filterElement) val sessions = Filter.queryOn(realm, Query(filter)) @@ -196,10 +191,7 @@ class BlindFilterInstrumentedTest : BaseFilterInstrumentedUnitTest() { listOfValues = arrayListOf(s2.blinds!!) } - blind1.filterSectionRow = FilterSectionRow.Blind - blind2.filterSectionRow = FilterSectionRow.Blind - - val filterElement = FilterCondition(filterElementRows = arrayListOf(blind1, blind2)) + val filterElement = FilterCondition(arrayListOf(blind1, blind2), FilterSectionRow.Blind) filter.updateValueBy(filterElement) val sessions = Filter.queryOn(realm, Query(filter)) diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt index d619df95..c5162051 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/DateFilterInstrumentedUnitTest.kt @@ -35,8 +35,7 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { cal.time = s1.startDate val filterElementRow = QueryCondition.AnyDayOfWeek().apply { listOfValues = arrayListOf(cal.get(Calendar.DAY_OF_WEEK)) } - filterElementRow.filterSectionRow = FilterSectionRow.DynamicDate - val filterElement = FilterCondition(arrayListOf(filterElementRow)) + val filterElement = FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.DynamicDate) filter.updateValueBy(filterElement) val sessions = Filter.queryOn(realm, Query(filter)) @@ -64,8 +63,7 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { cal.time = s1.startDate val filterElementRow = QueryCondition.AnyMonthOfYear().apply { listOfValues = arrayListOf(cal.get(Calendar.MONTH)) } - filterElementRow.filterSectionRow = FilterSectionRow.DynamicDate - val filterElement = FilterCondition(arrayListOf(filterElementRow)) + val filterElement = FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.DynamicDate) filter.updateValueBy(filterElement) val sessions = Filter.queryOn(realm, Query(filter)) @@ -92,8 +90,7 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AnyYear() cal.time = s1.startDate val filterElementRow = QueryCondition.AnyYear().apply { listOfValues = arrayListOf(cal.get(Calendar.YEAR)) } - filterElementRow.filterSectionRow = FilterSectionRow.DynamicDate - val filterElement = FilterCondition(arrayListOf(filterElementRow)) + val filterElement = FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.DynamicDate) filter.updateValueBy(filterElement) val sessions = Filter.queryOn(realm, Query(filter)) @@ -384,10 +381,9 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val s2 = Session.testInstance(100.0, true, cal.time, 1) realm.commitTransaction() - val filter = QueryCondition.StartedFromDate() - val filterElementRow = QueryCondition.StartedFromDate().apply { singleValue = s2.startDate!!} - filterElementRow.filterSectionRow = FilterSectionRow.FixedDate - filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow))) + val filter = QueryCondition.StartedFromDate(Date()) + val filterElementRow = QueryCondition.StartedFromDate(Date()).apply { singleValue = s2.startDate!!} + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.FixedDate)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -412,10 +408,9 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { realm.commitTransaction() - val filter = QueryCondition.StartedToDate() - val filterElementRow = QueryCondition.StartedToDate().apply { singleValue = s1.startDate!! } - filterElementRow.filterSectionRow = FilterSectionRow.FixedDate - filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow))) + val filter = QueryCondition.StartedToDate(Date()) + val filterElementRow = QueryCondition.StartedToDate(Date()).apply { singleValue = s1.startDate!! } + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.FixedDate)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -441,10 +436,9 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { realm.commitTransaction() - val filter = QueryCondition.EndedFromDate() - val filterElementRow = QueryCondition.EndedFromDate().apply { singleValue = s2.endDate() } - filterElementRow.filterSectionRow = FilterSectionRow.FixedDate - filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow))) + val filter = QueryCondition.EndedFromDate(Date()) + val filterElementRow = QueryCondition.EndedFromDate(Date()).apply { singleValue = s2.endDate() } + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.FixedDate)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -470,10 +464,9 @@ class DateFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { realm.commitTransaction() - val filter = QueryCondition.EndedToDate() - val filterElementRow = QueryCondition.EndedToDate().apply { singleValue = s1.endDate() } - filterElementRow.filterSectionRow = FilterSectionRow.FixedDate - filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow))) + val filter = QueryCondition.EndedToDate(Date()) + val filterElementRow = QueryCondition.EndedToDate(Date()).apply { singleValue = s1.endDate() } + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.FixedDate)) val sessions = Filter.queryOn(realm, Query(filter)) diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt index 022b63ec..91d1236a 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt @@ -5,6 +5,7 @@ import net.pokeranalytics.android.components.BaseFilterInstrumentedUnitTest import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.model.realm.Session +import net.pokeranalytics.android.ui.view.rowrepresentable.BaseFilterItemRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow import org.junit.Assert @@ -24,8 +25,9 @@ class RealmFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { filter.name = "testSaveLoadCashFilter" val filterElement = QueryCondition.IsCash -// filterElement.filterSectionRow = FilterSectionRow.CashOrTournament - filter.createOrUpdateFilterConditions(arrayListOf(filterElement), FilterSectionRow.CashOrTournament) + val filterItemRow = BaseFilterItemRow(filterElement, FilterSectionRow.CashOrTournament) + + filter.createOrUpdateFilterConditions(arrayListOf(filterItemRow)) val useCount = filter.countBy(FilterCategoryRow.GENERAL) Assert.assertEquals(1, useCount) diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/SessionFilterInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/SessionFilterInstrumentedUnitTest.kt index 3bb0073b..45b9957b 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/SessionFilterInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/SessionFilterInstrumentedUnitTest.kt @@ -110,8 +110,7 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AnyBankroll() val filterElementRow = QueryCondition.AnyBankroll().apply { setObject(b1) } - filterElementRow.filterSectionRow = FilterSectionRow.Bankroll - filter.updateValueBy(FilterCondition(filterElementRows = arrayListOf(filterElementRow))) + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.Bankroll)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -141,11 +140,9 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AnyBankroll() val filterElementRow = QueryCondition.AnyBankroll().apply { setObject(b1) } - filterElementRow.filterSectionRow = FilterSectionRow.Bankroll - val filterElementRow2 = QueryCondition.AnyBankroll().apply { setObject(b2) } - filterElementRow2.filterSectionRow = FilterSectionRow.Bankroll - filter.updateValueBy(FilterCondition(filterElementRows = arrayListOf(filterElementRow, filterElementRow2))) + + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow, filterElementRow2), FilterSectionRow.Bankroll)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -169,7 +166,7 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { realm.commitTransaction() val anyGame = QueryCondition.AnyGame(g2) - val fc = FilterCondition(filterElementRows = arrayListOf(anyGame)) + val fc = FilterCondition(arrayListOf(anyGame), FilterSectionRow.Game) val sessions = Filter.queryOn(realm, Query(fc.queryCondition)) Assert.assertEquals(1, sessions.size) @@ -197,10 +194,10 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { realm.commitTransaction() val filterElementRow = QueryCondition.AnyGame().apply { setObject(g2) } - filterElementRow.filterSectionRow = FilterSectionRow.Game val filterElementRow2 = QueryCondition.AnyGame().apply { setObject(g3) } - filterElementRow2.filterSectionRow = FilterSectionRow.Game - val filterCondition = FilterCondition(filterElementRows = arrayListOf(filterElementRow, filterElementRow2)) + + val filterCondition = FilterCondition(arrayListOf(filterElementRow, filterElementRow2), FilterSectionRow.Game) + val queryCondition = filterCondition.queryCondition val sessions = Filter.queryOn(realm, Query(queryCondition)) @@ -225,8 +222,7 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AnyLocation() val filterElementRow = QueryCondition.AnyLocation().apply { setObject(l1) } - filterElementRow.filterSectionRow = FilterSectionRow.Location - filter.updateValueBy(FilterCondition(filterElementRows = arrayListOf(filterElementRow))) + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.Location)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -257,11 +253,9 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AnyLocation() val filterElementRow = QueryCondition.AnyLocation().apply { setObject(l1) } - filterElementRow.filterSectionRow = FilterSectionRow.Location val filterElementRow2 = QueryCondition.AnyLocation().apply { setObject(l3) } - filterElementRow2.filterSectionRow = FilterSectionRow.Location - filter.updateValueBy(FilterCondition(filterElementRows = arrayListOf(filterElementRow, filterElementRow2))) + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow, filterElementRow2), FilterSectionRow.Location)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -287,8 +281,7 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AnyTournamentName() val filterElementRow = QueryCondition.AnyTournamentName().apply { setObject(t1) } - filterElementRow.filterSectionRow = FilterSectionRow.TournamentName - filter.updateValueBy(FilterCondition(filterElementRows = arrayListOf(filterElementRow))) + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.TournamentName)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -318,10 +311,8 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AnyTournamentName() val filterElementRow = QueryCondition.AnyTournamentName().apply { setObject(t1) } - filterElementRow.filterSectionRow = FilterSectionRow.TournamentName val filterElementRow2 = QueryCondition.AnyTournamentName().apply { setObject(t2) } - filterElementRow.filterSectionRow = FilterSectionRow.TournamentName - filter.updateValueBy(FilterCondition(filterElementRows = arrayListOf(filterElementRow, filterElementRow2))) + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow, filterElementRow2), FilterSectionRow.TournamentName)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -354,12 +345,10 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AllTournamentFeature() val filterElementRow = QueryCondition.AllTournamentFeature().apply { setObject(t1) } - filterElementRow.filterSectionRow = FilterSectionRow.TournamentFeature val filterElementRow2 = QueryCondition.AllTournamentFeature().apply { setObject(t2) } - filterElementRow2.filterSectionRow = FilterSectionRow.TournamentFeature val filterElementRow3 = QueryCondition.AllTournamentFeature().apply { setObject(t4) } - filterElementRow3.filterSectionRow = FilterSectionRow.TournamentFeature - filter.updateValueBy(FilterCondition(filterElementRows = arrayListOf(filterElementRow, filterElementRow2, filterElementRow3))) + + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow, filterElementRow2, filterElementRow3), FilterSectionRow.TournamentFeature)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -389,14 +378,11 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AnyTournamentFeature() val filterElementRow = QueryCondition.AnyTournamentFeature().apply { setObject(t1) } - filterElementRow.filterSectionRow = FilterSectionRow.TournamentFeature val filterElementRow2 = QueryCondition.AnyTournamentFeature().apply { setObject(t2) } - filterElementRow2.filterSectionRow = FilterSectionRow.TournamentFeature val filterElementRow3 = QueryCondition.AnyTournamentFeature().apply { setObject(t3) } - filterElementRow3.filterSectionRow = FilterSectionRow.TournamentFeature val filterElementRow4 = QueryCondition.AnyTournamentFeature().apply { setObject(t4) } - filterElementRow4.filterSectionRow = FilterSectionRow.TournamentFeature - filter.updateValueBy(FilterCondition(filterElementRows = arrayListOf(filterElementRow, filterElementRow2, filterElementRow3, filterElementRow4))) + + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow, filterElementRow2, filterElementRow3, filterElementRow4), FilterSectionRow.TournamentFeature)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -423,8 +409,7 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AnyTournamentFeature() val filterElementRow = QueryCondition.AnyTournamentFeature().apply { setObject(t2) } - filterElementRow.filterSectionRow = FilterSectionRow.TournamentFeature - filter.updateValueBy(FilterCondition(filterElementRows = arrayListOf(filterElementRow))) + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.TournamentFeature)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -448,10 +433,9 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.AnyTableSize() val filterElementRow = QueryCondition.AnyTableSize().apply { listOfValues = arrayListOf(2) } - filterElementRow.filterSectionRow = FilterSectionRow.TableSize val filterElementRow2 = QueryCondition.AnyTableSize().apply { listOfValues = arrayListOf(4) } - filterElementRow.filterSectionRow = FilterSectionRow.TableSize - filter.updateValueBy(FilterCondition(filterElementRows = arrayListOf(filterElementRow, filterElementRow2))) + + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow, filterElementRow2), FilterSectionRow.TableSize)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -475,8 +459,7 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.NetAmountWon() val filterElementRow = QueryCondition.more().apply { listOfValues = arrayListOf(204.0) } - filterElementRow.filterSectionRow = FilterSectionRow.Value - filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow))) + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.Value)) val sessions = Filter.queryOn(realm, Query(filterElementRow)) @@ -500,8 +483,7 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filter = QueryCondition.NetAmountWon() val filterElementRow = QueryCondition.less().apply { listOfValues = arrayListOf(540.0) } - filterElementRow.filterSectionRow = FilterSectionRow.Value - filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow))) + filter.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.Value)) val sessions = Filter.queryOn(realm, Query(filter)) @@ -525,13 +507,11 @@ class SessionFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { val filterMore = QueryCondition.NetAmountWon() val filterElementRow = QueryCondition.more().apply { listOfValues = arrayListOf(199.0) } - filterElementRow.filterSectionRow = FilterSectionRow.Value - filterMore.updateValueBy(FilterCondition(arrayListOf(filterElementRow))) + filterMore.updateValueBy(FilterCondition(arrayListOf(filterElementRow), FilterSectionRow.Value)) val filterLess = QueryCondition.NetAmountWon() val filterElementRow2 = QueryCondition.less().apply { listOfValues = arrayListOf(400.0) } - filterElementRow2.filterSectionRow = FilterSectionRow.Value - filterLess.updateValueBy(FilterCondition(arrayListOf(filterElementRow2))) + filterLess.updateValueBy(FilterCondition(arrayListOf(filterElementRow2), FilterSectionRow.Value)) val sessions = Filter.queryOn(realm, Query(filterMore, filterLess)) diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt index 308b8695..6caef630 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt @@ -25,6 +25,7 @@ import net.pokeranalytics.android.util.extensions.* import java.text.DateFormatSymbols import java.text.NumberFormat import java.util.* +import kotlin.reflect.KClass /** * Enum describing the way a query should be handled @@ -34,12 +35,32 @@ import java.util.* sealed class QueryCondition : RowRepresentable { companion object { + + fun newInstance(kClass: KClass): T { + return try { + kClass.objectInstance ?: kClass.java.newInstance() + } catch (e: Exception) { + // some object instance can fail due to: java.lang.Class has no zero argument constructor + // We should have just one constructor with a single parameter + + val primaryConstructor = kClass.java.declaredConstructors.first() + val paramClass = primaryConstructor.parameterTypes.first() + val param = when (paramClass) { + Int::class.java -> 0 + Double::class.java -> 0.0 + else -> paramClass.newInstance() + } + val constructor = kClass.java.getDeclaredConstructor(paramClass) + constructor.newInstance(param) + } + } + inline fun more(): T { - return T::class.java.newInstance().apply { this.operator = Operator.MORE } + return newInstance(T::class).apply { this.operator = Operator.MORE } } inline fun less(): T { - return T::class.java.newInstance().apply { this.operator = Operator.LESS } + return newInstance(T::class).apply { this.operator = Operator.LESS } } inline fun moreOrLess(): ArrayList { @@ -48,16 +69,7 @@ sealed class QueryCondition : RowRepresentable { fun valueOf(name: String): T { val kClass = Class.forName("${QueryCondition::class.qualifiedName}$$name").kotlin - val instance = try { - kClass.objectInstance ?: kClass.java.newInstance() - } catch (e: Exception) { - // some object instance can fail due to: java.lang.Class has no zero argument constructor - // We should have just one constructor with a single parameter - val primaryConstructor = kClass.java.declaredConstructors.first() - val param = primaryConstructor.parameterTypes.first() - primaryConstructor.newInstance(param.newInstance()) - } - return instance as T + return newInstance(kClass) as T } inline fun getInstance(): QueryCondition { @@ -633,7 +645,7 @@ sealed class QueryCondition : RowRepresentable { } } - class CustomFieldQuery() : QueryDataCondition() { + class CustomFieldQuery : QueryDataCondition() { override var entity: Class = CustomField::class.java } @@ -656,7 +668,9 @@ sealed class QueryCondition : RowRepresentable { val completeLabel = when (listOfValues.size) { 0 -> return NULL_TEXT 1, 2 -> { - return name + prefix + listOfValues.map { labelForValue(it, context) }.joinToString(", ") + return name + prefix + listOfValues.joinToString(", ") { + labelForValue(it, context) + } } else -> "${listOfValues.size} $prefix $name" } diff --git a/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt index 7bf65944..e187aac7 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/realm/FilterCondition.kt @@ -49,7 +49,7 @@ open class FilterCondition() : RealmObject() { var stringValue: String? = null var operator: Int? = null - inline fun getValues(): ArrayList < T > { + inline fun getValues(): ArrayList { return when (T::class) { Int::class -> ArrayList().apply { intValues?.map { add(it as T) } } Double::class -> ArrayList().apply { doubleValues?.map { add(it as T) } } @@ -58,7 +58,17 @@ open class FilterCondition() : RealmObject() { } } - inline fun getValue(): T { + fun getv(clazz: Class) : T { + return when (clazz) { + Int::class -> intValue ?: 0 + Double::class -> doubleValue?: 0.0 + Date::class -> dateValue ?: Date() + String::class -> stringValue ?: "" + else -> throw PokerAnalyticsException.QueryValueMapUnexpectedValue + } as T + } + + inline fun getValue(): T { return when (T::class) { Int::class -> intValue ?: 0 Double::class -> doubleValue?: 0.0 diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarDetailsActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarDetailsActivity.kt index 438a60a9..ad4e3d41 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarDetailsActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/calendar/CalendarDetailsActivity.kt @@ -3,7 +3,7 @@ package net.pokeranalytics.android.ui.modules.calendar import android.content.Context import android.content.Intent import android.os.Bundle -import androidx.lifecycle.ViewModelProviders +import androidx.lifecycle.ViewModelProvider import net.pokeranalytics.android.R import net.pokeranalytics.android.calculus.ComputedResults import net.pokeranalytics.android.model.filter.QueryCondition @@ -13,7 +13,7 @@ import net.pokeranalytics.android.ui.activity.components.BaseActivity class CalendarDetailsActivity : BaseActivity() { private val model: CalendarDetailsViewModel by lazy { - ViewModelProviders.of(this).get(CalendarDetailsViewModel::class.java) + ViewModelProvider(this).get(CalendarDetailsViewModel::class.java) } companion object { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt index b5b9da1a..2d0f0287 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt @@ -208,8 +208,8 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { } is IntFilterItemRow -> { when (value) { - is Int -> { - row.value = value + is String -> { + row.value = value.toInt() } is ArrayList<*> -> { val hours: Int? = try { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt index b9c98cec..c8ba5d44 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt @@ -82,8 +82,8 @@ class FilterDetailsViewModel(categoryRow: FilterCategoryRow, var filter: Filter) private fun defineSelectedItems() { this.rows.filterIsInstance().forEach { item -> - val condition = item.queryCondition - if (condition != null && this.filter.contains(condition)) { + val condition = item.rawCondition + if (this.filter.contains(condition)) { // Load items with appropriate value this.filter.filterConditions.firstOrNull { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt index 36952dcf..5e35642a 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt @@ -13,41 +13,11 @@ import java.util.* interface FilterItemRow : RowRepresentable { + val rawCondition: QueryCondition val queryCondition: QueryCondition? var filterSectionRow: FilterSectionRow - override fun editingDescriptors(map: Map): ArrayList? { - return when (this.queryCondition) { - is QueryCondition.Duration -> { - val hours: String? by map - val minutes: String? by map - arrayListOf( - RowRepresentableEditDescriptor(hours, R.string.hour, inputType = InputType.TYPE_CLASS_NUMBER), - RowRepresentableEditDescriptor(minutes, R.string.minute, inputType = InputType.TYPE_CLASS_NUMBER) - ) - } - is QueryCondition.ListOfValues<*> -> { - val valueAsString: String? by map - val hint = when (this.queryCondition?.operator) { - QueryCondition.Operator.MORE, QueryCondition.Operator.LESS -> { - when (this.queryCondition) { - is QueryCondition.CustomFieldNumberQuery -> R.string.value - is QueryCondition.CustomFieldAmountQuery -> R.string.amount - else -> this.filterSectionRow.resId - } - } - else -> this.resId - } - - arrayListOf( - RowRepresentableEditDescriptor(valueAsString, hint, inputType = InputType.TYPE_CLASS_NUMBER) - ) - } - else -> super.editingDescriptors(map) - } - } - - fun updateValue(it: FilterCondition) { } + fun updateValue(fc: FilterCondition) { } val sectionToExclude: List? get() { @@ -73,8 +43,7 @@ interface FilterValueHolder { open class BaseFilterItemRow(queryCondition: QueryCondition, override var filterSectionRow: FilterSectionRow) : FilterItemRow { - var rawCondition: QueryCondition = queryCondition - private set + override val rawCondition: QueryCondition = queryCondition override val queryCondition: QueryCondition? get() { return rawCondition } @@ -94,7 +63,36 @@ open class BaseFilterItemRow(queryCondition: QueryCondition, override var filter override val bottomSheetType: BottomSheetType get() { return this.rawCondition.bottomSheetType } + override fun editingDescriptors(map: Map): ArrayList? { + return when (this.rawCondition) { + is QueryCondition.Duration -> { + val hours: String? by map + val minutes: String? by map + arrayListOf( + RowRepresentableEditDescriptor(hours, R.string.hour, inputType = InputType.TYPE_CLASS_NUMBER), + RowRepresentableEditDescriptor(minutes, R.string.minute, inputType = InputType.TYPE_CLASS_NUMBER) + ) + } + is QueryCondition.ListOfValues<*> -> { + val valueAsString: String? by map + val hint = when (this.queryCondition?.operator) { + QueryCondition.Operator.MORE, QueryCondition.Operator.LESS -> { + when (this.queryCondition) { + is QueryCondition.CustomFieldNumberQuery -> R.string.value + is QueryCondition.CustomFieldAmountQuery -> R.string.amount + else -> this.filterSectionRow.resId + } + } + else -> this.resId + } + arrayListOf( + RowRepresentableEditDescriptor(valueAsString, hint, inputType = InputType.TYPE_CLASS_NUMBER) + ) + } + else -> super.editingDescriptors(map) + } + } } @@ -127,16 +125,14 @@ abstract class ValueFilterItemRow>(queryCondition: QueryConditi } override fun updateValue(fc: FilterCondition) { - - // TODO - -// this.value = fc.queryCondition. - + val queryCondition = fc.queryCondition as QueryCondition.SingleValue + this.value = queryCondition.singleValue } } -abstract class ValueListFilterItemRow>(queryCondition: QueryCondition.ListOfValues, filterSectionRow: FilterSectionRow): BaseFilterItemRow(queryCondition, filterSectionRow), FilterValueHolder { +abstract class ValueListFilterItemRow>(queryCondition: QueryCondition.ListOfValues, filterSectionRow: FilterSectionRow) + : BaseFilterItemRow(queryCondition, filterSectionRow), FilterValueHolder { private var listCondition: QueryCondition.ListOfValues = queryCondition @@ -157,7 +153,6 @@ abstract class ValueListFilterItemRow>(queryCondition: QueryCon } } - override fun valueFormatted(context: Context): CharSequence? { this.list.firstOrNull()?.let { return this.listCondition.labelForValue(it, context) @@ -175,11 +170,8 @@ abstract class ValueListFilterItemRow>(queryCondition: QueryCon // } override fun updateValue(fc: FilterCondition) { - - // TODO - -// this.value = fc.queryCondition. - + val queryCondition = fc.queryCondition as QueryCondition.ListOfValues + this.list = queryCondition.listOfValues } } diff --git a/app/src/test/java/net/pokeranalytics/android/InstantiationTest.kt b/app/src/test/java/net/pokeranalytics/android/InstantiationTest.kt new file mode 100644 index 00000000..5dfe6477 --- /dev/null +++ b/app/src/test/java/net/pokeranalytics/android/InstantiationTest.kt @@ -0,0 +1,27 @@ +package net.pokeranalytics.android + +import org.junit.Assert +import org.junit.Test + +class IntHolder(var value: Int) +class StringHolder(var value: String) + +class InstantiationTest : RealmUnitTest() { + + @Test + fun testIntInstance() { + + Assert.assertEquals(0, 0) + + val c = IntHolder::class.java + val constructor = c.declaredConstructors.first() + val type = constructor.parameterTypes.first() + when (type) { + Int::class.java -> { + // good + } + else -> Assert.fail() + } + } + +} From c358d4131f46daee4d340710ff13de6291f0b035 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 28 Sep 2020 17:06:36 +0200 Subject: [PATCH 05/11] Fixes various problems --- .../filter/RealmFilterInstrumentedUnitTest.kt | 4 +- .../android/model/filter/QueryCondition.kt | 104 ++++++++++-------- .../android/ui/fragment/StatisticsFragment.kt | 4 +- .../modules/filter/FilterDetailsFragment.kt | 6 +- .../modules/filter/FilterDetailsViewModel.kt | 3 +- .../{FilterElementRow.kt => FilterItemRow.kt} | 64 ++++++----- 6 files changed, 102 insertions(+), 83 deletions(-) rename app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/{FilterElementRow.kt => FilterItemRow.kt} (84%) diff --git a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt index 91d1236a..14db5813 100644 --- a/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt +++ b/app/src/androidTest/java/net/pokeranalytics/android/unitTests/filter/RealmFilterInstrumentedUnitTest.kt @@ -5,7 +5,7 @@ import net.pokeranalytics.android.components.BaseFilterInstrumentedUnitTest import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.model.realm.Session -import net.pokeranalytics.android.ui.view.rowrepresentable.BaseFilterItemRow +import net.pokeranalytics.android.ui.view.rowrepresentable.FixedValueFilterItemRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow import org.junit.Assert @@ -25,7 +25,7 @@ class RealmFilterInstrumentedUnitTest : BaseFilterInstrumentedUnitTest() { filter.name = "testSaveLoadCashFilter" val filterElement = QueryCondition.IsCash - val filterItemRow = BaseFilterItemRow(filterElement, FilterSectionRow.CashOrTournament) + val filterItemRow = FixedValueFilterItemRow(filterElement, FilterSectionRow.CashOrTournament) filter.createOrUpdateFilterConditions(arrayListOf(filterItemRow)) diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt index 6caef630..180c2085 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt @@ -31,7 +31,6 @@ import kotlin.reflect.KClass * Enum describing the way a query should be handled * Some queries requires a value to be checked upon through equals, in, more, less, between */ - sealed class QueryCondition : RowRepresentable { companion object { @@ -177,9 +176,23 @@ sealed class QueryCondition : RowRepresentable { } - abstract class SingleValue(value: T) : ListOfValues() where T : Comparable { - override var listOfValues = mutableListOf() + abstract class SingleValue(value: T) : QueryCondition() where T : Comparable { +// override var listOfValues = mutableListOf() var singleValue: T = value + + abstract fun labelForValue(value: T, context: Context): String + + override fun getDisplayName(context: Context): String { + return getDisplayName(context, singleValue) + } + + fun getDisplayName(context: Context, value: T): String { + val prefix = this.resId?.let { + context.getString(it) + " " + } ?: "" + return prefix + labelForValue(value, context) + } + } abstract class ListOfDouble : ListOfValues() { @@ -194,10 +207,6 @@ sealed class QueryCondition : RowRepresentable { override fun labelForValue(value: Double, context: Context): String { return value.toCurrency(UserDefaults.currency) } - - override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { - return DoubleValueListFilterItemRow(this, filterSectionRow) - } } abstract class ListOfInt : ListOfValues() { @@ -211,7 +220,9 @@ sealed class QueryCondition : RowRepresentable { override fun labelForValue(value: Int, context: Context): String { return value.toString() } + } + abstract class UserInputListOfInt : ListOfInt() { override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { return IntValueListFilterItemRow(this, filterSectionRow) } @@ -228,10 +239,6 @@ sealed class QueryCondition : RowRepresentable { super.updateValueBy(filterCondition) listOfValues = filterCondition.getValues() } - - override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { - return StringValueListFilterItemRow(this, filterSectionRow) - } } abstract class SingleDate(date: Date) : SingleValue(date) { @@ -239,7 +246,7 @@ sealed class QueryCondition : RowRepresentable { return value.shortDate() } - override var listOfValues = mutableListOf() +// override var listOfValues = mutableListOf() override fun updateValueBy(filterCondition: FilterCondition) { super.updateValueBy(filterCondition) @@ -261,6 +268,9 @@ sealed class QueryCondition : RowRepresentable { singleValue = filterCondition.getValue() } + } + + abstract class UserInputSingleInt(value: Int) : SingleInt(value) { override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { return IntFilterItemRow(this, filterSectionRow) } @@ -307,12 +317,11 @@ sealed class QueryCondition : RowRepresentable { } } - interface DateTime { val showTime: Boolean } - abstract class DateQuery(date: Date) : SingleDate(date), DateTime { + abstract class DateQuery(date: Date) : UserInputSingleDate(date), DateTime { override val showTime: Boolean = false override fun labelForValue(value: Date, context: Context): String { @@ -324,6 +333,12 @@ sealed class QueryCondition : RowRepresentable { } } + abstract class UserInputSingleDate(date: Date) : SingleDate(date) { + override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { + return DateFilterItemRow(this, filterSectionRow) + } + } + abstract class TimeQuery(date: Date) : DateQuery(date) { override val showTime: Boolean = true } @@ -446,15 +461,12 @@ sealed class QueryCondition : RowRepresentable { override fun entityName(context: Context): String { return context.getString(R.string.blinds) } - } -// object Last : SingleInt() { -// override var operator = Operator.EQUALS -// override fun getDisplayName(context: Context): String { -// //TODO update string "last %i" -// return "${context.getString(R.string.last_i_records)} $singleValue" -// } -// } + override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { + return FixedValueFilterItemRow(this, filterSectionRow) + } + + } class NumberOfTable : ListOfInt() { override fun labelForValue(value: Int, context: Context): String { @@ -466,7 +478,13 @@ sealed class QueryCondition : RowRepresentable { } } - class NumberOfRebuy() : ListOfDouble() { + open class UserInputListOfDouble : ListOfDouble() { + override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { + return DoubleValueListFilterItemRow(this, filterSectionRow) + } + } + + class NumberOfRebuy() : UserInputListOfDouble() { constructor(operator: Operator, numberOfRebuy: Double) : this() { this.operator = operator this.listOfValues = arrayListOf(numberOfRebuy) @@ -477,20 +495,20 @@ sealed class QueryCondition : RowRepresentable { } } - class TournamentFinalPosition() : ListOfInt() { + class TournamentFinalPosition() : UserInputListOfInt() { constructor(operator: Operator, finalPosition: Int) : this() { this.operator = operator this.listOfValues = arrayListOf(finalPosition) } override fun labelForValue(value: Int, context: Context): String { - val suffix = when (value%10) { + val suffix = when (value % 10) { 1 -> context.getString(R.string.ordinal_suffix_first) 2 -> context.getString(R.string.ordinal_suffix_second) 3 -> context.getString(R.string.ordinal_suffix_third) else -> context.getString(R.string.ordinal_suffix_default) } - return "$value$suffix "+context.getString(R.string.position) + return "$value$suffix " + context.getString(R.string.position) } override fun entityName(context: Context): String { @@ -498,14 +516,18 @@ sealed class QueryCondition : RowRepresentable { } } - open class NetAmount : ListOfDouble() + open class NetAmount : ListOfDouble() { + override fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { + return DoubleValueListFilterItemRow(this, filterSectionRow) + } + } class NetAmountWon : NetAmount() class NetAmountLost : NetAmount() { override var sign: Int = -1 } - class TournamentNumberOfPlayer : ListOfInt() { + class TournamentNumberOfPlayer : UserInputListOfInt() { override fun labelForValue(value: Int, context: Context): String { return value.toString() + " " + context.getString(R.string.number_of_players) } @@ -547,7 +569,7 @@ sealed class QueryCondition : RowRepresentable { } } - class AnyYear() : ListOfInt() { + class AnyYear() : UserInputListOfInt() { override fun labelForValue(value: Int, context: Context): String { return "$value" } @@ -580,14 +602,14 @@ sealed class QueryCondition : RowRepresentable { return value.toString() } - override fun entityName(context: Context): String { - return this.resId?.let { - " " + context.getString(it) - } ?: "" - } +// override fun entityName(context: Context): String { +// return this.resId?.let { +// " " + context.getString(it) +// } ?: "" +// } } - class Duration(value: Int) : SingleInt(value) { + class Duration(value: Int) : UserInputSingleInt(value) { override var operator = Operator.EQUALS var minutes: Int @@ -617,20 +639,10 @@ sealed class QueryCondition : RowRepresentable { class StartedFromTime(date: Date) : TimeQuery(date) { override var operator = Operator.MORE - -// constructor(date: Date) : this() { -// singleValue = date -// } - } class EndedToTime(date: Date) : TimeQuery(date) { override var operator = Operator.LESS - -// constructor(date: Date) : this() { -// singleValue = date -// } - } interface CustomFieldRelated { @@ -717,7 +729,7 @@ sealed class QueryCondition : RowRepresentable { } open fun toRowWrapper(filterSectionRow: FilterSectionRow): FilterItemRow { - return BaseFilterItemRow(this, filterSectionRow) + return FixedValueFilterItemRow(this, filterSectionRow) } /** diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt index 11078515..e5dbe17d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt @@ -167,9 +167,7 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener { */ private fun createSessionGroupsAndStartCompute(realm: Realm): Report { - val filter: Filter? = this.currentFilter(this.requireContext(), realm)?.let { - if (it.filterableType == currentFilterable) { it } else { null } - } + val filter: Filter? = null val allStats: List = listOf( Stat.NET_RESULT, diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt index 2d0f0287..4bb47f3c 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt @@ -114,7 +114,7 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { return } - (row as? BaseFilterItemRow)?.let { + (row as? FixedValueFilterItemRow)?.let { when (val condition = it.rawCondition) { is QueryCondition.DateQuery -> DateTimePickerManager.create( requireContext(), @@ -130,8 +130,8 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) showBottomSheet(row, this, data, true) } - is QueryCondition.ListOfValues<*> -> { - val valueAsString: String? = (row as FilterValueHolder).singleValue?.toString() + is QueryCondition.SingleValue<*>, is QueryCondition.ListOfValues<*> -> { + val valueAsString = (row as FilterItemRow).singleValue?.toString() // row.list.firstOrNull()?.let { // valueAsString = row.list.firstOrNull()?.toString() // } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt index c8ba5d44..b6780267 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt @@ -10,7 +10,6 @@ import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterItemRow -import net.pokeranalytics.android.ui.view.rowrepresentable.FilterValueHolder import net.pokeranalytics.android.util.NULL_TEXT class FilterDetailsViewModelFactory(var filter: Filter, var categoryRow: FilterCategoryRow): ViewModelProvider.Factory { @@ -41,7 +40,7 @@ class FilterDetailsViewModel(categoryRow: FilterCategoryRow, var filter: Filter) override fun charSequenceForRow(row: RowRepresentable, context: Context): CharSequence { return when (row) { - is FilterValueHolder -> { + is FilterItemRow -> { row.valueFormatted(context) } else -> super.charSequenceForRow(row, context, 0) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterItemRow.kt similarity index 84% rename from app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt rename to app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterItemRow.kt index 5e35642a..0f60bc85 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterItemRow.kt @@ -3,6 +3,7 @@ package net.pokeranalytics.android.ui.view.rowrepresentable import android.content.Context import android.text.InputType import net.pokeranalytics.android.R +import net.pokeranalytics.android.exceptions.PAIllegalStateException import net.pokeranalytics.android.model.filter.QueryCondition import net.pokeranalytics.android.model.realm.FilterCondition import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetType @@ -19,6 +20,16 @@ interface FilterItemRow : RowRepresentable { fun updateValue(fc: FilterCondition) { } + /*** + * The formatted value at the right of the table cell + */ + fun valueFormatted(context: Context): CharSequence? + + /*** + * The value at the right of the table cell + */ + val singleValue: Any? + val sectionToExclude: List? get() { val excluded = arrayListOf() @@ -34,19 +45,7 @@ interface FilterItemRow : RowRepresentable { } return null } -} - -interface FilterValueHolder { - fun valueFormatted(context: Context): CharSequence? - val singleValue: Any? -} - -open class BaseFilterItemRow(queryCondition: QueryCondition, override var filterSectionRow: FilterSectionRow) : FilterItemRow { - - override val rawCondition: QueryCondition = queryCondition - override val queryCondition: QueryCondition? - get() { return rawCondition } // Row Representable @@ -73,7 +72,7 @@ open class BaseFilterItemRow(queryCondition: QueryCondition, override var filter RowRepresentableEditDescriptor(minutes, R.string.minute, inputType = InputType.TYPE_CLASS_NUMBER) ) } - is QueryCondition.ListOfValues<*> -> { + is QueryCondition.SingleValue<*>, is QueryCondition.ListOfValues<*> -> { val valueAsString: String? by map val hint = when (this.queryCondition?.operator) { QueryCondition.Operator.MORE, QueryCondition.Operator.LESS -> { @@ -96,8 +95,24 @@ open class BaseFilterItemRow(queryCondition: QueryCondition, override var filter } +open class FixedValueFilterItemRow(queryCondition: QueryCondition, + override var filterSectionRow: FilterSectionRow) : FilterItemRow { -abstract class ValueFilterItemRow>(queryCondition: QueryCondition.SingleValue, filterSectionRow: FilterSectionRow): BaseFilterItemRow(queryCondition, filterSectionRow), FilterValueHolder { + override val rawCondition: QueryCondition = queryCondition + + override val queryCondition: QueryCondition? + get() { return rawCondition } + + override fun valueFormatted(context: Context): CharSequence? { + throw PAIllegalStateException("Not applicable") + } + + override val singleValue: Any? + get() { throw PAIllegalStateException("Not applicable") } + +} + +abstract class ValueFilterItemRow>(queryCondition: QueryCondition.SingleValue, filterSectionRow: FilterSectionRow): FixedValueFilterItemRow(queryCondition, filterSectionRow) { private var valueCondition: QueryCondition.SingleValue = queryCondition @@ -113,8 +128,9 @@ abstract class ValueFilterItemRow>(queryCondition: QueryConditi } override fun valueFormatted(context: Context): CharSequence? { - this.value?.let { - return this.valueCondition.labelForValue(it, context) + + (this.queryCondition as? QueryCondition.SingleValue)?.let { + return it.labelForValue(it.singleValue, context) } return NULL_TEXT } @@ -132,7 +148,7 @@ abstract class ValueFilterItemRow>(queryCondition: QueryConditi } abstract class ValueListFilterItemRow>(queryCondition: QueryCondition.ListOfValues, filterSectionRow: FilterSectionRow) - : BaseFilterItemRow(queryCondition, filterSectionRow), FilterValueHolder { + : FixedValueFilterItemRow(queryCondition, filterSectionRow) { private var listCondition: QueryCondition.ListOfValues = queryCondition @@ -154,8 +170,9 @@ abstract class ValueListFilterItemRow>(queryCondition: QueryCon } override fun valueFormatted(context: Context): CharSequence? { - this.list.firstOrNull()?.let { - return this.listCondition.labelForValue(it, context) + + (this.queryCondition as? QueryCondition.ListOfValues)?.let { + return it.labelForValue(this.list.first(), context) } return NULL_TEXT } @@ -165,14 +182,11 @@ abstract class ValueListFilterItemRow>(queryCondition: QueryCon return this.list.firstOrNull() } -// override fun getDisplayName(context: Context): String { -// return this.listCondition.getDisplayName(context, this.list) -// } - override fun updateValue(fc: FilterCondition) { val queryCondition = fc.queryCondition as QueryCondition.ListOfValues this.list = queryCondition.listOfValues } + } class DateFilterItemRow(queryCondition: QueryCondition.SingleDate, filterSectionRow: FilterSectionRow): ValueFilterItemRow(queryCondition, filterSectionRow) @@ -181,7 +195,3 @@ class IntFilterItemRow(queryCondition: QueryCondition.SingleInt, filterSectionRo class IntValueListFilterItemRow(queryCondition: QueryCondition.ListOfInt, filterSectionRow: FilterSectionRow): ValueListFilterItemRow(queryCondition, filterSectionRow) class DoubleValueListFilterItemRow(queryCondition: QueryCondition.ListOfDouble, filterSectionRow: FilterSectionRow): ValueListFilterItemRow(queryCondition, filterSectionRow) class StringValueListFilterItemRow(queryCondition: QueryCondition.ListOfString, filterSectionRow: FilterSectionRow): ValueListFilterItemRow(queryCondition, filterSectionRow) - -//interface FilterElementRow : RowRepresentable { -// -//} \ No newline at end of file From 8bdeb40824dfe105a1b66ba99824c57d3148799f Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 28 Sep 2020 17:29:44 +0200 Subject: [PATCH 06/11] Fixes a crash --- .../android/model/filter/QueryCondition.kt | 2 +- .../ui/view/rowrepresentable/FilterItemRow.kt | 4 +- .../res/layout/fragment_filter_details.xml | 76 +++++++------------ 3 files changed, 29 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt index 180c2085..115cfd97 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt @@ -594,7 +594,7 @@ sealed class QueryCondition : RowRepresentable { } } - class PastDay(value: Int) : SingleInt(value) { + class PastDay(value: Int) : UserInputSingleInt(value) { override var operator = Operator.EQUALS override val viewType: Int = RowViewType.TITLE_VALUE_CHECK.ordinal diff --git a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterItemRow.kt b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterItemRow.kt index 0f60bc85..e8cc52d1 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterItemRow.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterItemRow.kt @@ -104,11 +104,11 @@ open class FixedValueFilterItemRow(queryCondition: QueryCondition, get() { return rawCondition } override fun valueFormatted(context: Context): CharSequence? { - throw PAIllegalStateException("Not applicable") + throw PAIllegalStateException("Not applicable for $rawCondition") } override val singleValue: Any? - get() { throw PAIllegalStateException("Not applicable") } + get() { throw PAIllegalStateException("Not applicable for $rawCondition") } } diff --git a/app/src/main/res/layout/fragment_filter_details.xml b/app/src/main/res/layout/fragment_filter_details.xml index bab049a9..710f3260 100644 --- a/app/src/main/res/layout/fragment_filter_details.xml +++ b/app/src/main/res/layout/fragment_filter_details.xml @@ -1,61 +1,37 @@ - - - - - - - - - - - - - + + - - - - + android:layout_height="?attr/actionBarSize" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:title="@string/reports" /> - \ No newline at end of file + + + \ No newline at end of file From f38a85b48fdf3a996f1d341b80b2c89de1e5449f Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 28 Sep 2020 17:31:01 +0200 Subject: [PATCH 07/11] Reinstate filter use --- .../pokeranalytics/android/ui/fragment/StatisticsFragment.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt index e5dbe17d..9762d79a 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/StatisticsFragment.kt @@ -167,7 +167,9 @@ class StatisticsFragment : FilterableFragment(), RealmAsyncListener { */ private fun createSessionGroupsAndStartCompute(realm: Realm): Report { - val filter: Filter? = null + val filter: Filter? = this.currentFilter(this.requireContext(), realm)?.let { + if (it.filterableType == currentFilterable) { it } else { null } + } val allStats: List = listOf( Stat.NET_RESULT, From 6722ba22186c3ca1f59cbcf51befb749ea83097d Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 28 Sep 2020 18:27:00 +0200 Subject: [PATCH 08/11] Fixes issue with multi values list loading --- .../android/model/filter/QueryCondition.kt | 14 +++++++------- .../android/model/realm/Filter.kt | 8 +++++++- .../modules/filter/FilterDetailsViewModel.kt | 18 +++++++----------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt index 115cfd97..0822fa40 100644 --- a/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt +++ b/app/src/main/java/net/pokeranalytics/android/model/filter/QueryCondition.kt @@ -560,23 +560,23 @@ sealed class QueryCondition : RowRepresentable { } class AnyMonthOfYear() : ListOfInt() { - override fun labelForValue(value: Int, context: Context): String { - return DateFormatSymbols.getInstance(Locale.getDefault()).months[value].capitalize() - } - constructor(month: Int) : this() { listOfValues = arrayListOf(month) } - } - class AnyYear() : UserInputListOfInt() { override fun labelForValue(value: Int, context: Context): String { - return "$value" + return DateFormatSymbols.getInstance(Locale.getDefault()).months[value].capitalize() } + } + class AnyYear() : ListOfInt() { constructor(year: Int) : this() { listOfValues = arrayListOf(year) } + + override fun labelForValue(value: Int, context: Context): String { + return "$value" + } } object IsWeekDay : TrueQueryCondition() 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 5dc1487c..84a9e8a7 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 @@ -136,10 +136,16 @@ open class Filter : RealmObject(), RowRepresentable, Editable, Deletable, Counta Timber.d("list of saved queries ${filterConditions.map { it.queryCondition.id }}") Timber.d("list of contains ${filterElementRow.id}") val contained = filterConditions.flatMap { it.queryCondition.id }.contains(filterElementRow.id.first()) - Timber.d("list of : $contained") + Timber.d("is contained: $contained") return contained } + fun filterCondition(filterElementRow: QueryCondition): FilterCondition? { + return filterConditions.firstOrNull { + it.queryCondition.id.contains(filterElementRow.id.first()) + } + } + // /** // * Get the saved value for the given [filterElementRow] // */ diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt index b6780267..f96bfe0b 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt @@ -11,6 +11,7 @@ import net.pokeranalytics.android.ui.view.RowViewType import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterItemRow import net.pokeranalytics.android.util.NULL_TEXT +import timber.log.Timber class FilterDetailsViewModelFactory(var filter: Filter, var categoryRow: FilterCategoryRow): ViewModelProvider.Factory { @@ -79,21 +80,16 @@ class FilterDetailsViewModel(categoryRow: FilterCategoryRow, var filter: Filter) } private fun defineSelectedItems() { + this.rows.filterIsInstance().forEach { item -> val condition = item.rawCondition - if (this.filter.contains(condition)) { - - // Load items with appropriate value - this.filter.filterConditions.firstOrNull { - it.queryCondition.id == condition.id - }?.let { - item.updateValue(it) -// item.queryCondition?.updateValueBy(it) - this.selectedRows.add(item) - } - } + Timber.d("condition id: ${condition.id}") + this.filter.filterCondition(condition)?.let { + item.updateValue(it) + this.selectedRows.add(item) + } } } From 7cd1117ce342fac6dfb90a67dfc29aa484953b36 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 28 Sep 2020 18:42:42 +0200 Subject: [PATCH 09/11] Cleans commented code --- .../android/model/realm/Filter.kt | 12 --- .../modules/filter/FilterDetailsFragment.kt | 91 ------------------- .../modules/filter/FilterDetailsViewModel.kt | 22 ----- .../ui/modules/filter/FilterHandler.kt | 5 +- .../ui/modules/filter/FilterViewModel.kt | 6 -- .../ui/modules/filter/FiltersActivity.kt | 6 -- .../ui/modules/filter/FiltersFragment.kt | 17 ---- .../ui/modules/filter/FiltersListActivity.kt | 11 --- 8 files changed, 2 insertions(+), 168 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 84a9e8a7..883c9535 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 @@ -146,18 +146,6 @@ open class Filter : RealmObject(), RowRepresentable, Editable, Deletable, Counta } } -// /** -// * Get the saved value for the given [filterElementRow] -// */ -// fun loadValueForElement(filterElementRow: QueryCondition) { -// val filtered = filterConditions.filter { -// it.queryCondition.id == filterElementRow.id -// } -// if (filtered.isNotEmpty()) { -// return filterElementRow.updateValueBy(filtered.first()) -// } -// } - inline fun query(firstField: String? = null, vararg remainingFields: String): RealmQuery { val realmQuery = realm.where() diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt index 4bb47f3c..556d5f05 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt @@ -56,8 +56,6 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { override fun onBackPressed() { super.onBackPressed() saveData() -// requireFragmentManager().popBackStackImmediate("f1", 0) -// requireFragmentManager().popBackStackImmediate() } /** @@ -94,9 +92,6 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { } ?: throw PAIllegalStateException("Missing bundle") - //currentFilter = Filter.getFilterBydId(getRealm(), primaryKey) -// currentFilter = FiltersFragment.currentFilter - Timber.d(">> Filter = ${this.activityModel.currentFilter}") Timber.d("selectedRow = ${this.activityModel.selectedCategoryRow}") @@ -132,9 +127,6 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { } is QueryCondition.SingleValue<*>, is QueryCondition.ListOfValues<*> -> { val valueAsString = (row as FilterItemRow).singleValue?.toString() -// row.list.firstOrNull()?.let { -// valueAsString = row.list.firstOrNull()?.toString() -// } val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) showBottomSheet(row, this, data, true) } @@ -142,60 +134,6 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { } } -// when (row) { -// is DateFilterItemRow -> { -// when (val condition = row.rawCondition) { -// -// } -// } -// is IntFilterItemRow -> { -// when (val condition = row.rawCondition) { -// -// } -// } -// is ValueListFilterItemRow<*> -> { -// when (row.rawCondition) { -// -// } -// } -// } - - -// (row as? BaseFilterItemRow)?.let { filterItemRow -> -// val rawCondition = filterItemRow.rawCondition -// when (rawCondition) { -// is QueryCondition.DateQuery -> DateTimePickerManager.create( -// requireContext(), -// row, -// this, -// filterItemRow.value, -// onlyDate = !row.showTime, -// onlyTime = row.showTime -// ) -// is QueryCondition.Duration -> { -// val hours: String? = (row.minutes / 60).toString() -// val minutes: String? = (row.minutes % 60).toString() -//// row.minutes?.let { -//// hours = if (it / 60 > 0) (it / 60).toString() else null -//// minutes = if (it % 60 > 0) (it % 60).toString() else null -//// } -// val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) -// showBottomSheet(row, this, data, true) -// } -// is QueryCondition.ListOfValues<*> -> { -// var valueAsString: String? = null -// row.listOfValues.firstOrNull()?.let { -// valueAsString = row.listOfValues.firstOrNull()?.toString() -// } -// val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) -// showBottomSheet(row, this, data, true) -// } -// else -> { } -// } -// -// } - - } override fun onRowValueChanged(value: Any?, row: RowRepresentable) { @@ -246,33 +184,6 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { } } -// when (row) { -// is QueryCondition.DateQuery -> { -// if (value != null && value is Date) { -// row.singleValue = value -// } -// } -// is QueryCondition.Duration -> { -// if (value is ArrayList<*>) { -// -// } -// } -// is QueryCondition.SingleInt -> { -// if (value != null && value is String) { -// row.singleValue = value.toInt() -// } -// } -// is QueryCondition.ListOfDouble -> row.listOfValues = arrayListOf().apply { -// if (value != null && value is String) this.add(value.toDouble()) -// } -// is QueryCondition.ListOfInt -> row.listOfValues = arrayListOf().apply { -// if (value != null && value is String) this.add(value.toInt()) -// } -// is QueryCondition.ListOfString -> row.listOfValues = arrayListOf().apply { -// if (value != null && value is String) this.add(value) -// } -// } - // Remove the row before updating the selected rows list this.model.selectedRows.remove(row as FilterItemRow) updateRowsSelection(row, value == null) @@ -286,8 +197,6 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { this.model.updateRowsSelection(this.rowRepresentableAdapter, row, forceDeselection) -// println("list of selected rows : $selectedRows") - // Update UI this.rowRepresentableAdapter.refreshRow(row) } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt index f96bfe0b..ff4c26c5 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt @@ -26,9 +26,6 @@ class FilterDetailsViewModel(categoryRow: FilterCategoryRow, var filter: Filter) private var rows: ArrayList = ArrayList() val selectedRows = ArrayList() -// private var rowsForFilterSubcategoryRow: HashMap> = -// HashMap() - init { this.rows.addAll(categoryRow.filterElements) this.defineSelectedItems() @@ -47,25 +44,6 @@ class FilterDetailsViewModel(categoryRow: FilterCategoryRow, var filter: Filter) else -> super.charSequenceForRow(row, context, 0) } ?: NULL_TEXT -// val filterItemRow = row as? BaseFilterItemRow -// filterItemRow?.let { -// return when (val condition = it.rawCondition) { -//// is QueryCondition.SingleValue<*> -> filter -// is QueryCondition.ListOfValues<*> -> { -// condition.firstValue(context) ?: NULL_TEXT -// } -// else -> super.charSequenceForRow(row, context, 0) -// } -// } -// return NULL_TEXT - -// return when (row) { -// is BaseFilterItemRow -> { -// -// } -// is QueryCondition.ListOfValues<*> -> row.firstValue(context) -// else -> super.charSequenceForRow(row, context, 0) -// } ?: NULL_TEXT } override fun isSelected(position: Int, row: RowRepresentable, tag: Int): Boolean { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterHandler.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterHandler.kt index e7d73757..dadb2a24 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterHandler.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterHandler.kt @@ -34,6 +34,7 @@ enum class FilterableType(override var uniqueIdentifier: Int) : IntIdentifiable } interface FilterHandler { + companion object { const val INTENT_FILTER_UPDATE_FILTER_UI = "net.pokeranalytics.android.UPDATE_FILTER_UI" } @@ -55,8 +56,7 @@ interface FilterHandler { // Send broadcast val intent = Intent() - intent.action = - INTENT_FILTER_UPDATE_FILTER_UI + intent.action = INTENT_FILTER_UPDATE_FILTER_UI context.sendBroadcast(intent) } @@ -70,7 +70,6 @@ interface FilterHandler { var currentFilterable: FilterableType - /** * Manage filters */ diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterViewModel.kt index b3e4661d..ab42eaae 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterViewModel.kt @@ -25,12 +25,6 @@ class FilterViewModel : ViewModel(), StaticRowRepresentableDataSource { var isUpdating = false - -// val filterCategoryRow: FilterCategoryRow -// get() { -// return this.selectedCategoryRow as FilterCategoryRow -// } - fun init(realm: Realm) { if (this.currentFilter != null) { // can be called twice and we don't want that diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersActivity.kt index b4ff29bd..650998b6 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersActivity.kt @@ -90,15 +90,9 @@ class FiltersActivity : BaseActivity() { this.model.filterableType = FilterableType.valueByIdentifier(uniqueIdentifier) val filtersFragment = FiltersFragment() -// val bundle = Bundle() -// bundle.putString(BaseFragment.BundleKey.PRIMARY_KEY.value, filterId) -// bundle.putInt(BaseFragment.BundleKey.DATA_TYPE.value, uniqueIdentifier) -// fragment.arguments = bundle -// fragment.setData(filterId, filterableType) val fragmentTransaction = this.supportFragmentManager.beginTransaction() fragmentTransaction.add(R.id.container, filtersFragment, Tag.CATEGORIES.identifier) -// fragmentTransaction.addToBackStack(null) fragmentTransaction.commit() filtersFragment.updateMostUsedFiltersVisibility(!hideMostUsedFilters) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt index 57e610b3..d440f8d8 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersFragment.kt @@ -79,9 +79,6 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate { this.model.selectedCategoryRow?.let { rowRepresentableAdapter.refreshRow(it) } - - -// this.rowRepresentableAdapter.notifyDataSetChanged() } override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) { @@ -133,12 +130,6 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate { */ private fun initData() { -// this.arguments?.let { bundle -> -// this.model.primaryKey = bundle.getString(BundleKey.PRIMARY_KEY.value) -// val type = bundle.getInt(BundleKey.DATA_TYPE.value) -// this.model.filterableType = FilterableType.valueByIdentifier(type) -// } ?: throw PAIllegalStateException("Missing bundle") - this.model.init(getRealm()) this.rowRepresentableAdapter = RowRepresentableAdapter(this.model, this) @@ -152,15 +143,7 @@ open class FiltersFragment : RealmFragment(), RowRepresentableDelegate { val categoryRow = row as FilterCategoryRow this.model.selectedCategoryRow = categoryRow this.model.currentFilter?.let { _ -> - (activity as FiltersActivity).showDetailsFragment(categoryRow) - -// this.model.filterCategoryRow = row as FilterCategoryRow - -// FilterDetailsActivity.newInstanceForResult( -// this, filterId, (row as FilterCategoryRow).ordinal, -// REQUEST_CODE_FILTER_DETAILS -// ) } } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersListActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersListActivity.kt index 22efb843..1a1ef90f 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersListActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FiltersListActivity.kt @@ -24,15 +24,6 @@ class FiltersListActivity : BaseActivity() { companion object { -// fun newInstance(context: Context, dataType: Int) { -// context.startActivity( -// getIntent( -// context, -// dataType -// ) -// ) -// } - fun newSelectInstance(fragment: Fragment, showAddButton: Boolean = true) { val context = fragment.requireContext() fragment.startActivityForResult( @@ -74,8 +65,6 @@ class FiltersListActivity : BaseActivity() { this.model.showAddButton = showAddButton -// fragment.setData(dataType) -// fragment.updateUI(showAddButton) } } \ No newline at end of file From 5c4cfa1f4e07b1f8affd8e5aa4076981ee4ce14a Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 29 Sep 2020 09:42:29 +0200 Subject: [PATCH 10/11] Fix warnings --- .../android/ui/modules/filter/FilterDetailsViewModel.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt index ff4c26c5..61c9daad 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt @@ -13,7 +13,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.FilterItemRow import net.pokeranalytics.android.util.NULL_TEXT import timber.log.Timber -class FilterDetailsViewModelFactory(var filter: Filter, var categoryRow: FilterCategoryRow): ViewModelProvider.Factory { +class FilterDetailsViewModelFactory(var filter: Filter, private var categoryRow: FilterCategoryRow): ViewModelProvider.Factory { override fun create(modelClass: Class): T { return FilterDetailsViewModel(categoryRow, filter) as T From b65695d80cebc8fa74fa87ff4f125ab3f5afaac5 Mon Sep 17 00:00:00 2001 From: Laurent Date: Wed, 30 Sep 2020 12:07:37 +0200 Subject: [PATCH 11/11] Put existing values as hints by default in bottom sheet --- .../android/ui/fragment/components/BaseFragment.kt | 2 +- .../ui/fragment/components/bottomsheet/BottomSheetFragment.kt | 2 +- .../android/ui/modules/filter/FilterDetailsFragment.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt index 1e3ddd1f..a40e1aff 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/BaseFragment.kt @@ -144,7 +144,7 @@ abstract class BaseFragment : Fragment() { isClearable: Boolean? = true, currentCurrency: Currency? = null, isDeletable: Boolean? = false, - valueHasPlaceholder: Boolean? = null, + valueHasPlaceholder: Boolean? = true, alternativeLabels: Boolean = false) { BottomSheetFragment.create(activity as BaseActivity, diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt index 03ad07ed..678f4f73 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/bottomsheet/BottomSheetFragment.kt @@ -60,7 +60,7 @@ open class BottomSheetFragment : BottomSheetDialogFragment() { isClearable: Boolean? = true, currentCurrency: Currency? = null, isDeletable: Boolean? = false, - valueHasPlaceholder: Boolean? = null, + valueHasPlaceholder: Boolean? = true, alternativeLabels: Boolean = false ): BottomSheetFragment { val bottomSheetFragment = newInstance(row.bottomSheetType) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt index 556d5f05..276fcc97 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsFragment.kt @@ -128,7 +128,7 @@ open class FilterDetailsFragment : RealmFragment(), RowRepresentableDelegate { is QueryCondition.SingleValue<*>, is QueryCondition.ListOfValues<*> -> { val valueAsString = (row as FilterItemRow).singleValue?.toString() val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) - showBottomSheet(row, this, data, true) + showBottomSheet(row, this, data, true, valueHasPlaceholder = true) } else -> { } }