forked from agzam/vyatsu-schedule
101 lines
3.3 KiB
Kotlin
101 lines
3.3 KiB
Kotlin
package agzam.vyatsu.ui.groups
|
|||
|
|
|
||
|
|
import agzam.vyatsu.domain.model.Group
|
||
|
|
import agzam.vyatsu.domain.repository.GroupRepository
|
||
|
|
import androidx.lifecycle.ViewModel
|
||
|
|
import androidx.lifecycle.viewModelScope
|
||
|
|
import kotlinx.coroutines.Dispatchers
|
||
|
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||
|
|
import kotlinx.coroutines.flow.StateFlow
|
||
|
|
import kotlinx.coroutines.flow.asStateFlow
|
||
|
|
import kotlinx.coroutines.launch
|
||
|
|
import kotlinx.coroutines.withContext
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @author Agzam
|
||
|
|
*/
|
||
|
|
class GroupPickerViewModel(private val repository: GroupRepository) : ViewModel() {
|
||
|
|
|
||
|
|
private val _uiState = MutableStateFlow(GroupPickerUiState())
|
||
|
|
val uiState: StateFlow<GroupPickerUiState> = _uiState.asStateFlow()
|
||
|
|
|
||
|
|
init {
|
||
|
|
load()
|
||
|
|
}
|
||
|
|
|
||
|
|
private fun load() {
|
||
|
|
viewModelScope.launch {
|
||
|
|
withContext(Dispatchers.IO) {
|
||
|
|
val ok = try {
|
||
|
|
repository.refreshIfStale()
|
||
|
|
} catch (e: Exception) {
|
||
|
|
_uiState.value = _uiState.value.copy(
|
||
|
|
error = e.message ?: "Не удалось загрузить группы"
|
||
|
|
)
|
||
|
|
false
|
||
|
|
}
|
||
|
|
if (!ok && _uiState.value.groups.isEmpty()) {
|
||
|
|
_uiState.value = _uiState.value.copy(
|
||
|
|
error = _uiState.value.error ?: "Не удалось обновить список групп"
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
repository.observeGroups().collect { groups ->
|
||
|
|
val query = _uiState.value.searchQuery
|
||
|
|
_uiState.value = _uiState.value.copy(
|
||
|
|
isLoading = false,
|
||
|
|
groups = groups,
|
||
|
|
filteredGroups = filterGroups(groups, query),
|
||
|
|
error = null
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fun search(query: String) {
|
||
|
|
val groups = _uiState.value.groups
|
||
|
|
_uiState.value = _uiState.value.copy(
|
||
|
|
searchQuery = query,
|
||
|
|
filteredGroups = filterGroups(groups, query)
|
||
|
|
)
|
||
|
|
}
|
||
|
|
|
||
|
|
private fun filterGroups(groups: List<Group>, query: String): List<Group> {
|
||
|
|
if (query.isBlank()) return groups
|
||
|
|
val lowerQuery = query.lowercase()
|
||
|
|
return groups.filter { group ->
|
||
|
|
group.name.lowercase().contains(lowerQuery) || group.faculty.lowercase().contains(lowerQuery)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
fun retry() {
|
||
|
|
_uiState.value = _uiState.value.copy(isLoading = true, error = null)
|
||
|
|
load()
|
||
|
|
}
|
||
|
|
|
||
|
|
fun refresh() {
|
||
|
|
_uiState.value = _uiState.value.copy(isLoading = true, error = null)
|
||
|
|
viewModelScope.launch {
|
||
|
|
withContext(Dispatchers.IO) {
|
||
|
|
try {
|
||
|
|
repository.forceRefresh()
|
||
|
|
} catch (e: Exception) {
|
||
|
|
_uiState.value = _uiState.value.copy(
|
||
|
|
isLoading = false,
|
||
|
|
error = e.message ?: "Не удалось обновить список групп"
|
||
|
|
)
|
||
|
|
return@withContext
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
data class GroupPickerUiState(
|
||
|
|
val isLoading: Boolean = true,
|
||
|
|
val error: String? = null,
|
||
|
|
val groups: List<Group> = emptyList(),
|
||
|
|
val searchQuery: String = "",
|
||
|
|
val filteredGroups: List<Group> = emptyList()
|
||
|
|
)
|