1. TagPickerViewModel.text is eliminated

2. The "create new tag" pseudo-TagData list item is eliminated and replaced by separate item in LazyColumn to make thins more straightforward
3. @Composable TarRow introduced to generalize layout in separate rows for "create tag" and others
pull/2849/head
hady 2 months ago
parent 3771e619b6
commit 3bf9257ecc

@ -20,6 +20,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
@ -97,7 +98,7 @@ class TagPickerActivityCompose : ThemedInjectingAppCompatActivity() {
} /* onCreate */
override fun onBackPressed() {
if (Strings.isNullOrEmpty(viewModel.pattern.value)) {
if (Strings.isNullOrEmpty(viewModel.searchText.value)) {
val data = Intent()
data.putExtra(EXTRA_TASKS, taskIds)
data.putParcelableArrayListExtra(EXTRA_PARTIALLY_SELECTED, viewModel.getPartiallySelected())
@ -164,7 +165,7 @@ internal fun SearchBar(
viewModel: TagPickerViewModel,
onBack: () -> Unit
) {
val searchPattern = remember { viewModel.pattern }
val searchPattern = remember { viewModel.searchText }
val invitation = LocalContext.current.getString(R.string.enter_tag_name)
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
@ -191,7 +192,7 @@ internal fun SearchBar(
} /* SearchBar */
@Composable
internal fun PickerBox(
internal fun PickerBox (
viewModel: TagPickerViewModel,
tags: State<List<TagData>>,
getTagIcon: (TagData) -> Int = { R.drawable.ic_outline_label_24px },
@ -201,53 +202,69 @@ internal fun PickerBox(
viewModel.viewModelScope.launch {
viewModel.toggle(it, viewModel.getState(it) != ToggleableState.On) }
}
val newItem: (TagData) -> Unit = {
viewModel.viewModelScope.launch { viewModel.createNew(it.name!!); viewModel.search("") }
val newItem: (String) -> Unit = {
viewModel.viewModelScope.launch { viewModel.createNew(it); viewModel.search("") }
}
LazyColumn {
items( tags.value, key = { if (it.id == null) -1 else it.id!! } )
if (viewModel.tagToCreate.value != "") {
item(key = -1) {
val text = LocalContext.current.getString(R.string.new_tag) + " \"${viewModel.tagToCreate.value}\""
TagRow(
icon = ImageVector.vectorResource(R.drawable.ic_outline_add_24px),
iconColor = Color(LocalContext.current.getColor(R.color.icon_tint_with_alpha)),
text = text,
onClick = { newItem(viewModel.searchText.value) }
)
}
}
items( tags.value, key = { tag -> tag.id!! } )
{
val checked = remember { mutableStateOf ( viewModel.getState(it) ) }
Row(modifier = Modifier
.fillMaxWidth()
.clickable {
if (it.id == null) newItem(it)
else {
onClick(it); checked.value = viewModel.getState(it)
}
},
verticalAlignment = Alignment.CenterVertically,
val clickChecked: () -> Unit = { onClick(it); checked.value = viewModel.getState(it) }
TagRow(
icon = ImageVector.vectorResource(getTagIcon(it)),
iconColor = getTagColor(it),
text = it.name!!,
onClick = clickChecked
) {
Icon(
imageVector = ImageVector.vectorResource(getTagIcon(it)),
contentDescription = "",
TriStateCheckbox(
modifier = Modifier.padding(6.dp),
tint = getTagColor(it)
state = checked.value,
onClick = clickChecked
)
if ( it.id == null ) {
val text = LocalContext.current.getString(R.string.new_tag) + " \"${it.name!!}\""
Text( text,
modifier = Modifier
.padding(horizontal = 24.dp)
.clickable { newItem(it) } )
} else {
Text(it.name!!,
modifier = Modifier
.weight(1f)
.padding(horizontal = 24.dp)
)
TriStateCheckbox(
modifier = Modifier.padding(6.dp),
state = checked.value,
onClick = { onClick(it); checked.value = viewModel.getState(it) }
)
}
}
}
}
} /* PickerBox */
@Composable
internal fun TagRow (
icon: ImageVector,
iconColor: Color,
text: String,
onClick: () -> Unit,
checkBox: @Composable RowScope.() -> Unit = {}
) {
Row(modifier = Modifier.fillMaxWidth().clickable{ onClick() },
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
imageVector = icon,
contentDescription = "",
modifier = Modifier.padding(6.dp),
tint = iconColor
)
Text(
text,
modifier = Modifier.weight(1f).padding(horizontal = 24.dp)
)
checkBox()
}
} /* TagRow */
/*
internal fun genTestTags(): List<TagData>
{

@ -21,12 +21,14 @@ class TagPickerViewModel @Inject constructor(
private val tags = MutableLiveData<List<TagData>>()
private val selected: MutableSet<TagData> = HashSet()
private val partiallySelected: MutableSet<TagData> = HashSet()
var text: String? = null
private set
private val _pattern = mutableStateOf("")
val pattern: State<String>
get() = _pattern
val searchText: State<String>
get() = _searchText
private val _searchText = mutableStateOf("")
val tagToCreate: State<String>
get() = _tagToCreate
private val _tagToCreate = mutableStateOf("")
fun observe(owner: LifecycleOwner, observer: (List<TagData>) -> Unit) =
tags.observe(owner, observer)
@ -47,17 +49,16 @@ class TagPickerViewModel @Inject constructor(
fun getPartiallySelected() = ArrayList(partiallySelected)
fun search(newText: String) {
if (!newText.equals(text, ignoreCase = true)) {
if (newText == "" || !newText.equals(_searchText.value, ignoreCase = true)) {
viewModelScope.launch {
val results = tagDataDao.searchTags(newText)
onUpdate(results.toMutableList())
onUpdate(newText, results.toMutableList())
}
}
text = newText
_pattern.value = newText
_searchText.value = newText
}
private fun onUpdate(results: MutableList<TagData>) {
private fun onUpdate(newText: String, results: MutableList<TagData>) {
val sorted = results
.sortedWith { l, r ->
val lSelected = selected.contains(l) || partiallySelected.contains(r)
@ -71,9 +72,10 @@ class TagPickerViewModel @Inject constructor(
}
}
.toMutableList()
if (pattern.value != "" && !results.any { pattern.value.equals(it.name, ignoreCase = true) }) {
sorted.add(0, TagData(pattern.value))
}
if ( newText != "" && !results.any {newText.equals(it.name, ignoreCase = true) } )
_tagToCreate.value = newText
else
_tagToCreate.value = ""
tags.value = sorted
}

Loading…
Cancel
Save