From e38960ff845bddbd463c43801ad01834f77474f2 Mon Sep 17 00:00:00 2001 From: Iván Ávalos Date: Mon, 17 Jan 2022 02:06:41 -0600 Subject: Implemented timer that fetches units every 10 seconds, and updated map to work with timer --- .../src/google/java/GoogleMainApplication.kt | 2 + .../src/google/java/ManagerMessagingService.kt | 2 + .../mx/trackermap/TrackerMap/android/TrackerApp.kt | 2 + .../TrackerMap/android/details/DetailsActivity.kt | 2 + .../android/details/UnitDetailsAdapter.kt | 2 + .../details/commands/UnitCommandsFragment.kt | 2 + .../details/information/UnitInformationFragment.kt | 2 + .../information/UnitInformationViewModel.kt | 2 + .../android/details/reports/UnitReportsFragment.kt | 2 + .../TrackerMap/android/devices/DevicesFragment.kt | 2 + .../TrackerMap/android/map/UnitMapFragment.kt | 13 ++++++- .../TrackerMap/android/session/LoginFragment.kt | 2 + .../android/session/UserInformationActivity.kt | 2 + .../TrackerMap/android/units/UnitFragment.kt | 3 +- .../TrackerMap/android/units/UnitsActivity.kt | 7 ++++ .../TrackerMap/android/units/UnitsViewModel.kt | 2 + androidApp/src/main/res/values-es-rMX/strings.xml | 1 + androidApp/src/main/res/values/strings.xml | 1 + .../TrackerMap/controllers/UnitsController.kt | 45 +++++++++++++++------- .../mx/trackermap/TrackerMap/utils/Coroutines.kt | 20 ++++++++++ 20 files changed, 99 insertions(+), 17 deletions(-) create mode 100644 shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/Coroutines.kt diff --git a/androidApp/src/google/java/GoogleMainApplication.kt b/androidApp/src/google/java/GoogleMainApplication.kt index 96062e1..e491b9f 100644 --- a/androidApp/src/google/java/GoogleMainApplication.kt +++ b/androidApp/src/google/java/GoogleMainApplication.kt @@ -26,8 +26,10 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager import com.google.firebase.messaging.FirebaseMessaging import kotlinx.coroutines.DelicateCoroutinesApi import mx.trackermap.TrackerMap.android.session.LoginFragment +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class GoogleMainApplication : TrackerApp() { override fun onCreate() { diff --git a/androidApp/src/google/java/ManagerMessagingService.kt b/androidApp/src/google/java/ManagerMessagingService.kt index b10475f..07ee427 100644 --- a/androidApp/src/google/java/ManagerMessagingService.kt +++ b/androidApp/src/google/java/ManagerMessagingService.kt @@ -25,8 +25,10 @@ import com.google.firebase.messaging.FirebaseMessagingService import com.google.firebase.messaging.RemoteMessage import kotlinx.coroutines.DelicateCoroutinesApi import mx.trackermap.TrackerMap.android.units.UnitsActivity +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class ManagerMessagingService : FirebaseMessagingService() { @SuppressLint("UnspecifiedImmutableFlag") diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt index b4a3411..1811733 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/TrackerApp.kt @@ -19,8 +19,10 @@ import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.core.context.startKoin import org.koin.core.logger.Level import org.koin.dsl.module +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime open class TrackerApp : Application() { override fun onCreate() { diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/DetailsActivity.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/DetailsActivity.kt index 7fd1203..56d5c4b 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/DetailsActivity.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/DetailsActivity.kt @@ -13,8 +13,10 @@ import kotlinx.coroutines.DelicateCoroutinesApi import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.android.databinding.DetailsActivityBinding import mx.trackermap.TrackerMap.android.shared.UnitRenderData +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class DetailsActivity : AppCompatActivity() { private var _binding: DetailsActivityBinding? = null diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/UnitDetailsAdapter.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/UnitDetailsAdapter.kt index 8987af1..cc2a7c2 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/UnitDetailsAdapter.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/UnitDetailsAdapter.kt @@ -8,8 +8,10 @@ import kotlinx.coroutines.DelicateCoroutinesApi import mx.trackermap.TrackerMap.android.details.commands.UnitCommandsFragment import mx.trackermap.TrackerMap.android.details.information.UnitInformationFragment import mx.trackermap.TrackerMap.android.details.reports.UnitReportsFragment +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class UnitDetailsAdapter( activity: FragmentActivity, private val deviceId: Int, diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt index 61a4e37..cd8d7af 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/commands/UnitCommandsFragment.kt @@ -16,8 +16,10 @@ import mx.trackermap.TrackerMap.android.databinding.UnitDetailsCommandsBinding import mx.trackermap.TrackerMap.android.details.UnitDetailsAdapter import mx.trackermap.TrackerMap.android.shared.MarkerTransformations import org.koin.androidx.viewmodel.ext.android.viewModel +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class UnitCommandsFragment: Fragment() { private var _binding: UnitDetailsCommandsBinding? = null private val binding get() = _binding!! diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationFragment.kt index e75f475..ab94547 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationFragment.kt @@ -24,8 +24,10 @@ import mx.trackermap.TrackerMap.client.models.UnitInformation import mx.trackermap.TrackerMap.utils.Formatter import mx.trackermap.TrackerMap.utils.SpeedUnit import org.koin.androidx.viewmodel.ext.android.viewModel +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class UnitInformationFragment : Fragment() { private var _binding: UnitDetailsInformationBinding? = null diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt index 4705c00..721fa68 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/information/UnitInformationViewModel.kt @@ -9,8 +9,10 @@ import kotlinx.coroutines.launch import mx.trackermap.TrackerMap.client.models.UnitInformation import mx.trackermap.TrackerMap.controllers.UnitsController import org.koin.core.component.KoinComponent +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class UnitInformationViewModel constructor( private val unitsController: UnitsController ) : ViewModel(), KoinComponent { diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt index 4c87b31..d3e008f 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/details/reports/UnitReportsFragment.kt @@ -32,8 +32,10 @@ import mx.trackermap.TrackerMap.utils.ReportDates import org.koin.androidx.viewmodel.ext.android.viewModel import java.lang.Exception import kotlin.math.max +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class UnitReportsFragment : Fragment() { private var _binding: UnitDetailsReportsBinding? = null diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesFragment.kt index 923feab..dce8ceb 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/devices/DevicesFragment.kt @@ -14,8 +14,10 @@ import mx.trackermap.TrackerMap.android.shared.UnitRenderData import mx.trackermap.TrackerMap.android.units.UnitFragment import mx.trackermap.TrackerMap.android.units.UnitsViewModel import mx.trackermap.TrackerMap.client.models.UnitInformation +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class DevicesFragment(private val unitsViewModel: UnitsViewModel) : UnitFragment(unitsViewModel) { private var _binding: DevicesFragmentBinding? = null diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt index 0658f56..3ab25e4 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt @@ -6,6 +6,7 @@ import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.Toast import androidx.core.text.HtmlCompat import kotlinx.coroutines.DelicateCoroutinesApi import mx.trackermap.TrackerMap.android.R @@ -17,14 +18,18 @@ import mx.trackermap.TrackerMap.android.units.UnitFragment import mx.trackermap.TrackerMap.android.units.UnitsViewModel import mx.trackermap.TrackerMap.client.models.MapLayer import mx.trackermap.TrackerMap.client.models.UnitInformation +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class UnitMapFragment(private val unitsViewModel: UnitsViewModel) : UnitFragment(unitsViewModel) { private var _binding: UnitMapFragmentBinding? = null private val binding get() = _binding!! private lateinit var unitsMapFragment: MapFragment + private var shouldCenter = true + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -53,6 +58,7 @@ class UnitMapFragment(private val unitsViewModel: UnitsViewModel) : UnitFragment } private fun initializeMap() { + shouldCenter = true unitsMapFragment = childFragmentManager.findFragmentById(R.id.unitsMap) as MapFragment unitsMapFragment.markerCallback = unitsViewModel::selectUnitWith @@ -65,11 +71,14 @@ class UnitMapFragment(private val unitsViewModel: UnitsViewModel) : UnitFragment unitsViewModel.units.observe(viewLifecycleOwner) { units -> Log.d("UnitMapFragment", "Available units: $units") - unitsMapFragment.display( units.mapNotNull(MarkerTransformations::unitToMarker).toTypedArray(), - isReport = false + isReport = false, + center = shouldCenter ) + if (units.isNotEmpty()) { + shouldCenter = false + } } unitsViewModel.selectedUnit.observe(viewLifecycleOwner) { selectedUnit -> diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt index f48eb93..f1b23a6 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/LoginFragment.kt @@ -18,8 +18,10 @@ import mx.trackermap.TrackerMap.android.databinding.LoginBinding import mx.trackermap.TrackerMap.android.units.UnitsActivity import mx.trackermap.TrackerMap.controllers.SessionController import org.koin.androidx.viewmodel.ext.android.viewModel +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class LoginFragment : Fragment() { private var _binding: LoginBinding? = null private val binding get() = _binding!! diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationActivity.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationActivity.kt index dababb5..5fad118 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationActivity.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/session/UserInformationActivity.kt @@ -14,8 +14,10 @@ import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.android.databinding.UserInformationActivityBinding import mx.trackermap.TrackerMap.controllers.SessionController import org.koin.androidx.viewmodel.ext.android.viewModel +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class UserInformationActivity : AppCompatActivity() { private var _binding: UserInformationActivityBinding? = null diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitFragment.kt index ab3afc1..e514094 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitFragment.kt @@ -2,7 +2,8 @@ package mx.trackermap.TrackerMap.android.units import androidx.fragment.app.Fragment import kotlinx.coroutines.DelicateCoroutinesApi +import kotlin.time.ExperimentalTime -open class UnitFragment @DelicateCoroutinesApi constructor( +open class UnitFragment @DelicateCoroutinesApi @ExperimentalTime constructor( private val unitsViewModel: UnitsViewModel ) : Fragment() \ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt index e9b9010..30e34b3 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt @@ -6,6 +6,7 @@ import android.os.Bundle import android.util.Log import android.view.View import android.view.inputmethod.InputMethodManager +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.TooltipCompat @@ -20,8 +21,10 @@ import mx.trackermap.TrackerMap.android.map.UnitMapFragment import mx.trackermap.TrackerMap.android.session.UserInformationActivity import mx.trackermap.TrackerMap.client.models.MapLayer import org.koin.androidx.viewmodel.ext.android.viewModel +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class UnitsActivity : AppCompatActivity() { private var _binding: UnitsActivityBinding? = null @@ -115,6 +118,9 @@ class UnitsActivity : AppCompatActivity() { } private fun setupObservers() { + unitsViewModel.units.observe(this) { + Toast.makeText(this, getString(R.string.shared_loading), Toast.LENGTH_SHORT).show() + } unitsViewModel.unitsDisplayMode.observe(this) { displayMode -> binding.displayModeToggle.setImageResource( when (displayMode) { @@ -162,6 +168,7 @@ class UnitsActivity : AppCompatActivity() { } private fun removeObservers() { + unitsViewModel.units.removeObservers(this) unitsViewModel.unitsDisplayMode.removeObservers(this) unitsViewModel.selectedUnit.removeObservers(this) } diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt index 2d2994b..efa5781 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsViewModel.kt @@ -12,8 +12,10 @@ 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 { diff --git a/androidApp/src/main/res/values-es-rMX/strings.xml b/androidApp/src/main/res/values-es-rMX/strings.xml index 6b2bd11..739023b 100644 --- a/androidApp/src/main/res/values-es-rMX/strings.xml +++ b/androidApp/src/main/res/values-es-rMX/strings.xml @@ -5,6 +5,7 @@ Cancelar Cerrar Enviar + Cargando Nombre de usuario diff --git a/androidApp/src/main/res/values/strings.xml b/androidApp/src/main/res/values/strings.xml index 31c0ed4..babb741 100644 --- a/androidApp/src/main/res/values/strings.xml +++ b/androidApp/src/main/res/values/strings.xml @@ -18,6 +18,7 @@ Cancel Close Send + Loading Username diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/UnitsController.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/UnitsController.kt index 584f656..21692e7 100644 --- a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/UnitsController.kt +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/controllers/UnitsController.kt @@ -1,17 +1,23 @@ package mx.trackermap.TrackerMap.controllers +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.* import kotlinx.coroutines.launch import mx.trackermap.TrackerMap.client.apis.DevicesApi import mx.trackermap.TrackerMap.client.apis.PositionsApi import mx.trackermap.TrackerMap.client.models.Position import mx.trackermap.TrackerMap.client.models.UnitInformation +import mx.trackermap.TrackerMap.utils.Coroutines +import kotlin.time.Duration.Companion.seconds +import kotlin.time.ExperimentalTime @DelicateCoroutinesApi +@ExperimentalTime class UnitsController( private val devicesApi: DevicesApi, private val positionsApi: PositionsApi @@ -23,28 +29,39 @@ class UnitsController( init { GlobalScope.launch { - fetchUnits() + fetchUnits(this) } GlobalScope.launch { setupFlows() } } - private suspend fun fetchUnits() { - val devices = devicesApi.devicesGet() - val positions = positionsApi.positionsGet() - val positionsMap: MutableMap = mutableMapOf() - - positions.forEach { position -> - position.deviceId?.let { - positionsMap[it] = position + private suspend fun fetchUnits(scope: CoroutineScope) { + Coroutines.tickerFlow(10.seconds) + .map { + print("Fetching new positions...\n") + positionsApi.positionsGet() } - } + .distinctUntilChanged { old, new -> + old.contentEquals(new) + } + .onEach { positions -> + print("Position(s) changed! Reloading data...\n") + val devices = devicesApi.devicesGet() + val positionsMap: MutableMap = mutableMapOf() - val units = devices.map { - UnitInformation(it, positionsMap[it.id]) - } - unitsFlow.value = units + positions.forEach { position -> + position.deviceId?.let { + positionsMap[it] = position + } + } + + val units = devices.map { + UnitInformation(it, positionsMap[it.id]) + } + unitsFlow.value = units + } + .launchIn(scope) } fun search(query: String) { diff --git a/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/Coroutines.kt b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/Coroutines.kt new file mode 100644 index 0000000..c953887 --- /dev/null +++ b/shared/src/commonMain/kotlin/mx/trackermap/TrackerMap/utils/Coroutines.kt @@ -0,0 +1,20 @@ +package mx.trackermap.TrackerMap.utils + +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.flow +import kotlin.time.Duration +import kotlin.time.ExperimentalTime + +class Coroutines { + companion object { + // Source: https://stackoverflow.com/questions/54827455/how-to-implement-timer-with-kotlin-coroutines/54828055#54828055 + @ExperimentalTime + fun tickerFlow(period: Duration, initialDelay: Duration = Duration.ZERO) = flow { + delay(initialDelay) + while (true) { + emit(Unit) + delay(period) + } + } + } +} \ No newline at end of file -- cgit v1.2.3