mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-05-24 23:01:22 -04:00
style(car): align visual patterns with main app design system
- Rename SignalQuality enum to match core: POOR→BAD, UNKNOWN→NONE - Add last heard time to node list subtitles (was only in detail view) - Add message timestamps in conversation view - Align string resources with core terminology (bad/none vs poor/unknown) - Use DateFormatter.formatRelativeTime() consistently across all screens Ensures car experience uses consistent terminology and information density with the main Meshtastic app. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -61,8 +61,8 @@ enum class SignalQuality {
|
||||
EXCELLENT,
|
||||
GOOD,
|
||||
FAIR,
|
||||
POOR,
|
||||
UNKNOWN,
|
||||
BAD,
|
||||
NONE,
|
||||
}
|
||||
|
||||
data class TopologyHeader(val totalNodes: Int, val onlineNodes: Int, val meshName: String?)
|
||||
|
||||
@@ -25,6 +25,7 @@ import androidx.car.app.model.ItemList
|
||||
import androidx.car.app.model.ListTemplate
|
||||
import androidx.car.app.model.Row
|
||||
import androidx.car.app.model.Template
|
||||
import org.meshtastic.core.common.util.DateFormatter
|
||||
import org.meshtastic.feature.car.R
|
||||
import org.meshtastic.feature.car.service.MessageSnapshot
|
||||
|
||||
@@ -42,7 +43,13 @@ class ConversationScreen(
|
||||
|
||||
val listBuilder = ItemList.Builder()
|
||||
messages.forEach { msg ->
|
||||
listBuilder.addItem(Row.Builder().setTitle(msg.senderName).addText(msg.text).build())
|
||||
val timeText =
|
||||
if (msg.timestamp != 0L) {
|
||||
" • ${DateFormatter.formatRelativeTime(msg.timestamp)}"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
listBuilder.addItem(Row.Builder().setTitle(msg.senderName).addText("${msg.text}$timeText").build())
|
||||
}
|
||||
|
||||
val actionStrip =
|
||||
|
||||
@@ -39,6 +39,7 @@ import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.cancel
|
||||
import kotlinx.coroutines.flow.firstOrNull
|
||||
import kotlinx.coroutines.launch
|
||||
import org.meshtastic.core.common.util.DateFormatter
|
||||
import org.meshtastic.core.model.ConnectionState
|
||||
import org.meshtastic.feature.car.R
|
||||
import org.meshtastic.feature.car.model.NodeUi
|
||||
@@ -197,12 +198,18 @@ class HomeScreen(carContext: CarContext, private val stateCoordinator: CarStateC
|
||||
SignalQuality.EXCELLENT -> carContext.getString(R.string.car_signal_excellent)
|
||||
SignalQuality.GOOD -> carContext.getString(R.string.car_signal_good)
|
||||
SignalQuality.FAIR -> carContext.getString(R.string.car_signal_fair)
|
||||
SignalQuality.POOR -> carContext.getString(R.string.car_signal_poor)
|
||||
SignalQuality.UNKNOWN -> carContext.getString(R.string.car_signal_unknown)
|
||||
SignalQuality.BAD -> carContext.getString(R.string.car_signal_bad)
|
||||
SignalQuality.NONE -> carContext.getString(R.string.car_signal_none)
|
||||
}
|
||||
val battery = node.batteryPercent?.let { " • $it%" } ?: ""
|
||||
val lastHeard =
|
||||
if (node.lastHeard != 0L) {
|
||||
" • ${DateFormatter.formatRelativeTime(node.lastHeard)}"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
val status = if (!node.isOnline) " • ${carContext.getString(R.string.car_status_offline)}" else ""
|
||||
return "$signal$battery$status"
|
||||
return "$signal$battery$lastHeard$status"
|
||||
}
|
||||
|
||||
private fun buildDisconnectedTemplate(): Template = PaneTemplate.Builder(
|
||||
|
||||
@@ -26,6 +26,7 @@ import androidx.car.app.model.ListTemplate
|
||||
import androidx.car.app.model.Row
|
||||
import androidx.car.app.model.Template
|
||||
import androidx.core.graphics.drawable.IconCompat
|
||||
import org.meshtastic.core.common.util.DateFormatter
|
||||
import org.meshtastic.feature.car.R
|
||||
import org.meshtastic.feature.car.model.NodeDashboardUiState
|
||||
import org.meshtastic.feature.car.model.NodeUi
|
||||
@@ -86,11 +87,17 @@ class NodeDashboardScreen(
|
||||
SignalQuality.EXCELLENT -> carContext.getString(R.string.car_signal_excellent)
|
||||
SignalQuality.GOOD -> carContext.getString(R.string.car_signal_good)
|
||||
SignalQuality.FAIR -> carContext.getString(R.string.car_signal_fair)
|
||||
SignalQuality.POOR -> carContext.getString(R.string.car_signal_poor)
|
||||
SignalQuality.UNKNOWN -> carContext.getString(R.string.car_signal_unknown)
|
||||
SignalQuality.BAD -> carContext.getString(R.string.car_signal_bad)
|
||||
SignalQuality.NONE -> carContext.getString(R.string.car_signal_none)
|
||||
}
|
||||
val battery = node.batteryPercent?.let { " • $it%" } ?: ""
|
||||
val lastHeard =
|
||||
if (node.lastHeard != 0L) {
|
||||
" • ${DateFormatter.formatRelativeTime(node.lastHeard)}"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
val status = if (!node.isOnline) " • ${carContext.getString(R.string.car_status_offline)}" else ""
|
||||
return "$signal$battery$status"
|
||||
return "$signal$battery$lastHeard$status"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,8 +102,8 @@ class NodeDetailScreen(
|
||||
SignalQuality.EXCELLENT -> carContext.getString(R.string.car_signal_excellent)
|
||||
SignalQuality.GOOD -> carContext.getString(R.string.car_signal_good)
|
||||
SignalQuality.FAIR -> carContext.getString(R.string.car_signal_fair)
|
||||
SignalQuality.POOR -> carContext.getString(R.string.car_signal_poor)
|
||||
SignalQuality.UNKNOWN -> carContext.getString(R.string.car_signal_unknown)
|
||||
SignalQuality.BAD -> carContext.getString(R.string.car_signal_bad)
|
||||
SignalQuality.NONE -> carContext.getString(R.string.car_signal_none)
|
||||
}
|
||||
|
||||
private fun formatLastHeard(epochMillis: Long): String {
|
||||
|
||||
@@ -288,12 +288,12 @@ class CarStateCoordinator(
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun determineSignalQuality(snr: Float, rssi: Int): SignalQuality = when {
|
||||
snr == Float.MAX_VALUE || rssi == Int.MAX_VALUE -> SignalQuality.UNKNOWN
|
||||
snr == Float.MAX_VALUE || rssi == Int.MAX_VALUE -> SignalQuality.NONE
|
||||
snr > SNR_GOOD_THRESHOLD && rssi > RSSI_GOOD_THRESHOLD -> SignalQuality.EXCELLENT
|
||||
snr > SNR_GOOD_THRESHOLD && rssi > RSSI_FAIR_THRESHOLD -> SignalQuality.GOOD
|
||||
snr > SNR_FAIR_THRESHOLD && rssi > RSSI_GOOD_THRESHOLD -> SignalQuality.GOOD
|
||||
snr > SNR_FAIR_THRESHOLD -> SignalQuality.FAIR
|
||||
else -> SignalQuality.POOR
|
||||
else -> SignalQuality.BAD
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@
|
||||
<string name="car_reconnecting">Radio connection lost. Will reconnect automatically.</string>
|
||||
<string name="car_reconnecting_title">Reconnecting…</string>
|
||||
<string name="car_reconnecting_body">The app will automatically reconnect when the radio is available.</string>
|
||||
<string name="car_signal_bad">Bad</string>
|
||||
<string name="car_signal_excellent">Excellent</string>
|
||||
<string name="car_signal_fair">Fair</string>
|
||||
<string name="car_signal_good">Good</string>
|
||||
<string name="car_signal_poor">Poor</string>
|
||||
<string name="car_signal_unknown">Unknown</string>
|
||||
<string name="car_signal_none">None</string>
|
||||
<string name="car_status_battery">Battery</string>
|
||||
<string name="car_status_last_heard">Last Heard</string>
|
||||
<string name="car_status_offline">Offline</string>
|
||||
|
||||
Reference in New Issue
Block a user