refactor: handle selected contacts in a local variable

pull/1128/head
andrekir 2024-07-06 08:31:52 -03:00
rodzic 56d9f03748
commit 2b4b1d7683
3 zmienionych plików z 29 dodań i 43 usunięć

Wyświetl plik

@ -11,12 +11,9 @@ import com.geeksville.mesh.database.entity.Packet
import com.geeksville.mesh.repository.datastore.ChannelSetRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.updateAndGet
import kotlinx.coroutines.launch
import java.text.DateFormat
import java.util.Date
@ -53,21 +50,6 @@ class ContactsViewModel @Inject constructor(
private val packetRepository: PacketRepository,
) : ViewModel(), Logging {
private val _selectedContacts = MutableStateFlow(emptySet<String>())
val selectedContacts get() = _selectedContacts.asStateFlow()
fun updateSelectedContacts(contact: String) = _selectedContacts.updateAndGet {
if (it.contains(contact)) {
it.minus(contact)
} else {
it.plus(contact)
}
}
fun clearSelectedContacts() {
_selectedContacts.value = emptySet()
}
val contactList = combine(
nodeDB.myNodeInfo,
packetRepository.getContacts(),
@ -124,4 +106,4 @@ class ContactsViewModel @Inject constructor(
fun deleteContacts(contacts: List<String>) = viewModelScope.launch(Dispatchers.IO) {
packetRepository.deleteContacts(contacts)
}
}
}

Wyświetl plik

@ -1,6 +1,5 @@
package com.geeksville.mesh.ui
import android.content.res.Configuration
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
@ -27,7 +26,7 @@ import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewLightDark
import androidx.compose.ui.unit.dp
import com.geeksville.mesh.R
import com.geeksville.mesh.model.Contact
@ -122,8 +121,7 @@ fun ContactItem(
}
}
@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
@PreviewLightDark
@Composable
private fun ContactItemPreview() {
AppTheme {

Wyświetl plik

@ -18,13 +18,13 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.toMutableStateList
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.unit.dp
import androidx.fragment.app.viewModels
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.geeksville.mesh.android.Logging
import com.geeksville.mesh.R
@ -43,7 +43,7 @@ class ContactsFragment : ScreenFragment("Messages"), Logging {
private val model: ContactsViewModel by viewModels()
private val contacts get() = model.contactList.value
private val selectedList get() = model.selectedContacts.value.toList()
private val selectedList = emptyList<String>().toMutableStateList()
private val selectedContacts get() = contacts.filter { it.contactKey in selectedList }
private val isAllMuted get() = selectedContacts.all { it.isMuted }
@ -63,13 +63,15 @@ class ContactsFragment : ScreenFragment("Messages"), Logging {
actionMode = (activity as AppCompatActivity).startSupportActionMode(actionModeCallback)
}
val selected = model.updateSelectedContacts(contact.contactKey)
if (selected.isEmpty()) {
selectedList.apply {
if (!remove(contact.contactKey)) add(contact.contactKey)
}
if (selectedList.isEmpty()) {
// finish action mode when no items selected
actionMode?.finish()
} else {
// show total items selected on action mode title
actionMode?.title = selected.size.toString()
actionMode?.title = selectedList.size.toString()
}
}
@ -86,8 +88,15 @@ class ContactsFragment : ScreenFragment("Messages"), Logging {
return ComposeView(requireContext()).apply {
setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed)
setContent {
val contacts by model.contactList.collectAsStateWithLifecycle()
AppTheme {
ContactsScreen(model, ::onClick, ::onLongClick)
ContactListView(
contacts = contacts,
selectedList = selectedList,
onClick = ::onClick,
onLongClick = ::onLongClick,
)
}
}
}
@ -171,14 +180,12 @@ class ContactsFragment : ScreenFragment("Messages"), Logging {
R.id.selectAllButton -> {
// if all selected -> unselect all
if (selectedList.size == contacts.size) {
model.clearSelectedContacts()
selectedList.clear()
mode.finish()
} else {
// else --> select all
model.clearSelectedContacts()
contacts.forEach {
model.updateSelectedContacts(it.contactKey)
}
selectedList.clear()
selectedList.addAll(contacts.map { it.contactKey })
actionMode?.title = contacts.size.toString()
}
}
@ -187,7 +194,7 @@ class ContactsFragment : ScreenFragment("Messages"), Logging {
}
override fun onDestroyActionMode(mode: ActionMode) {
model.clearSelectedContacts()
selectedList.clear()
actionMode = null
}
}
@ -195,26 +202,25 @@ class ContactsFragment : ScreenFragment("Messages"), Logging {
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ContactsScreen(
model: ContactsViewModel = hiltViewModel(),
fun ContactListView(
contacts: List<Contact>,
selectedList: List<String>,
onClick: (Contact) -> Unit,
onLongClick: (Contact) -> Unit,
) {
val contacts by model.contactList.collectAsStateWithLifecycle(emptyList())
val selectedKeys by model.selectedContacts.collectAsStateWithLifecycle()
// val inSelectionMode by remember { derivedStateOf { selectedContacts.isNotEmpty() } }
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(6.dp),
) {
items(contacts, key = { it.contactKey }) { contact ->
val selected = selectedKeys.contains(contact.contactKey)
val selected = selectedList.contains(contact.contactKey)
val selectedColor = if (selected) Color.Gray else MaterialTheme.colors.background
ContactItem(
contact = contact,
modifier = Modifier
.background(color = if (selected) Color.Gray else MaterialTheme.colors.background)
.background(color = selectedColor)
.combinedClickable(
onClick = { onClick(contact) },
onLongClick = { onLongClick(contact) },