Merge pull request #2920 from remychantenay/android-label-name-length-validation

Android: Add label name length validation upon creation
This commit is contained in:
Jackson Harper
2023-10-17 16:47:32 +08:00
committed by GitHub
3 changed files with 47 additions and 30 deletions

View File

@ -3,6 +3,7 @@
package app.omnivore.omnivore.ui.components
import LabelChip
import android.widget.Toast
import androidx.compose.foundation.*
import androidx.compose.foundation.interaction.FocusInteraction
import androidx.compose.foundation.interaction.MutableInteractionSource
@ -219,12 +220,12 @@ class LabelChipView(label: SavedItemLabel) : Chip(label.name) {
val label = label
}
fun findOrCreateLabel(labelsViewModel: LabelsViewModel, labels: List<SavedItemLabel>, name: TextFieldValue): SavedItemLabel {
val found = labels.find { it.name == name.text }
fun findOrCreateLabel(labelsViewModel: LabelsViewModel, labels: List<SavedItemLabel>, name: String): SavedItemLabel {
val found = labels.find { it.name == name }
if (found != null) {
return found
}
return labelsViewModel.createNewSavedItemLabelWithTemp(name.text, LabelSwatchHelper.random())
return labelsViewModel.createNewSavedItemLabelWithTemp(name, LabelSwatchHelper.random())
}
@Composable
@ -308,7 +309,7 @@ fun LabelsSelectionSheetContent(
LabelChipView(it)
} ?: null
} else {
LabelChipView(findOrCreateLabel(labelsViewModel = labelsViewModel, labels = labels, name = it))
LabelChipView(findOrCreateLabel(labelsViewModel = labelsViewModel, labels = labels, name = it.text))
}
},
chipLeadingIcon = { chip -> CircleIcon(colorHex = chip.label.color) },
@ -341,19 +342,34 @@ fun LabelsSelectionSheetContent(
)
if (!isLibraryMode && filterTextValue.text.isNotEmpty() && currentLabel == null) {
val context = LocalContext.current
Row(
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clickable {
val label = findOrCreateLabel(
labelsViewModel = labelsViewModel,
labels = labels,
name = filterTextValue
)
state.addChip(LabelChipView(label))
filterTextValue = TextFieldValue()
val labelName = filterTextValue.text.trim()
when(labelsViewModel.validateLabelName(labelName)) {
LabelsViewModel.Error.LabelNameTooLong -> {
Toast.makeText(
context,
context.getString(R.string.label_selection_sheet_label_too_long_error_msg,
labelsViewModel.labelNameMaxLength),
Toast.LENGTH_SHORT
).show()
}
null -> {
val label = findOrCreateLabel(
labelsViewModel = labelsViewModel,
labels = labels,
name = labelName
)
state.addChip(LabelChipView(label))
filterTextValue = TextFieldValue()
}
}
}
.padding(horizontal = 10.dp)
.padding(top = 10.dp, bottom = 5.dp)
@ -364,7 +380,7 @@ fun LabelsSelectionSheetContent(
contentDescription = null,
modifier = Modifier.padding(end = 8.dp)
)
Text(text = stringResource(R.string.label_selection_sheet_text_create, filterTextValue.text))
Text(text = stringResource(R.string.label_selection_sheet_text_create, filterTextValue.text.trim()))
}
}

View File

@ -1,34 +1,16 @@
package app.omnivore.omnivore.ui.components
import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.util.Log
import android.widget.Toast
import androidx.compose.ui.platform.LocalContext
import androidx.core.content.ContextCompat.startActivity
import androidx.lifecycle.*
import app.omnivore.omnivore.DatastoreKeys
import app.omnivore.omnivore.DatastoreRepository
import app.omnivore.omnivore.dataService.*
import app.omnivore.omnivore.graphql.generated.type.CreateLabelInput
import app.omnivore.omnivore.graphql.generated.type.SetLabelsInput
import app.omnivore.omnivore.models.ServerSyncStatus
import app.omnivore.omnivore.networking.*
import app.omnivore.omnivore.persistence.entities.SavedItem
import app.omnivore.omnivore.persistence.entities.SavedItemAndSavedItemLabelCrossRef
import app.omnivore.omnivore.persistence.entities.SavedItemLabel
import app.omnivore.omnivore.ui.components.LabelSwatchHelper
import app.omnivore.omnivore.ui.library.SavedItemAction
import com.apollographql.apollo3.api.Optional.Companion.presentIfNotNull
import com.google.gson.Gson
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.distinctUntilChanged
import java.time.Instant
import java.time.LocalDate
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
@ -42,6 +24,24 @@ class LabelsViewModel @Inject constructor(
private val dataService: DataService,
private val networker: Networker
): ViewModel() {
val labelNameMaxLength = 64
enum class Error {
LabelNameTooLong
}
/**
* Checks whether or not the provided label name is valid.
* @param labelName The name of the label.
* @return null if valid, [Error] otherwise.
*/
fun validateLabelName(labelName: String): Error? {
if (labelName.count() > labelNameMaxLength) {
return Error.LabelNameTooLong
}
return null
}
fun createNewSavedItemLabelWithTemp(labelName: String, hexColorValue: String): SavedItemLabel {
val tempId = UUID.randomUUID().toString()

View File

@ -103,6 +103,7 @@
<string name="label_selection_sheet_action_search">Search</string>
<string name="label_selection_sheet_action_save">Save</string>
<string name="label_selection_sheet_text_create">Create a new label named \"%1$s\"</string>
<string name="label_selection_sheet_label_too_long_error_msg">The name provided is too long (must be less or equal than %1$d characters)</string>
<!-- LibraryFilterBar -->
<string name="library_filter_bar_label_labels">Labels</string>