diff --git a/app/src/androidTest/java/com/willowtree/vocable/room/MigrationTest.kt b/app/src/androidTest/java/com/willowtree/vocable/room/MigrationTest.kt index cacad511..3d911f5d 100644 --- a/app/src/androidTest/java/com/willowtree/vocable/room/MigrationTest.kt +++ b/app/src/androidTest/java/com/willowtree/vocable/room/MigrationTest.kt @@ -15,6 +15,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.platform.app.InstrumentationRegistry import com.willowtree.vocable.presets.PresetCategories import com.willowtree.vocable.utils.VocableSharedPreferences +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.test.runTest import org.junit.Assert import org.junit.Assert.assertEquals @@ -322,7 +323,7 @@ class MigrationTest { "custom", 0L, null, - mapOf("english" to "custom"), + LocalesWithText( mapOf("english" to "custom")), false, 7 ), @@ -330,7 +331,7 @@ class MigrationTest { "recents", 0L, null, - mapOf("english" to "recents"), + LocalesWithText( mapOf("english" to "recents")), false, 8 ) @@ -346,7 +347,7 @@ class MigrationTest { "custom", 0L, 0L, - mapOf("english" to "hi"), + LocalesWithText( mapOf("english" to "hi")), 0 ) ), customPhrases @@ -358,7 +359,7 @@ class MigrationTest { "recents", 0L, 0L, - mapOf("english" to "hi"), + LocalesWithText( mapOf("english" to "hi")), 0 ) ), recentPhrases diff --git a/app/src/main/java/com/willowtree/vocable/AppKoinModule.kt b/app/src/main/java/com/willowtree/vocable/AppKoinModule.kt index ed300bfa..c9ed7286 100644 --- a/app/src/main/java/com/willowtree/vocable/AppKoinModule.kt +++ b/app/src/main/java/com/willowtree/vocable/AppKoinModule.kt @@ -15,9 +15,9 @@ import com.willowtree.vocable.settings.EditCategoryMenuViewModel import com.willowtree.vocable.utils.DateProvider import com.willowtree.vocable.utils.ILocalizedResourceUtility import com.willowtree.vocable.utils.JavaDateProvider -import com.willowtree.vocable.utils.JavaLocaleProvider -import com.willowtree.vocable.utils.LocaleProvider -import com.willowtree.vocable.utils.LocalizedResourceUtility +import com.willowtree.vocable.utils.locale.JavaLocaleProvider +import com.willowtree.vocable.utils.locale.LocaleProvider +import com.willowtree.vocable.utils.locale.LocalizedResourceUtility import com.willowtree.vocable.utils.RandomUUIDProvider import com.willowtree.vocable.utils.UUIDProvider import com.willowtree.vocable.utils.VocableSharedPreferences diff --git a/app/src/main/java/com/willowtree/vocable/CategoriesUseCase.kt b/app/src/main/java/com/willowtree/vocable/CategoriesUseCase.kt index 67e1b58b..5fd20b73 100644 --- a/app/src/main/java/com/willowtree/vocable/CategoriesUseCase.kt +++ b/app/src/main/java/com/willowtree/vocable/CategoriesUseCase.kt @@ -8,8 +8,9 @@ import com.willowtree.vocable.room.CategoryDto import com.willowtree.vocable.room.CategorySortOrder import com.willowtree.vocable.room.StoredCategoriesRepository import com.willowtree.vocable.utils.DateProvider -import com.willowtree.vocable.utils.LocaleProvider import com.willowtree.vocable.utils.UUIDProvider +import com.willowtree.vocable.utils.locale.LocalesWithText +import com.willowtree.vocable.utils.locale.LocaleProvider import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -34,7 +35,7 @@ class CategoriesUseCase( override suspend fun updateCategoryName( categoryId: String, - localizedName: Map + localizedName: LocalesWithText ) { presetsRepository.updateCategoryName(categoryId, localizedName) } @@ -53,7 +54,7 @@ class CategoriesUseCase( uuidProvider.randomUUIDString(), dateProvider.currentTimeMillis(), null, - mapOf(Pair(localeProvider.getDefaultLocaleString(), categoryName)), + LocalesWithText(mapOf(Pair(localeProvider.getDefaultLocaleString(), categoryName))), false, sortOrder ) diff --git a/app/src/main/java/com/willowtree/vocable/ICategoriesUseCase.kt b/app/src/main/java/com/willowtree/vocable/ICategoriesUseCase.kt index 534e9d1a..a1cc57b5 100644 --- a/app/src/main/java/com/willowtree/vocable/ICategoriesUseCase.kt +++ b/app/src/main/java/com/willowtree/vocable/ICategoriesUseCase.kt @@ -2,11 +2,12 @@ package com.willowtree.vocable import com.willowtree.vocable.presets.Category import com.willowtree.vocable.room.CategorySortOrder +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.flow.Flow interface ICategoriesUseCase { fun categories(): Flow> - suspend fun updateCategoryName(categoryId: String, localizedName: Map) + suspend fun updateCategoryName(categoryId: String, localizedName: LocalesWithText) suspend fun addCategory(categoryName: String, sortOrder: Int) suspend fun updateCategorySortOrders(categorySortOrders: List) } \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/PhrasesUseCase.kt b/app/src/main/java/com/willowtree/vocable/PhrasesUseCase.kt index 83ac785f..d79e5e48 100644 --- a/app/src/main/java/com/willowtree/vocable/PhrasesUseCase.kt +++ b/app/src/main/java/com/willowtree/vocable/PhrasesUseCase.kt @@ -6,6 +6,7 @@ import com.willowtree.vocable.presets.PresetCategories import com.willowtree.vocable.presets.asPhrase import com.willowtree.vocable.room.PhraseDto import com.willowtree.vocable.utils.DateProvider +import com.willowtree.vocable.utils.locale.LocalesWithText class PhrasesUseCase( private val presetsRepository: IPresetsRepository, @@ -26,11 +27,11 @@ class PhrasesUseCase( presetsRepository.deletePhrase(phraseId) } - suspend fun updatePhrase(phraseId: Long, localizedUtterance: Map) { + suspend fun updatePhrase(phraseId: Long, localizedUtterance: LocalesWithText) { presetsRepository.updatePhrase(phraseId, localizedUtterance) } - suspend fun addPhrase(localizedUtterance: Map, parentCategoryId: String) { + suspend fun addPhrase(localizedUtterance: LocalesWithText, parentCategoryId: String) { presetsRepository.addPhrase(PhraseDto( 0L, parentCategoryId, diff --git a/app/src/main/java/com/willowtree/vocable/presets/CategoriesFragment.kt b/app/src/main/java/com/willowtree/vocable/presets/CategoriesFragment.kt index 77f8279f..69d135a4 100644 --- a/app/src/main/java/com/willowtree/vocable/presets/CategoriesFragment.kt +++ b/app/src/main/java/com/willowtree/vocable/presets/CategoriesFragment.kt @@ -16,7 +16,7 @@ import com.willowtree.vocable.customviews.CategoryButton import com.willowtree.vocable.customviews.PointerListener import com.willowtree.vocable.databinding.CategoriesFragmentBinding import com.willowtree.vocable.databinding.CategoryButtonBinding -import com.willowtree.vocable.utils.LocalizedResourceUtility +import com.willowtree.vocable.utils.locale.LocalizedResourceUtility import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ViewModelOwner import org.koin.androidx.viewmodel.ext.android.viewModel diff --git a/app/src/main/java/com/willowtree/vocable/presets/Category.kt b/app/src/main/java/com/willowtree/vocable/presets/Category.kt index 0c279eb6..daa88d18 100644 --- a/app/src/main/java/com/willowtree/vocable/presets/Category.kt +++ b/app/src/main/java/com/willowtree/vocable/presets/Category.kt @@ -2,13 +2,14 @@ package com.willowtree.vocable.presets import android.os.Parcelable import com.willowtree.vocable.room.CategoryDto +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.parcelize.Parcelize sealed class Category : Parcelable { abstract val categoryId: String abstract val sortOrder: Int abstract val hidden: Boolean - abstract val localizedName: Map? + abstract val localizedName: LocalesWithText? abstract val resourceId: Int? abstract fun withSortOrder(sortOrder: Int): Category @@ -18,7 +19,7 @@ sealed class Category : Parcelable { data class StoredCategory( override val categoryId: String, override val resourceId: Int?, - override val localizedName: Map?, + override val localizedName: LocalesWithText?, override var hidden: Boolean, override var sortOrder: Int ) : Category() { @@ -29,7 +30,7 @@ sealed class Category : Parcelable { @Parcelize data class Recents( override val resourceId: Int?, - override val localizedName: Map?, + override val localizedName: LocalesWithText?, override val hidden: Boolean, override val sortOrder: Int ) : Category() { @@ -45,7 +46,7 @@ sealed class Category : Parcelable { override val hidden: Boolean, override val resourceId: Int ) : Category() { - override val localizedName: Map? = null + override val localizedName: LocalesWithText? = null override fun withSortOrder(sortOrder: Int): Category = copy(sortOrder = sortOrder) override fun withHidden(hidden: Boolean): Category = copy(hidden = hidden) } diff --git a/app/src/main/java/com/willowtree/vocable/presets/IPresetsRepository.kt b/app/src/main/java/com/willowtree/vocable/presets/IPresetsRepository.kt index de8bcae1..855f206b 100644 --- a/app/src/main/java/com/willowtree/vocable/presets/IPresetsRepository.kt +++ b/app/src/main/java/com/willowtree/vocable/presets/IPresetsRepository.kt @@ -3,6 +3,7 @@ package com.willowtree.vocable.presets import com.willowtree.vocable.room.CategoryDto import com.willowtree.vocable.room.CategorySortOrder import com.willowtree.vocable.room.PhraseDto +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.flow.Flow //TODO: PK - Rename this once we make the jump to rename [PresetsRepository] -> "RoomPresetsRepository" @@ -20,13 +21,13 @@ interface IPresetsRepository { suspend fun getAllCategories(): List suspend fun deletePhrase(phraseId: Long) suspend fun updateCategorySortOrders(categorySortOrders: List) - suspend fun updateCategoryName(categoryId: String, localizedName: Map) + suspend fun updateCategoryName(categoryId: String, localizedName: LocalesWithText) suspend fun updateCategoryHidden(categoryId: String, hidden: Boolean) suspend fun addCategory(category: CategoryDto) suspend fun getCategoryById(categoryId: String): CategoryDto suspend fun deleteCategory(categoryId: String) suspend fun getRecentPhrases(): List suspend fun updatePhraseLastSpoken(phraseId: Long, lastSpokenDate: Long) - suspend fun updatePhrase(phraseId: Long, localizedUtterance: Map) + suspend fun updatePhrase(phraseId: Long, localizedUtterance: LocalesWithText) suspend fun addPhrase(phrase: PhraseDto) } \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/presets/Phrase.kt b/app/src/main/java/com/willowtree/vocable/presets/Phrase.kt index b75e56cd..161c3d65 100644 --- a/app/src/main/java/com/willowtree/vocable/presets/Phrase.kt +++ b/app/src/main/java/com/willowtree/vocable/presets/Phrase.kt @@ -2,18 +2,19 @@ package com.willowtree.vocable.presets import android.os.Parcelable import com.willowtree.vocable.room.PhraseDto +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.parcelize.Parcelize sealed class Phrase : Parcelable { abstract val phraseId: Long - abstract val localizedUtterance: Map? + abstract val localizedUtterance: LocalesWithText? abstract val sortOrder: Int } @Parcelize data class CustomPhrase( override val phraseId: Long, - override val localizedUtterance: Map?, + override val localizedUtterance: LocalesWithText?, override val sortOrder: Int ) : Phrase(), Parcelable diff --git a/app/src/main/java/com/willowtree/vocable/presets/PresetsRepository.kt b/app/src/main/java/com/willowtree/vocable/presets/PresetsRepository.kt index 2346444f..57bab248 100644 --- a/app/src/main/java/com/willowtree/vocable/presets/PresetsRepository.kt +++ b/app/src/main/java/com/willowtree/vocable/presets/PresetsRepository.kt @@ -8,6 +8,7 @@ import com.willowtree.vocable.room.PhraseDto import com.willowtree.vocable.room.PhraseLocalizedUtterance import com.willowtree.vocable.room.PhraseSpokenDate import com.willowtree.vocable.room.VocableDatabase +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.flow.Flow import org.koin.core.component.KoinComponent import org.koin.core.component.get @@ -59,7 +60,7 @@ class PresetsRepository(val context: Context) : KoinComponent, IPresetsRepositor database.categoryDao().deleteCategory(categoryId) } - override suspend fun updatePhrase(phraseId: Long, localizedUtterance: Map) { + override suspend fun updatePhrase(phraseId: Long, localizedUtterance: LocalesWithText) { database.phraseDao().updatePhraseLocalizedUtterance(PhraseLocalizedUtterance(phraseId, localizedUtterance)) } @@ -67,7 +68,7 @@ class PresetsRepository(val context: Context) : KoinComponent, IPresetsRepositor database.phraseDao().updatePhraseSpokenDate(PhraseSpokenDate(phraseId, lastSpokenDate)) } - override suspend fun updateCategoryName(categoryId: String, localizedName: Map) { + override suspend fun updateCategoryName(categoryId: String, localizedName: LocalesWithText) { database.categoryDao().updateCategory(CategoryLocalizedName(categoryId, localizedName)) } @@ -93,7 +94,7 @@ class PresetsRepository(val context: Context) : KoinComponent, IPresetsRepositor presetCategory.id, System.currentTimeMillis(), null, - mapOf(Pair(Locale.getDefault().toString(), context.getString(phrasesIds.getResourceId(index, -1)))), + LocalesWithText(mapOf(Pair(Locale.getDefault().toString(), context.getString(phrasesIds.getResourceId(index, -1))))), phraseObjects.size ) ) diff --git a/app/src/main/java/com/willowtree/vocable/presets/adapter/PhraseAdapter.kt b/app/src/main/java/com/willowtree/vocable/presets/adapter/PhraseAdapter.kt index fe772269..9b6e928a 100644 --- a/app/src/main/java/com/willowtree/vocable/presets/adapter/PhraseAdapter.kt +++ b/app/src/main/java/com/willowtree/vocable/presets/adapter/PhraseAdapter.kt @@ -9,7 +9,7 @@ import com.willowtree.vocable.R import com.willowtree.vocable.databinding.PhraseButtonAddBinding import com.willowtree.vocable.databinding.PhraseButtonBinding import com.willowtree.vocable.presets.Phrase -import com.willowtree.vocable.utils.LocalizedResourceUtility +import com.willowtree.vocable.utils.locale.LocalizedResourceUtility import org.koin.core.component.KoinComponent import org.koin.core.component.inject import java.util.Locale diff --git a/app/src/main/java/com/willowtree/vocable/room/CategoryDto.kt b/app/src/main/java/com/willowtree/vocable/room/CategoryDto.kt index f37c035e..09b17f5b 100644 --- a/app/src/main/java/com/willowtree/vocable/room/CategoryDto.kt +++ b/app/src/main/java/com/willowtree/vocable/room/CategoryDto.kt @@ -4,6 +4,7 @@ import android.os.Parcelable import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.parcelize.Parcelize @Entity(tableName = "Category") @@ -12,7 +13,7 @@ data class CategoryDto( @PrimaryKey @ColumnInfo(name = "category_id") val categoryId: String, @ColumnInfo(name = "creation_date") val creationDate: Long, @ColumnInfo(name = "resource_id") val resourceId: Int?, - @ColumnInfo(name = "localized_name") var localizedName: Map?, + @ColumnInfo(name = "localized_name") var localizedName: LocalesWithText?, var hidden: Boolean, @ColumnInfo(name = "sort_order") var sortOrder: Int ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/room/CategoryLocalizedName.kt b/app/src/main/java/com/willowtree/vocable/room/CategoryLocalizedName.kt index 229246a8..245e4bf9 100644 --- a/app/src/main/java/com/willowtree/vocable/room/CategoryLocalizedName.kt +++ b/app/src/main/java/com/willowtree/vocable/room/CategoryLocalizedName.kt @@ -1,8 +1,9 @@ package com.willowtree.vocable.room import androidx.room.ColumnInfo +import com.willowtree.vocable.utils.locale.LocalesWithText data class CategoryLocalizedName( @ColumnInfo(name = "category_id") val categoryId: String, - @ColumnInfo(name = "localized_name") var localizedName: Map + @ColumnInfo(name = "localized_name") var localizedName: LocalesWithText ) \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/room/Converters.kt b/app/src/main/java/com/willowtree/vocable/room/Converters.kt index b138fcee..f54683e9 100644 --- a/app/src/main/java/com/willowtree/vocable/room/Converters.kt +++ b/app/src/main/java/com/willowtree/vocable/room/Converters.kt @@ -4,6 +4,8 @@ import androidx.room.TypeConverter import com.squareup.moshi.JsonAdapter import com.squareup.moshi.Moshi import com.squareup.moshi.Types +import com.willowtree.vocable.utils.locale.LocaleString +import com.willowtree.vocable.utils.locale.LocalesWithText import org.koin.core.component.KoinComponent import org.koin.core.component.inject @@ -14,8 +16,7 @@ object Converters : KoinComponent { @TypeConverter @JvmStatic fun stringMapToJson(stringMap: Map?): String { - val type = - Types.newParameterizedType(Map::class.java, String::class.java, String::class.java) + val type = Types.newParameterizedType(Map::class.java, String::class.java, String::class.java) val adapter: JsonAdapter> = moshi.adapter(type) return adapter.toJson(stringMap) } @@ -24,10 +25,30 @@ object Converters : KoinComponent { @JvmStatic fun jsonToStringMap(json: String?): Map? { return json?.let { - val type = - Types.newParameterizedType(Map::class.java, String::class.java, String::class.java) + val type = Types.newParameterizedType(Map::class.java, String::class.java, String::class.java) val adapter: JsonAdapter> = moshi.adapter(type) adapter.fromJson(it) } } + + @TypeConverter + @JvmStatic + fun stringMapToLanguagesWithText(localesWithText: LocalesWithText): String { + val type = Types.newParameterizedType(Map::class.java, LocaleString::class.java, String::class.java) + val adapter: JsonAdapter> = moshi.adapter(type) + return adapter.toJson(localesWithText.localesTextMap) + } + + @TypeConverter + @JvmStatic + fun languagesWithTextToStringMap(json: String?): LocalesWithText? { + return json?.let { + val type = Types.newParameterizedType(Map::class.java, LocaleString::class.java, String::class.java) + val adapter: JsonAdapter> = moshi.adapter(type) + adapter.fromJson(it)?.let { stringMap -> + LocalesWithText(stringMap) + } + + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/room/PhraseDto.kt b/app/src/main/java/com/willowtree/vocable/room/PhraseDto.kt index 56e46ff8..b821ad90 100644 --- a/app/src/main/java/com/willowtree/vocable/room/PhraseDto.kt +++ b/app/src/main/java/com/willowtree/vocable/room/PhraseDto.kt @@ -4,6 +4,7 @@ import android.os.Parcelable import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.PrimaryKey +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.parcelize.Parcelize @Entity(tableName = "Phrase") @@ -13,6 +14,6 @@ data class PhraseDto( @ColumnInfo(name = "parent_category_id") val parentCategoryId: String?, @ColumnInfo(name = "creation_date") val creationDate: Long, @ColumnInfo(name = "last_spoken_date") val lastSpokenDate: Long?, - @ColumnInfo(name = "localized_utterance") var localizedUtterance: Map?, + @ColumnInfo(name = "localized_utterance") var localizedUtterance: LocalesWithText?, @ColumnInfo(name = "sort_order") var sortOrder: Int ) : Parcelable \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/room/PhraseLocalizedUtterance.kt b/app/src/main/java/com/willowtree/vocable/room/PhraseLocalizedUtterance.kt index 010ae5c9..eb51c29d 100644 --- a/app/src/main/java/com/willowtree/vocable/room/PhraseLocalizedUtterance.kt +++ b/app/src/main/java/com/willowtree/vocable/room/PhraseLocalizedUtterance.kt @@ -1,8 +1,9 @@ package com.willowtree.vocable.room import androidx.room.ColumnInfo +import com.willowtree.vocable.utils.locale.LocalesWithText data class PhraseLocalizedUtterance( @ColumnInfo(name = "phrase_id") val phraseId: Long, - @ColumnInfo(name = "localized_utterance") var localizedUtterance: Map + @ColumnInfo(name = "localized_utterance") var localizedUtterance: LocalesWithText ) diff --git a/app/src/main/java/com/willowtree/vocable/settings/AddPhraseViewModel.kt b/app/src/main/java/com/willowtree/vocable/settings/AddPhraseViewModel.kt index e9157c12..f942d5e8 100644 --- a/app/src/main/java/com/willowtree/vocable/settings/AddPhraseViewModel.kt +++ b/app/src/main/java/com/willowtree/vocable/settings/AddPhraseViewModel.kt @@ -6,6 +6,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.willowtree.vocable.PhrasesUseCase import com.willowtree.vocable.presets.PresetsRepository +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject @@ -26,7 +27,7 @@ class AddPhraseViewModel : ViewModel(), KoinComponent { it.localizedUtterance?.containsValue(phraseStr) == true }) { phrasesUseCase.addPhrase( - mapOf(Pair(Locale.getDefault().toString(), phraseStr)), + LocalesWithText(mapOf(Pair(Locale.getDefault().toString(), phraseStr))), categoryId ) liveShowPhraseAdded.postValue(true) diff --git a/app/src/main/java/com/willowtree/vocable/settings/AddUpdateCategoryViewModel.kt b/app/src/main/java/com/willowtree/vocable/settings/AddUpdateCategoryViewModel.kt index 230466cf..ba8d1d9d 100644 --- a/app/src/main/java/com/willowtree/vocable/settings/AddUpdateCategoryViewModel.kt +++ b/app/src/main/java/com/willowtree/vocable/settings/AddUpdateCategoryViewModel.kt @@ -7,7 +7,8 @@ import androidx.lifecycle.viewModelScope import com.willowtree.vocable.ICategoriesUseCase import com.willowtree.vocable.room.CategorySortOrder import com.willowtree.vocable.utils.ILocalizedResourceUtility -import com.willowtree.vocable.utils.LocaleProvider +import com.willowtree.vocable.utils.locale.LocalesWithText +import com.willowtree.vocable.utils.locale.LocaleProvider import kotlinx.coroutines.delay import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch @@ -37,17 +38,16 @@ class AddUpdateCategoryViewModel( } val toUpdate = categoriesUseCase.categories().first().firstOrNull { it.categoryId == categoryId } - toUpdate?.let { - val currentName = it.localizedName?.get(localeProvider.getDefaultLocaleString()) + toUpdate?.localizedName?.let { localizedNames -> + val currentName = localizedNames[localeProvider.getDefaultLocaleString()] if (currentName == updatedName) { return@let } - val updatedNameMap = it.localizedName?.toMutableMap() ?: mutableMapOf() - updatedNameMap[localeProvider.getDefaultLocaleString()] = updatedName + val updatedLocalizedNames: LocalesWithText = localizedNames.set(localeProvider.getDefaultLocaleString(), updatedName) - categoriesUseCase.updateCategoryName(it.categoryId, updatedNameMap) + categoriesUseCase.updateCategoryName(toUpdate.categoryId, updatedLocalizedNames) liveShowCategoryUpdateMessage.postValue(true) delay(CATEGORY_MESSAGE_DELAY) liveShowCategoryUpdateMessage.postValue(false) diff --git a/app/src/main/java/com/willowtree/vocable/settings/EditCategoriesListFragment.kt b/app/src/main/java/com/willowtree/vocable/settings/EditCategoriesListFragment.kt index 29508aa8..11981d91 100644 --- a/app/src/main/java/com/willowtree/vocable/settings/EditCategoriesListFragment.kt +++ b/app/src/main/java/com/willowtree/vocable/settings/EditCategoriesListFragment.kt @@ -12,7 +12,7 @@ import com.willowtree.vocable.customviews.NoSayTextButton import com.willowtree.vocable.databinding.CategoryEditButtonBinding import com.willowtree.vocable.databinding.FragmentEditCategoriesListBinding import com.willowtree.vocable.presets.Category -import com.willowtree.vocable.utils.LocalizedResourceUtility +import com.willowtree.vocable.utils.locale.LocalizedResourceUtility import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ViewModelOwner import org.koin.androidx.viewmodel.ext.android.viewModel diff --git a/app/src/main/java/com/willowtree/vocable/settings/EditCategoryMenuFragment.kt b/app/src/main/java/com/willowtree/vocable/settings/EditCategoryMenuFragment.kt index f92a426d..38dbf9ae 100644 --- a/app/src/main/java/com/willowtree/vocable/settings/EditCategoryMenuFragment.kt +++ b/app/src/main/java/com/willowtree/vocable/settings/EditCategoryMenuFragment.kt @@ -11,7 +11,7 @@ import com.willowtree.vocable.BindingInflater import com.willowtree.vocable.R import com.willowtree.vocable.databinding.FragmentEditCategoryMenuBinding import com.willowtree.vocable.presets.PresetCategories -import com.willowtree.vocable.utils.LocalizedResourceUtility +import com.willowtree.vocable.utils.locale.LocalizedResourceUtility import org.koin.android.ext.android.inject import org.koin.androidx.viewmodel.ext.android.viewModel diff --git a/app/src/main/java/com/willowtree/vocable/settings/EditKeyboardFragment.kt b/app/src/main/java/com/willowtree/vocable/settings/EditKeyboardFragment.kt index 8920ef38..86d268ca 100644 --- a/app/src/main/java/com/willowtree/vocable/settings/EditKeyboardFragment.kt +++ b/app/src/main/java/com/willowtree/vocable/settings/EditKeyboardFragment.kt @@ -14,7 +14,7 @@ import com.willowtree.vocable.R import com.willowtree.vocable.databinding.FragmentEditKeyboardBinding import com.willowtree.vocable.keyboard.adapter.KeyboardAdapter import com.willowtree.vocable.utils.ItemOffsetDecoration -import com.willowtree.vocable.utils.LocalizedResourceUtility +import com.willowtree.vocable.utils.locale.LocalizedResourceUtility import org.koin.android.ext.android.inject import java.util.* diff --git a/app/src/main/java/com/willowtree/vocable/settings/EditPhrasesKeyboardFragment.kt b/app/src/main/java/com/willowtree/vocable/settings/EditPhrasesKeyboardFragment.kt index 7be5b7b9..9c10dbb9 100644 --- a/app/src/main/java/com/willowtree/vocable/settings/EditPhrasesKeyboardFragment.kt +++ b/app/src/main/java/com/willowtree/vocable/settings/EditPhrasesKeyboardFragment.kt @@ -10,7 +10,7 @@ import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.navArgs import com.willowtree.vocable.R import com.willowtree.vocable.presets.Phrase -import java.util.Locale +import com.willowtree.vocable.utils.locale.LocalesWithText class EditPhrasesKeyboardFragment : EditKeyboardFragment() { @@ -48,11 +48,8 @@ class EditPhrasesKeyboardFragment : EditKeyboardFragment() { if (!isDefaultTextVisible()) { binding.keyboardInput.text.let { text -> if (text.isNotBlank()) { - val phraseUtterance = - phrase.localizedUtterance?.toMutableMap()?.apply { - put(Locale.getDefault().toString(), text.toString()) - } - viewModel.updatePhrase(phrase.phraseId, phraseUtterance ?: emptyMap()) + val languageWithText = phrase.localizedUtterance ?: LocalesWithText(emptyMap()) + viewModel.updatePhrase(phrase.phraseId, languageWithText) addNewPhrase = false } } diff --git a/app/src/main/java/com/willowtree/vocable/settings/EditPhrasesViewModel.kt b/app/src/main/java/com/willowtree/vocable/settings/EditPhrasesViewModel.kt index 19961131..83675251 100644 --- a/app/src/main/java/com/willowtree/vocable/settings/EditPhrasesViewModel.kt +++ b/app/src/main/java/com/willowtree/vocable/settings/EditPhrasesViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.willowtree.vocable.PhrasesUseCase +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject @@ -16,7 +17,7 @@ class EditPhrasesViewModel : ViewModel(), KoinComponent { private val liveShowPhraseAdded = MutableLiveData() val showPhraseAdded: LiveData = liveShowPhraseAdded - fun updatePhrase(phraseId: Long, localizedUtterance: Map) { + fun updatePhrase(phraseId: Long, localizedUtterance: LocalesWithText) { viewModelScope.launch { phrasesUseCase.updatePhrase(phraseId, localizedUtterance) liveShowPhraseAdded.postValue(true) diff --git a/app/src/main/java/com/willowtree/vocable/settings/customcategories/adapter/CustomCategoryPhraseAdapter.kt b/app/src/main/java/com/willowtree/vocable/settings/customcategories/adapter/CustomCategoryPhraseAdapter.kt index 7e773886..d083b516 100644 --- a/app/src/main/java/com/willowtree/vocable/settings/customcategories/adapter/CustomCategoryPhraseAdapter.kt +++ b/app/src/main/java/com/willowtree/vocable/settings/customcategories/adapter/CustomCategoryPhraseAdapter.kt @@ -9,7 +9,7 @@ import com.willowtree.vocable.R import com.willowtree.vocable.customviews.NoSayTextButton import com.willowtree.vocable.databinding.EditCustomCategoryPhraseItemBinding import com.willowtree.vocable.presets.Phrase -import com.willowtree.vocable.utils.LocalizedResourceUtility +import com.willowtree.vocable.utils.locale.LocalizedResourceUtility import org.koin.core.component.KoinComponent import org.koin.core.component.inject diff --git a/app/src/main/java/com/willowtree/vocable/utils/LocaleProvider.kt b/app/src/main/java/com/willowtree/vocable/utils/LocaleProvider.kt deleted file mode 100644 index 00b64cd1..00000000 --- a/app/src/main/java/com/willowtree/vocable/utils/LocaleProvider.kt +++ /dev/null @@ -1,5 +0,0 @@ -package com.willowtree.vocable.utils - -interface LocaleProvider { - fun getDefaultLocaleString(): String -} \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/utils/LocaleUtils.kt b/app/src/main/java/com/willowtree/vocable/utils/LocaleUtils.kt deleted file mode 100644 index 476b89cb..00000000 --- a/app/src/main/java/com/willowtree/vocable/utils/LocaleUtils.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.willowtree.vocable.utils - -import java.util.* - -object LocaleUtils { - - private const val LOCALE_DELIMITER = "_" - - fun getTextForLocale(localizedPairs: Map): String { - return getLocalizedPair(localizedPairs).first - } - - /** - * Gets a Pair that contains the text to be displayed and/or spoken and the - * closest matching Locale for the text. This method will first try to find the string for the - * device's default locale. Then it will try to find the string that matches - * just the language of the device's default locale. It will then try to default to the English - * language locale. If no English version of the string exists, it will simply return the first - * string in the map and its corresponding locale. - * - * @param localizedPairs The map of language/locale codes and corresponding strings - * @return A Pair representing the closest matching text and locale - */ - fun getLocalizedPair(localizedPairs: Map): Pair { - var locale: Locale? = null - var text: String? = null - getLocaleList().forEach { - if (text != null) return@forEach - locale = it - text = localizedPairs[it.toString()] - } - if (text == null) { - localizedPairs.keys.firstOrNull()?.let { - locale = getLocaleForLanguage(it) - text = localizedPairs[it] - } - } - return Pair(text ?: "", locale ?: Locale.ENGLISH) - } - - private fun getLocaleList(): List { - val defaultLocale = Locale.getDefault() - return mutableListOf().apply { - // First the device's default locale - add(defaultLocale) - // Then just the language locale - add(Locale(defaultLocale.language)) - // Default to English - add(Locale.ENGLISH) - } - } - - private fun getLocaleForLanguage(language: String): Locale { - val split = language.split(LOCALE_DELIMITER) - val languageStr = split.first() - val countryStr = split.getOrNull(1) ?: "" - return Locale(languageStr, countryStr) - } -} \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/utils/JavaLocaleProvider.kt b/app/src/main/java/com/willowtree/vocable/utils/locale/JavaLocaleProvider.kt similarity index 78% rename from app/src/main/java/com/willowtree/vocable/utils/JavaLocaleProvider.kt rename to app/src/main/java/com/willowtree/vocable/utils/locale/JavaLocaleProvider.kt index 1d3442ed..b1ff5e0e 100644 --- a/app/src/main/java/com/willowtree/vocable/utils/JavaLocaleProvider.kt +++ b/app/src/main/java/com/willowtree/vocable/utils/locale/JavaLocaleProvider.kt @@ -1,4 +1,4 @@ -package com.willowtree.vocable.utils +package com.willowtree.vocable.utils.locale import java.util.Locale diff --git a/app/src/main/java/com/willowtree/vocable/utils/locale/LocaleProvider.kt b/app/src/main/java/com/willowtree/vocable/utils/locale/LocaleProvider.kt new file mode 100644 index 00000000..404faa33 --- /dev/null +++ b/app/src/main/java/com/willowtree/vocable/utils/locale/LocaleProvider.kt @@ -0,0 +1,5 @@ +package com.willowtree.vocable.utils.locale + +interface LocaleProvider { + fun getDefaultLocaleString(): LocaleString +} \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/utils/locale/LocaleWithText.kt b/app/src/main/java/com/willowtree/vocable/utils/locale/LocaleWithText.kt new file mode 100644 index 00000000..c9088250 --- /dev/null +++ b/app/src/main/java/com/willowtree/vocable/utils/locale/LocaleWithText.kt @@ -0,0 +1,8 @@ +package com.willowtree.vocable.utils.locale + +import java.util.Locale + + +typealias LocaleWithText = Pair +fun LocaleWithText.locale() = first +fun LocaleWithText.text() = second \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/utils/locale/LocalesWithText.kt b/app/src/main/java/com/willowtree/vocable/utils/locale/LocalesWithText.kt new file mode 100644 index 00000000..46d5ffde --- /dev/null +++ b/app/src/main/java/com/willowtree/vocable/utils/locale/LocalesWithText.kt @@ -0,0 +1,111 @@ +package com.willowtree.vocable.utils.locale + +import android.os.Parcelable +import kotlinx.parcelize.IgnoredOnParcel +import kotlinx.parcelize.Parcelize +import java.util.Locale + +private const val LOCALE_DELIMITER = "_" + +/** + * A typealias for a String containing LOCALE_DELIMITER separated language and country codes + */ +typealias LocaleString = String + +private fun LocaleString.toLocale(): Locale { + val split = split(LOCALE_DELIMITER) + val languageStr = split.first() + val countryStr = split.getOrNull(1) ?: "" + return Locale(languageStr, countryStr) +} + +/** + * A typealias for a map of language codes and corresponding text as Strings + */ +@Parcelize +data class LocalesWithText( + val localesTextMap: Map +) : Parcelable { + + /** + * Gets the string corresponding to the given localeString. + * @param localeString The localeString to match against + * @return The string corresponding to the given localeString. + */ + operator fun get(localeString: LocaleString): String? = localesTextMap[localeString] + + /** + * Gets the string corresponding to the given locale matched against LocaleString. + * @param locale The locale to match against turned into String + */ + private operator fun get(locale: Locale): String? = localesTextMap[locale.toString()] + + /** + * Sets the string corresponding to the given localeString. + * @param localeString String version of the locale + * @param text for the localeString + * @return A new LocalesWithText with the given localeString and text added to the map + */ + operator fun set(localeString: LocaleString, text: String): LocalesWithText { + return LocalesWithText(localesTextMap.toMutableMap().apply { + this[localeString] = text + }) + } + + /** + * Checks if the contains the given string. + */ + fun containsValue(phraseStr: String): Boolean = localesTextMap.containsValue(phraseStr) + + /** + * Gets a list of all the languages in the map + * @return A list of all the languages in the map, keys.toList() + */ + @IgnoredOnParcel + val locales: List = localesTextMap.keys.toList() + + /** + * Gets a TextWithLocale that contains the text to be displayed and/or spoken and the + * closest matching Locale for the text. This method will first try to find the string for the + * device's default locale. Then it will try to find the string that matches + * just the language of the device's default locale. It will then try to default to the English + * language locale. If no English version of the string exists, it will simply return the first + * string in the map and its corresponding locale. + * + * @return A text for localization + */ + @IgnoredOnParcel + val localizedText: LocaleWithText + get() { + var locale: Locale? = null + var text: String? = null + // Attempts to localize text given a list of default Locales + defaultLocaleList.forEach { + if (text != null) return@forEach + locale = it + text = this[it] + } + if (text == null) { + locales.firstOrNull()?.let { + locale = it.toLocale() + text = this[it] + } + } + return Pair(locale ?: Locale.ENGLISH, text ?: "") + } + + @IgnoredOnParcel + private val defaultLocaleList: List + get() { + val defaultLocale = Locale.getDefault() + return mutableListOf().apply { + // First the device's default locale + add(defaultLocale) + // Then just the language locale + add(Locale(defaultLocale.language)) + // Default to English + add(Locale.ENGLISH) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/willowtree/vocable/utils/LocalizedResourceUtility.kt b/app/src/main/java/com/willowtree/vocable/utils/locale/LocalizedResourceUtility.kt similarity index 69% rename from app/src/main/java/com/willowtree/vocable/utils/LocalizedResourceUtility.kt rename to app/src/main/java/com/willowtree/vocable/utils/locale/LocalizedResourceUtility.kt index 44e4e2e2..0d4ded75 100644 --- a/app/src/main/java/com/willowtree/vocable/utils/LocalizedResourceUtility.kt +++ b/app/src/main/java/com/willowtree/vocable/utils/locale/LocalizedResourceUtility.kt @@ -1,9 +1,10 @@ -package com.willowtree.vocable.utils +package com.willowtree.vocable.utils.locale import android.content.Context import android.content.res.Resources import com.willowtree.vocable.presets.Category import com.willowtree.vocable.presets.Phrase +import com.willowtree.vocable.utils.ILocalizedResourceUtility import org.koin.core.component.KoinComponent import org.koin.core.component.get @@ -12,9 +13,7 @@ class LocalizedResourceUtility : KoinComponent, ILocalizedResourceUtility { val resources: Resources = get().resources override fun getTextFromCategory(category: Category?): String { - return category?.localizedName?.let { - LocaleUtils.getTextForLocale(it) - } ?: category?.resourceId?.let { + return category?.localizedName?.localizedText?.text() ?: category?.resourceId?.let { if (it != 0) { resources.getString(it) } else { @@ -24,8 +23,6 @@ class LocalizedResourceUtility : KoinComponent, ILocalizedResourceUtility { } fun getTextFromPhrase(phrase: Phrase?): String { - return phrase?.localizedUtterance?.let { - LocaleUtils.getTextForLocale(it) - } ?: "" + return phrase?.localizedUtterance?.localizedText?.text() ?: "" } -} +} \ No newline at end of file diff --git a/app/src/test/java/com/willowtree/vocable/CategoriesUseCaseTest.kt b/app/src/test/java/com/willowtree/vocable/CategoriesUseCaseTest.kt index 892b3aef..8ac1736b 100644 --- a/app/src/test/java/com/willowtree/vocable/CategoriesUseCaseTest.kt +++ b/app/src/test/java/com/willowtree/vocable/CategoriesUseCaseTest.kt @@ -8,6 +8,7 @@ import com.willowtree.vocable.room.createCategoryDto import com.willowtree.vocable.utils.ConstantUUIDProvider import com.willowtree.vocable.utils.FakeDateProvider import com.willowtree.vocable.utils.FakeLocaleProvider +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import kotlinx.coroutines.test.runTest @@ -37,12 +38,12 @@ class CategoriesUseCaseTest { listOf( createCategoryDto( "customCategory1", - localizedName = mapOf("en_US" to "Custom"), + localizedName = LocalesWithText(mapOf("en_US" to "Custom")), resourceId = 1 ), createCategoryDto( "customCategory2", - localizedName = mapOf("en_US" to "Other"), + localizedName = LocalesWithText(mapOf("en_US" to "Other")), resourceId = 2 ) ) @@ -64,14 +65,14 @@ class CategoriesUseCaseTest { Category.StoredCategory( categoryId = "customCategory1", resourceId = 1, - localizedName = mapOf("en_US" to "Custom"), + localizedName = LocalesWithText(mapOf("en_US" to "Custom")), hidden = false, sortOrder = 0 ), Category.StoredCategory( categoryId = "customCategory2", resourceId = 2, - localizedName = mapOf("en_US" to "Other"), + localizedName = LocalesWithText(mapOf("en_US" to "Other")), hidden = false, sortOrder = 0 ), diff --git a/app/src/test/java/com/willowtree/vocable/FakeCategoriesUseCase.kt b/app/src/test/java/com/willowtree/vocable/FakeCategoriesUseCase.kt index efe5964a..e469641f 100644 --- a/app/src/test/java/com/willowtree/vocable/FakeCategoriesUseCase.kt +++ b/app/src/test/java/com/willowtree/vocable/FakeCategoriesUseCase.kt @@ -2,6 +2,7 @@ package com.willowtree.vocable import com.willowtree.vocable.presets.Category import com.willowtree.vocable.room.CategorySortOrder +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.update @@ -26,7 +27,7 @@ class FakeCategoriesUseCase : ICategoriesUseCase { override suspend fun updateCategoryName( categoryId: String, - localizedName: Map + localizedName: LocalesWithText ) { _categories.update { categories -> categories.map { @@ -44,7 +45,7 @@ class FakeCategoriesUseCase : ICategoriesUseCase { it + Category.StoredCategory( "", null, - mapOf("en_US" to categoryName), + LocalesWithText(mapOf("en_US" to categoryName)), false, sortOrder ) diff --git a/app/src/test/java/com/willowtree/vocable/presets/CategoryExt.kt b/app/src/test/java/com/willowtree/vocable/presets/CategoryExt.kt index 9a3f7d89..aa758d06 100644 --- a/app/src/test/java/com/willowtree/vocable/presets/CategoryExt.kt +++ b/app/src/test/java/com/willowtree/vocable/presets/CategoryExt.kt @@ -1,9 +1,11 @@ package com.willowtree.vocable.presets +import com.willowtree.vocable.utils.locale.LocalesWithText + fun createStoredCategory( categoryId: String, resourceId: Int? = null, - localizedName: Map? = mapOf("en_US" to "category"), + localizedName: LocalesWithText? = LocalesWithText(mapOf("en_US" to "category")), hidden: Boolean = false, sortOrder: Int = 0 ): Category.StoredCategory = Category.StoredCategory( diff --git a/app/src/test/java/com/willowtree/vocable/presets/FakePresetsRepository.kt b/app/src/test/java/com/willowtree/vocable/presets/FakePresetsRepository.kt index be26e7a7..66c9d1a6 100644 --- a/app/src/test/java/com/willowtree/vocable/presets/FakePresetsRepository.kt +++ b/app/src/test/java/com/willowtree/vocable/presets/FakePresetsRepository.kt @@ -3,6 +3,7 @@ package com.willowtree.vocable.presets import com.willowtree.vocable.room.CategoryDto import com.willowtree.vocable.room.CategorySortOrder import com.willowtree.vocable.room.PhraseDto +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.map @@ -16,7 +17,7 @@ class FakePresetsRepository : IPresetsRepository { categoryId = "1", creationDate = 0L, resourceId = null, - localizedName = mapOf("en_US" to "category"), + localizedName = LocalesWithText( mapOf("en_US" to "category")), hidden = false, sortOrder = 0 ) @@ -30,7 +31,7 @@ class FakePresetsRepository : IPresetsRepository { parentCategoryId = "1", creationDate = 0L, lastSpokenDate = 0L, - localizedUtterance = mapOf("en_US" to "Hello"), + localizedUtterance =LocalesWithText( mapOf("en_US" to "Hello")), sortOrder = 0 ) ) @@ -79,7 +80,7 @@ class FakePresetsRepository : IPresetsRepository { override suspend fun updateCategoryName( categoryId: String, - localizedName: Map + localizedName: LocalesWithText ) { _allCategories.update { allCategories -> allCategories.map { @@ -113,7 +114,7 @@ class FakePresetsRepository : IPresetsRepository { TODO("Not yet implemented") } - override suspend fun updatePhrase(phraseId: Long, localizedUtterance: Map) { + override suspend fun updatePhrase(phraseId: Long, localizedUtterance: LocalesWithText) { TODO("Not yet implemented") } diff --git a/app/src/test/java/com/willowtree/vocable/presets/PresetsViewModelTest.kt b/app/src/test/java/com/willowtree/vocable/presets/PresetsViewModelTest.kt index 05427309..ff651046 100644 --- a/app/src/test/java/com/willowtree/vocable/presets/PresetsViewModelTest.kt +++ b/app/src/test/java/com/willowtree/vocable/presets/PresetsViewModelTest.kt @@ -8,6 +8,7 @@ import com.willowtree.vocable.getOrAwaitValue import com.willowtree.vocable.room.CategoryDto import com.willowtree.vocable.room.PhraseDto import com.willowtree.vocable.utils.FakeDateProvider +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.test.UnconfinedTestDispatcher @@ -41,7 +42,7 @@ class PresetsViewModelTest { Category.StoredCategory( categoryId = "1", resourceId = null, - localizedName = mapOf("en_US" to "category"), + localizedName = LocalesWithText(mapOf("en_US" to "category")), hidden = false, sortOrder = 0 ) @@ -55,7 +56,7 @@ class PresetsViewModelTest { Category.StoredCategory( categoryId = "1", resourceId = null, - localizedName = mapOf("en_US" to "category"), + localizedName = LocalesWithText(mapOf("en_US" to "category")), hidden = false, sortOrder = 0 ) @@ -71,14 +72,14 @@ class PresetsViewModelTest { Category.StoredCategory( categoryId = "1", resourceId = null, - localizedName = mapOf("en_US" to "category"), + localizedName = LocalesWithText(mapOf("en_US" to "category")), hidden = false, sortOrder = 0 ), Category.StoredCategory( categoryId = "2", resourceId = null, - localizedName = mapOf("en_US" to "second category"), + localizedName = LocalesWithText(mapOf("en_US" to "second category")), hidden = false, sortOrder = 0 ) @@ -100,7 +101,7 @@ class PresetsViewModelTest { Category.StoredCategory( categoryId = "1", resourceId = null, - localizedName = mapOf("en_US" to "category"), + localizedName = LocalesWithText(mapOf("en_US" to "category")), hidden = false, sortOrder = 0 ), @@ -116,7 +117,7 @@ class PresetsViewModelTest { categoryId = "1", creationDate = 0L, resourceId = null, - localizedName = mapOf("en_US" to "category"), + localizedName = LocalesWithText(mapOf("en_US" to "category")), hidden = false, sortOrder = 0 ), @@ -124,7 +125,7 @@ class PresetsViewModelTest { categoryId = "2", creationDate = 0L, resourceId = null, - localizedName = mapOf("en_US" to "second category"), + localizedName = LocalesWithText(mapOf("en_US" to "second category")), hidden = false, sortOrder = 0 ) @@ -137,7 +138,7 @@ class PresetsViewModelTest { parentCategoryId = "1", creationDate = 0L, lastSpokenDate = 0L, - localizedUtterance = mapOf("en_US" to "Hello"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Hello")), sortOrder = 0 ) ), @@ -147,7 +148,7 @@ class PresetsViewModelTest { parentCategoryId = "2", creationDate = 0L, lastSpokenDate = 0L, - localizedUtterance = mapOf("en_US" to "Goodbye"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Goodbye")), sortOrder = 0 ) ) @@ -159,7 +160,7 @@ class PresetsViewModelTest { listOf( CustomPhrase( phraseId = 2L, - localizedUtterance = mapOf("en_US" to "Goodbye"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Goodbye")), sortOrder = 0 ), null @@ -176,7 +177,7 @@ class PresetsViewModelTest { categoryId = "2", creationDate = 0L, resourceId = null, - localizedName = mapOf("en_US" to "category"), + localizedName = LocalesWithText(mapOf("en_US" to "category")), hidden = false, sortOrder = 0 ) @@ -189,7 +190,7 @@ class PresetsViewModelTest { parentCategoryId = "2", creationDate = 0L, lastSpokenDate = 0L, - localizedUtterance = mapOf("en_US" to "Hello"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Hello")), sortOrder = 1 ), PhraseDto( @@ -197,7 +198,7 @@ class PresetsViewModelTest { parentCategoryId = "2", creationDate = 0L, lastSpokenDate = 0L, - localizedUtterance = mapOf("en_US" to "Goodbye"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Goodbye")), sortOrder = 0 ) ) @@ -208,12 +209,12 @@ class PresetsViewModelTest { listOf( CustomPhrase( phraseId = 2L, - localizedUtterance = mapOf("en_US" to "Goodbye"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Goodbye")), sortOrder = 0 ), CustomPhrase( phraseId = 1L, - localizedUtterance = mapOf("en_US" to "Hello"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Hello")), sortOrder = 1 ), null @@ -230,7 +231,7 @@ class PresetsViewModelTest { categoryId = PresetCategories.RECENTS.id, creationDate = 0L, resourceId = null, - localizedName = mapOf("en_US" to "category"), + localizedName = LocalesWithText(mapOf("en_US" to "category")), hidden = false, sortOrder = 0 ) @@ -242,7 +243,7 @@ class PresetsViewModelTest { parentCategoryId = PresetCategories.RECENTS.id, creationDate = 0L, lastSpokenDate = 0L, - localizedUtterance = mapOf("en_US" to "Hello"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Hello")), sortOrder = 1 ), PhraseDto( @@ -250,7 +251,7 @@ class PresetsViewModelTest { parentCategoryId = PresetCategories.RECENTS.id, creationDate = 0L, lastSpokenDate = 0L, - localizedUtterance = mapOf("en_US" to "Goodbye"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Goodbye")), sortOrder = 0 ) ) @@ -260,12 +261,12 @@ class PresetsViewModelTest { listOf( CustomPhrase( phraseId = 1L, - localizedUtterance = mapOf("en_US" to "Hello"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Hello")), sortOrder = 1 ), CustomPhrase( phraseId = 2L, - localizedUtterance = mapOf("en_US" to "Goodbye"), + localizedUtterance = LocalesWithText(mapOf("en_US" to "Goodbye")), sortOrder = 0 ) ), diff --git a/app/src/test/java/com/willowtree/vocable/room/CategoryDtoExt.kt b/app/src/test/java/com/willowtree/vocable/room/CategoryDtoExt.kt index 48819d5b..7a03c38a 100644 --- a/app/src/test/java/com/willowtree/vocable/room/CategoryDtoExt.kt +++ b/app/src/test/java/com/willowtree/vocable/room/CategoryDtoExt.kt @@ -1,10 +1,12 @@ package com.willowtree.vocable.room +import com.willowtree.vocable.utils.locale.LocalesWithText + fun createCategoryDto( categoryId: String, creationDate: Long = 0L, resourceId: Int? = null, - localizedName: Map? = mapOf("en_US" to "category"), + localizedName: LocalesWithText? = LocalesWithText(mapOf("en_US" to "category")), hidden: Boolean = false, sortOrder: Int = 0 ): CategoryDto = CategoryDto( diff --git a/app/src/test/java/com/willowtree/vocable/room/FakeStoredCategoriesRepository.kt b/app/src/test/java/com/willowtree/vocable/room/FakeStoredCategoriesRepository.kt index f9ab61cc..316e3ef3 100644 --- a/app/src/test/java/com/willowtree/vocable/room/FakeStoredCategoriesRepository.kt +++ b/app/src/test/java/com/willowtree/vocable/room/FakeStoredCategoriesRepository.kt @@ -1,5 +1,6 @@ package com.willowtree.vocable.room +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow @@ -8,10 +9,11 @@ class FakeStoredCategoriesRepository : StoredCategoriesRepository { "categoryId", 0L, 0, - emptyMap(), + LocalesWithText( emptyMap()), false, 0 - ))) + ) + )) override fun getAllCategories(): Flow> { return _allCategories diff --git a/app/src/test/java/com/willowtree/vocable/settings/AddUpdateCategoryViewModelTest.kt b/app/src/test/java/com/willowtree/vocable/settings/AddUpdateCategoryViewModelTest.kt index f8695a7a..7dcb5bf7 100644 --- a/app/src/test/java/com/willowtree/vocable/settings/AddUpdateCategoryViewModelTest.kt +++ b/app/src/test/java/com/willowtree/vocable/settings/AddUpdateCategoryViewModelTest.kt @@ -6,6 +6,7 @@ import com.willowtree.vocable.MainDispatcherRule import com.willowtree.vocable.presets.Category import com.willowtree.vocable.utils.FakeLocaleProvider import com.willowtree.vocable.utils.FakeLocalizedResourceUtility +import com.willowtree.vocable.utils.locale.LocalesWithText import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import kotlinx.coroutines.test.runTest @@ -75,7 +76,7 @@ class AddUpdateCategoryViewModelTest { Category.StoredCategory( categoryId = "", resourceId = null, - localizedName = mapOf("en_US" to "New Category"), + localizedName = LocalesWithText(mapOf("en_US" to "New Category")), hidden = false, sortOrder = 1 ) @@ -91,7 +92,7 @@ class AddUpdateCategoryViewModelTest { Category.StoredCategory( categoryId = "1", resourceId = null, - localizedName = mapOf("en_US" to "Category"), + localizedName = LocalesWithText(mapOf("en_US" to "Category")), hidden = false, sortOrder = 0 ) @@ -107,7 +108,7 @@ class AddUpdateCategoryViewModelTest { Category.StoredCategory( categoryId = "1", resourceId = null, - localizedName = mapOf("en_US" to "New Category"), + localizedName = LocalesWithText(mapOf("en_US" to "New Category")), hidden = false, sortOrder = 0 ) @@ -123,7 +124,7 @@ class AddUpdateCategoryViewModelTest { Category.StoredCategory( categoryId = "1", resourceId = null, - localizedName = mapOf("en_US" to "Category", "es_US" to "Spanish"), + localizedName = LocalesWithText(mapOf("en_US" to "Category", "es_US" to "Spanish")), hidden = false, sortOrder = 0 ) @@ -139,7 +140,7 @@ class AddUpdateCategoryViewModelTest { Category.StoredCategory( categoryId = "1", resourceId = null, - localizedName = mapOf("en_US" to "New Category", "es_US" to "Spanish"), + localizedName = LocalesWithText(mapOf("en_US" to "New Category", "es_US" to "Spanish")), hidden = false, sortOrder = 0 ) diff --git a/app/src/test/java/com/willowtree/vocable/utils/FakeLocaleProvider.kt b/app/src/test/java/com/willowtree/vocable/utils/FakeLocaleProvider.kt index 5162d1c8..3861d7de 100644 --- a/app/src/test/java/com/willowtree/vocable/utils/FakeLocaleProvider.kt +++ b/app/src/test/java/com/willowtree/vocable/utils/FakeLocaleProvider.kt @@ -1,5 +1,7 @@ package com.willowtree.vocable.utils +import com.willowtree.vocable.utils.locale.LocaleProvider + class FakeLocaleProvider : LocaleProvider { override fun getDefaultLocaleString(): String = "en_US" -} \ No newline at end of file +} diff --git a/app/src/test/java/com/willowtree/vocable/utils/FakeLocalizedResourceUtility.kt b/app/src/test/java/com/willowtree/vocable/utils/FakeLocalizedResourceUtility.kt index 85343560..0c761baa 100644 --- a/app/src/test/java/com/willowtree/vocable/utils/FakeLocalizedResourceUtility.kt +++ b/app/src/test/java/com/willowtree/vocable/utils/FakeLocalizedResourceUtility.kt @@ -4,6 +4,6 @@ import com.willowtree.vocable.presets.Category class FakeLocalizedResourceUtility : ILocalizedResourceUtility { override fun getTextFromCategory(category: Category?): String { - return category?.localizedName?.entries?.first()?.value ?: "" + return category?.localizedName?.localesTextMap?.entries?.first()?.value ?: "" } } \ No newline at end of file diff --git a/app/src/test/java/com/willowtree/vocable/utils/LocaleUtilsTest.kt b/app/src/test/java/com/willowtree/vocable/utils/LocaleUtilsTest.kt index 72458f75..dd12b927 100644 --- a/app/src/test/java/com/willowtree/vocable/utils/LocaleUtilsTest.kt +++ b/app/src/test/java/com/willowtree/vocable/utils/LocaleUtilsTest.kt @@ -1,8 +1,11 @@ package com.willowtree.vocable.utils +import com.willowtree.vocable.utils.locale.LocalesWithText +import com.willowtree.vocable.utils.locale.locale +import com.willowtree.vocable.utils.locale.text import org.junit.Assert import org.junit.Test -import java.util.* +import java.util.Locale class LocaleUtilsTest { @@ -20,53 +23,53 @@ class LocaleUtilsTest { @Test fun `full locale pair returned for full locale`() { - val localizedPairs = mapOf(FR_CA_PAIR, FR_PAIR, EN_PAIR) + val localizedPairs = LocalesWithText(mapOf(FR_CA_PAIR, FR_PAIR, EN_PAIR)) Locale.setDefault(Locale.CANADA_FRENCH) - val localizedPair = LocaleUtils.getLocalizedPair(localizedPairs) - Assert.assertEquals(FR_CA_HELLO, localizedPair.first) - Assert.assertEquals(Locale.CANADA_FRENCH, localizedPair.second) + val textWithLocal = localizedPairs.localizedText + Assert.assertEquals(FR_CA_HELLO, textWithLocal.text()) + Assert.assertEquals(Locale.CANADA_FRENCH, textWithLocal.locale()) } @Test fun `language-only locale pair returned for full locale`() { - val localizedPairs = mapOf(FR_PAIR, EN_PAIR) + val localizedPairs = LocalesWithText(mapOf(FR_PAIR, EN_PAIR)) Locale.setDefault(Locale.CANADA_FRENCH) - val localizedPair = LocaleUtils.getLocalizedPair(localizedPairs) - Assert.assertEquals(FR_HELLO, localizedPair.first) - Assert.assertEquals(Locale.FRENCH, localizedPair.second) + val textWithLocal = localizedPairs.localizedText + Assert.assertEquals(FR_HELLO, textWithLocal.text()) + Assert.assertEquals(Locale.FRENCH, textWithLocal.locale()) } @Test fun `English locale pair returned for full locale`() { - val localizedPairs = mapOf(EN_PAIR) + val localizedPairs = LocalesWithText(mapOf(EN_PAIR)) Locale.setDefault(Locale.CANADA_FRENCH) - val localizedPair = LocaleUtils.getLocalizedPair(localizedPairs) - Assert.assertEquals(EN_HELLO, localizedPair.first) - Assert.assertEquals(Locale.ENGLISH, localizedPair.second) + val textWithLocal = localizedPairs.localizedText + Assert.assertEquals(EN_HELLO, textWithLocal.text()) + Assert.assertEquals(Locale.ENGLISH, textWithLocal.locale()) } @Test fun `default to first map value if no value exists for locale`() { - val localizedPairs = mapOf(DE_DE_PAIR) + val localizedPairs = LocalesWithText(mapOf(DE_DE_PAIR)) Locale.setDefault(Locale.CANADA_FRENCH) - val localizedPair = LocaleUtils.getLocalizedPair(localizedPairs) - Assert.assertEquals(DE_DE_HELLO, localizedPair.first) - Assert.assertEquals(Locale.GERMANY, localizedPair.second) + val textWithLocal = localizedPairs.localizedText + Assert.assertEquals(DE_DE_HELLO, textWithLocal.text()) + Assert.assertEquals(Locale.GERMANY, textWithLocal.locale()) } @Test fun `empty map returns default values`() { - val localizedPairs = mapOf() - val localizedPair = LocaleUtils.getLocalizedPair(localizedPairs) - Assert.assertEquals("", localizedPair.first) - Assert.assertEquals(Locale.ENGLISH, localizedPair.second) + val localizedPairs = LocalesWithText(mapOf()) + val textWithLocal = localizedPairs.localizedText + Assert.assertEquals("", textWithLocal.text()) + Assert.assertEquals(Locale.ENGLISH, textWithLocal.locale()) } @Test fun `getTextForLocale returns closest match`() { - val localizedPairs = mapOf(FR_CA_PAIR, FR_PAIR, EN_PAIR) + val localizedPairs = LocalesWithText(mapOf(FR_CA_PAIR, FR_PAIR, EN_PAIR)) Locale.setDefault(Locale.CANADA_FRENCH) - val textForLocale = LocaleUtils.getTextForLocale(localizedPairs) - Assert.assertEquals(FR_CA_HELLO, textForLocale) + val textForLocale = localizedPairs.localizedText + Assert.assertEquals(FR_CA_HELLO, textForLocale.text()) } } \ No newline at end of file