/** * TrackerMap * Copyright (C) 2021-2022 Iván Ávalos , Henoch Ojeda * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package mx.trackermap.TrackerMap.android.units import android.util.Log import androidx.lifecycle.* import com.mousebird.maply.Point2d import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.flow.collect import kotlinx.coroutines.launch import mx.trackermap.TrackerMap.client.models.Geofence import mx.trackermap.TrackerMap.client.models.MapLayer import mx.trackermap.TrackerMap.client.models.UnitInformation import mx.trackermap.TrackerMap.controllers.GeofencesController import mx.trackermap.TrackerMap.controllers.UnitsController import org.koin.core.component.KoinComponent import org.koin.core.component.inject import kotlin.time.ExperimentalTime @DelicateCoroutinesApi @ExperimentalTime class UnitsViewModel( savedStateHandle: SavedStateHandle ) : ViewModel(), KoinComponent { enum class UnitsDisplayMode { MAP, LIST } data class Camera ( val point: Point2d, val animated: Boolean, ) private val unitsController: UnitsController by inject() private val geofenceController: GeofencesController by inject() private var _searchQuery = savedStateHandle.getLiveData("searchQuery", "") private var _unitsDisplayMode = MutableLiveData(UnitsDisplayMode.MAP) private var _units = MutableLiveData>() private var _displayedUnits = MutableLiveData>() private var _oldSelectedUnit = MutableLiveData() private var _selectedUnit = MutableLiveData() private var _mapLayerType = MutableLiveData() private var _geofences = MutableLiveData>() private val _camera = MutableLiveData() val searchQuery: LiveData get() = _searchQuery val unitsDisplayMode: LiveData get() = _unitsDisplayMode val units: LiveData> get() = _units val displayedUnits: LiveData> get() = _displayedUnits val oldSelectedUnit: LiveData get() = _oldSelectedUnit val selectedUnit: LiveData get() = _selectedUnit val mapLayerType: LiveData get() = _mapLayerType val geofences: LiveData> get() = _geofences val camera: LiveData get() = _camera init { Log.d("UnitsViewModel", "Initializing Units View Model") unitsController.fetchUnits(viewModelScope) viewModelScope.launch { setupUnitsObserver() } viewModelScope.launch { setupDisplayedUnitsObserver() } viewModelScope.launch { setupGeofenceObserver() } } private suspend fun setupUnitsObserver() { unitsController.displayedUnitsFlow.collect { units -> Log.d("UnitsViewModel", "Collecting units") this._displayedUnits.value = units } } private suspend fun setupDisplayedUnitsObserver() { unitsController.unitsFlow.collect { units -> Log.d("UnitsViewModel", "Collecting displayed units") this._units.value = units updateSelectedUnit() } } private suspend fun setupGeofenceObserver() { geofenceController.geofencesFlow.collect { Log.d("UnitsViewModel", "Collecting geofences") this._geofences.postValue(it) } } fun selectUnit(unit: UnitInformation?, switchToMap: Boolean = true) { Log.d("UnitsViewModel", "Selecting unit ${unit?.device?.name}") _oldSelectedUnit.postValue(_selectedUnit.value) _selectedUnit.postValue(unit) if (unit != null && switchToMap) { setDisplayMode(UnitsDisplayMode.MAP) } } fun selectUnitWithPositionId(id: Int?, switchToMap: Boolean = true) { if (id == null) { Log.d("UnitsViewModel", "Deselecting unit") selectUnit(null, switchToMap = switchToMap) return } Log.d("UnitsViewModel", "Selecting unit with position id: $id") val unit = _units.value?.find { it.position?.id == id } selectUnit(unit, switchToMap = switchToMap) } private fun selectUnitWithUnitId(id: Int?, switchToMap: Boolean = true) { if (id == null) { Log.d("UnitsViewModel", "Deselecting unit") selectUnit(null, switchToMap = switchToMap) return } Log.d("UnitsViewModel", "Selecting unit with device id: $id") val unit = _units.value?.find { it.device.id == id } selectUnit(unit, switchToMap = switchToMap) } private fun updateSelectedUnit() { selectedUnit.value?.let { selected -> Log.d("UnitsViewModel", "Updating selected unit with id: ${selected.device.id}") selectUnitWithUnitId(selected.device.id, switchToMap = false) } } fun setDisplayMode(displayMode: UnitsDisplayMode) { Log.d("UnitsViewModel", "Setting Display mode to $displayMode") _unitsDisplayMode.postValue(displayMode) } fun setMapLayerType(layer: MapLayer.Type) { _mapLayerType.postValue(layer) } fun toggleDisplayMode() { Log.d("UnitsViewModel", "Toggling Display mode") val newDisplayMode = if (unitsDisplayMode.value == UnitsDisplayMode.MAP) { _selectedUnit.postValue(null) UnitsDisplayMode.LIST } else { UnitsDisplayMode.MAP } _unitsDisplayMode.postValue(newDisplayMode) } fun search(query: String) { unitsController.search(query) } fun moveCamera(point: Camera) { _camera.postValue(point) } fun clearCamera() { _camera.postValue(null) } }