diff --git a/app/build.gradle b/app/build.gradle index 937f8190..3aa2feed 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -79,6 +79,11 @@ android { versionNameSuffix = '_nov2020' versionCode = 52110 + android.defaultConfig.versionCode } + oct2021 { + dimension = 'endOfUse' + versionNameSuffix = '_oct2021' + versionCode = 52120 + android.defaultConfig.versionCode + } } configurations { 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 f52f3e2e..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,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.FixedValueFilterItemRow 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)) + val filterItemRow = FixedValueFilterItemRow(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/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..33b972b3 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,31 +16,49 @@ 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.util.NULL_TEXT import net.pokeranalytics.android.util.UserDefaults import net.pokeranalytics.android.util.extensions.* import java.text.DateFormatSymbols import java.text.NumberFormat import java.util.* -import kotlin.collections.ArrayList +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 : FilterElementRow { +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 { @@ -49,8 +67,7 @@ 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() - return instance as T + return newInstance(kClass) as T } inline fun getInstance(): QueryCondition { @@ -125,25 +142,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 +172,32 @@ 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) : 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() { 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() @@ -174,7 +210,7 @@ sealed class QueryCondition : FilterElementRow { 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() @@ -187,7 +223,7 @@ sealed class QueryCondition : FilterElementRow { 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 } @@ -198,46 +234,30 @@ sealed class QueryCondition : FilterElementRow { } } - 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() } + } - 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 getDisplayName(context: Context): String { @@ -247,7 +267,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 +283,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" } @@ -281,26 +301,23 @@ sealed class QueryCondition : FilterElementRow { } } - interface DateTime { 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 +360,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,14 +441,6 @@ 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" - } - } - class NumberOfTable : ListOfInt() { override fun labelForValue(value: Int, context: Context): String { return value.toString() + " " + context.getString(R.string.tables) @@ -476,13 +469,13 @@ sealed class QueryCondition : FilterElementRow { } 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 { @@ -507,19 +500,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 } @@ -530,23 +523,23 @@ sealed class QueryCondition : FilterElementRow { } 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() : ListOfInt() { 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() @@ -564,7 +557,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 @@ -572,16 +565,17 @@ sealed class QueryCondition : FilterElementRow { 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 : SingleInt() { + class Duration(value: Int) : SingleInt(value) { override var operator = Operator.EQUALS - var minutes: Int? + + var minutes: Int get() { return singleValue } @@ -589,12 +583,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,22 +600,12 @@ 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 - } - } - class EndedToTime() : TimeQuery() { + class EndedToTime(date: Date) : TimeQuery(date) { override var operator = Operator.LESS - - constructor(date: Date) : this() { - singleValue = date - } - } interface CustomFieldRelated { @@ -639,12 +620,8 @@ sealed class QueryCondition : FilterElementRow { } } - class CustomFieldQuery() : QueryDataCondition() { + class CustomFieldQuery : QueryDataCondition() { override var entity: Class = CustomField::class.java - - constructor(customField: CustomField) : this() { - this.setObject(customField) - } } open class CustomFieldNumberQuery() : ListOfDouble(), CustomFieldRelated { @@ -666,7 +643,9 @@ sealed class QueryCondition : FilterElementRow { 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" } @@ -762,15 +741,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 +776,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 +814,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 +824,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 +837,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 +891,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..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 @@ -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 } @@ -132,19 +136,13 @@ 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 } - /** - * 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()) + fun filterCondition(filterElementRow: QueryCondition): FilterCondition? { + return filterConditions.firstOrNull { + it.queryCondition.id.contains(filterElementRow.id.first()) } } 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..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 @@ -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 }) @@ -48,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) } } @@ -57,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 @@ -91,4 +102,5 @@ open class FilterCondition() : RealmObject() { fun setValue(value:String) { stringValue = value } + } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt index 111cee96..4e55ea8d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SettingsFragment.kt @@ -12,6 +12,7 @@ import android.view.ViewGroup import android.widget.Toast import androidx.core.content.FileProvider import androidx.recyclerview.widget.LinearLayoutManager +import com.android.billingclient.api.Purchase import com.google.android.play.core.review.ReviewManagerFactory import io.realm.Realm import kotlinx.android.synthetic.main.fragment_settings.* @@ -37,6 +38,7 @@ import net.pokeranalytics.android.ui.view.rowrepresentable.SettingRow import net.pokeranalytics.android.util.* import net.pokeranalytics.android.util.billing.AppGuard import net.pokeranalytics.android.util.billing.IAPProducts +import net.pokeranalytics.android.util.billing.PurchaseListener import net.pokeranalytics.android.util.csv.ProductCSVDescriptors import net.pokeranalytics.android.util.extensions.dateTimeFileFormatted import timber.log.Timber @@ -45,7 +47,7 @@ import java.io.IOException import java.util.* -class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepresentableDataSource { +class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRepresentableDataSource, PurchaseListener { companion object { @@ -69,6 +71,16 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep private lateinit var settingsAdapterRow: RowRepresentableAdapter + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + AppGuard.registerListener(this) + } + + override fun onDestroy() { + super.onDestroy() + AppGuard.unregisterListener(this) + } + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) return inflater.inflate(R.layout.fragment_settings, container, false) @@ -299,4 +311,12 @@ class SettingsFragment : RealmFragment(), RowRepresentableDelegate, StaticRowRep } + override fun purchaseDidSucceed(purchase: Purchase) { + this.settingsAdapterRow.refreshRow(SettingRow.SUBSCRIPTION) + } + + override fun noPurchaseRetrieved() { + + } + } \ No newline at end of file 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..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 @@ -168,8 +168,8 @@ 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 } - } + if (it.filterableType == currentFilterable) { it } else { null } + } val allStats: List = listOf( Stat.NET_RESULT, diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt index 503464c1..88fcd6ec 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/SubscriptionFragment.kt @@ -32,12 +32,12 @@ import net.pokeranalytics.android.ui.fragment.components.ScreenSlidePageFragment import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.billing.AppGuard import net.pokeranalytics.android.util.billing.IAPProducts -import net.pokeranalytics.android.util.billing.PurchaseDelegate +import net.pokeranalytics.android.util.billing.PurchaseListener import java.lang.ref.WeakReference import java.time.Period import java.time.format.DateTimeParseException -class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, PurchaseDelegate, ViewPager.OnPageChangeListener { +class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, PurchaseListener, ViewPager.OnPageChangeListener { companion object { val parallax: Float = 64f.px @@ -67,6 +67,8 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas return } + AppGuard.registerListener(this) + this.showLoader(R.string.loading_please_wait) if (!AppGuard.requestProducts(this)) { this.hideLoader() @@ -86,6 +88,11 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas initUI() } + override fun onDestroy() { + super.onDestroy() + AppGuard.unregisterListener(this) + } + private fun initData() { this.showSessionMessage = arguments?.getBoolean(BundleKey.SHOW_MESSAGE.value) ?: false } @@ -133,7 +140,7 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas this.purchase.setOnClickListener { this.selectedProduct?.let { - AppGuard.initiatePurchase(this.requireActivity(), it, this) + AppGuard.initiatePurchase(this.requireActivity(), it) } ?: run { throw PAIllegalStateException("Attempt to initiate purchase while no product has been chosen") } @@ -236,6 +243,10 @@ class SubscriptionFragment : BaseFragment(), SkuDetailsResponseListener, Purchas this.activity?.finish() } + override fun noPurchaseRetrieved() { + + } + // OnPageChangeListener override fun onPageScrollStateChanged(state: Int) {} 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/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/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/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/feed/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedFragment.kt index daeb7ce5..c9f3b386 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/feed/FeedFragment.kt @@ -8,6 +8,7 @@ import android.widget.Toast import androidx.core.app.ActivityOptionsCompat import androidx.core.view.isVisible import androidx.interpolator.view.animation.FastOutSlowInInterpolator +import com.android.billingclient.api.Purchase import com.google.android.material.tabs.TabLayout import io.realm.RealmModel import io.realm.RealmResults @@ -37,11 +38,12 @@ import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager import net.pokeranalytics.android.util.Preferences import net.pokeranalytics.android.util.billing.AppGuard +import net.pokeranalytics.android.util.billing.PurchaseListener import net.pokeranalytics.android.util.extensions.count import timber.log.Timber import java.util.* -class FeedFragment : FilterableFragment(), RowRepresentableDelegate { +class FeedFragment : FilterableFragment(), RowRepresentableDelegate, PurchaseListener { private enum class Tab { SESSIONS, @@ -104,6 +106,11 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { } + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + AppGuard.registerListener(this) + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -205,6 +212,11 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { } + override fun onDestroy() { + AppGuard.unregisterListener(this) + super.onDestroy() + } + override fun onDestroyView() { super.onDestroyView() realmTransactions.removeAllChangeListeners() @@ -313,7 +325,6 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { this.showSubscriptionButton() } } - this.showSubscriptionButton() } @@ -419,11 +430,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { /** * Create a new cash game */ - private fun createNewSession( - isTournament: Boolean, - sessionId: String? = null, - duplicate: Boolean = false - ) { + private fun createNewSession(isTournament: Boolean, sessionId: String? = null, duplicate: Boolean = false) { val sessionCount = getRealm().count(Session::class.java) if (!AppGuard.isProUser && sessionCount >= AppGuard.MAX_SESSIONS_BEFORE_REQUESTING_SUBSCRIPTION) { // && !BuildConfig.DEBUG @@ -473,10 +480,6 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { */ private fun createNewHandHistory() { -// val intent = Intent(requireContext(), TestActivity::class.java) -// startActivity(intent) -// return - AppGuard.endOfUse?.let { endDate -> if (Date().after(endDate)) { this.showEndOfUseMessage() @@ -577,4 +580,12 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { this.sessionAdapter.notifyDataSetChanged() // refreshes session durations } + override fun purchaseDidSucceed(purchase: Purchase) { + this.showSubscriptionButton() + } + + override fun noPurchaseRetrieved() { + this.showSubscriptionButton() + } + } \ No newline at end of file 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..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 @@ -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) @@ -53,11 +56,8 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSo override fun onBackPressed() { super.onBackPressed() saveData() -// requireFragmentManager().popBackStackImmediate("f1", 0) -// requireFragmentManager().popBackStackImmediate() } - /** * Init UI */ @@ -80,39 +80,24 @@ 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()) + Timber.d(">> Filter = ${this.activityModel.currentFilter}") + Timber.d("selectedRow = ${this.activityModel.selectedCategoryRow}") - this.rows.clear() - this.rowsForFilterSubcategoryRow.clear() - this.rows.addAll(filterCategoryRow.filterElements) - - 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 } @@ -124,49 +109,31 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSo return } - 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 + (row as? FixedValueFilterItemRow)?.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) } - 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 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, valueHasPlaceholder = true) } - val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) - showBottomSheet(row, this, data, true) + else -> { } } } - } - 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) } override fun onRowValueChanged(value: Any?, row: RowRepresentable) { @@ -174,80 +141,61 @@ 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 String -> { + row.value = value.toInt() } - 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 + else -> { row.value = 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) } } // 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) - } - } - - println("list of selected rows : $selectedRows") + this.model.updateRowsSelection(this.rowRepresentableAdapter, row, forceDeselection) // Update UI this.rowRepresentableAdapter.refreshRow(row) @@ -258,18 +206,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..61c9daad --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/modules/filter/FilterDetailsViewModel.kt @@ -0,0 +1,96 @@ +package net.pokeranalytics.android.ui.modules.filter + +import android.content.Context +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +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.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, private 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() + + init { + this.rows.addAll(categoryRow.filterElements) + this.defineSelectedItems() + } + + override fun adapterRows(): List? { + return this.rows + } + + override fun charSequenceForRow(row: RowRepresentable, context: Context): CharSequence { + + return when (row) { + is FilterItemRow -> { + row.valueFormatted(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.rawCondition + Timber.d("condition id: ${condition.id}") + + this.filter.filterCondition(condition)?.let { + item.updateValue(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/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 450c633a..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 @@ -20,14 +20,10 @@ class FilterViewModel : ViewModel(), StaticRowRepresentableDataSource { var filterCopy: Filter? = null private var categoryRows: ArrayList = ArrayList() var primaryKey: String? = null - var selectedCategoryRow: RowRepresentable? = null - var isUpdating = false - // Details - val filterCategoryRow: FilterCategoryRow - get() { - return this.selectedCategoryRow as FilterCategoryRow - } + var selectedCategoryRow: FilterCategoryRow? = null + + var isUpdating = false 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..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 @@ -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() { @@ -88,23 +90,17 @@ 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) } - 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..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 @@ -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 @@ -78,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) { @@ -132,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) @@ -148,17 +140,10 @@ 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 { _ -> - - (activity as FiltersActivity).showDetailsFragment() - -// this.model.filterCategoryRow = row as FilterCategoryRow - -// FilterDetailsActivity.newInstanceForResult( -// this, filterId, (row as FilterCategoryRow).ordinal, -// REQUEST_CODE_FILTER_DETAILS -// ) + val categoryRow = row as FilterCategoryRow + this.model.selectedCategoryRow = categoryRow + this.model.currentFilter?.let { _ -> + (activity as FiltersActivity).showDetailsFragment(categoryRow) } } 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 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 deleted file mode 100644 index 43860b3a..00000000 --- a/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterElementRow.kt +++ /dev/null @@ -1,61 +0,0 @@ -package net.pokeranalytics.android.ui.view.rowrepresentable - -import android.text.InputType -import net.pokeranalytics.android.R -import net.pokeranalytics.android.model.filter.QueryCondition -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 { - override fun editingDescriptors(map: Map): ArrayList? { - return when (this) { - 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.operator) { - QueryCondition.Operator.MORE, QueryCondition.Operator.LESS -> { - when (this) { - 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) - } - } - - var filterSectionRow: FilterSectionRow - - val sectionToExclude: List? - get() { - val excluded = arrayListOf() - if (!this.filterSectionRow.allowMultiSelection) { - excluded.add(this.filterSectionRow) - } - this.filterSectionRow.exclusiveWith?.let { exclusives -> - excluded.addAll(exclusives) - } - - if (excluded.size > 0) { - return excluded - } - return null - } -} \ No newline at end of file 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 new file mode 100644 index 00000000..e8cc52d1 --- /dev/null +++ b/app/src/main/java/net/pokeranalytics/android/ui/view/rowrepresentable/FilterItemRow.kt @@ -0,0 +1,197 @@ +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 +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 { + + val rawCondition: QueryCondition + val queryCondition: QueryCondition? + var filterSectionRow: FilterSectionRow + + 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() + if (!this.filterSectionRow.allowMultiSelection) { + excluded.add(this.filterSectionRow) + } + this.filterSectionRow.exclusiveWith?.let { exclusives -> + excluded.addAll(exclusives) + } + + if (excluded.size > 0) { + return excluded + } + return null + } + + + // Row Representable + + override fun getDisplayName(context: Context): String { + return this.rawCondition.getDisplayName(context) + } + + override val resId: Int? + get() { return this.rawCondition.resId } + + override val viewType: Int + get() { return this.rawCondition.viewType } + + 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.SingleValue<*>, 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) + } + } + +} + +open class FixedValueFilterItemRow(queryCondition: QueryCondition, + override var filterSectionRow: FilterSectionRow) : FilterItemRow { + + override val rawCondition: QueryCondition = queryCondition + + override val queryCondition: QueryCondition? + get() { return rawCondition } + + override fun valueFormatted(context: Context): CharSequence? { + throw PAIllegalStateException("Not applicable for $rawCondition") + } + + override val singleValue: Any? + get() { throw PAIllegalStateException("Not applicable for $rawCondition") } + +} + +abstract class ValueFilterItemRow>(queryCondition: QueryCondition.SingleValue, filterSectionRow: FilterSectionRow): FixedValueFilterItemRow(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 valueFormatted(context: Context): CharSequence? { + + (this.queryCondition as? QueryCondition.SingleValue)?.let { + return it.labelForValue(it.singleValue, context) + } + return NULL_TEXT + } + + override val singleValue: Any? + get() { + return this.value + } + + override fun updateValue(fc: FilterCondition) { + val queryCondition = fc.queryCondition as QueryCondition.SingleValue + this.value = queryCondition.singleValue + } + +} + +abstract class ValueListFilterItemRow>(queryCondition: QueryCondition.ListOfValues, filterSectionRow: FilterSectionRow) + : FixedValueFilterItemRow(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 valueFormatted(context: Context): CharSequence? { + + (this.queryCondition as? QueryCondition.ListOfValues)?.let { + return it.labelForValue(this.list.first(), context) + } + return NULL_TEXT + } + + override val singleValue: Any? + get() { + return this.list.firstOrNull() + } + + 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) +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) 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..101f3565 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,140 @@ 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 { + rowWrapper(it, this@FilterSectionRow) +// it.toRowWrapper(this@FilterSectionRow) + } + } + + private fun rowWrapper(queryCondition: QueryCondition, section: FilterSectionRow): FilterItemRow { + return when (queryCondition) { + // Int List + is QueryCondition.TournamentFinalPosition -> IntValueListFilterItemRow(queryCondition, section) + is QueryCondition.TournamentNumberOfPlayer -> IntValueListFilterItemRow(queryCondition, section) + // Double List + is QueryCondition.NumberOfRebuy -> DoubleValueListFilterItemRow(queryCondition, section) + is QueryCondition.NetAmount -> DoubleValueListFilterItemRow(queryCondition, section) + // Int + is QueryCondition.PastDay -> IntFilterItemRow(queryCondition, section) + is QueryCondition.Duration -> IntFilterItemRow(queryCondition, section) + // Dates + is QueryCondition.StartedFromDate -> DateFilterItemRow(queryCondition, section) + is QueryCondition.StartedFromTime -> DateFilterItemRow(queryCondition, section) + is QueryCondition.StartedToDate -> DateFilterItemRow(queryCondition, section) + is QueryCondition.EndedToDate -> DateFilterItemRow(queryCondition, section) + is QueryCondition.EndedToTime -> DateFilterItemRow(queryCondition, section) + else -> FixedValueFilterItemRow(queryCondition, section) + } + } + + 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() - 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() + 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 + + // 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() { diff --git a/app/src/main/java/net/pokeranalytics/android/util/billing/AppGuard.kt b/app/src/main/java/net/pokeranalytics/android/util/billing/AppGuard.kt index d20b35c2..07268fd9 100644 --- a/app/src/main/java/net/pokeranalytics/android/util/billing/AppGuard.kt +++ b/app/src/main/java/net/pokeranalytics/android/util/billing/AppGuard.kt @@ -18,8 +18,9 @@ enum class IAPProducts(var identifier: String) { PRO("unlimited") } -interface PurchaseDelegate { +interface PurchaseListener { fun purchaseDidSucceed(purchase: Purchase) + fun noPurchaseRetrieved() } /** @@ -61,7 +62,6 @@ object AppGuard : PurchasesUpdatedListener { */ val isProUser: Boolean get() { - if (this.endOfUse != null) return true return if (BuildConfig.DEBUG) { @@ -78,6 +78,7 @@ object AppGuard : PurchasesUpdatedListener { "august2020" -> "01/8/2020" "april2021" -> "09/4/2021" "nov2020" -> "08/11/2020" + "oct2021" -> "01/10/2021" else -> null } @@ -92,7 +93,7 @@ object AppGuard : PurchasesUpdatedListener { /** * A delegate to notify when the purchase has succeeded */ - private var purchaseDelegate: PurchaseDelegate? = null + private var purchaseListeners: MutableList = mutableListOf() /** * Initialization of AppGuard @@ -205,9 +206,7 @@ object AppGuard : PurchasesUpdatedListener { /** * Initiates purchase with the product [skuDetails] */ - fun initiatePurchase(activity: Activity, skuDetails: SkuDetails, delegate: PurchaseDelegate) { - - this.purchaseDelegate = delegate + fun initiatePurchase(activity: Activity, skuDetails: SkuDetails) { val flowParams = BillingFlowParams.newBuilder() .setSkuDetails(skuDetails) @@ -224,9 +223,13 @@ object AppGuard : PurchasesUpdatedListener { override fun onPurchasesUpdated(result: BillingResult, purchases: MutableList?) { - if (result.responseCode == BillingResponseCode.OK && purchases != null) { - for (purchase in purchases) { - handlePurchase(purchase) + if (result.responseCode == BillingResponseCode.OK) { + if (purchases != null && purchases.isNotEmpty()) { + for (purchase in purchases) { + handlePurchase(purchase) + } + } else { + sendNoPurchaseRetrievedEvent() } } else if (result.responseCode == BillingResponseCode.USER_CANCELED) { Timber.d("purchase cancel message: ${result.debugMessage}") @@ -239,6 +242,12 @@ object AppGuard : PurchasesUpdatedListener { } + private fun sendNoPurchaseRetrievedEvent() { + this.purchaseListeners.forEach { listener -> + listener.noPurchaseRetrieved() + } + } + // /** // * Purchase callback // */ @@ -279,12 +288,13 @@ object AppGuard : PurchasesUpdatedListener { } this._isProUser = true - this.purchaseDelegate?.let { + + this.purchaseListeners.forEach { listener -> Handler(Looper.getMainLooper()).post { - it.purchaseDidSucceed(purchase) + listener.purchaseDidSucceed(purchase) } - this.purchaseDelegate = null } + } } @@ -317,4 +327,18 @@ object AppGuard : PurchasesUpdatedListener { return context.getString(resId) } + /*** + * Removes a listener + */ + fun registerListener(listener: PurchaseListener) { + this.purchaseListeners.add(listener) + } + + /*** + * Removes a listener + */ + fun unregisterListener(listener: PurchaseListener) { + this.purchaseListeners.remove(listener) + } + } \ No newline at end of file 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 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() + } + } + +}