class SearchStoresMapViewModel( private val storeCache: StoreCache, private val mapper: StoreUiMapper ) : ViewModel() { private val appliedFilters: MutableSet = mutableSetOf() private val filtersChannel = BroadcastChannel>(Channel.CONFLATED) private val queryChannel = BroadcastChannel(Channel.CONFLATED) private val _stores: LiveData> = filtersChannel.asFlow() .combine(queryChannel.asFlow().onEach { delay(400) }) { text, filters -> text to filters } .map { (filters: Set, text: String) -> searchStores(text, filters) } .map { stores: List -> mapper.map(stores) } .asLiveData() private fun searchStores(text: String, filters: Set): List = storeCache.getByStatus(filters).filter { store -> filterStoresByText(text, store) } private fun filterStoresByText( text: String, store: Store ): Boolean = if (text.isBlank()) { true } else { store.name.contains(text, true) } val stores: LiveData> get() = _stores init { viewModelScope.launch { queryChannel.send("") filtersChannel.send(appliedFilters) } } fun search(text: String? = "") { viewModelScope.launch { queryChannel.send(text.orEmpty()) } } fun onFilterChanged(status: OpenStatus, checked: Boolean) { if (checked) { appliedFilters.add(status) } else { appliedFilters.remove(status) } viewModelScope.launch { filtersChannel.send(appliedFilters) } } }