From 225889ad947bf44b1b0955e3345764fd8d64755e Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Fri, 24 Apr 2026 19:25:51 -0500
Subject: [PATCH 1/7] chore(deps): update core/proto/src/main/proto digest to
249a808 (#5239)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
core/proto/src/main/proto | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/core/proto/src/main/proto b/core/proto/src/main/proto
index 97ea65a10..249a80855 160000
--- a/core/proto/src/main/proto
+++ b/core/proto/src/main/proto
@@ -1 +1 @@
-Subproject commit 97ea65a10d31f24d84c8510342f2cd2d213c35a5
+Subproject commit 249a80855a2adb76fb0904dac8bf6285d45f330f
From 9100c583b6b67afd55fcd0e5217a56702e63aff0 Mon Sep 17 00:00:00 2001
From: James Rich <2199651+jamesarich@users.noreply.github.com>
Date: Sat, 25 Apr 2026 11:14:29 -0500
Subject: [PATCH 2/7] chore: Scheduled updates (Firmware, Hardware,
Translations, Graphs) (#5241)
Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com>
---
.../composeResources/values-de/strings.xml | 13 +++++++++++++
.../composeResources/values-el/strings.xml | 2 ++
.../composeResources/values-uk/strings.xml | 16 ++++++++++++++--
3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/core/resources/src/commonMain/composeResources/values-de/strings.xml b/core/resources/src/commonMain/composeResources/values-de/strings.xml
index 6bafa634e..1080557d5 100644
--- a/core/resources/src/commonMain/composeResources/values-de/strings.xml
+++ b/core/resources/src/commonMain/composeResources/values-de/strings.xml
@@ -794,6 +794,8 @@
Host Kennzahlen
Benutzerzählerdaten
Metadaten
+ Sitzung aktiv
+ Knoten nicht erreichbar - erneut versuchen oder Standort wechseln.
Erneut versuchen
Aktionen
Firmware
@@ -905,10 +907,21 @@
Firmware-Version
Kürzliche Netzwerkgeräte
Entdeckte Netzwerkgeräte
+ Suche nach Netzwerkgeräten
Suche...
+ Suche nach Bluetoothgeräten
Suche...
Verfügbare Bluetooth Geräte
+ Keine Geräte gefunden
+ Keine Bluetoothgeräte gefunden
+ Stelle sicher, daß Du in der Reichweite des Gerätes bist.
+ Kein Netzwerkgerät gefunden
+ Stelle sicher, daß Du im selben Netzwerk bist wie das Gerät.
+ Kein USB-Gerät gefunden
+ Verbinde das Gerät über den seriellen Anschluß oder USB.
Kein Gerät verbunden
+ Suche nach Knoten
+ Knoten in der Nähe erscheinen hier, sobald sie erreicht wurden.
Erste Schritte
Willkommen bei
Bleibe überall in Verbindung
diff --git a/core/resources/src/commonMain/composeResources/values-el/strings.xml b/core/resources/src/commonMain/composeResources/values-el/strings.xml
index caf6e271b..e55e029a2 100644
--- a/core/resources/src/commonMain/composeResources/values-el/strings.xml
+++ b/core/resources/src/commonMain/composeResources/values-el/strings.xml
@@ -25,6 +25,8 @@
μέσω MQTT
Αναμονή για αναγνώριση
Λήξη χρονικού ορίου
+ Max. Anzahl Wiederholungen erreicht
+ Kein Kanal
Εσφαλμένο Αίτημα
Άγνωστο Δημόσιο Κλειδί
diff --git a/core/resources/src/commonMain/composeResources/values-uk/strings.xml b/core/resources/src/commonMain/composeResources/values-uk/strings.xml
index 6f9fc58ac..bff9ccb49 100644
--- a/core/resources/src/commonMain/composeResources/values-uk/strings.xml
+++ b/core/resources/src/commonMain/composeResources/values-uk/strings.xml
@@ -805,7 +805,7 @@
Показники Pax
Метадані
Оновити метаданні
- Сессія активна
+ Сесія активна
Повторити
Дії
Прошивка
@@ -981,7 +981,7 @@
Невстановлене - 0
- Пройшло через %1$d вузол
- - Пройшло через %1$d вузлів
+ - Пройшло через %1$d вузли
- Пройшло через %1$d вузлів
- Пройшло через %1$d вузли
@@ -1046,6 +1046,18 @@
Назад
Скинути
Завжди увімк.
+
+ - %1$d секунда
+ - %1$d секунд
+ - %1$d секунд
+ - %1$d секунд
+
+
+ - %1$d хвилина
+ - %1$d хвилин
+ - %1$d хвилин
+ - %1$d хвилин
+
- %1$d година
- %1$d години
From fb1092e3c70f6ed142967af5463a0aabc09bfa85 Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Sat, 25 Apr 2026 11:14:36 -0500
Subject: [PATCH 3/7] chore(deps): update io.nlopez.compose.rules:detekt to
v0.5.8 (#5242)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index f22520a13..47d9605ae 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -249,7 +249,7 @@ androidx-room-gradlePlugin = { module = "androidx.room3:room3-gradle-plugin", ve
compose-gradlePlugin = { module = "org.jetbrains.kotlin:compose-compiler-gradle-plugin", version.ref = "kotlin" }
compose-multiplatform-gradlePlugin = { module = "org.jetbrains.compose:compose-gradle-plugin", version.ref = "compose-multiplatform" }
datadog-gradlePlugin = { module = "com.datadoghq.dd-sdk-android-gradle-plugin:com.datadoghq.dd-sdk-android-gradle-plugin.gradle.plugin", version.ref = "datadog-gradle" }
-detekt-compose = { module = "io.nlopez.compose.rules:detekt", version = "0.5.7" }
+detekt-compose = { module = "io.nlopez.compose.rules:detekt", version = "0.5.8" }
detekt-formatting = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
detekt-gradlePlugin = { module = "io.gitlab.arturbosch.detekt:detekt-gradle-plugin", version.ref = "detekt" }
firebase-crashlytics-gradlePlugin = { module = "com.google.firebase:firebase-crashlytics-gradle", version.ref = "firebase-crashlytics-gradle" }
From b1c7902ec16253de82e6f012f50f4f5f5817bf2c Mon Sep 17 00:00:00 2001
From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com>
Date: Sat, 25 Apr 2026 11:14:42 -0500
Subject: [PATCH 4/7] chore(deps): update vico to v3.2.0-next.2 (#5243)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
---
gradle/libs.versions.toml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 47d9605ae..3c05f2eb3 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -79,7 +79,7 @@ uri-kmp = "0.0.21"
osmdroid-android = "6.1.20"
spotless = "8.4.0"
wire = "6.2.0"
-vico = "3.2.0-next.1"
+vico = "3.2.0-next.2"
kable = "0.42.0"
mqttastic = "0.2.0"
jmdns = "3.6.3"
From a035fedcdf974bb60a938d91723393ecdb27fbaf Mon Sep 17 00:00:00 2001
From: James Rich <2199651+jamesarich@users.noreply.github.com>
Date: Sat, 25 Apr 2026 13:39:06 -0500
Subject: [PATCH 5/7] chore: Scheduled updates (Firmware, Hardware,
Translations, Graphs) (#5244)
---
.../composeResources/values-de/strings.xml | 22 +++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/core/resources/src/commonMain/composeResources/values-de/strings.xml b/core/resources/src/commonMain/composeResources/values-de/strings.xml
index 1080557d5..dbed3a28f 100644
--- a/core/resources/src/commonMain/composeResources/values-de/strings.xml
+++ b/core/resources/src/commonMain/composeResources/values-de/strings.xml
@@ -114,6 +114,10 @@
Kurze Reichweite - Turbo
Kurze Reichweite - Schnell
Kurze Reichweite - Langsam
+ Leicht - Schnell
+ Leicht - Langsam
+ Schmal - Schnell
+ Schmal - Langsam
Durch die Aktivierung von WLAN wird die Bluetooth Verbindung zur App deaktiviert.
Durch Aktivieren von Ethernet wird die Bluetooth Verbindung zur App deaktiviert. TCP Knotenverbindungen sind auf Apple Geräten nicht verfügbar.
Aktivieren Sie die Übertragung von Paketen per UDP über das lokale Netzwerk.
@@ -794,7 +798,12 @@
Host Kennzahlen
Benutzerzählerdaten
Metadaten
+ Metadaten aktualisieren
+ Verbinden & Verwalten
+ Fernverwaltung wird aufgebaut
Sitzung aktiv
+ Aktualisierung erforderlich
+ Verbinden Sie sich mit einem Funkgerät, um entfernte Knoten zu verwalten.
Knoten nicht erreichbar - erneut versuchen oder Standort wechseln.
Erneut versuchen
Aktionen
@@ -912,6 +921,7 @@
Suche nach Bluetoothgeräten
Suche...
Verfügbare Bluetooth Geräte
+ Gerät manuell hinzufügen.
Keine Geräte gefunden
Keine Bluetoothgeräte gefunden
Stelle sicher, daß Du in der Reichweite des Gerätes bist.
@@ -920,8 +930,10 @@
Kein USB-Gerät gefunden
Verbinde das Gerät über den seriellen Anschluß oder USB.
Kein Gerät verbunden
+ Verbinden Sie sich mit einem Gerät, um Knoten in der Nähe zu finden.
Suche nach Knoten
Knoten in der Nähe erscheinen hier, sobald sie erreicht wurden.
+ Verbindung einrichten
Erste Schritte
Willkommen bei
Bleibe überall in Verbindung
@@ -1241,8 +1253,18 @@
Netzwerk eingeben oder auswählen
WLAN erfolgreich konfiguriert!
WLAN Konfiguration konnte nicht angewendet werden
+ Gerät verbunden
+ Ihr mPWRD-OS Gerät ist dem Wi-Fi-Netzwerk beigetreten.
IP Adresse
+ Geräteeinrichtung abschließen
+ Melden Sie sich über SSH an, um den Standardnamen und das Standardpasswort zu ändern.
Benutzername
+ SSH Kommando
+ ssh %1$s@%2$s
+ SSH Kommando verfügbar, nachdem eine IP zugewiesen wurde.
+ SSH Client öffnen
+ Wenn sich keine App öffnet, kopieren Sie den SSH Befehl und fügen ihn in Ihren SSH Client ein.
+ IP nicht verfügbar
Fertig
Meshtastic Desktop
Meshtastic anzeigen
From bbb7f8b23fa3e19fb93d9f59f8ec998e6e66bf0c Mon Sep 17 00:00:00 2001
From: James Rich <2199651+jamesarich@users.noreply.github.com>
Date: Sat, 25 Apr 2026 14:23:21 -0500
Subject: [PATCH 6/7] fix(crashlytics): resolve beta 2.7.14 crash issues
(#5245)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../core/data/repository/PacketRepositoryImpl.kt | 5 +++--
.../kotlin/org/meshtastic/core/database/dao/PacketDao.kt | 5 +++--
.../meshtastic/core/database/dao/CommonPacketDaoTest.kt | 2 +-
.../org/meshtastic/feature/widget/LocalStatsWidget.kt | 9 ++++-----
4 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/core/data/src/commonMain/kotlin/org/meshtastic/core/data/repository/PacketRepositoryImpl.kt b/core/data/src/commonMain/kotlin/org/meshtastic/core/data/repository/PacketRepositoryImpl.kt
index 149c62d2b..5f32d491d 100644
--- a/core/data/src/commonMain/kotlin/org/meshtastic/core/data/repository/PacketRepositoryImpl.kt
+++ b/core/data/src/commonMain/kotlin/org/meshtastic/core/data/repository/PacketRepositoryImpl.kt
@@ -110,8 +110,9 @@ class PacketRepositoryImpl(private val dbManager: DatabaseProvider, private val
dao.upsertContactSettings(listOf(updated))
}
- override suspend fun getQueuedPackets(): List =
- withContext(dispatchers.io) { dbManager.currentDb.value.packetDao().getQueuedPackets() }
+ override suspend fun getQueuedPackets(): List = withContext(dispatchers.io) {
+ dbManager.currentDb.value.packetDao().getAllDataPackets().filter { it.status == MessageStatus.QUEUED }
+ }
suspend fun insertRoomPacket(packet: RoomPacket) =
withContext(dispatchers.io) { dbManager.currentDb.value.packetDao().insert(packet) }
diff --git a/core/database/src/commonMain/kotlin/org/meshtastic/core/database/dao/PacketDao.kt b/core/database/src/commonMain/kotlin/org/meshtastic/core/database/dao/PacketDao.kt
index c2ef9c516..3fe4f3d15 100644
--- a/core/database/src/commonMain/kotlin/org/meshtastic/core/database/dao/PacketDao.kt
+++ b/core/database/src/commonMain/kotlin/org/meshtastic/core/database/dao/PacketDao.kt
@@ -338,15 +338,16 @@ interface PacketDao {
)
suspend fun findPacketBySfppHash(hash: ByteString): Packet?
+ // Fetches all DataPackets for the current node, ordered by time.
+ // Callers should filter by status in Kotlin (avoids SQLite json_extract dependency).
@Query(
"""
SELECT data FROM packet
WHERE (myNodeNum = 0 OR myNodeNum = (SELECT myNodeNum FROM my_node))
- AND json_extract(data, '${"$"}.status') = 'QUEUED'
ORDER BY received_time ASC
""",
)
- suspend fun getQueuedPackets(): List
+ suspend fun getAllDataPackets(): List
@Query(
"""
diff --git a/core/database/src/commonTest/kotlin/org/meshtastic/core/database/dao/CommonPacketDaoTest.kt b/core/database/src/commonTest/kotlin/org/meshtastic/core/database/dao/CommonPacketDaoTest.kt
index 71a7fef1c..cd0c9c672 100644
--- a/core/database/src/commonTest/kotlin/org/meshtastic/core/database/dao/CommonPacketDaoTest.kt
+++ b/core/database/src/commonTest/kotlin/org/meshtastic/core/database/dao/CommonPacketDaoTest.kt
@@ -164,7 +164,7 @@ abstract class CommonPacketDaoTest {
),
)
packetDao.insert(queuedPacket)
- val queued = packetDao.getQueuedPackets()
+ val queued = packetDao.getAllDataPackets().filter { it.status == MessageStatus.QUEUED }
assertNotNull(queued)
assertEquals(1, queued.size)
assertEquals("Queued", queued.first().text)
diff --git a/feature/widget/src/main/kotlin/org/meshtastic/feature/widget/LocalStatsWidget.kt b/feature/widget/src/main/kotlin/org/meshtastic/feature/widget/LocalStatsWidget.kt
index 099b24cc3..bb4f4e27e 100644
--- a/feature/widget/src/main/kotlin/org/meshtastic/feature/widget/LocalStatsWidget.kt
+++ b/feature/widget/src/main/kotlin/org/meshtastic/feature/widget/LocalStatsWidget.kt
@@ -18,6 +18,7 @@ package org.meshtastic.feature.widget
import android.annotation.SuppressLint
import android.content.Context
+import android.content.Intent
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.collectAsState
@@ -36,13 +37,13 @@ import androidx.glance.Image
import androidx.glance.ImageProvider
import androidx.glance.LocalContext
import androidx.glance.LocalSize
-import androidx.glance.action.actionStartActivity
import androidx.glance.action.clickable
import androidx.glance.appwidget.CircularProgressIndicator
import androidx.glance.appwidget.GlanceAppWidget
import androidx.glance.appwidget.LinearProgressIndicator
import androidx.glance.appwidget.SizeMode
import androidx.glance.appwidget.action.actionRunCallback
+import androidx.glance.appwidget.action.actionStartActivity
import androidx.glance.appwidget.components.CircleIconButton
import androidx.glance.appwidget.components.Scaffold
import androidx.glance.appwidget.components.TitleBar
@@ -148,10 +149,8 @@ class LocalStatsWidget :
GlanceModifier.fillMaxSize()
.clickable(
actionStartActivity(
- android.content.ComponentName(
- context.packageName,
- "org.meshtastic.app.MainActivity",
- ),
+ context.packageManager.getLaunchIntentForPackage(context.packageName)
+ ?: Intent().setClassName(context.packageName, "org.meshtastic.app.MainActivity"),
),
),
) {
From 534b4fde2475c9ba77acdd74f095521888f05f90 Mon Sep 17 00:00:00 2001
From: James Rich <2199651+jamesarich@users.noreply.github.com>
Date: Sat, 25 Apr 2026 15:52:58 -0500
Subject: [PATCH 7/7] feat(messaging): send message on Enter keypress (#5246)
---
.../meshtastic/feature/messaging/Message.kt | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/feature/messaging/src/commonMain/kotlin/org/meshtastic/feature/messaging/Message.kt b/feature/messaging/src/commonMain/kotlin/org/meshtastic/feature/messaging/Message.kt
index 5a37c085d..82f305ba3 100644
--- a/feature/messaging/src/commonMain/kotlin/org/meshtastic/feature/messaging/Message.kt
+++ b/feature/messaging/src/commonMain/kotlin/org/meshtastic/feature/messaging/Message.kt
@@ -52,6 +52,12 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.key.Key
+import androidx.compose.ui.input.key.KeyEventType
+import androidx.compose.ui.input.key.isShiftPressed
+import androidx.compose.ui.input.key.key
+import androidx.compose.ui.input.key.onKeyEvent
+import androidx.compose.ui.input.key.type
import androidx.compose.ui.platform.LocalClipboard
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.input.ImeAction
@@ -458,7 +464,18 @@ private fun MessageInput(
val canSend = !isOverLimit && currentText.isNotEmpty() && isEnabled
OutlinedTextField(
- modifier = modifier.fillMaxWidth().padding(horizontal = 8.dp, vertical = 4.dp),
+ modifier =
+ modifier.fillMaxWidth().padding(horizontal = 8.dp, vertical = 4.dp).onKeyEvent { keyEvent ->
+ val isEnterNoShift = keyEvent.key == Key.Enter && !keyEvent.isShiftPressed
+ if (isEnterNoShift) {
+ if (keyEvent.type == KeyEventType.KeyUp && canSend) {
+ onSendMessage()
+ }
+ true // consume both KeyDown and KeyUp to prevent newline insertion
+ } else {
+ false
+ }
+ },
state = textFieldState,
lineLimits = TextFieldLineLimits.MultiLine(1, MAX_LINES),
label = { Text(stringResource(Res.string.message_input_label)) },