Skip to content

Commit 337e164

Browse files
dadachiclaude
andauthored
Drop maximum_name_length; remove How-To-Use from Settings (#35)
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) <noreply@anthropic.com>
1 parent 8c3ff14 commit 337e164

15 files changed

Lines changed: 40 additions & 181 deletions

File tree

app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/NatConstants.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ object NatConstants {
99
const val TERMS_OF_USE_URL: String = "https://nativeapptemplate.com/terms"
1010

1111
const val MINIMUM_PASSWORD_LENGTH: Int = 8
12+
const val MAXIMUM_ITEM_TAG_NAME_LENGTH: Int = 100
1213
const val MAXIMUM_ITEM_TAG_DESCRIPTION_LENGTH: Int = 1_000
1314

1415
const val PLACEHOLDER_FULLNAME: String = "John Smith"

app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/data/login/LoginRepository.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,4 @@ interface LoginRepository {
5555
fun isShopDeleted(): Flow<Boolean>
5656

5757
fun didShowTapShopBelowTip(): Flow<Boolean>
58-
59-
fun getMaximumNameLength(): Flow<Int>
6058
}

app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/data/login/LoginRepositoryImpl.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,4 @@ class LoginRepositoryImpl @Inject constructor(
127127
override fun isShopDeleted(): Flow<Boolean> = natPreferencesDataSource.isShopDeleted()
128128

129129
override fun didShowTapShopBelowTip(): Flow<Boolean> = natPreferencesDataSource.didShowTapShopBelowTip()
130-
131-
override fun getMaximumNameLength(): Flow<Int> = natPreferencesDataSource.getMaximumNameLength()
132130
}

app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/datastore/NatPreferencesDataSource.kt

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ class NatPreferencesDataSource @Inject constructor(
5050
androidAppVersion = it.androidAppVersion,
5151
shouldUpdatePrivacy = it.shouldUpdatePrivacy,
5252
shouldUpdateTerms = it.shouldUpdateTerms,
53-
maximumNameLength = it.maximumNameLength,
5453
shopLimitCount = it.shopLimitCount,
5554

5655
isEmailUpdated = it.isEmailUpdated,
@@ -109,7 +108,6 @@ class NatPreferencesDataSource @Inject constructor(
109108

110109
this.shouldUpdatePrivacy = permissions.getShouldUpdatePrivacy()!!
111110
this.shouldUpdateTerms = permissions.getShouldUpdateTerms()!!
112-
this.maximumNameLength = permissions.getMaximumNameLength()!!
113111
this.shopLimitCount = permissions.getShopLimitCount()!!
114112
}
115113
}
@@ -244,9 +242,4 @@ class NatPreferencesDataSource @Inject constructor(
244242
.map { data ->
245243
data.didShowTapShopBelowTip
246244
}
247-
248-
fun getMaximumNameLength(): Flow<Int> = userPreferences.data
249-
.map { data ->
250-
data.maximumNameLength
251-
}
252245
}

app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/settings/SettingsView.kt

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -262,34 +262,6 @@ private fun SettingsContentView(
262262
)
263263
HorizontalDivider()
264264
}
265-
item {
266-
ListItem(
267-
headlineContent = {
268-
Text(
269-
stringResource(R.string.how_to_use),
270-
style = MaterialTheme.typography.titleMedium,
271-
color = MaterialTheme.colorScheme.onPrimaryContainer,
272-
)
273-
},
274-
leadingContent = {
275-
Icon(
276-
Icons.Outlined.Info,
277-
contentDescription = stringResource(R.string.how_to_use),
278-
tint = MaterialTheme.colorScheme.onSurfaceVariant,
279-
)
280-
},
281-
modifier = Modifier
282-
.clickable {
283-
context.startActivity(
284-
Intent(
285-
Intent.ACTION_VIEW,
286-
Uri.parse(NatConstants.HOW_TO_USE_URL),
287-
),
288-
)
289-
},
290-
)
291-
HorizontalDivider()
292-
}
293265
item {
294266
ListItem(
295267
headlineContent = {

app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_detail/ItemTagEditViewModel.kt

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import androidx.navigation.toRoute
77
import com.nativeapptemplate.nativeapptemplatefree.NatConstants
88
import com.nativeapptemplate.nativeapptemplatefree.common.errors.codedDescription
99
import com.nativeapptemplate.nativeapptemplatefree.data.item_tag.ItemTagRepository
10-
import com.nativeapptemplate.nativeapptemplatefree.data.login.LoginRepository
1110
import com.nativeapptemplate.nativeapptemplatefree.model.ItemTag
1211
import com.nativeapptemplate.nativeapptemplatefree.model.ItemTagBody
1312
import com.nativeapptemplate.nativeapptemplatefree.model.ItemTagBodyDetail
@@ -18,7 +17,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
1817
import kotlinx.coroutines.flow.StateFlow
1918
import kotlinx.coroutines.flow.asStateFlow
2019
import kotlinx.coroutines.flow.catch
21-
import kotlinx.coroutines.flow.combine
2220
import kotlinx.coroutines.flow.update
2321
import kotlinx.coroutines.launch
2422
import javax.inject.Inject
@@ -28,7 +26,7 @@ data class ItemTagEditUiState(
2826

2927
val name: String = "",
3028
val description: String = "",
31-
val maximumNameLength: Int = -1,
29+
val maximumNameLength: Int = NatConstants.MAXIMUM_ITEM_TAG_NAME_LENGTH,
3230
val isUpdated: Boolean = false,
3331

3432
val isLoading: Boolean = true,
@@ -39,7 +37,6 @@ data class ItemTagEditUiState(
3937
@HiltViewModel
4038
class ItemTagEditViewModel @Inject constructor(
4139
savedStateHandle: SavedStateHandle,
42-
private val loginRepository: LoginRepository,
4340
private val itemTagRepository: ItemTagRepository,
4441
) : ViewModel() {
4542
private val itemTagId = savedStateHandle.toRoute<ItemTagEditRoute>().id
@@ -62,29 +59,28 @@ class ItemTagEditViewModel @Inject constructor(
6259

6360
viewModelScope.launch {
6461
val itemTagFlow: Flow<ItemTag> = itemTagRepository.getItemTag(itemTagId)
65-
val maximumNameLengthFlow = loginRepository.getMaximumNameLength()
66-
67-
combine(itemTagFlow, maximumNameLengthFlow) { itemTag, maximumNameLength ->
68-
_uiState.update {
69-
it.copy(
70-
itemTag = itemTag,
71-
name = itemTag.getName(),
72-
description = itemTag.getDescription(),
73-
maximumNameLength = maximumNameLength,
74-
success = true,
75-
isLoading = false,
76-
)
62+
63+
itemTagFlow
64+
.catch { exception ->
65+
val message = exception.codedDescription
66+
_uiState.update {
67+
it.copy(
68+
message = message,
69+
isLoading = false,
70+
)
71+
}
7772
}
78-
}.catch { exception ->
79-
val message = exception.codedDescription
80-
_uiState.update {
81-
it.copy(
82-
message = message,
83-
isLoading = false,
84-
)
73+
.collect { itemTag ->
74+
_uiState.update {
75+
it.copy(
76+
itemTag = itemTag,
77+
name = itemTag.getName(),
78+
description = itemTag.getDescription(),
79+
success = true,
80+
isLoading = false,
81+
)
82+
}
8583
}
86-
}.collect {
87-
}
8884
}
8985
}
9086

app/src/main/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_list/ItemTagCreateViewModel.kt

Lines changed: 4 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import androidx.navigation.toRoute
77
import com.nativeapptemplate.nativeapptemplatefree.NatConstants
88
import com.nativeapptemplate.nativeapptemplatefree.common.errors.codedDescription
99
import com.nativeapptemplate.nativeapptemplatefree.data.item_tag.ItemTagRepository
10-
import com.nativeapptemplate.nativeapptemplatefree.data.login.LoginRepository
1110
import com.nativeapptemplate.nativeapptemplatefree.model.ItemTag
1211
import com.nativeapptemplate.nativeapptemplatefree.model.ItemTagBody
1312
import com.nativeapptemplate.nativeapptemplatefree.model.ItemTagBodyDetail
@@ -25,18 +24,17 @@ import javax.inject.Inject
2524
data class ItemTagCreateUiState(
2625
val name: String = "",
2726
val description: String = "",
28-
val maximumNameLength: Int = -1,
27+
val maximumNameLength: Int = NatConstants.MAXIMUM_ITEM_TAG_NAME_LENGTH,
2928
val isCreated: Boolean = false,
3029

31-
val isLoading: Boolean = true,
32-
val success: Boolean = false,
30+
val isLoading: Boolean = false,
31+
val success: Boolean = true,
3332
val message: String = "",
3433
)
3534

3635
@HiltViewModel
3736
class ItemTagCreateViewModel @Inject constructor(
3837
savedStateHandle: SavedStateHandle,
39-
private val loginRepository: LoginRepository,
4038
private val itemTagRepository: ItemTagRepository,
4139
) : ViewModel() {
4240
private val shopId = savedStateHandle.toRoute<ItemTagCreateRoute>().shopId
@@ -45,40 +43,8 @@ class ItemTagCreateViewModel @Inject constructor(
4543
val uiState: StateFlow<ItemTagCreateUiState> = _uiState.asStateFlow()
4644

4745
fun reload() {
48-
fetchData()
49-
}
50-
51-
private fun fetchData() {
5246
_uiState.update {
53-
it.copy(
54-
isLoading = true,
55-
success = false,
56-
isCreated = false,
57-
)
58-
}
59-
60-
viewModelScope.launch {
61-
val maximumNameLengthFlow = loginRepository.getMaximumNameLength()
62-
63-
maximumNameLengthFlow
64-
.catch { exception ->
65-
val message = exception.codedDescription
66-
_uiState.update {
67-
it.copy(
68-
message = message,
69-
isLoading = false,
70-
)
71-
}
72-
}
73-
.collect { maximumNameLength ->
74-
_uiState.update {
75-
it.copy(
76-
maximumNameLength = maximumNameLength,
77-
success = true,
78-
isLoading = false,
79-
)
80-
}
81-
}
47+
ItemTagCreateUiState()
8248
}
8349
}
8450

app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/demo/login/DemoLoginRepository.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,6 @@ class DemoLoginRepository @Inject constructor(
100100

101101
override fun didShowTapShopBelowTip(): Flow<Boolean> = MutableStateFlow(true)
102102

103-
override fun getMaximumNameLength(): Flow<Int> = MutableStateFlow(100)
104-
105103
@OptIn(ExperimentalSerializationApi::class)
106104
private suspend inline fun <reified T> getDataFromJsonFile(fileName: String): T =
107105
withContext(ioDispatcher) {

app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/testing/repository/TestLoginRepository.kt

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import kotlinx.coroutines.flow.Flow
1111
import kotlinx.coroutines.flow.MutableSharedFlow
1212
import kotlinx.coroutines.flow.MutableStateFlow
1313
import kotlinx.coroutines.flow.filterNotNull
14-
import kotlinx.coroutines.flow.map
1514

1615
val emptyUserData = UserData()
1716

@@ -134,8 +133,6 @@ class TestLoginRepository : LoginRepository {
134133

135134
override fun didShowTapShopBelowTip(): Flow<Boolean> = MutableStateFlow(true)
136135

137-
override fun getMaximumNameLength(): Flow<Int> = userData.map { it.maximumNameLength }
138-
139136
/**
140137
* A test-only API.
141138
*/

app/src/test/kotlin/com/nativeapptemplate/nativeapptemplatefree/ui/shop_settings/item_tag_detail/ItemTagEditViewModelTest.kt

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ package com.nativeapptemplate.nativeapptemplatefree.ui.shop_settings.item_tag_de
22

33
import androidx.lifecycle.SavedStateHandle
44
import androidx.navigation.testing.invoke
5+
import com.nativeapptemplate.nativeapptemplatefree.NatConstants
56
import com.nativeapptemplate.nativeapptemplatefree.model.Attributes
67
import com.nativeapptemplate.nativeapptemplatefree.model.Data
78
import com.nativeapptemplate.nativeapptemplatefree.model.ItemTag
89
import com.nativeapptemplate.nativeapptemplatefree.testing.repository.TestItemTagRepository
9-
import com.nativeapptemplate.nativeapptemplatefree.testing.repository.TestLoginRepository
10-
import com.nativeapptemplate.nativeapptemplatefree.testing.repository.emptyUserData
1110
import com.nativeapptemplate.nativeapptemplatefree.testing.util.MainDispatcherRule
1211
import com.nativeapptemplate.nativeapptemplatefree.ui.shop_settings.navigation.ItemTagEditRoute
1312
import kotlinx.coroutines.flow.collect
@@ -36,7 +35,6 @@ class ItemTagEditViewModelTest {
3635
@get:Rule
3736
val dispatcherRule = MainDispatcherRule()
3837

39-
private val loginRepository = TestLoginRepository()
4038
private val itemTagRepository = TestItemTagRepository()
4139

4240
private lateinit var viewModel: ItemTagEditViewModel
@@ -47,7 +45,6 @@ class ItemTagEditViewModelTest {
4745
savedStateHandle = SavedStateHandle(
4846
route = ItemTagEditRoute(id = testInputItemTag.datum!!.id!!),
4947
),
50-
loginRepository = loginRepository,
5148
itemTagRepository = itemTagRepository,
5249
)
5350
}
@@ -57,11 +54,15 @@ class ItemTagEditViewModelTest {
5754
assertTrue(viewModel.uiState.value.isLoading)
5855
}
5956

57+
@Test
58+
fun maximumNameLength_matchesConstant() = runTest {
59+
assertEquals(NatConstants.MAXIMUM_ITEM_TAG_NAME_LENGTH, viewModel.uiState.value.maximumNameLength)
60+
}
61+
6062
@Test
6163
fun stateItemTag_whenSuccess_matchesItemTagFromRepository() = runTest {
6264
backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() }
6365

64-
loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100))
6566
itemTagRepository.sendItemTag((testInputItemTag))
6667

6768
viewModel.reload()
@@ -78,12 +79,6 @@ class ItemTagEditViewModelTest {
7879
fun stateIsUpdated_whenUpdatingItemTag_becomesTrue() = runTest {
7980
backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() }
8081

81-
val maximumNameLength = 100
82-
val userData = emptyUserData.copy(
83-
maximumNameLength = maximumNameLength,
84-
)
85-
86-
loginRepository.sendUserData(userData)
8782
itemTagRepository.sendItemTag(testInputItemTag)
8883

8984
viewModel.reload()
@@ -102,7 +97,6 @@ class ItemTagEditViewModelTest {
10297
fun unchangedNameAndDescription_isInvalid() = runTest {
10398
backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() }
10499

105-
loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100))
106100
itemTagRepository.sendItemTag(testInputItemTag)
107101
viewModel.reload()
108102

@@ -114,7 +108,6 @@ class ItemTagEditViewModelTest {
114108
fun changedDescriptionOnly_isValid() = runTest {
115109
backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() }
116110

117-
loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100))
118111
itemTagRepository.sendItemTag(testInputItemTag)
119112
viewModel.reload()
120113

@@ -127,7 +120,6 @@ class ItemTagEditViewModelTest {
127120
fun blankName_isInvalid() = runTest {
128121
backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() }
129122

130-
loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100))
131123
itemTagRepository.sendItemTag(testInputItemTag)
132124
viewModel.reload()
133125

@@ -141,7 +133,6 @@ class ItemTagEditViewModelTest {
141133
fun nameWithSymbolsAndUnicode_isValid() = runTest {
142134
backgroundScope.launch(UnconfinedTestDispatcher()) { viewModel.uiState.collect() }
143135

144-
loginRepository.sendUserData(emptyUserData.copy(maximumNameLength = 100))
145136
itemTagRepository.sendItemTag(testInputItemTag)
146137
viewModel.reload()
147138

0 commit comments

Comments
 (0)