Skip to content

Commit

Permalink
Merge pull request #522 from willowtreeapps/EditCategoryPhrasesViewModel
Browse files Browse the repository at this point in the history
Move functionality of EditCategoryPhrasesFragment from EditCategoriesViewModel into a new EditCategoryPhrasesViewModel
  • Loading branch information
josmith42 authored Apr 10, 2024
2 parents 96c95d9 + b82d05f commit 6f97ac5
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.willowtree.vocable.settings

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.willowtree.vocable.MainDispatcherRule
import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.presets.PresetCategories
import com.willowtree.vocable.presets.PresetPhrase
import com.willowtree.vocable.room.PresetPhrasesRepository
import com.willowtree.vocable.utility.VocableKoinTestRule
import junit.framework.TestCase.assertEquals
import kotlinx.coroutines.runBlocking
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.koin.core.component.KoinComponent
import org.koin.core.component.get

class EditCategoryPhrasesViewModelTest: KoinComponent {

@get:Rule
val koinTestRule = VocableKoinTestRule()

@get:Rule
val mainDispatcherRule = MainDispatcherRule()

@get:Rule
val instantTaskExecutorRule = InstantTaskExecutorRule()

private lateinit var viewModel: EditCategoryPhrasesViewModel

@Before
fun setUp() {
val presetPhrasesRepository: PresetPhrasesRepository = get()
runBlocking {
presetPhrasesRepository.populateDatabase()
}
viewModel = get()
}

@Test
fun getCategoryName_withRecents_returnsRecents() {
val result = viewModel.getCategoryName(Category.Recents(false, 0))
assertEquals("Recents", result)
}

@Test
fun getCategoryName_withPresetCategory_returnsCategoryName() {
val result = viewModel.getCategoryName(Category.PresetCategory(PresetCategories.GENERAL.id, 0, false))
assertEquals("General", result)
}

@Test
fun fetchCategoryPhrases_withGeneral_returnsCorrectPhraseList() {
viewModel.fetchCategoryPhrases(Category.PresetCategory(PresetCategories.GENERAL.id, 0, false))
viewModel.categoryPhraseList.observeForever {
assertEquals(9, it.size)
assertEquals("preset_please", it[0].phraseId)
}
}

@Test
fun deletePhraseFromCategory_withPlease_deletesPleaseCorrectly() {
viewModel.deletePhraseFromCategory(
phrase = PresetPhrase(
phraseId = "preset_please",
sortOrder = 0,
lastSpokenDate = 0,
deleted = false,
parentCategoryId = PresetCategories.GENERAL.id
),
category = Category.PresetCategory(
categoryId = PresetCategories.GENERAL.id,
sortOrder = 0,
hidden = false
)
)

viewModel.categoryPhraseList.observeForever {
assertEquals(8, it.size)
assertEquals("preset_thank_you", it[0].phraseId)
}
}
}
4 changes: 3 additions & 1 deletion app/src/main/java/com/willowtree/vocable/AppKoinModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.willowtree.vocable.room.VocableDatabase
import com.willowtree.vocable.settings.AddUpdateCategoryViewModel
import com.willowtree.vocable.settings.EditCategoriesViewModel
import com.willowtree.vocable.settings.EditCategoryMenuViewModel
import com.willowtree.vocable.settings.EditCategoryPhrasesViewModel
import com.willowtree.vocable.settings.selectionmode.SelectionModeViewModel
import com.willowtree.vocable.utils.DateProvider
import com.willowtree.vocable.utils.FaceTrackingManager
Expand Down Expand Up @@ -87,7 +88,8 @@ val vocableKoinModule = module {
single { VocableDatabase.createVocableDatabase(get()) }
single { get<VocableDatabase>().presetPhrasesDao() }
viewModel { PresetsViewModel(get(), get()) }
viewModel { EditCategoriesViewModel(get(), get(), get()) }
viewModel { EditCategoriesViewModel(get()) }
viewModel { EditCategoryPhrasesViewModel(get(), get()) }
viewModel { AddUpdateCategoryViewModel(get(), get(), get()) }
viewModel { EditCategoryMenuViewModel(get()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,15 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.willowtree.vocable.ICategoriesUseCase
import com.willowtree.vocable.IPhrasesUseCase
import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.presets.Phrase
import com.willowtree.vocable.room.CategorySortOrder
import com.willowtree.vocable.settings.editcategories.EditCategoriesPage
import com.willowtree.vocable.utils.ILocalizedResourceUtility
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

class EditCategoriesViewModel(
private val phrasesUseCase: IPhrasesUseCase,
private val categoriesUseCase: ICategoriesUseCase,
private val localizedResourceUtility: ILocalizedResourceUtility
private val categoriesUseCase: ICategoriesUseCase
) : ViewModel() {

private val liveOrderCategoryList = MutableLiveData<List<Category>>()
Expand All @@ -35,9 +30,6 @@ class EditCategoriesViewModel(
private val liveLastViewedIndex = MutableLiveData<Int>()
val lastViewedIndex: LiveData<Int> = liveLastViewedIndex

private val liveCategoryPhraseList = MutableLiveData<List<Phrase>>()
val categoryPhraseList: LiveData<List<Phrase>> = liveCategoryPhraseList

private var overallCategories = listOf<Category>()

fun refreshCategories() {
Expand Down Expand Up @@ -72,28 +64,6 @@ class EditCategoriesViewModel(
}
}

fun deletePhraseFromCategory(phrase: Phrase, category: Category) {
viewModelScope.launch {

phrasesUseCase.deletePhrase(phrase.phraseId)

// Refresh phrase list
fetchCategoryPhrases(category)
}
}

fun getCategoryName(category: Category): String {
return localizedResourceUtility.getTextFromCategory(category)
}

fun fetchCategoryPhrases(category: Category) {
viewModelScope.launch {
val phrasesForCategory = phrasesUseCase.getPhrasesForCategory(category.categoryId)
.sortedBy { it.sortOrder }
liveCategoryPhraseList.postValue(phrasesForCategory)
}
}

fun moveCategoryUp(categoryId: String) {
viewModelScope.launch {
val catIndex = overallCategories.indexOfFirst { it.categoryId == categoryId }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import androidx.viewpager2.widget.ViewPager2
Expand All @@ -28,7 +27,7 @@ class EditCategoryPhrasesFragment : BaseFragment<FragmentEditCategoryPhrasesBind

override val bindingInflater: BindingInflater<FragmentEditCategoryPhrasesBinding> =
FragmentEditCategoryPhrasesBinding::inflate
private val editCategoriesViewModel: EditCategoriesViewModel by viewModel(owner = {
private val editCategoriesViewModel: EditCategoryPhrasesViewModel by viewModel(owner = {
ViewModelOwner.from(requireActivity())
})

Expand Down Expand Up @@ -120,17 +119,16 @@ class EditCategoryPhrasesFragment : BaseFragment<FragmentEditCategoryPhrasesBind
subscribeToViewModel()

with(editCategoriesViewModel) {
refreshCategories()
fetchCategoryPhrases(args.category)
}
}

private fun subscribeToViewModel() {
editCategoriesViewModel.categoryPhraseList.observe(viewLifecycleOwner, Observer {
editCategoriesViewModel.categoryPhraseList.observe(viewLifecycleOwner) {
it?.let {
handlePhrases(it)
}
})
}
}

override fun getAllViews(): List<View> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.willowtree.vocable.settings

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.willowtree.vocable.IPhrasesUseCase
import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.presets.Phrase
import com.willowtree.vocable.utils.ILocalizedResourceUtility
import kotlinx.coroutines.launch

class EditCategoryPhrasesViewModel(
private val phrasesUseCase: IPhrasesUseCase,
private val localizedResourceUtility: ILocalizedResourceUtility
): ViewModel() {
private val liveCategoryPhraseList = MutableLiveData<List<Phrase>>()
val categoryPhraseList: LiveData<List<Phrase>> = liveCategoryPhraseList

fun getCategoryName(category: Category): String {
return localizedResourceUtility.getTextFromCategory(category)
}

fun fetchCategoryPhrases(category: Category) {
viewModelScope.launch {
val phrasesForCategory = phrasesUseCase.getPhrasesForCategory(category.categoryId)
.sortedBy { it.sortOrder }
liveCategoryPhraseList.postValue(phrasesForCategory)
}
}

fun deletePhraseFromCategory(phrase: Phrase, category: Category) {
viewModelScope.launch {

phrasesUseCase.deletePhrase(phrase.phraseId)

// Refresh phrase list
fetchCategoryPhrases(category)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import com.willowtree.vocable.R
import com.willowtree.vocable.databinding.FragmentCustomCategoryPhraseListBinding
import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.presets.Phrase
import com.willowtree.vocable.settings.EditCategoriesViewModel
import com.willowtree.vocable.settings.EditCategoryPhrasesFragmentDirections
import com.willowtree.vocable.settings.EditCategoryPhrasesViewModel
import com.willowtree.vocable.settings.customcategories.adapter.CustomCategoryPhraseAdapter
import com.willowtree.vocable.utils.ItemOffsetDecoration
import org.koin.androidx.viewmodel.ViewModelOwner
Expand All @@ -35,7 +35,7 @@ class CustomCategoryPhraseListFragment : BaseFragment<FragmentCustomCategoryPhra
}
}

private val editCategoriesViewModel: EditCategoriesViewModel by viewModel(owner = {
private val editCategoriesViewModel: EditCategoryPhrasesViewModel by viewModel(owner = {
ViewModelOwner.from(requireActivity())
})
private lateinit var category: Category
Expand All @@ -62,7 +62,6 @@ class CustomCategoryPhraseListFragment : BaseFragment<FragmentCustomCategoryPhra
}

val numColumns = resources.getInteger(R.integer.custom_category_phrase_columns)
val numRows = resources.getInteger(R.integer.custom_category_phrase_rows)

val phrases = arguments?.getParcelableArrayList<Phrase>(KEY_PHRASES)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import android.content.Context
import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.presets.Phrase
import com.willowtree.vocable.utils.ILocalizedResourceUtility
import org.koin.core.component.KoinComponent

class LocalizedResourceUtility(
private val context: Context,
) : KoinComponent, ILocalizedResourceUtility {
) : ILocalizedResourceUtility {

override fun getTextFromCategory(category: Category?): String {
return category?.text(context) ?: ""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package com.willowtree.vocable.settings

import androidx.arch.core.executor.testing.InstantTaskExecutorRule
import com.willowtree.vocable.FakeCategoriesUseCase
import com.willowtree.vocable.FakePhrasesUseCase
import com.willowtree.vocable.MainDispatcherRule
import com.willowtree.vocable.presets.createStoredCategory
import com.willowtree.vocable.settings.editcategories.EditCategoriesPage
import com.willowtree.vocable.utils.FakeLocalizedResourceUtility
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.test.runTest
Expand All @@ -23,13 +21,10 @@ class EditCategoriesViewModelTest {
val instantTaskExecutorRule = InstantTaskExecutorRule()

private val categoriesUseCase = FakeCategoriesUseCase()
private val phrasesUseCase = FakePhrasesUseCase()

private fun createViewModel(): EditCategoriesViewModel {
return EditCategoriesViewModel(
phrasesUseCase,
categoriesUseCase,
FakeLocalizedResourceUtility()
categoriesUseCase
)
}

Expand Down

0 comments on commit 6f97ac5

Please sign in to comment.