From 7ff5547d051e664180320166be9ef5fb6b9eca04 Mon Sep 17 00:00:00 2001 From: dadachi Date: Mon, 27 Apr 2026 18:14:48 +0900 Subject: [PATCH] Drop maximum_name_length; remove How-To-Use from Settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two unrelated substrate-v2 cleanups bundled here. ## 1. Drop maximum_name_length from permissions; move to NatConstants The server no longer sends maximum_name_length in /shopkeeper/permissions; the client already tolerated its absence via a default. Promote the value to a constant and drop the dead plumbing. ### Stop reading maximum_name_length from /shopkeeper/permissions - Meta: drop the @SerialName("maximum_name_length") field. - Permissions: drop getMaximumNameLength() helper. - UserData: drop maximumNameLength field. - user_preferences.proto: reserved 23 (was maximum_name_length) so the wire number isn't reused. - NatPreferencesDataSource: drop the read in the userData mapping, the write in setPermissions, and the getMaximumNameLength() flow. - LoginRepository (interface + impl + DemoLoginRepository + TestLoginRepository): drop getMaximumNameLength(). ### Move maximumNameLength to NatConstants - NatConstants: add MAXIMUM_ITEM_TAG_NAME_LENGTH = 100. - ItemTagCreateViewModel + ItemTagEditViewModel: - UiState.maximumNameLength default now reads the constant. - Drop the loginRepository constructor param — it was only used for getMaximumNameLength(). - ItemTagCreateViewModel.reload() simplifies to a state reset. - ItemTagEditViewModel.fetchData() drops the combine() pairing the item-tag flow with the maximum-name-length flow. - Tests rewritten to drop the now-removed loginRepository wiring and the dead .copy(maximumNameLength = 100) calls; new maximumNameLength_matchesConstant tests assert against the NatConstants value (100). ## 2. Remove "How To Use" entry from Settings Drop the SettingsView list item linking to myturntag.com/how — a queue-product help page that no longer matches the substrate-v2 generic CRUD app surface. The string resource (R.string.how_to_use), the NatConstants.HOW_TO_USE_URL constant, and the OnboardingView call site are left in place because they are still wired and may be repurposed. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../nativeapptemplatefree/NatConstants.kt | 1 + .../data/login/LoginRepository.kt | 2 - .../data/login/LoginRepositoryImpl.kt | 2 - .../datastore/NatPreferencesDataSource.kt | 7 --- .../ui/settings/SettingsView.kt | 28 --------- .../item_tag_detail/ItemTagEditViewModel.kt | 46 +++++++-------- .../item_tag_list/ItemTagCreateViewModel.kt | 42 ++----------- .../demo/login/DemoLoginRepository.kt | 2 - .../testing/repository/TestLoginRepository.kt | 3 - .../ItemTagEditViewModelTest.kt | 21 ++----- .../ItemTagCreateViewModelTest.kt | 59 +++---------------- .../src/main/proto/user_preferences.proto | 2 +- .../nativeapptemplatefree/model/Meta.kt | 3 - .../model/Permissions.kt | 2 - .../nativeapptemplatefree/model/UserData.kt | 1 - 15 files changed, 40 insertions(+), 181 deletions(-) diff --git a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/NatConstants.kt b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/NatConstants.kt index 8a0a194..3a11a1c 100644 --- a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/NatConstants.kt +++ b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/NatConstants.kt @@ -9,6 +9,7 @@ object NatConstants { const val TERMS_OF_USE_URL: String = "https://nativeapptemplate.com/terms" const val MINIMUM_PASSWORD_LENGTH: Int = 8 + const val MAXIMUM_ITEM_TAG_NAME_LENGTH: Int = 100 const val MAXIMUM_ITEM_TAG_DESCRIPTION_LENGTH: Int = 1_000 const val PLACEHOLDER_FULLNAME: String = "John Smith" diff --git a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/data/login/LoginRepository.kt b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/data/login/LoginRepository.kt index 0497cce..b771210 100644 --- a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/data/login/LoginRepository.kt +++ b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/data/login/LoginRepository.kt @@ -55,6 +55,4 @@ interface LoginRepository { fun isShopDeleted(): Flow fun didShowTapShopBelowTip(): Flow - - fun getMaximumNameLength(): Flow } diff --git a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/data/login/LoginRepositoryImpl.kt b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/data/login/LoginRepositoryImpl.kt index d73c0a6..8329870 100644 --- a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/data/login/LoginRepositoryImpl.kt +++ b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/data/login/LoginRepositoryImpl.kt @@ -127,6 +127,4 @@ class LoginRepositoryImpl @Inject constructor( override fun isShopDeleted(): Flow = natPreferencesDataSource.isShopDeleted() override fun didShowTapShopBelowTip(): Flow = natPreferencesDataSource.didShowTapShopBelowTip() - - override fun getMaximumNameLength(): Flow = natPreferencesDataSource.getMaximumNameLength() } diff --git a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/datastore/NatPreferencesDataSource.kt b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/datastore/NatPreferencesDataSource.kt index 497a15b..fe012f5 100644 --- a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/datastore/NatPreferencesDataSource.kt +++ b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/datastore/NatPreferencesDataSource.kt @@ -50,7 +50,6 @@ class NatPreferencesDataSource @Inject constructor( androidAppVersion = it.androidAppVersion, shouldUpdatePrivacy = it.shouldUpdatePrivacy, shouldUpdateTerms = it.shouldUpdateTerms, - maximumNameLength = it.maximumNameLength, shopLimitCount = it.shopLimitCount, isEmailUpdated = it.isEmailUpdated, @@ -109,7 +108,6 @@ class NatPreferencesDataSource @Inject constructor( this.shouldUpdatePrivacy = permissions.getShouldUpdatePrivacy()!! this.shouldUpdateTerms = permissions.getShouldUpdateTerms()!! - this.maximumNameLength = permissions.getMaximumNameLength()!! this.shopLimitCount = permissions.getShopLimitCount()!! } } @@ -244,9 +242,4 @@ class NatPreferencesDataSource @Inject constructor( .map { data -> data.didShowTapShopBelowTip } - - fun getMaximumNameLength(): Flow = userPreferences.data - .map { data -> - data.maximumNameLength - } } diff --git a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/settings/SettingsView.kt b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/settings/SettingsView.kt index 880d8c1..3aebea8 100644 --- a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/settings/SettingsView.kt +++ b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/settings/SettingsView.kt @@ -262,34 +262,6 @@ private fun SettingsContentView( ) HorizontalDivider() } - item { - ListItem( - headlineContent = { - Text( - stringResource(R.string.how_to_use), - style = MaterialTheme.typography.titleMedium, - color = MaterialTheme.colorScheme.onPrimaryContainer, - ) - }, - leadingContent = { - Icon( - Icons.Outlined.Info, - contentDescription = stringResource(R.string.how_to_use), - tint = MaterialTheme.colorScheme.onSurfaceVariant, - ) - }, - modifier = Modifier - .clickable { - context.startActivity( - Intent( - Intent.ACTION_VIEW, - Uri.parse(NatConstants.HOW_TO_USE_URL), - ), - ) - }, - ) - HorizontalDivider() - } item { ListItem( headlineContent = { diff --git a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_detail/ItemTagEditViewModel.kt b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_detail/ItemTagEditViewModel.kt index 0ca6a50..56c8589 100644 --- a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_detail/ItemTagEditViewModel.kt +++ b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_detail/ItemTagEditViewModel.kt @@ -7,7 +7,6 @@ import androidx.navigation.toRoute import com.nativeapptemplate.nativeapptemplatefree.NatConstants import com.nativeapptemplate.nativeapptemplatefree.common.errors.codedDescription import com.nativeapptemplate.nativeapptemplatefree.data.item_tag.ItemTagRepository -import com.nativeapptemplate.nativeapptemplatefree.data.login.LoginRepository import com.nativeapptemplate.nativeapptemplatefree.model.ItemTag import com.nativeapptemplate.nativeapptemplatefree.model.ItemTagBody import com.nativeapptemplate.nativeapptemplatefree.model.ItemTagBodyDetail @@ -18,7 +17,6 @@ import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.catch -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @@ -28,7 +26,7 @@ data class ItemTagEditUiState( val name: String = "", val description: String = "", - val maximumNameLength: Int = -1, + val maximumNameLength: Int = NatConstants.MAXIMUM_ITEM_TAG_NAME_LENGTH, val isUpdated: Boolean = false, val isLoading: Boolean = true, @@ -39,7 +37,6 @@ data class ItemTagEditUiState( @HiltViewModel class ItemTagEditViewModel @Inject constructor( savedStateHandle: SavedStateHandle, - private val loginRepository: LoginRepository, private val itemTagRepository: ItemTagRepository, ) : ViewModel() { private val itemTagId = savedStateHandle.toRoute().id @@ -62,29 +59,28 @@ class ItemTagEditViewModel @Inject constructor( viewModelScope.launch { val itemTagFlow: Flow = itemTagRepository.getItemTag(itemTagId) - val maximumNameLengthFlow = loginRepository.getMaximumNameLength() - - combine(itemTagFlow, maximumNameLengthFlow) { itemTag, maximumNameLength -> - _uiState.update { - it.copy( - itemTag = itemTag, - name = itemTag.getName(), - description = itemTag.getDescription(), - maximumNameLength = maximumNameLength, - success = true, - isLoading = false, - ) + + itemTagFlow + .catch { exception -> + val message = exception.codedDescription + _uiState.update { + it.copy( + message = message, + isLoading = false, + ) + } } - }.catch { exception -> - val message = exception.codedDescription - _uiState.update { - it.copy( - message = message, - isLoading = false, - ) + .collect { itemTag -> + _uiState.update { + it.copy( + itemTag = itemTag, + name = itemTag.getName(), + description = itemTag.getDescription(), + success = true, + isLoading = false, + ) + } } - }.collect { - } } } diff --git a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_list/ItemTagCreateViewModel.kt b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_list/ItemTagCreateViewModel.kt index 63afae9..df7ad8d 100644 --- a/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_list/ItemTagCreateViewModel.kt +++ b/app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_list/ItemTagCreateViewModel.kt @@ -7,7 +7,6 @@ import androidx.navigation.toRoute import com.nativeapptemplate.nativeapptemplatefree.NatConstants import com.nativeapptemplate.nativeapptemplatefree.common.errors.codedDescription import com.nativeapptemplate.nativeapptemplatefree.data.item_tag.ItemTagRepository -import com.nativeapptemplate.nativeapptemplatefree.data.login.LoginRepository import com.nativeapptemplate.nativeapptemplatefree.model.ItemTag import com.nativeapptemplate.nativeapptemplatefree.model.ItemTagBody import com.nativeapptemplate.nativeapptemplatefree.model.ItemTagBodyDetail @@ -25,18 +24,17 @@ import javax.inject.Inject data class ItemTagCreateUiState( val name: String = "", val description: String = "", - val maximumNameLength: Int = -1, + val maximumNameLength: Int = NatConstants.MAXIMUM_ITEM_TAG_NAME_LENGTH, val isCreated: Boolean = false, - val isLoading: Boolean = true, - val success: Boolean = false, + val isLoading: Boolean = false, + val success: Boolean = true, val message: String = "", ) @HiltViewModel class ItemTagCreateViewModel @Inject constructor( savedStateHandle: SavedStateHandle, - private val loginRepository: LoginRepository, private val itemTagRepository: ItemTagRepository, ) : ViewModel() { private val shopId = savedStateHandle.toRoute().shopId @@ -45,40 +43,8 @@ class ItemTagCreateViewModel @Inject constructor( val uiState: StateFlow = _uiState.asStateFlow() fun reload() { - fetchData() - } - - private fun fetchData() { _uiState.update { - it.copy( - isLoading = true, - success = false, - isCreated = false, - ) - } - - viewModelScope.launch { - val maximumNameLengthFlow = loginRepository.getMaximumNameLength() - - maximumNameLengthFlow - .catch { exception -> - val message = exception.codedDescription - _uiState.update { - it.copy( - message = message, - isLoading = false, - ) - } - } - .collect { maximumNameLength -> - _uiState.update { - it.copy( - maximumNameLength = maximumNameLength, - success = true, - isLoading = false, - ) - } - } + ItemTagCreateUiState() } } diff --git a/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/demo/login/DemoLoginRepository.kt b/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/demo/login/DemoLoginRepository.kt index 2b8a600..f780a12 100644 --- a/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/demo/login/DemoLoginRepository.kt +++ b/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/demo/login/DemoLoginRepository.kt @@ -100,8 +100,6 @@ class DemoLoginRepository @Inject constructor( override fun didShowTapShopBelowTip(): Flow = MutableStateFlow(true) - override fun getMaximumNameLength(): Flow = MutableStateFlow(100) - @OptIn(ExperimentalSerializationApi::class) private suspend inline fun getDataFromJsonFile(fileName: String): T = withContext(ioDispatcher) { diff --git a/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/testing/repository/TestLoginRepository.kt b/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/testing/repository/TestLoginRepository.kt index 5a99c8a..5cdee04 100644 --- a/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/testing/repository/TestLoginRepository.kt +++ b/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/testing/repository/TestLoginRepository.kt @@ -11,7 +11,6 @@ import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.filterNotNull -import kotlinx.coroutines.flow.map val emptyUserData = UserData() @@ -134,8 +133,6 @@ class TestLoginRepository : LoginRepository { override fun didShowTapShopBelowTip(): Flow = MutableStateFlow(true) - override fun getMaximumNameLength(): Flow = userData.map { it.maximumNameLength } - /** * A test-only API. */ diff --git a/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_detail/ItemTagEditViewModelTest.kt b/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_detail/ItemTagEditViewModelTest.kt index 190dc2c..10a1aa2 100644 --- a/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_detail/ItemTagEditViewModelTest.kt +++ b/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_detail/ItemTagEditViewModelTest.kt @@ -2,12 +2,11 @@ package com.nativeapptemplate.nativeapptemplatefree.ui.shop_settings.item_tag_de import androidx.lifecycle.SavedStateHandle import androidx.navigation.testing.invoke +import com.nativeapptemplate.nativeapptemplatefree.NatConstants import com.nativeapptemplate.nativeapptemplatefree.model.Attributes import com.nativeapptemplate.nativeapptemplatefree.model.Data import com.nativeapptemplate.nativeapptemplatefree.model.ItemTag import com.nativeapptemplate.nativeapptemplatefree.testing.repository.TestItemTagRepository -import com.nativeapptemplate.nativeapptemplatefree.testing.repository.TestLoginRepository -import com.nativeapptemplate.nativeapptemplatefree.testing.repository.emptyUserData import com.nativeapptemplate.nativeapptemplatefree.testing.util.MainDispatcherRule import com.nativeapptemplate.nativeapptemplatefree.ui.shop_settings.navigation.ItemTagEditRoute import kotlinx.coroutines.flow.collect @@ -36,7 +35,6 @@ class ItemTagEditViewModelTest { @get:Rule val dispatcherRule = MainDispatcherRule() - private val loginRepository = TestLoginRepository() private val itemTagRepository = TestItemTagRepository() private lateinit var viewModel: ItemTagEditViewModel @@ -47,7 +45,6 @@ class ItemTagEditViewModelTest { savedStateHandle = SavedStateHandle( route = ItemTagEditRoute(id = testInputItemTag.datum!!.id!!), ), - loginRepository = loginRepository, itemTagRepository = itemTagRepository, ) } @@ -57,11 +54,15 @@ class ItemTagEditViewModelTest { assertTrue(viewModel.uiState.value.isLoading) } + @Test + fun maximumNameLength_matchesConstant() = runTest { + assertEquals(NatConstants.MAXIMUM_ITEM_TAG_NAME_LENGTH, viewModel.uiState.value.maximumNameLength) + } + @Test fun stateItemTag_whenSuccess_matchesItemTagFromRepository() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) itemTagRepository.sendItemTag((testInputItemTag)) viewModel.reload() @@ -78,12 +79,6 @@ class ItemTagEditViewModelTest { fun stateIsUpdated_whenUpdatingItemTag_becomesTrue() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - val maximumNameLength = 100 - val userData = emptyUserData.copy( - maximumNameLength = maximumNameLength, - ) - - loginRepository.sendUserData(userData) itemTagRepository.sendItemTag(testInputItemTag) viewModel.reload() @@ -102,7 +97,6 @@ class ItemTagEditViewModelTest { fun unchangedNameAndDescription_isInvalid() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) itemTagRepository.sendItemTag(testInputItemTag) viewModel.reload() @@ -114,7 +108,6 @@ class ItemTagEditViewModelTest { fun changedDescriptionOnly_isValid() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) itemTagRepository.sendItemTag(testInputItemTag) viewModel.reload() @@ -127,7 +120,6 @@ class ItemTagEditViewModelTest { fun blankName_isInvalid() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) itemTagRepository.sendItemTag(testInputItemTag) viewModel.reload() @@ -141,7 +133,6 @@ class ItemTagEditViewModelTest { fun nameWithSymbolsAndUnicode_isValid() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) itemTagRepository.sendItemTag(testInputItemTag) viewModel.reload() diff --git a/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_list/ItemTagCreateViewModelTest.kt b/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_list/ItemTagCreateViewModelTest.kt index 0a91fce..2381950 100644 --- a/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_list/ItemTagCreateViewModelTest.kt +++ b/app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_list/ItemTagCreateViewModelTest.kt @@ -2,17 +2,15 @@ package com.nativeapptemplate.nativeapptemplatefree.ui.shop_settings.item_tag_li import androidx.lifecycle.SavedStateHandle import androidx.navigation.testing.invoke +import com.nativeapptemplate.nativeapptemplatefree.NatConstants import com.nativeapptemplate.nativeapptemplatefree.model.Attributes import com.nativeapptemplate.nativeapptemplatefree.model.Data import com.nativeapptemplate.nativeapptemplatefree.model.ItemTag import com.nativeapptemplate.nativeapptemplatefree.model.Shop import com.nativeapptemplate.nativeapptemplatefree.testing.repository.TestItemTagRepository -import com.nativeapptemplate.nativeapptemplatefree.testing.repository.TestLoginRepository -import com.nativeapptemplate.nativeapptemplatefree.testing.repository.emptyUserData import com.nativeapptemplate.nativeapptemplatefree.testing.util.MainDispatcherRule import com.nativeapptemplate.nativeapptemplatefree.ui.shop_settings.navigation.ItemTagCreateRoute import kotlinx.coroutines.flow.collect -import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.runTest @@ -37,7 +35,6 @@ class ItemTagCreateViewModelTest { @get:Rule val dispatcherRule = MainDispatcherRule() - private val loginRepository = TestLoginRepository() private val itemTagRepository = TestItemTagRepository() private lateinit var viewModel: ItemTagCreateViewModel @@ -48,49 +45,21 @@ class ItemTagCreateViewModelTest { savedStateHandle = SavedStateHandle( route = ItemTagCreateRoute(shopId = testInputShop.datum!!.id!!), ), - loginRepository = loginRepository, itemTagRepository = itemTagRepository, ) } @Test - fun stateIsInitiallyLoading() = runTest { - assertTrue(viewModel.uiState.value.isLoading) - } - - @Test - fun stateMaximumNameLength_whenSuccess_matchesMaximumNameLengthFromRepository() = runTest { - backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - - val maximumNameLength = 100 - - val userData = emptyUserData.copy( - maximumNameLength = maximumNameLength, - ) - - loginRepository.sendUserData(userData) - - viewModel.reload() - val uiStateValue = viewModel.uiState.value - assertTrue(uiStateValue.success) - assertFalse(uiStateValue.isLoading) - - assertEquals(loginRepository.getMaximumNameLength().first(), maximumNameLength) + fun maximumNameLength_matchesConstant() = runTest { + assertEquals(NatConstants.MAXIMUM_ITEM_TAG_NAME_LENGTH, viewModel.uiState.value.maximumNameLength) } @Test fun stateIsCreated_whenCreatingItemTag_becomesTrue() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - val maximumNameLength = 100 - val userData = emptyUserData.copy( - maximumNameLength = maximumNameLength, - ) - - loginRepository.sendUserData(userData) itemTagRepository.sendItemTag(testInputItemTag) - viewModel.reload() val newName = "Buy milk" viewModel.updateName(newName) assertEquals(viewModel.uiState.value.name, newName) @@ -106,8 +75,6 @@ class ItemTagCreateViewModelTest { fun blankName_isInvalid() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) - viewModel.reload() viewModel.updateName("") assertTrue(viewModel.hasInvalidDataName()) @@ -118,8 +85,6 @@ class ItemTagCreateViewModelTest { fun singleCharacterName_isValid() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) - viewModel.reload() viewModel.updateName("A") assertFalse(viewModel.hasInvalidDataName()) @@ -129,8 +94,6 @@ class ItemTagCreateViewModelTest { fun nameWithSymbolsAndUnicode_isValid() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) - viewModel.reload() viewModel.updateName("Buy milk 🥛 + bread") assertFalse(viewModel.hasInvalidDataName()) @@ -140,9 +103,7 @@ class ItemTagCreateViewModelTest { fun nameAtMaximumLength_isValid() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) - viewModel.reload() - viewModel.updateName("A".repeat(100)) + viewModel.updateName("A".repeat(NatConstants.MAXIMUM_ITEM_TAG_NAME_LENGTH)) assertFalse(viewModel.hasInvalidDataName()) } @@ -151,9 +112,7 @@ class ItemTagCreateViewModelTest { fun nameAboveMaximumLength_isRejectedByUpdater() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) - viewModel.reload() - viewModel.updateName("A".repeat(101)) + viewModel.updateName("A".repeat(NatConstants.MAXIMUM_ITEM_TAG_NAME_LENGTH + 1)) // updater clamps; value should remain blank (initial) assertEquals("", viewModel.uiState.value.name) @@ -163,9 +122,7 @@ class ItemTagCreateViewModelTest { fun descriptionAtMaximumLength_isValid() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) - viewModel.reload() - viewModel.updateDescription("D".repeat(1_000)) + viewModel.updateDescription("D".repeat(NatConstants.MAXIMUM_ITEM_TAG_DESCRIPTION_LENGTH)) assertFalse(viewModel.hasInvalidDataDescription()) } @@ -174,9 +131,7 @@ class ItemTagCreateViewModelTest { fun descriptionAboveMaximumLength_isRejectedByUpdater() = runTest { backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() } - loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100)) - viewModel.reload() - viewModel.updateDescription("D".repeat(1_001)) + viewModel.updateDescription("D".repeat(NatConstants.MAXIMUM_ITEM_TAG_DESCRIPTION_LENGTH + 1)) assertEquals("", viewModel.uiState.value.description) } diff --git a/datastore-proto/src/main/proto/user_preferences.proto b/datastore-proto/src/main/proto/user_preferences.proto index 454c918..90d4e2e 100644 --- a/datastore-proto/src/main/proto/user_preferences.proto +++ b/datastore-proto/src/main/proto/user_preferences.proto @@ -29,7 +29,7 @@ message UserPreferences { int32 android_app_version = 20; bool should_update_privacy = 21; bool should_update_terms = 22; - int32 maximum_name_length = 23; + reserved 23; // was maximum_name_length, now in NatConstants int32 shop_limit_count = 28; bool is_email_updated = 32; diff --git a/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/Meta.kt b/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/Meta.kt index 430a5b2..92e4720 100644 --- a/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/Meta.kt +++ b/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/Meta.kt @@ -23,9 +23,6 @@ data class Meta( @SerialName("should_update_terms") var shouldUpdateTerms: Boolean? = null, - @SerialName("maximum_name_length") - var maximumNameLength: Int = 100, - @SerialName("shop_limit_count") var shopLimitCount: Int = 0, diff --git a/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/Permissions.kt b/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/Permissions.kt index 15adc61..ee4a068 100644 --- a/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/Permissions.kt +++ b/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/Permissions.kt @@ -21,7 +21,5 @@ data class Permissions( fun getShouldUpdateTerms(): Boolean? = meta?.shouldUpdateTerms - fun getMaximumNameLength(): Int? = meta?.maximumNameLength - fun getShopLimitCount(): Int? = meta?.shopLimitCount } diff --git a/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/UserData.kt b/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/UserData.kt index 0f4db14..71626cb 100644 --- a/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/UserData.kt +++ b/model/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/model/UserData.kt @@ -40,7 +40,6 @@ data class UserData( var androidAppVersion: Int = -1, var shouldUpdatePrivacy: Boolean = false, var shouldUpdateTerms: Boolean = false, - var maximumNameLength: Int = -1, var shopLimitCount: Int = -1, var isEmailUpdated: Boolean = false,