refactor: Conducting time filter at the component lvl to avoid metric nav cards from being disabled when we don't have recent data (#1402)

This commit is contained in:
Robert-0410 2024-11-13 02:24:40 -08:00 committed by GitHub
parent f6af9b8782
commit 013e3de792
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 54 additions and 50 deletions

View file

@ -20,11 +20,9 @@ import com.geeksville.mesh.database.entity.MeshLog
import com.geeksville.mesh.repository.datastore.RadioConfigRepository
import com.geeksville.mesh.ui.Route
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update
@ -35,6 +33,7 @@ import java.io.FileNotFoundException
import java.io.FileWriter
import java.text.SimpleDateFormat
import java.util.Locale
import java.util.concurrent.TimeUnit
import javax.inject.Inject
data class MetricsState(
@ -54,6 +53,21 @@ data class MetricsState(
fun hasTracerouteLogs() = tracerouteRequests.isNotEmpty()
fun hasPositionLogs() = positionLogs.isNotEmpty()
fun deviceMetricsFiltered(timeFrame: TimeFrame): List<Telemetry> {
val oldestTime = timeFrame.calculateOldestTime()
return deviceMetrics.filter { it.time >= oldestTime }
}
fun environmentMetricsFiltered(timeFrame: TimeFrame): List<Telemetry> {
val oldestTime = timeFrame.calculateOldestTime()
return environmentMetrics.filter { it.time >= oldestTime }
}
fun signalMetricsFiltered(timeFrame: TimeFrame): List<MeshPacket> {
val oldestTime = timeFrame.calculateOldestTime()
return signalMetrics.filter { it.rxTime >= oldestTime }
}
companion object {
val Empty = MetricsState()
}
@ -64,20 +78,20 @@ data class MetricsState(
*/
@Suppress("MagicNumber")
enum class TimeFrame(
val milliseconds: Long,
val seconds: Long,
@StringRes val strRes: Int
) {
TWENTY_FOUR_HOURS(86400000L, R.string.twenty_four_hours),
FORTY_EIGHT_HOURS(172800000L, R.string.forty_eight_hours),
ONE_WEEK(604800000L, R.string.one_week),
TWO_WEEKS(1209600000L, R.string.two_weeks),
ONE_MONTH(2629800000L, R.string.one_month),
TWENTY_FOUR_HOURS(TimeUnit.DAYS.toSeconds(1), R.string.twenty_four_hours),
FORTY_EIGHT_HOURS(TimeUnit.DAYS.toSeconds(2), R.string.forty_eight_hours),
ONE_WEEK(TimeUnit.DAYS.toSeconds(7), R.string.one_week),
TWO_WEEKS(TimeUnit.DAYS.toSeconds(14), R.string.two_weeks),
FOUR_WEEKS(TimeUnit.DAYS.toSeconds(28), R.string.four_weeks),
MAX(0L, R.string.max);
fun calculateOldestTime(): Long = if (this == MAX) {
MAX.milliseconds
MAX.seconds
} else {
System.currentTimeMillis() - this.milliseconds
System.currentTimeMillis() / 1000 - this.seconds
}
}
@ -131,27 +145,20 @@ class MetricsViewModel @Inject constructor(
}
}.launchIn(viewModelScope)
@OptIn(ExperimentalCoroutinesApi::class)
_timeFrame.flatMapLatest { timeFrame ->
meshLogRepository.getTelemetryFrom(destNum, timeFrame.calculateOldestTime()).onEach { telemetry ->
_state.update { state ->
state.copy(
deviceMetrics = telemetry.filter { it.hasDeviceMetrics() },
environmentMetrics = telemetry.filter {
it.hasEnvironmentMetrics() && it.environmentMetrics.relativeHumidity >= 0f
},
)
}
meshLogRepository.getTelemetryFrom(destNum).onEach { telemetry ->
_state.update { state ->
state.copy(
deviceMetrics = telemetry.filter { it.hasDeviceMetrics() },
environmentMetrics = telemetry.filter {
it.hasEnvironmentMetrics() && it.environmentMetrics.relativeHumidity >= 0f
}
)
}
}.launchIn(viewModelScope)
@OptIn(ExperimentalCoroutinesApi::class)
_timeFrame.flatMapLatest { timeFrame ->
val oldestTime = timeFrame.calculateOldestTime()
meshLogRepository.getMeshPacketsFrom(destNum, oldestTime = oldestTime).onEach { meshPackets ->
_state.update { state ->
state.copy(signalMetrics = meshPackets.filter { it.hasValidSignal() })
}
meshLogRepository.getMeshPacketsFrom(destNum).onEach { meshPackets ->
_state.update { state ->
state.copy(signalMetrics = meshPackets.filter { it.hasValidSignal() })
}
}.launchIn(viewModelScope)