From cb19f4e19ff2bf1d79a24443d1ba4b25b44458f0 Mon Sep 17 00:00:00 2001 From: Jonas Lochmann Date: Mon, 26 Oct 2020 01:00:00 +0100 Subject: [PATCH] Add category filter for the usage history --- app/build.gradle | 9 ++- .../BottomSheetSelectionListDialog.kt | 2 +- .../SelectUsageHistoryCategoryDialog.kt | 76 +++++++++++++++++++ .../usagehistory/UsageHistoryFragment.kt | 49 +++++++----- .../usagehistory/UsageHistoryModel.kt | 59 ++++++++++++++ .../layout/bottom_sheet_selection_list.xml | 2 + .../res/layout/fragment_usage_history.xml | 68 ++++++++++------- .../res/values-de/strings-usage-history.xml | 1 + .../main/res/values/strings-usage-history.xml | 3 +- 9 files changed, 220 insertions(+), 49 deletions(-) create mode 100644 app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/SelectUsageHistoryCategoryDialog.kt create mode 100644 app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/UsageHistoryModel.kt diff --git a/app/build.gradle b/app/build.gradle index 15e04cc..a4dcffc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -143,8 +143,12 @@ android { } compileOptions { - sourceCompatibility JavaVersion.VERSION_1_7 - targetCompatibility JavaVersion.VERSION_1_7 + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions { + jvmTarget = "1.8" } } @@ -161,6 +165,7 @@ dependencies { implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation "com.google.android.material:material:1.2.1" + implementation 'androidx.fragment:fragment-ktx:1.2.5' implementation "android.arch.navigation:navigation-fragment-ktx:$nav_version" implementation "android.arch.navigation:navigation-ui:$nav_version" diff --git a/app/src/main/java/io/timelimit/android/ui/fragment/BottomSheetSelectionListDialog.kt b/app/src/main/java/io/timelimit/android/ui/fragment/BottomSheetSelectionListDialog.kt index 9998fa8..0df0c8b 100644 --- a/app/src/main/java/io/timelimit/android/ui/fragment/BottomSheetSelectionListDialog.kt +++ b/app/src/main/java/io/timelimit/android/ui/fragment/BottomSheetSelectionListDialog.kt @@ -28,7 +28,7 @@ abstract class BottomSheetSelectionListDialog: BottomSheetDialogFragment() { private lateinit var binding: BottomSheetSelectionListBinding private var didClearList = false - abstract val title: String + abstract val title: String? override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { binding = BottomSheetSelectionListBinding.inflate(inflater, container, false) diff --git a/app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/SelectUsageHistoryCategoryDialog.kt b/app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/SelectUsageHistoryCategoryDialog.kt new file mode 100644 index 0000000..4e2a76a --- /dev/null +++ b/app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/SelectUsageHistoryCategoryDialog.kt @@ -0,0 +1,76 @@ +/* + * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.timelimit.android.ui.manage.category.usagehistory + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.Fragment +import androidx.fragment.app.FragmentManager +import io.timelimit.android.R +import io.timelimit.android.extensions.showSafe +import io.timelimit.android.logic.DefaultAppLogic +import io.timelimit.android.ui.fragment.BottomSheetSelectionListDialog + +class SelectUsageHistoryCategoryDialog: BottomSheetSelectionListDialog() { + companion object { + private const val USER_ID = "userId" + private const val CURRENT_CATEGORY_ID = "currentCategoryId" + private const val DIALOG_TAG = "SelectUsageHistoryCategoryDialog" + + fun newInstance(userId: String, currentCategoryId: String?, target: Fragment) = SelectUsageHistoryCategoryDialog().apply { + setTargetFragment(target, 0) + arguments = Bundle().apply { + putString(USER_ID, userId) + if (currentCategoryId != null) putString(CURRENT_CATEGORY_ID, currentCategoryId) + } + } + } + + override val title: String? get() = null + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + val userId: String = requireArguments().getString(USER_ID)!! + val currentCategoryId: String? = requireArguments().getString(CURRENT_CATEGORY_ID) + val target = targetFragment as Listener + + DefaultAppLogic.with(requireContext()).database.category().getCategoriesByChildId(userId).observe(viewLifecycleOwner) { categories -> + clearList() + + categories.forEach { + addListItem( + label = it.title, + checked = it.id == currentCategoryId, + click = { target.onCategoryFilterSelected(it.id); dismiss() } + ) + } + + addListItem( + labelRes = R.string.usage_history_filter_all_categories, + checked = currentCategoryId == null, + click = { target.onAllCategoriesSelected(); dismiss() } + ) + } + } + + fun show(fragmentManager: FragmentManager) = showSafe(fragmentManager, DIALOG_TAG) + + interface Listener { + fun onAllCategoriesSelected() + fun onCategoryFilterSelected(categoryId: String) + } +} \ No newline at end of file diff --git a/app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/UsageHistoryFragment.kt b/app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/UsageHistoryFragment.kt index c639217..123c392 100644 --- a/app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/UsageHistoryFragment.kt +++ b/app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/UsageHistoryFragment.kt @@ -20,13 +20,12 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment -import androidx.lifecycle.Observer -import androidx.paging.LivePagedListBuilder +import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearLayoutManager +import io.timelimit.android.R import io.timelimit.android.databinding.FragmentUsageHistoryBinding -import io.timelimit.android.logic.DefaultAppLogic -class UsageHistoryFragment : Fragment() { +class UsageHistoryFragment : Fragment(), SelectUsageHistoryCategoryDialog.Listener { companion object { private const val USER_ID = "userId" private const val CATEGORY_ID = "categoryId" @@ -39,30 +38,44 @@ class UsageHistoryFragment : Fragment() { } } + private val model: UsageHistoryModel by viewModels() override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { val binding = FragmentUsageHistoryBinding.inflate(inflater, container, false) - val database = DefaultAppLogic.with(context!!).database val adapter = UsageHistoryAdapter() - val userId = requireArguments().getString(USER_ID)!! - val categoryId = requireArguments().getString(CATEGORY_ID) - adapter.showCategoryTitle = categoryId == null + if (requireArguments().getString(CATEGORY_ID) != null) { + binding.selectCategoryButton.visibility = View.GONE + } - LivePagedListBuilder( - categoryId?.let { database.usedTimes().getUsedTimeListItemsByCategoryId(it) } - ?: database.usedTimes().getUsedTimeListItemsByUserId(userId), - 10 - ) - .build() - .observe(viewLifecycleOwner, Observer { - binding.isEmpty = it.isEmpty() - adapter.submitList(it) - }) + if (!model.didInit) { + model.userId.value = requireArguments().getString(USER_ID)!! + model.categoryId.value = requireArguments().getString(CATEGORY_ID) + + model.didInit = true + } + + model.categoryId.observe(viewLifecycleOwner) { adapter.showCategoryTitle = it == null } + model.selectedCategoryName.observe(viewLifecycleOwner) { binding.selectCategoryButton.text = it ?: getString(R.string.usage_history_filter_all_categories) } + model.listContent.observe(viewLifecycleOwner) { + binding.isEmpty = it.isEmpty() + adapter.submitList(it) + } binding.recycler.adapter = adapter binding.recycler.layoutManager = LinearLayoutManager(context) + binding.selectCategoryButton.setOnClickListener { + SelectUsageHistoryCategoryDialog.newInstance( + userId = model.userId.value!!, + currentCategoryId = model.categoryId.value, + target = this + ).show(parentFragmentManager) + } + return binding.root } + + override fun onAllCategoriesSelected() { model.categoryId.value = null } + override fun onCategoryFilterSelected(categoryId: String) { model.categoryId.value = categoryId } } diff --git a/app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/UsageHistoryModel.kt b/app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/UsageHistoryModel.kt new file mode 100644 index 0000000..180e5c6 --- /dev/null +++ b/app/src/main/java/io/timelimit/android/ui/manage/category/usagehistory/UsageHistoryModel.kt @@ -0,0 +1,59 @@ +/* + * TimeLimit Copyright 2019 - 2020 Jonas Lochmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package io.timelimit.android.ui.manage.category.usagehistory + +import android.app.Application +import androidx.lifecycle.AndroidViewModel +import androidx.lifecycle.MutableLiveData +import androidx.paging.LivePagedListBuilder +import io.timelimit.android.livedata.liveDataFromValue +import io.timelimit.android.livedata.map +import io.timelimit.android.livedata.switchMap +import io.timelimit.android.logic.DefaultAppLogic + +class UsageHistoryModel(application: Application): AndroidViewModel(application) { + private val database = DefaultAppLogic.with(application).database + + var didInit = false + + val userId = MutableLiveData() + val categoryId = MutableLiveData() + + val listContent = userId.switchMap { userId -> + categoryId.switchMap { categoryId -> + val items = if (categoryId == null) { + database.usedTimes().getUsedTimeListItemsByUserId(userId) + } else { + database.usedTimes().getUsedTimeListItemsByCategoryId(categoryId) + } + + LivePagedListBuilder(items, 10).build() + } + } + + val selectedCategoryName = userId.switchMap { userId -> + categoryId.switchMap { categoryId -> + if (categoryId == null) + liveDataFromValue(null as String?) + else + database.category().getCategoryByChildIdAndId(childId = userId, categoryId = categoryId).map { + if (it == null) this.categoryId.value = null + + it?.title + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/bottom_sheet_selection_list.xml b/app/src/main/res/layout/bottom_sheet_selection_list.xml index 71beac2..ebfc6b1 100644 --- a/app/src/main/res/layout/bottom_sheet_selection_list.xml +++ b/app/src/main/res/layout/bottom_sheet_selection_list.xml @@ -27,6 +27,7 @@ type="boolean" /> + 2019 Jonas Lochmann + TimeLimit Copyright 2019 - 2020 Jonas Lochmann This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation version 3 of the License. @@ -24,44 +24,58 @@ - + android:layout_height="match_parent" + android:orientation="vertical"> - + android:layout_height="wrap_content" /> - - + android:layout_height="match_parent" /> - + + + android:layout_height="wrap_content"> - + - + - + - + + + + diff --git a/app/src/main/res/values-de/strings-usage-history.xml b/app/src/main/res/values-de/strings-usage-history.xml index 56547fb..0adf577 100644 --- a/app/src/main/res/values-de/strings-usage-history.xml +++ b/app/src/main/res/values-de/strings-usage-history.xml @@ -23,4 +23,5 @@ von %s bis %s Sitzungsdauerbegrenzung von %s mit %s Pause Letzte Verwendung: %s + Alle Kategorien diff --git a/app/src/main/res/values/strings-usage-history.xml b/app/src/main/res/values/strings-usage-history.xml index 73c9c8a..4f4dd57 100644 --- a/app/src/main/res/values/strings-usage-history.xml +++ b/app/src/main/res/values/strings-usage-history.xml @@ -13,7 +13,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . --> - + Usage history There is no usage history @@ -24,4 +24,5 @@ from %s until %s Session duration limit of %s with %s break Last usage: %s + All Categories