Skip to content

Commit

Permalink
Merge pull request #507 from willowtreeapps/feature/delete-preset-cat…
Browse files Browse the repository at this point in the history
…egories

Implement deletion of phrases when deleting category
  • Loading branch information
PaulKlauser authored Feb 20, 2024
2 parents 54ee7e3 + 1a20be3 commit e628dca
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.presets.PresetCategories
import com.willowtree.vocable.presets.PresetPhrase
import com.willowtree.vocable.presets.RoomPresetCategoriesRepository
import com.willowtree.vocable.room.CategorySortOrder
import com.willowtree.vocable.room.PhraseDto
import com.willowtree.vocable.room.RoomPresetPhrasesRepository
import com.willowtree.vocable.room.RoomStoredCategoriesRepository
import com.willowtree.vocable.room.RoomStoredPhrasesRepository
import com.willowtree.vocable.room.VocableDatabase
import com.willowtree.vocable.utility.FakeDateProvider
import com.willowtree.vocable.utility.StubLegacyCategoriesAndPhrasesRepository
import com.willowtree.vocable.utils.locale.LocalesWithText
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
Expand All @@ -32,12 +38,29 @@ class CategoriesUseCaseTest {
database
)

private val presetPhrasesRepository = RoomPresetPhrasesRepository(
database.presetPhrasesDao(),
FakeDateProvider()
)

private val storedPhrasesRepository = RoomStoredPhrasesRepository(
database,
FakeDateProvider()
)

private fun createUseCase(): CategoriesUseCase {
return CategoriesUseCase(
ConstantUUIDProvider(),
FakeLocaleProvider(),
storedCategoriesRepository,
presetCategoriesRepository
presetCategoriesRepository,
PhrasesUseCase(
StubLegacyCategoriesAndPhrasesRepository(),
storedPhrasesRepository,
presetPhrasesRepository,
FakeDateProvider(),
ConstantUUIDProvider()
)
)
}

Expand Down Expand Up @@ -318,6 +341,14 @@ class CategoriesUseCaseTest {
sortOrder = 0
)
)
storedPhrasesRepository.addPhrase(PhraseDto(
phraseId = "phrase1",
parentCategoryId = "storedCategory1",
creationDate = 0,
lastSpokenDate = null,
localizedUtterance = LocalesWithText(mapOf("en_US" to "phrase1")),
sortOrder = 0
))

val useCase = createUseCase()

Expand All @@ -327,6 +358,10 @@ class CategoriesUseCaseTest {
presetCategoriesRepository.getPresetCategories().first(),
useCase.categories().first()
)
assertEquals(
null,
storedPhrasesRepository.getPhrase("phrase1")
)
}

@Test
Expand All @@ -340,5 +375,10 @@ class CategoriesUseCaseTest {
.filter { it.categoryId != PresetCategories.BASIC_NEEDS.id },
useCase.categories().first()
)

