SDP-GeoHunt/geo-hunt

View on GitHub
app/src/main/java/com/github/geohunt/app/ui/screens/maps/MapsViewModel.kt

Summary

Maintainability
A
1 hr
Test Coverage
B
82%
package com.github.geohunt.app.ui.screens.maps

import android.app.Application
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.github.geohunt.app.data.repository.AppContainer
import com.github.geohunt.app.data.repository.ChallengeRepositoryInterface
import com.github.geohunt.app.data.repository.LocationRepositoryInterface
import com.github.geohunt.app.model.Challenge
import com.github.geohunt.app.model.Location
import com.github.geohunt.app.ui.components.utils.viewmodels.exceptionHandler
import com.github.geohunt.app.utility.aggregateFlows
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

class MapsViewModel(
    private val challengeRepository: ChallengeRepositoryInterface,
    private val locationRepository: LocationRepositoryInterface
) : ViewModel() {
    private val _challenges: MutableStateFlow<List<Challenge>?> = MutableStateFlow(null)
    val challenges: StateFlow<List<Challenge>?> = _challenges.asStateFlow()

    private val _currentLocation: MutableStateFlow<Location?> = MutableStateFlow(null)
    val currentLocation: StateFlow<Location?> = _currentLocation.asStateFlow()

    fun updateFetchableChallenges(sectorHashes: List<String>) {
        viewModelScope.launch {
            val aggregateChallengeFlow = sectorHashes.map { sectorHash ->
                challengeRepository.getSectorChallenges(sectorHash)
            }.aggregateFlows()

            aggregateChallengeFlow.collect {
                _challenges.value = it
            }
        }
    }
    fun startLocationUpdate(onFailure: (Throwable) -> Unit = {}) {
        viewModelScope.launch(exceptionHandler(onFailure)) {
            locationRepository.getLocations(viewModelScope).collect {
                _currentLocation.value = it
            }
        }
    }

    fun reset() {
        _currentLocation.value = null
    }

    companion object {
        val Factory: ViewModelProvider.Factory = viewModelFactory {
            initializer {
                val application = this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as Application
                val container = AppContainer.getInstance(application)

                MapsViewModel(
                    container.challenges,
                    container.location
                )
            }
        }
    }
}