Skip to content

Commit

Permalink
Merge pull request #524 from willowtreeapps/refactor/edit-categories-…
Browse files Browse the repository at this point in the history
…pager

Issue 416: Refactor pager code of edit categories screen
  • Loading branch information
josmith42 authored Apr 11, 2024
2 parents 6be9a12 + 79b4dcb commit a57ac68
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 170 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import com.willowtree.vocable.*
import com.willowtree.vocable.customviews.PointerListener
import com.willowtree.vocable.databinding.FragmentPresetsBinding
import com.willowtree.vocable.utils.SpokenText
import com.willowtree.vocable.utils.VocableFragmentStateAdapter
import com.willowtree.vocable.utils.LegacyFragmentStateAdapter
import com.willowtree.vocable.utils.VocableTextToSpeech
import org.koin.androidx.viewmodel.ViewModelOwner
import org.koin.androidx.viewmodel.ext.android.viewModel
Expand Down Expand Up @@ -324,7 +324,7 @@ class PresetsFragment : BaseFragment<FragmentPresetsBinding>() {
}

inner class CategoriesPagerAdapter(fm: FragmentManager) :
VocableFragmentStateAdapter<Category>(fm, viewLifecycleOwner.lifecycle) {
LegacyFragmentStateAdapter<Category>(fm, viewLifecycleOwner.lifecycle) {

override fun getMaxItemsPerPage(): Int = maxCategories

Expand All @@ -343,7 +343,7 @@ class PresetsFragment : BaseFragment<FragmentPresetsBinding>() {
}

inner class PhrasesPagerAdapter(fm: FragmentManager) :
VocableFragmentStateAdapter<Phrase?>(fm, viewLifecycleOwner.lifecycle) {
LegacyFragmentStateAdapter<Phrase?>(fm, viewLifecycleOwner.lifecycle) {

override fun setItems(items: List<Phrase?>) {
super.setItems(items)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.View
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import androidx.viewpager2.widget.ViewPager2
import com.willowtree.vocable.BaseFragment
Expand All @@ -20,7 +19,8 @@ import kotlin.math.min

class EditCategoriesFragment : BaseFragment<FragmentEditCategoriesBinding>() {

override val bindingInflater: BindingInflater<FragmentEditCategoriesBinding> = FragmentEditCategoriesBinding::inflate
override val bindingInflater: BindingInflater<FragmentEditCategoriesBinding> =
FragmentEditCategoriesBinding::inflate

private lateinit var categoriesAdapter: CategoriesPagerAdapter
private val editCategoriesViewModel: EditCategoriesViewModel by viewModel(owner = {
Expand All @@ -41,6 +41,7 @@ class EditCategoriesFragment : BaseFragment<FragmentEditCategoriesBinding>() {
true
)
}

else -> {
binding.editCategoriesViewPager.setCurrentItem(currentPosition - 1, true)
}
Expand All @@ -52,6 +53,7 @@ class EditCategoriesFragment : BaseFragment<FragmentEditCategoriesBinding>() {
categoriesAdapter.itemCount - 1 -> {
binding.editCategoriesViewPager.setCurrentItem(0, true)
}

else -> {
binding.editCategoriesViewPager.setCurrentItem(currentPosition + 1, true)
}
Expand All @@ -61,24 +63,29 @@ class EditCategoriesFragment : BaseFragment<FragmentEditCategoriesBinding>() {

maxEditCategories = resources.getInteger(R.integer.max_edit_categories)

binding.editCategoriesViewPager.registerOnPageChangeCallback(object :
ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
val pageNum = position % categoriesAdapter.numPages + 1
binding.categoryPageNumber.text = getString(
R.string.phrases_page_number,
pageNum,
categoriesAdapter.numPages
)

activity?.let { activity ->
allViews.clear()
if (activity is MainActivity) {
activity.resetAllViews()
binding.editCategoriesViewPager.apply {
isSaveEnabled = false
adapter = categoriesAdapter
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
val pageNum = position % categoriesAdapter.numPages + 1
post {
binding.categoryPageNumber.text = getString(
R.string.phrases_page_number,
pageNum,
categoriesAdapter.numPages
)
}

activity?.let { activity ->
allViews.clear()
if (activity is MainActivity) {
activity.resetAllViews()
}
}
}
}
})
})
}

binding.backButton.action = {
findNavController().popBackStack()
Expand All @@ -100,45 +107,23 @@ class EditCategoriesFragment : BaseFragment<FragmentEditCategoriesBinding>() {
}

private fun subscribeToViewModel() {
editCategoriesViewModel.addRemoveCategoryList.observe(viewLifecycleOwner, Observer {
editCategoriesViewModel.categoryList.observe(viewLifecycleOwner) {
it?.let { categories ->
binding.editCategoriesViewPager.apply {
isSaveEnabled = false
adapter = categoriesAdapter
categoriesAdapter.setItems(categories)
// Move adapter to middle so user can scroll both directions
val middle = categoriesAdapter.itemCount / 2
if (middle % categoriesAdapter.numPages == 0) {
setCurrentItem(middle, false)
} else {
val mod = middle % categoriesAdapter.numPages
setCurrentItem(
middle + (categoriesAdapter.numPages - mod),
false
)
}
}
categoriesAdapter.setItems(categories)
}
})
}

editCategoriesViewModel.lastViewedIndex.observe(viewLifecycleOwner, Observer {
editCategoriesViewModel.lastViewedIndex.observe(viewLifecycleOwner) {
it?.let { index ->
val pageNum = index / maxEditCategories
val middle = categoriesAdapter.itemCount / 2
val toScrollTo = if (middle % categoriesAdapter.numPages == 0) {
middle + pageNum
} else {
val mod = middle % categoriesAdapter.numPages
middle + (categoriesAdapter.numPages - mod) + pageNum
}
// Wait until view pager has finished its layout
binding.editCategoriesViewPager.post {
if (isAdded && binding.editCategoriesViewPager.currentItem != toScrollTo) {
binding.editCategoriesViewPager.setCurrentItem(toScrollTo, false)
if (isAdded && binding.editCategoriesViewPager.currentItem != pageNum) {
binding.editCategoriesViewPager.setCurrentItem(pageNum, false)
}
}
}
})
}
}

inner class CategoriesPagerAdapter(fm: FragmentManager) :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import androidx.navigation.fragment.findNavController
import com.willowtree.vocable.BaseFragment
import com.willowtree.vocable.BindingInflater
import com.willowtree.vocable.R
import com.willowtree.vocable.customviews.NoSayTextButton
import com.willowtree.vocable.databinding.CategoryEditButtonBinding
import com.willowtree.vocable.databinding.FragmentEditCategoriesListBinding
import com.willowtree.vocable.presets.Category
Expand Down Expand Up @@ -102,21 +101,23 @@ class EditCategoriesListFragment : BaseFragment<FragmentEditCategoriesListBindin
}

private fun subscribeToViewModel() {
editCategoriesViewModel.orderCategoryList.observe(viewLifecycleOwner) { list ->
editCategoriesViewModel.categoryList.observe(viewLifecycleOwner) { list ->
list?.let { overallList ->
val hiddenCategories = overallList.filter { it.hidden }
if (endPosition > overallList.size) {
endPosition = overallList.size - 1
}
overallList.subList(startPosition, endPosition)
.forEachIndexed { index, category ->
bindCategoryEditButton(
editButtonList[index],
category,
startPosition + index,
overallList.size - hiddenCategories.size
)
}
if (startPosition <= endPosition) {
overallList.subList(startPosition, endPosition)
.forEachIndexed { index, category ->
bindCategoryEditButton(
editButtonList[index],
category,
startPosition + index,
overallList.size - hiddenCategories.size
)
}
}
}
}
}
Expand All @@ -128,7 +129,7 @@ class EditCategoriesListFragment : BaseFragment<FragmentEditCategoriesListBindin
size: Int
) {
with(editButtonBinding) {
(individualEditCategoryButton as NoSayTextButton).text = localizedResourceUtility.getTextFromCategory(category)
individualEditCategoryButton.text = localizedResourceUtility.getTextFromCategory(category)

moveCategoryUpButton.isEnabled = !category.hidden && overallIndex > 0
moveCategoryDownButton.isEnabled =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.willowtree.vocable.settings
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import com.willowtree.vocable.ICategoriesUseCase
import com.willowtree.vocable.presets.Category
Expand All @@ -16,11 +17,7 @@ class EditCategoriesViewModel(
private val categoriesUseCase: ICategoriesUseCase
) : ViewModel() {

private val liveOrderCategoryList = MutableLiveData<List<Category>>()
val orderCategoryList: LiveData<List<Category>> = liveOrderCategoryList

private val liveAddRemoveCategoryList = MutableLiveData<List<Category>>()
val addRemoveCategoryList: LiveData<List<Category>> = liveAddRemoveCategoryList
val categoryList: LiveData<List<Category>> = categoriesUseCase.categories().asLiveData()

val categoryPages = categoriesUseCase.categories().map { categories ->
val pageSize = 8
Expand All @@ -38,12 +35,6 @@ class EditCategoriesViewModel(
val oldCategories = overallCategories

overallCategories = categoriesUseCase.categories().first()
overallCategories =
overallCategories.filter { !it.hidden } + overallCategories.filter { it.hidden }


liveOrderCategoryList.postValue(overallCategories)
liveAddRemoveCategoryList.postValue(overallCategories)

// Check if a new category was added and scroll to it
if (oldCategories.isNotEmpty() && oldCategories.size < overallCategories.size) {
Expand All @@ -66,67 +57,44 @@ class EditCategoriesViewModel(

fun moveCategoryUp(categoryId: String) {
viewModelScope.launch {
val catIndex = overallCategories.indexOfFirst { it.categoryId == categoryId }
if (catIndex > 0) {
val previousCat = overallCategories[catIndex - 1]

overallCategories = overallCategories.map {
when (it.categoryId) {
categoryId -> {
it.withSortOrder(it.sortOrder - 1)
}

previousCat.categoryId -> {
it.withSortOrder(it.sortOrder + 1)
}

else -> {
it
}
}
}.sortedBy { it.sortOrder }
val categories = categoriesUseCase.categories().first()
val catIndex = categories.indexOfFirst { it.categoryId == categoryId }
if (catIndex in 1 until categories.size) {
val category = categories[catIndex]
val previousCat = categories[catIndex - 1]

liveOrderCategoryList.postValue(overallCategories)

categoriesUseCase.updateCategorySortOrders(
overallCategories.map {
CategorySortOrder(it.categoryId, it.sortOrder)
}
)
swapSortOrders(categories, previousCat, category)
}
}
}

fun moveCategoryDown(categoryId: String) {
viewModelScope.launch {
val catIndex = overallCategories.indexOfFirst { it.categoryId == categoryId }
if (catIndex > -1) {
val nextCat = overallCategories[catIndex + 1]

overallCategories = overallCategories.map {
when (it.categoryId) {
categoryId -> {
it.withSortOrder(it.sortOrder + 1)
}

nextCat.categoryId -> {
it.withSortOrder(it.sortOrder - 1)
}

else -> {
it
}
}
}.sortedBy { it.sortOrder }
val categories = categoriesUseCase.categories().first()
val catIndex = categories.indexOfFirst { it.categoryId == categoryId }
if (catIndex in 0 until categories.size - 1) {
val category = categories[catIndex]
val nextCat = categories[catIndex + 1]

liveOrderCategoryList.postValue(overallCategories)

categoriesUseCase.updateCategorySortOrders(
overallCategories.map {
CategorySortOrder(it.categoryId, it.sortOrder)
}
)
swapSortOrders(categories, category, nextCat)
}
}
}

private suspend fun swapSortOrders(
categories: List<Category>,
leftCategory: Category,
rightCategory: Category
) {
categoriesUseCase.updateCategorySortOrders(
categories.map {
val sortOrder = when (it.categoryId) {
rightCategory.categoryId -> leftCategory.sortOrder
leftCategory.categoryId -> rightCategory.sortOrder
else -> it.sortOrder
}
CategorySortOrder(it.categoryId, sortOrder)
}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.presets.Phrase
import com.willowtree.vocable.presets.PresetCategories
import com.willowtree.vocable.settings.customcategories.CustomCategoryPhraseListFragment
import com.willowtree.vocable.utils.VocableFragmentStateAdapter
import com.willowtree.vocable.utils.LegacyFragmentStateAdapter
import org.koin.androidx.viewmodel.ViewModelOwner
import org.koin.androidx.viewmodel.ext.android.viewModel

Expand Down Expand Up @@ -167,7 +167,7 @@ class EditCategoryPhrasesFragment : BaseFragment<FragmentEditCategoryPhrasesBind
}

inner class PhrasesPagerAdapter(fm: FragmentManager) :
VocableFragmentStateAdapter<Phrase>(fm, viewLifecycleOwner.lifecycle) {
LegacyFragmentStateAdapter<Phrase>(fm, viewLifecycleOwner.lifecycle) {

override fun setItems(items: List<Phrase>) {
super.setItems(items)
Expand Down
Loading

0 comments on commit a57ac68

Please sign in to comment.