assertEquals(
emptyList<PresetPhrase>(),
presetPhrasesRepository.getPhrasesForCategory(PresetCategories.BASIC_NEEDS.id)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ import com.willowtree.vocable.CategoriesUseCase
import com.willowtree.vocable.ConstantUUIDProvider
import com.willowtree.vocable.FakeLocaleProvider
import com.willowtree.vocable.MainDispatcherRule
import com.willowtree.vocable.PhrasesUseCase
import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.presets.PresetCategories
import com.willowtree.vocable.presets.RoomPresetCategoriesRepository
import com.willowtree.vocable.room.RoomPresetPhrasesRepository
import com.willowtree.vocable.room.RoomStoredCategoriesRepository
import com.willowtree.vocable.room.RoomStoredPhrasesRepository
import com.willowtree.vocable.room.VocableDatabase
import com.willowtree.vocable.utility.FakeDateProvider
import com.willowtree.vocable.utility.StubLegacyCategoriesAndPhrasesRepository
import com.willowtree.vocable.utils.locale.LocalesWithText
import com.willowtree.vocable.utils.locale.LocalizedResourceUtility
import kotlinx.coroutines.test.runTest
Expand Down Expand Up @@ -43,11 +48,28 @@ class AddUpdateCategoryViewModelTest {
database
)

private val presetPhrasesRepository = RoomPresetPhrasesRepository(
database.presetPhrasesDao(),
FakeDateProvider()
)

private val storedPhrasesRepository = RoomStoredPhrasesRepository(
database,
FakeDateProvider()
)

private val categoriesUseCase = CategoriesUseCase(
ConstantUUIDProvider(),
FakeLocaleProvider(),
storedCategoriesRepository,
presetCategoriesRepository
presetCategoriesRepository,
PhrasesUseCase(
StubLegacyCategoriesAndPhrasesRepository(),
storedPhrasesRepository,
presetPhrasesRepository,
FakeDateProvider(),
ConstantUUIDProvider()
)
)

private fun createViewModel(): AddUpdateCategoryViewModel {
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/com/willowtree/vocable/AppKoinModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ object AppKoinModule {
single { LegacyCategoriesAndPhrasesRepository(get(), get()) } bind ILegacyCategoriesAndPhrasesRepository::class
single { Moshi.Builder().add(KotlinJsonAdapterFactory()).build() }
single { LocalizedResourceUtility(androidContext()) } bind ILocalizedResourceUtility::class
single { CategoriesUseCase(get(), get(), get(), get()) } bind ICategoriesUseCase::class
single { CategoriesUseCase(get(), get(), get(), get(), get()) } bind ICategoriesUseCase::class
single { PhrasesUseCase(get(), get(), get(), get(), get()) } bind IPhrasesUseCase::class
single { RandomUUIDProvider() } bind UUIDProvider::class
single { JavaDateProvider() } bind DateProvider::class
Expand All @@ -86,6 +86,6 @@ object AppKoinModule {
viewModel { PresetsViewModel(get(), get()) }
viewModel { EditCategoriesViewModel(get(), get(), get()) }
viewModel { AddUpdateCategoryViewModel(get(), get(), get()) }
viewModel { EditCategoryMenuViewModel(get(), get()) }
viewModel { EditCategoryMenuViewModel(get()) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ class CategoriesUseCase(
private val uuidProvider: UUIDProvider,
private val localeProvider: LocaleProvider,
private val storedCategoriesRepository: StoredCategoriesRepository,
private val presetCategoriesRepository: PresetCategoriesRepository
private val presetCategoriesRepository: PresetCategoriesRepository,
private val phrasesUseCase: PhrasesUseCase
) : ICategoriesUseCase {

override fun categories(): Flow<List<Category>> =
Expand Down Expand Up @@ -86,6 +87,9 @@ class CategoriesUseCase(
}

override suspend fun deleteCategory(categoryId: String) {
phrasesUseCase.getPhrasesForCategory(categoryId).forEach {
phrasesUseCase.deletePhrase(it.phraseId)
}
storedCategoriesRepository.deleteCategory(categoryId)
presetCategoriesRepository.deleteCategory(categoryId)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ package com.willowtree.vocable.settings
import android.os.Bundle
import android.view.View
import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import com.willowtree.vocable.BaseFragment
Expand All @@ -12,6 +15,7 @@ import com.willowtree.vocable.R
import com.willowtree.vocable.databinding.FragmentEditCategoryMenuBinding
import com.willowtree.vocable.presets.PresetCategories
import com.willowtree.vocable.utils.locale.LocalizedResourceUtility
import kotlinx.coroutines.launch
import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel

Expand Down Expand Up @@ -42,6 +46,15 @@ class EditCategoryMenuFragment : BaseFragment<FragmentEditCategoryMenuBinding>()
setUpRemoveCategoryButton()
setUpCategoryTitle()
}
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
editCategoryMenuViewModel.popBackStack.collect {
if (it) {
findNavController().popBackStack()
}
}
}
}
}

private fun setUpCategoryTitle() {
Expand Down Expand Up @@ -84,8 +97,6 @@ class EditCategoryMenuFragment : BaseFragment<FragmentEditCategoryMenuBinding>()
resources.getString(R.string.delete)
dialogPositiveButton.action = {
editCategoryMenuViewModel.deleteCategory()

findNavController().popBackStack()
}
dialogNegativeButton.text = resources.getString(R.string.settings_dialog_cancel)
dialogNegativeButton.action = {
Expand All @@ -94,7 +105,8 @@ class EditCategoryMenuFragment : BaseFragment<FragmentEditCategoryMenuBinding>()
}
}
}
binding.removeCategoryButton.isEnabled = editCategoryMenuViewModel.lastCategoryRemaining.value == false
binding.removeCategoryButton.isEnabled =
editCategoryMenuViewModel.lastCategoryRemaining.value == false
}

private fun toggleDialogVisibility(visible: Boolean) {
Expand All @@ -113,7 +125,7 @@ class EditCategoryMenuFragment : BaseFragment<FragmentEditCategoryMenuBinding>()
binding.editPhrasesButton.isEnabled = false
} else {
binding.editPhrasesButton.isEnabled = true
binding.editPhrasesButton.action = {
binding.editPhrasesButton.action = {
val action =
EditCategoryMenuFragmentDirections.actionEditCategoryMenuFragmentToEditCategoryPhrasesFragment(
(editCategoryMenuViewModel.currentCategory.value ?: args.category)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.willowtree.vocable.ICategoriesUseCase
import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.presets.ILegacyCategoriesAndPhrasesRepository
import com.willowtree.vocable.presets.PresetCategories
import com.willowtree.vocable.room.CategorySortOrder
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class EditCategoryMenuViewModel(
private val presetsRepository: ILegacyCategoriesAndPhrasesRepository,
private val categoriesUseCase: ICategoriesUseCase
) : ViewModel() {

Expand All @@ -24,6 +23,9 @@ class EditCategoryMenuViewModel(
private val _lastCategoryRemaining = MutableLiveData<Boolean>()
val lastCategoryRemaining: LiveData<Boolean> = _lastCategoryRemaining

private val _popBackStack = MutableStateFlow(false)
val popBackStack = _popBackStack.asStateFlow()

//TODO: PK - Can this be moved to `init`, and the id can be fetched from nav args?
fun updateCategoryById(categoryId: String) {
viewModelScope.launch {
Expand All @@ -48,51 +50,10 @@ class EditCategoryMenuViewModel(
viewModelScope.launch {
val category = _currentCategory.value

// Delete any phrases whose only associated category is the one being deleted
// First get the ids of all phrases associated with the category being deleted
val phrasesForCategory = category?.let { categoryPhrase ->
presetsRepository.getPhrasesForCategory(categoryPhrase.categoryId)
.sortedBy { it.sortOrder }
}


//Delete from Recents by utterance
if (phrasesForCategory != null) {
presetsRepository.deletePhrases(
presetsRepository.getPhrasesForCategory(PresetCategories.RECENTS.id)
.filter {
phrasesForCategory.map { phrase ->
phrase.localizedUtterance
}.contains(it.localizedUtterance)
}
)
}

//Delete phrases
presetsRepository.deletePhrases(
phrasesForCategory ?: listOf()
)

// Delete the category
if (category != null) {
categoriesUseCase.deleteCategory(category.categoryId)
}

// Update the sort order of remaining categories
val overallCategories = presetsRepository.getAllCategories()
val categoriesToUpdate =
overallCategories.filter { it.sortOrder > category?.sortOrder ?: 0 }
categoriesToUpdate.forEach {
it.sortOrder--
}
if (categoriesToUpdate.isNotEmpty()) {
categoriesUseCase.updateCategorySortOrders(categoriesToUpdate.map {
CategorySortOrder(
it.categoryId,
it.sortOrder
)
})
}
_popBackStack.update { true }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import com.willowtree.vocable.FakeCategoriesUseCase
import com.willowtree.vocable.MainDispatcherRule
import com.willowtree.vocable.getOrAwaitValue
import com.willowtree.vocable.presets.Category
import com.willowtree.vocable.presets.FakeLegacyCategoriesAndPhrasesRepository
import com.willowtree.vocable.utils.locale.LocalesWithText
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.test.runTest
Expand All @@ -25,7 +24,6 @@ class EditCategoryMenuViewModelTest {

private fun createViewModel(): EditCategoryMenuViewModel {
return EditCategoryMenuViewModel(
FakeLegacyCategoriesAndPhrasesRepository(),
categoriesUseCase
)
}
Expand Down

0 comments on commit e628dca

Please sign in to comment.