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/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 diff --git a/core/resources/src/commonMain/composeResources/values-de/strings.xml b/core/resources/src/commonMain/composeResources/values-de/strings.xml index 6bafa634e..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,6 +798,13 @@ 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 Firmware @@ -905,10 +916,24 @@ Firmware-Version Kürzliche Netzwerkgeräte Entdeckte Netzwerkgeräte + Suche nach Netzwerkgeräten Suche... + 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. + 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 + 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 @@ -1228,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 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 години 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)) }, 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"), ), ), ) { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4534f2768..247a29e23 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -80,7 +80,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" @@ -251,7 +251,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" }