From df17928eb82be2c5fe1c1c28225d5c3db874946a Mon Sep 17 00:00:00 2001 From: Aurelien Hubert Date: Thu, 23 May 2019 17:33:34 +0200 Subject: [PATCH] Add first version of Filter management --- .../android/model/realm/Filter.kt | 3 +- .../ui/activity/FilterDetailsActivity.kt | 6 +- .../android/ui/activity/FiltersActivity.kt | 1 - .../android/ui/fragment/DataListFragment.kt | 1 - .../android/ui/fragment/FeedFragment.kt | 20 ++- .../ui/fragment/FilterDetailsFragment.kt | 144 +++++++++-------- .../android/ui/fragment/FiltersFragment.kt | 146 +++++++++++------- .../components/DeletableItemFragment.kt | 4 + .../fragment/components/FilterableFragment.kt | 52 ++++++- .../android/ui/interfaces/FilterHandler.kt | 19 ++- app/src/main/res/layout/fragment_feed.xml | 12 +- app/src/main/res/layout/fragment_filters.xml | 53 +++++-- .../main/res/layout/view_selected_filter.xml | 41 +++++ 13 files changed, 332 insertions(+), 170 deletions(-) create mode 100644 app/src/main/res/layout/view_selected_filter.xml 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 cba181ef..df148089 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 @@ -29,7 +29,8 @@ open class Filter : RealmObject(), RowRepresentable, Identifiable, Deletable { fun newInstance(realm: Realm, filterableType:Int): Filter { val filter = Filter() filter.filterableTypeOrdinal = filterableType - return realm.copyToRealm(filter) + return filter + //return realm.copyToRealm(filter) } // Get a queryWith by its id diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/FilterDetailsActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/FilterDetailsActivity.kt index cdedb52f..dcd63a61 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/FilterDetailsActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/FilterDetailsActivity.kt @@ -5,6 +5,7 @@ import android.content.Intent import android.os.Bundle import androidx.fragment.app.Fragment import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.fragment.FilterDetailsFragment @@ -16,6 +17,7 @@ class FilterDetailsActivity : PokerAnalyticsActivity() { } companion object { + /** * Default constructor */ @@ -29,7 +31,8 @@ class FilterDetailsActivity : PokerAnalyticsActivity() { /** * Create a new instance for result */ - fun newInstanceForResult(fragment: Fragment, filterId: String, filterCategoryOrdinal: Int, requestCode: Int) { + fun newInstanceForResult(fragment: Fragment, filterId: String, filterCategoryOrdinal: Int, requestCode: Int, filter: Filter? = null) { + val intent = Intent(fragment.requireContext(), FilterDetailsActivity::class.java) intent.putExtra(IntentKey.FILTER_ID.keyName, filterId) intent.putExtra(IntentKey.FILTER_CATEGORY_ORDINAL.keyName, filterCategoryOrdinal) @@ -63,7 +66,6 @@ class FilterDetailsActivity : PokerAnalyticsActivity() { fragmentTransaction.add(R.id.container, fragment) fragmentTransaction.commit() fragment.setData(filterId, filterCategoryOrdinal) - } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/activity/FiltersActivity.kt b/app/src/main/java/net/pokeranalytics/android/ui/activity/FiltersActivity.kt index 0a7ec411..5c2b621d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/activity/FiltersActivity.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/activity/FiltersActivity.kt @@ -5,7 +5,6 @@ import android.content.Intent import android.os.Bundle import androidx.fragment.app.Fragment import net.pokeranalytics.android.R -import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.ui.activity.components.PokerAnalyticsActivity import net.pokeranalytics.android.ui.fragment.FiltersFragment import net.pokeranalytics.android.ui.interfaces.FilterActivityRequestCode diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt index 19d24c7e..ac4d5f01 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/DataListFragment.kt @@ -134,7 +134,6 @@ class DataListFragment : DeletableItemFragment(), LiveRowRepresentableDataSource EditableDataActivity.newInstanceForResult(this, this.dataType, identifier, REQUEST_CODE_DETAILS) } } - } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt index a0111047..f671ed67 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FeedFragment.kt @@ -1,6 +1,5 @@ package net.pokeranalytics.android.ui.fragment -import android.app.Activity import android.app.Activity.RESULT_OK import android.content.Intent import android.os.Bundle @@ -28,11 +27,11 @@ import net.pokeranalytics.android.ui.adapter.FeedTransactionRowRepresentableAdap import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.fragment.components.FilterableFragment import net.pokeranalytics.android.ui.interfaces.FilterActivityRequestCode -import net.pokeranalytics.android.ui.interfaces.FilterHandler import net.pokeranalytics.android.ui.interfaces.FilterableType import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.SmoothScrollLinearLayoutManager import net.pokeranalytics.android.util.Preferences +import timber.log.Timber import java.text.SimpleDateFormat import java.util.* @@ -85,7 +84,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { if (data.getBooleanExtra(DataListActivity.IntentKey.ITEM_DELETED.keyName, false)) { deleteSelectedTransaction() } - } else if (requestCode == FilterActivityRequestCode.SELECT_FILTER.ordinal && resultCode == Activity.RESULT_OK) { + } else if (requestCode == FilterActivityRequestCode.SELECT_FILTER.ordinal && resultCode == RESULT_OK) { data?.let { this.saveFilter(this.requireContext(), it.getStringExtra(FiltersActivity.IntentKey.FILTER_ID.keyName)) } @@ -99,15 +98,17 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { realmTransactions.removeAllChangeListeners() } + /* override fun setUserVisibleHint(isVisibleToUser: Boolean) { super.setUserVisibleHint(isVisibleToUser) - if (isVisibleToUser) { + if (isVisibleToUser && view != null) { if (FilterHandler.filterWasUpdated) { this.initData() FilterHandler.filterWasUpdated = false } } } + */ override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { when (row) { @@ -174,15 +175,14 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { val sdf = SimpleDateFormat("dd/M/yyyy hh:mm", Locale.getDefault()) betaLimitDate = sdf.parse("17/7/2019 10:00") - val filter : Filter? = this.currentFilter(this.requireContext(), getRealm()) - this.loadSessions(filter) - this.loadTransactions(filter) + val viewManager = SmoothScrollLinearLayoutManager(requireContext()) recyclerView.apply { setHasFixedSize(true) layoutManager = viewManager - adapter = feedSessionAdapter } + + applyFilter() } private fun loadSessions(filter : Filter? = null) { @@ -204,6 +204,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { val pendingSessions = sessionFilter?.let { getRealm().where().alwaysFalse().findAll() } ?: run { getRealm().where().isNull("year").isNull("month").findAll().sort("startDate", Sort.DESCENDING) } val distinctDateSessions = sessionFilter?.results("year", "month") ?: run { getRealm().where().distinct("year", "month").findAll() }.sort("startDate", Sort.DESCENDING) this.feedSessionAdapter = FeedSessionRowRepresentableAdapter(this, realmSessions, pendingSessions, distinctDateSessions) + recyclerView.adapter = feedSessionAdapter } private fun loadTransactions(filter : Filter? = null) { @@ -287,6 +288,8 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { } override fun applyFilter() { + super.applyFilter() + Timber.d("applyFilter") val filter: Filter? = this.currentFilter(this.requireContext(), getRealm()) this.loadSessions(filter) this.loadTransactions(filter) @@ -300,6 +303,7 @@ class FeedFragment : FilterableFragment(), RowRepresentableDelegate { } override fun removeFilter() { + super.removeFilter() this.loadSessions() this.loadTransactions() if (currentFilterable== FilterableType.SESSION) { diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FilterDetailsFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FilterDetailsFragment.kt index 1d6a480e..e752e1eb 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FilterDetailsFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FilterDetailsFragment.kt @@ -5,7 +5,6 @@ import android.content.Context import android.content.Intent import android.os.Bundle import android.view.LayoutInflater -import android.view.Menu import android.view.View import android.view.ViewGroup import androidx.recyclerview.widget.LinearLayoutManager @@ -22,33 +21,26 @@ import net.pokeranalytics.android.ui.fragment.components.RealmFragment import net.pokeranalytics.android.ui.fragment.components.bottomsheet.BottomSheetFragment import net.pokeranalytics.android.ui.helpers.DateTimePickerManager 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.FilterElementRow import net.pokeranalytics.android.ui.view.rowrepresentable.FilterSectionRow import net.pokeranalytics.android.util.NULL_TEXT -import net.pokeranalytics.android.util.extensions.shortDate -import net.pokeranalytics.android.util.extensions.shortTime -import net.pokeranalytics.android.util.extensions.toMinutes import timber.log.Timber import java.util.* import kotlin.collections.ArrayList -open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { +open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataSource, RowRepresentableDelegate { lateinit var rowRepresentableAdapter: RowRepresentableAdapter - private lateinit var primaryKey: String - private lateinit var filterCategoryRow: FilterCategoryRow + private lateinit var primaryKey: String + private lateinit var filterCategoryRow: FilterCategoryRow private var currentFilter: Filter? = null private var rows: ArrayList = ArrayList() private var rowsForFilterSubcategoryRow: HashMap> = HashMap() - private var filterMenu: Menu? = null private val selectedRows = ArrayList() - private var isUpdating = false - private var shouldOpenKeyboard = true override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) @@ -63,49 +55,54 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataS override fun onBackPressed() { super.onBackPressed() - println("<<<<< back pressed") + println("<<<<< back pressed") saveData() } override fun onRowSelected(position: Int, row: RowRepresentable, fromAction: Boolean) { super.onRowSelected(position, row, fromAction) - Timber.d("Row: $row") - - if (row.viewType == RowViewType.TITLE_CHECK.ordinal) { - updateRowsSelection(row) - return - } + if (row.viewType == RowViewType.TITLE_CHECK.ordinal) { + updateRowsSelection(row) + return + } when (row) { - is QueryCondition.DateQuery -> DateTimePickerManager.create(requireContext(), row, this, row.singleValue, onlyDate = !row.showTime, onlyTime = row.showTime) + 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 - } - val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) + 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 + } + val data = row.editingDescriptors(mapOf("hours" to hours, "minutes" to minutes)) + BottomSheetFragment.create(fragmentManager, row, this, data, true) + } + is QueryCondition.ListOfValues<*> -> { + var valueAsString: String? = null + row.listOfValues.firstOrNull()?.let { + valueAsString = row.listOfValues.firstOrNull()?.toString() + } + val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) BottomSheetFragment.create(fragmentManager, row, this, data, true) } - is QueryCondition.ListOfValues<*> -> { - var valueAsString: String? = null - row.listOfValues.firstOrNull()?.let { - valueAsString = row.listOfValues.firstOrNull()?.toString() - } - val data = row.editingDescriptors(mapOf("valueAsString" to valueAsString)) - BottomSheetFragment.create(fragmentManager, row, this, data, true) - } } } override fun stringForRow(row: RowRepresentable, context: Context): String { - return when (row) { - is QueryCondition.ListOfValues<*> -> row.firstValue(context) - else -> super.stringForRow(row) - } ?: NULL_TEXT - } + return when (row) { + is QueryCondition.ListOfValues<*> -> row.firstValue(context) + else -> super.stringForRow(row) + } ?: NULL_TEXT + } override fun isSelected(row: RowRepresentable): Boolean { return selectedRows.contains(row) @@ -125,32 +122,32 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataS null } val minutes = try { - (value[1] as String?)?.toInt() + (value[1] as String?)?.toInt() } catch (e: Exception) { null } - 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 - } + 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 + } } else { row.minutes = null } } - is QueryCondition.SingleInt -> row.singleValue = if (value != null && value is String) value.toInt() else null - is QueryCondition.ListOfDouble-> row.listOfValues = arrayListOf().apply { - if (value != null && value is String) this.add(value.toDouble()) - } - is QueryCondition.ListOfInt-> row.listOfValues = arrayListOf().apply { - if (value != null && value is String) this.add(value.toInt()) - } - is QueryCondition.ListOfString-> row.listOfValues = arrayListOf().apply { - if (value != null && value is String) this.add(value) - } - } + 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 QueryCondition.ListOfInt -> row.listOfValues = arrayListOf().apply { + if (value != null && value is String) this.add(value.toInt()) + } + is QueryCondition.ListOfString -> row.listOfValues = arrayListOf().apply { + if (value != null && value is String) this.add(value) + } + } // Remove the row before updating the selected rows list selectedRows.remove(row as FilterElementRow) @@ -189,24 +186,24 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataS */ private fun initData() { - currentFilter = Filter.getFilterBydId(getRealm(), primaryKey) + //currentFilter = Filter.getFilterBydId(getRealm(), primaryKey) + currentFilter = FiltersFragment.currentFilter + this.appBar.toolbar.title = filterCategoryRow.localizedTitle(requireContext()) - this.appBar.toolbar.title = filterCategoryRow.localizedTitle(requireContext()) + this.rows.clear() + this.rowsForFilterSubcategoryRow.clear() + this.rows.addAll(filterCategoryRow.filterElements) - this.rows.clear() - this.rowsForFilterSubcategoryRow.clear() - this.rows.addAll(filterCategoryRow.filterElements) - - this.rows.forEach { element -> - if (element is QueryCondition && currentFilter?.contains(element) == true) { - currentFilter?.loadValueForElement(element) - this.selectedRows.add(element) - } + this.rows.forEach { element -> + if (element is QueryCondition && currentFilter?.contains(element) == true) { + currentFilter?.loadValueForElement(element) + this.selectedRows.add(element) } + } - this.rowRepresentableAdapter = RowRepresentableAdapter(this, this) - this.recyclerView.adapter = rowRepresentableAdapter + this.rowRepresentableAdapter = RowRepresentableAdapter(this, this) + this.recyclerView.adapter = rowRepresentableAdapter } /** @@ -231,7 +228,7 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataS } } - println("list of selected rows : $selectedRows") + println("list of selected rows : $selectedRows") // Update UI rowRepresentableAdapter.refreshRow(row) @@ -249,7 +246,7 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataS val realm = getRealm() realm.beginTransaction() - currentFilter?.remove(filterCategoryRow) + currentFilter?.remove(filterCategoryRow) currentFilter?.createOrUpdateFilterConditions(selectedRows) realm.commitTransaction() @@ -257,7 +254,6 @@ open class FilterDetailsFragment : RealmFragment(), StaticRowRepresentableDataS Timber.d("Condition: $it") } - finishActivityWithResult(currentFilter?.id) } diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt index 5a4bd9c4..b6813b9d 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/FiltersFragment.kt @@ -12,7 +12,9 @@ import kotlinx.android.synthetic.main.fragment_editable_data.recyclerView import kotlinx.android.synthetic.main.fragment_filters.* import kotlinx.android.synthetic.main.fragment_filters.view.toolbar import net.pokeranalytics.android.R +import net.pokeranalytics.android.model.LiveData import net.pokeranalytics.android.model.realm.Filter +import net.pokeranalytics.android.ui.activity.DataListActivity import net.pokeranalytics.android.ui.activity.FilterDetailsActivity import net.pokeranalytics.android.ui.activity.FiltersActivity import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter @@ -20,6 +22,7 @@ import net.pokeranalytics.android.ui.adapter.RowRepresentableDelegate import net.pokeranalytics.android.ui.adapter.StaticRowRepresentableDataSource import net.pokeranalytics.android.ui.extensions.px import net.pokeranalytics.android.ui.fragment.components.RealmFragment +import net.pokeranalytics.android.ui.interfaces.FilterActivityRequestCode import net.pokeranalytics.android.ui.interfaces.FilterableType import net.pokeranalytics.android.ui.view.RowRepresentable import net.pokeranalytics.android.ui.view.rowrepresentable.FilterCategoryRow @@ -32,11 +35,13 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, companion object { const val REQUEST_CODE_FILTER_DETAILS = 100 + + var currentFilter: Filter? = null + } private lateinit var rowRepresentableAdapter: RowRepresentableAdapter - private var currentFilter: Filter? = null private var filterCopy: Filter? = null private var rows: ArrayList = ArrayList() @@ -46,6 +51,7 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, private var selectedRow: RowRepresentable? = null private var isUpdating = false + private var isSaved = false override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { super.onCreateView(inflater, container, savedInstanceState) @@ -56,24 +62,37 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, super.onViewCreated(view, savedInstanceState) initUI() initData() + updateMostUsedFilters() } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) + Timber.d("requestCode: $requestCode") + Timber.d("resultCode: $resultCode") + Timber.d("data: $data") + if (requestCode == REQUEST_CODE_FILTER_DETAILS && resultCode == RESULT_OK) { + // Update object /* - Timber.d("onActivityResult: $requestCode") - if (data != null && data.hasExtra(FilterDetailsActivity.IntentKey.FILTER_ID.keyName)) { - val filterId = data.getStringExtra(FilterDetailsActivity.IntentKey.FILTER_ID.keyName) - Timber.d("Updated queryWith: ${filterId}") + currentFilter?.id?.let { currentFilterId -> + Filter.getFilterBydId(getRealm(), currentFilterId)?.let { filter -> + currentFilter = filter + } } */ selectedRow?.let { rowRepresentableAdapter.refreshRow(it) } + } else if (requestCode == FilterActivityRequestCode.SELECT_FILTER.ordinal && resultCode == RESULT_OK) { + if (data != null && data.hasExtra(FiltersActivity.IntentKey.FILTER_ID.keyName)) { + val filterId = data.getStringExtra(FiltersActivity.IntentKey.FILTER_ID.keyName) + finishActivityWithResult(filterId) + } else { + updateMostUsedFilters() + } } } @@ -96,7 +115,6 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, override fun onOptionsItemSelected(item: MenuItem?): Boolean { when (item!!.itemId) { R.id.save -> validateUpdates() - R.id.delete -> deleteFilter() } return true } @@ -142,48 +160,9 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, layoutManager = viewManager } - val filters = getRealm().sorted(Filter::class.java) - val currentFilterId = Preferences.getActiveFilterId(requireContext()) - - mostUsedFilters.removeAllViews() - filters.forEachIndexed { index, filter -> - if (index < 5) { - val chip = Chip(requireContext()) - chip.id = View.generateViewId() - chip.tag = filter.id - chip.text = filter.getDisplayName(requireContext()) - chip.chipStartPadding = 8f.px - chip.chipEndPadding = 8f.px - - chip.isCloseIconVisible = true - chip.isChecked = filter.id == currentFilterId - chip.setOnCloseIconClickListener { - Preferences.removeActiveFilterId(requireContext()) - chip.isChecked = false - } - chip.setOnClickListener { - deleteFilter(false) - finishActivityWithResult(filter.id) - } - mostUsedFilters.addView(chip) - } - } - - /* - Limit.values().forEach { - val chip = Chip(requireContext()) - chip.id = it.ordinal - chip.text = it.shortName - chip.chipStartPadding = 8f.px - chip.chipEndPadding = 8f.px - chip.isChecked = false - mostUsedFilters.addView(chip) - } - - mostUsedFilters.setOnCheckedChangeListener { _, i -> + moreFilters.setOnClickListener { + DataListActivity.newSelectInstance(this, LiveData.FILTER.ordinal) } - */ - } /** @@ -198,17 +177,19 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, Timber.d("Filters: ${filters.size}") primaryKey?.let { - currentFilter = Filter.getFilterBydId(realm, it) + currentFilter = realm.copyFromRealm(Filter.getFilterBydId(realm, it)) isUpdating = true } ?: run { realm.beginTransaction() - currentFilter = Filter.newInstance(realm, this.filterableType.ordinal) + currentFilter = Filter.newInstance(realm, this.filterableType.ordinal) //realm.copyFromRealm(Filter.newInstance(realm, this.filterableType.ordinal)) realm.commitTransaction() } // Create a copy if the user cancels the updates currentFilter?.let { - filterCopy = getRealm().copyFromRealm(it) + if (it.isValid && it.isManaged) { + filterCopy = getRealm().copyFromRealm(it) + } } rows.clear() @@ -219,12 +200,55 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, } + /** + * Update the most used filters chips + */ + private fun updateMostUsedFilters() { + + if (isUpdating) { + mostUsedFiltersLayout.visibility = View.GONE + return + } + + val filters = getRealm().sorted(Filter::class.java) + val currentFilterId = Preferences.getActiveFilterId(requireContext()) + + mostUsedFilters.removeAllViews() + filters.forEachIndexed { index, filter -> + if (index < 3) { + val chip = Chip(requireContext()) + chip.id = View.generateViewId() + chip.tag = filter.id + chip.text = filter.getDisplayName(requireContext()) + chip.chipStartPadding = 8f.px + chip.chipEndPadding = 8f.px + + chip.isChecked = filter.id == currentFilterId + chip.setOnCloseIconClickListener { + + chip.isChecked = false + } + chip.setOnClickListener { + if (chip.isChecked) { + deleteFilter(false) + finishActivityWithResult(filter.id) + } else { + Preferences.removeActiveFilterId(requireContext()) + deleteFilter(true) + } + } + mostUsedFilters.addView(chip) + } + } + + } + /** * Update menu UI */ private fun updateMenuUI() { - filterMenu?.findItem(R.id.delete)?.isVisible = isUpdating filterMenu?.findItem(R.id.save)?.isVisible = true + filterMenu?.findItem(R.id.delete)?.isVisible = false } /** @@ -232,6 +256,16 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, */ private fun validateUpdates() { Timber.d("Validate queryWith updates") + + val realm = getRealm() + realm.beginTransaction() + currentFilter?.let { + it.name = it.query.getName(requireContext()) + Timber.d("name: ${it.name}") + realm.copyToRealmOrUpdate(it) + } + realm.commitTransaction() + val filterId = currentFilter?.id ?: "" finishActivityWithResult(filterId) } @@ -258,10 +292,12 @@ open class FiltersFragment : RealmFragment(), StaticRowRepresentableDataSource, */ private fun deleteFilter(closeActivity: Boolean = true) { Timber.d("Delete queryWith") - val realm = getRealm() - realm.beginTransaction() - currentFilter?.deleteFromRealm() - realm.commitTransaction() + if (currentFilter?.isValid == true && currentFilter?.isManaged == true) { + val realm = getRealm() + realm.beginTransaction() + currentFilter?.deleteFromRealm() + realm.commitTransaction() + } if (closeActivity) { finishActivityWithResult("") diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt index 0eeb818a..5ad10ce0 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/DeletableItemFragment.kt @@ -15,8 +15,10 @@ import kotlinx.coroutines.launch import net.pokeranalytics.android.R import net.pokeranalytics.android.model.interfaces.Deletable import net.pokeranalytics.android.model.interfaces.Identifiable +import net.pokeranalytics.android.model.realm.Filter import net.pokeranalytics.android.ui.activity.DataListActivity import net.pokeranalytics.android.ui.adapter.RowRepresentableAdapter +import timber.log.Timber /** * Deletable Item Fragment @@ -87,6 +89,8 @@ abstract class DeletableItemFragment : RealmFragment() { val deletableItem = (itemToDelete as Deletable) + Timber.d("deletableItem: ${(deletableItem as Filter).getDisplayName(requireContext())}") + // Check if the object is valid for the deletion if (deletableItem.isValidForDelete(this.getRealm())) { deletedItem = getRealm().copyFromRealm(itemToDelete) diff --git a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/FilterableFragment.kt b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/FilterableFragment.kt index 4f89c398..3d88f52f 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/FilterableFragment.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/fragment/components/FilterableFragment.kt @@ -3,18 +3,23 @@ package net.pokeranalytics.android.ui.fragment.components import android.os.Bundle import android.view.* import androidx.appcompat.widget.Toolbar -import net.pokeranalytics.android.R +import kotlinx.android.synthetic.main.view_selected_filter.view.* +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import net.pokeranalytics.android.ui.interfaces.FilterHandler import net.pokeranalytics.android.ui.interfaces.FilterableType import timber.log.Timber + /** * A class which define the fragment as Filterable * - Add an filter icon menu * - Access to the filters actions (new, select, modify, remove) * - ... */ -open class FilterableFragment: RealmFragment(), FilterHandler { +open class FilterableFragment : RealmFragment(), FilterHandler { override var currentFilterable: FilterableType = FilterableType.ALL @@ -29,18 +34,18 @@ open class FilterableFragment: RealmFragment(), FilterHandler { super.onCreateOptionsMenu(menu, inflater) Timber.d("onCreateOptionsMenu") - view?.findViewById(R.id.toolbar)?.let { toolbar -> + view?.findViewById(net.pokeranalytics.android.R.id.toolbar)?.let { toolbar -> Timber.d("toolbar menu ${toolbar.menu}") - toolbar.menu.removeItem(R.id.menu_item_filter) - filterMenuItem = toolbar.menu?.add(0, R.id.menu_item_filter, 0, R.string.filter) - filterMenuItem?.setIcon(R.drawable.ic_outline_filter_list) + toolbar.menu.removeItem(net.pokeranalytics.android.R.id.menu_item_filter) + filterMenuItem = toolbar.menu?.add(0, net.pokeranalytics.android.R.id.menu_item_filter, 0, net.pokeranalytics.android.R.string.filter) + filterMenuItem?.setIcon(net.pokeranalytics.android.R.drawable.ic_outline_filter_list) filterMenuItem?.setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM) } } override fun onOptionsItemSelected(item: MenuItem?): Boolean { - when(item?.itemId) { - R.id.menu_item_filter -> { + when (item?.itemId) { + net.pokeranalytics.android.R.id.menu_item_filter -> { manageFilters(this) } } @@ -51,9 +56,40 @@ open class FilterableFragment: RealmFragment(), FilterHandler { } override fun applyFilter() { + displaySelectedFilter() } override fun removeFilter() { + hideSelectedFilter() + } + + private fun displaySelectedFilter() { + + currentFilter(requireContext(), getRealm())?.let { filter -> + view?.findViewById(net.pokeranalytics.android.R.id.selectedFilter)?.let { viewGroup -> + + val layoutCurrentFilter = LayoutInflater.from(requireContext()).inflate(net.pokeranalytics.android.R.layout.view_selected_filter, viewGroup, false) + layoutCurrentFilter.filterName.text = filter.getDisplayName(requireContext()) + layoutCurrentFilter.deselectFilter.setOnClickListener { + saveFilter(requireContext(), "") + } + + viewGroup.removeAllViews() + viewGroup.addView(layoutCurrentFilter) + + GlobalScope.launch(Dispatchers.Main) { + delay(300) + viewGroup.visibility = View.VISIBLE + } + } + } } + private fun hideSelectedFilter() { + view?.findViewById(net.pokeranalytics.android.R.id.selectedFilter).let { + GlobalScope.launch(Dispatchers.Main) { + it?.visibility = View.GONE + } + } + } } \ No newline at end of file diff --git a/app/src/main/java/net/pokeranalytics/android/ui/interfaces/FilterHandler.kt b/app/src/main/java/net/pokeranalytics/android/ui/interfaces/FilterHandler.kt index cbfdd6a7..8f176ea6 100644 --- a/app/src/main/java/net/pokeranalytics/android/ui/interfaces/FilterHandler.kt +++ b/app/src/main/java/net/pokeranalytics/android/ui/interfaces/FilterHandler.kt @@ -1,18 +1,12 @@ package net.pokeranalytics.android.ui.interfaces import android.content.Context -import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import io.realm.Realm import io.realm.kotlin.where -import net.pokeranalytics.android.R -import net.pokeranalytics.android.model.LiveData -import net.pokeranalytics.android.model.filter.Filterable import net.pokeranalytics.android.model.realm.Filter -import net.pokeranalytics.android.ui.activity.DataListActivity import net.pokeranalytics.android.ui.activity.FiltersActivity import net.pokeranalytics.android.util.Preferences -import timber.log.Timber enum class FilterActivityRequestCode { SELECT_FILTER, @@ -41,7 +35,11 @@ interface FilterHandler { fun saveFilter(context: Context, filterId:String) { Preferences.setActiveFilterId(filterId, context) filterWasUpdated = true - this.applyFilter() + if (filterId.isNotEmpty()) { + this.applyFilter() + } else { + this.removeFilter() + } } fun currentFilter(context: Context, realm: Realm): Filter? { @@ -62,6 +60,12 @@ interface FilterHandler { val context = fragment.requireContext() val filterId = Preferences.getActiveFilterId(context) + + FiltersActivity.newInstanceForResult(fragment = fragment, currentFilterable = currentFilterable) + + + + /* val filterSelected = filterId != null val realm = Realm.getDefaultInstance() @@ -101,5 +105,6 @@ interface FilterHandler { } builder.show() + */ } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_feed.xml b/app/src/main/res/layout/fragment_feed.xml index b2ebe18c..e287e2ee 100644 --- a/app/src/main/res/layout/fragment_feed.xml +++ b/app/src/main/res/layout/fragment_feed.xml @@ -3,6 +3,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" + android:animateLayoutChanges="true" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".ui.activity.HomeActivity"> @@ -47,6 +48,15 @@ + + - - + + + + + + + + diff --git a/app/src/main/res/layout/view_selected_filter.xml b/app/src/main/res/layout/view_selected_filter.xml new file mode 100644 index 00000000..1ebccbed --- /dev/null +++ b/app/src/main/res/layout/view_selected_filter.xml @@ -0,0 +1,41 @@ + + + + + + + + \ No newline at end of file