mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor: add custom formatting to LocalStats fields
This commit is contained in:
parent
1219d3037e
commit
6230f13bff
4 changed files with 90 additions and 67 deletions
|
|
@ -29,12 +29,24 @@ import androidx.lifecycle.MutableLiveData
|
|||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.geeksville.mesh.*
|
||||
import com.geeksville.mesh.AppOnlyProtos
|
||||
import com.geeksville.mesh.ChannelProtos
|
||||
import com.geeksville.mesh.ChannelProtos.ChannelSettings
|
||||
import com.geeksville.mesh.ConfigProtos.Config
|
||||
import com.geeksville.mesh.DataPacket
|
||||
import com.geeksville.mesh.IMeshService
|
||||
import com.geeksville.mesh.LocalOnlyProtos.LocalConfig
|
||||
import com.geeksville.mesh.LocalOnlyProtos.LocalModuleConfig
|
||||
import com.geeksville.mesh.MeshProtos
|
||||
import com.geeksville.mesh.Portnums
|
||||
import com.geeksville.mesh.Position
|
||||
import com.geeksville.mesh.R
|
||||
import com.geeksville.mesh.android.Logging
|
||||
import com.geeksville.mesh.channel
|
||||
import com.geeksville.mesh.channelSet
|
||||
import com.geeksville.mesh.channelSettings
|
||||
import com.geeksville.mesh.config
|
||||
import com.geeksville.mesh.copy
|
||||
import com.geeksville.mesh.database.MeshLogRepository
|
||||
import com.geeksville.mesh.database.PacketRepository
|
||||
import com.geeksville.mesh.database.QuickChatActionRepository
|
||||
|
|
@ -47,6 +59,8 @@ import com.geeksville.mesh.repository.radio.RadioInterfaceService
|
|||
import com.geeksville.mesh.service.MeshService
|
||||
import com.geeksville.mesh.service.ServiceAction
|
||||
import com.geeksville.mesh.ui.map.MAP_STYLE_ID
|
||||
import com.geeksville.mesh.util.getShortDate
|
||||
import com.geeksville.mesh.util.getShortDateTime
|
||||
import com.geeksville.mesh.util.positionToMeter
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -67,11 +81,8 @@ import kotlinx.coroutines.withContext
|
|||
import java.io.BufferedWriter
|
||||
import java.io.FileNotFoundException
|
||||
import java.io.FileWriter
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
|
|
@ -150,30 +161,6 @@ data class Contact(
|
|||
val isMuted: Boolean,
|
||||
)
|
||||
|
||||
// return time if within 24 hours, otherwise date
|
||||
private fun getShortDate(time: Long): String? {
|
||||
val date = if (time != 0L) Date(time) else return null
|
||||
val isWithin24Hours = System.currentTimeMillis() - date.time <= TimeUnit.DAYS.toMillis(1)
|
||||
|
||||
return if (isWithin24Hours) {
|
||||
DateFormat.getTimeInstance(DateFormat.SHORT).format(date)
|
||||
} else {
|
||||
DateFormat.getDateInstance(DateFormat.SHORT).format(date)
|
||||
}
|
||||
}
|
||||
|
||||
// return time if within 24 hours, otherwise date/time
|
||||
private fun getShortDateTime(time: Long): String {
|
||||
val date = Date(time)
|
||||
val isWithin24Hours = System.currentTimeMillis() - date.time <= TimeUnit.DAYS.toMillis(1)
|
||||
|
||||
return if (isWithin24Hours) {
|
||||
DateFormat.getTimeInstance(DateFormat.SHORT).format(date)
|
||||
} else {
|
||||
DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(date)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("LongParameterList")
|
||||
@HiltViewModel
|
||||
class UIViewModel @Inject constructor(
|
||||
|
|
|
|||
|
|
@ -36,9 +36,7 @@ import com.geeksville.mesh.TelemetryProtos.LocalStats
|
|||
import com.geeksville.mesh.android.notificationManager
|
||||
import com.geeksville.mesh.database.entity.NodeEntity
|
||||
import com.geeksville.mesh.util.PendingIntentCompat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import com.geeksville.mesh.util.formatUptime
|
||||
|
||||
@Suppress("TooManyFunctions")
|
||||
class MeshServiceNotifications(
|
||||
|
|
@ -150,37 +148,29 @@ class MeshServiceNotifications(
|
|||
}
|
||||
}
|
||||
|
||||
private fun formatStatsString(stats: LocalStats?, currentStatsUpdatedAtMillis: Long?): String {
|
||||
val updatedAt = "Next update at: ${
|
||||
currentStatsUpdatedAtMillis?.let {
|
||||
val date = Date(it + FIFTEEN_MINUTES_IN_MILLIS) // Add 15 minutes in milliseconds
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||
dateFormat.format(date)
|
||||
} ?: "???"
|
||||
}"
|
||||
val statsJoined = stats?.allFields?.mapNotNull { (k, v) ->
|
||||
if (k.name == "num_online_nodes" || k.name == "num_total_nodes") {
|
||||
return@mapNotNull null
|
||||
}
|
||||
"${
|
||||
private fun LocalStats?.formatToString(): String = this?.allFields?.mapNotNull { (k, v) ->
|
||||
when (k.name) {
|
||||
"num_online_nodes", "num_total_nodes" -> return@mapNotNull null
|
||||
"uptime_seconds" -> "Uptime: ${formatUptime(v as Int)}"
|
||||
"channel_utilization" -> "ChUtil: %.2f%%".format(v)
|
||||
"air_util_tx" -> "AirUtilTX: %.2f%%".format(v)
|
||||
else -> "${
|
||||
k.name.replace('_', ' ').split(" ")
|
||||
.joinToString(" ") { it.replaceFirstChar { char -> char.uppercase() } }
|
||||
}=$v"
|
||||
}?.joinToString("\n") ?: "No Local Stats"
|
||||
return "$updatedAt\n$statsJoined"
|
||||
}
|
||||
}: $v"
|
||||
}
|
||||
}?.joinToString("\n") ?: "No Local Stats"
|
||||
|
||||
fun updateServiceStateNotification(
|
||||
summaryString: String? = null,
|
||||
localStats: LocalStats? = null,
|
||||
currentStatsUpdatedAtMillis: Long? = null,
|
||||
) {
|
||||
val statsString = formatStatsString(localStats, currentStatsUpdatedAtMillis)
|
||||
notificationManager.notify(
|
||||
notifyId,
|
||||
createServiceStateNotification(
|
||||
name = summaryString.orEmpty(),
|
||||
message = statsString,
|
||||
message = localStats.formatToString(),
|
||||
nextUpdateAt = currentStatsUpdatedAtMillis?.plus(FIFTEEN_MINUTES_IN_MILLIS)
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ import com.geeksville.mesh.ui.preview.NodeEntityPreviewParameterProvider
|
|||
import com.geeksville.mesh.ui.theme.AppTheme
|
||||
import com.geeksville.mesh.util.DistanceUnit
|
||||
import com.geeksville.mesh.util.formatAgo
|
||||
import com.geeksville.mesh.util.formatUptime
|
||||
import com.geeksville.mesh.util.thenIf
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.math.ln
|
||||
|
||||
@Composable
|
||||
|
|
@ -349,22 +349,6 @@ private fun InfoCard(
|
|||
}
|
||||
}
|
||||
|
||||
private fun formatUptime(seconds: Int): String = formatUptime(seconds.toLong())
|
||||
|
||||
private fun formatUptime(seconds: Long): String {
|
||||
val days = TimeUnit.SECONDS.toDays(seconds)
|
||||
val hours = TimeUnit.SECONDS.toHours(seconds) % TimeUnit.DAYS.toHours(1)
|
||||
val minutes = TimeUnit.SECONDS.toMinutes(seconds) % TimeUnit.HOURS.toMinutes(1)
|
||||
val secs = seconds % TimeUnit.MINUTES.toSeconds(1)
|
||||
|
||||
return listOfNotNull(
|
||||
"${days}d".takeIf { days > 0 },
|
||||
"${hours}h".takeIf { hours > 0 },
|
||||
"${minutes}m".takeIf { minutes > 0 },
|
||||
"${secs}s".takeIf { secs > 0 },
|
||||
).joinToString(" ")
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Suppress("LongMethod", "CyclomaticComplexMethod")
|
||||
@Composable
|
||||
|
|
|
|||
62
app/src/main/java/com/geeksville/mesh/util/DateTimeUtils.kt
Normal file
62
app/src/main/java/com/geeksville/mesh/util/DateTimeUtils.kt
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2024 Meshtastic LLC
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.geeksville.mesh.util
|
||||
|
||||
import java.text.DateFormat
|
||||
import java.util.Date
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
// return time if within 24 hours, otherwise date
|
||||
fun getShortDate(time: Long): String? {
|
||||
val date = if (time != 0L) Date(time) else return null
|
||||
val isWithin24Hours = System.currentTimeMillis() - date.time <= TimeUnit.DAYS.toMillis(1)
|
||||
|
||||
return if (isWithin24Hours) {
|
||||
DateFormat.getTimeInstance(DateFormat.SHORT).format(date)
|
||||
} else {
|
||||
DateFormat.getDateInstance(DateFormat.SHORT).format(date)
|
||||
}
|
||||
}
|
||||
|
||||
// return time if within 24 hours, otherwise date/time
|
||||
fun getShortDateTime(time: Long): String {
|
||||
val date = Date(time)
|
||||
val isWithin24Hours = System.currentTimeMillis() - date.time <= TimeUnit.DAYS.toMillis(1)
|
||||
|
||||
return if (isWithin24Hours) {
|
||||
DateFormat.getTimeInstance(DateFormat.SHORT).format(date)
|
||||
} else {
|
||||
DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT).format(date)
|
||||
}
|
||||
}
|
||||
|
||||
fun formatUptime(seconds: Int): String = formatUptime(seconds.toLong())
|
||||
|
||||
private fun formatUptime(seconds: Long): String {
|
||||
val days = TimeUnit.SECONDS.toDays(seconds)
|
||||
val hours = TimeUnit.SECONDS.toHours(seconds) % TimeUnit.DAYS.toHours(1)
|
||||
val minutes = TimeUnit.SECONDS.toMinutes(seconds) % TimeUnit.HOURS.toMinutes(1)
|
||||
val secs = seconds % TimeUnit.MINUTES.toSeconds(1)
|
||||
|
||||
return listOfNotNull(
|
||||
"${days}d".takeIf { days > 0 },
|
||||
"${hours}h".takeIf { hours > 0 },
|
||||
"${minutes}m".takeIf { minutes > 0 },
|
||||
"${secs}s".takeIf { secs > 0 },
|
||||
).joinToString(" ")
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue