mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
refactor: leverage new dependency features from recent updates (#5057)
This commit is contained in:
parent
929e273978
commit
9c8532f80d
18 changed files with 47 additions and 57 deletions
|
|
@ -21,8 +21,6 @@ package org.meshtastic.app.map
|
|||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Paint
|
||||
import android.net.Uri
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.compose.rememberLauncherForActivityResult
|
||||
|
|
@ -56,7 +54,6 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.graphics.createBitmap
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
|
|
@ -67,8 +64,6 @@ import com.google.android.gms.location.LocationResult
|
|||
import com.google.android.gms.location.LocationServices
|
||||
import com.google.android.gms.location.Priority
|
||||
import com.google.android.gms.maps.CameraUpdateFactory
|
||||
import com.google.android.gms.maps.model.BitmapDescriptor
|
||||
import com.google.android.gms.maps.model.BitmapDescriptorFactory
|
||||
import com.google.android.gms.maps.model.CameraPosition
|
||||
import com.google.android.gms.maps.model.JointType
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
|
|
@ -798,7 +793,6 @@ private fun MainMapContent(
|
|||
mapFilterState = mapFilterState,
|
||||
myNodeNum = myNodeNum ?: 0,
|
||||
isConnected = isConnected,
|
||||
unicodeEmojiToBitmapProvider = ::unicodeEmojiToBitmap,
|
||||
onEditWaypointRequest = onEditWaypointRequest,
|
||||
selectedWaypointId = selectedWaypointId,
|
||||
)
|
||||
|
|
@ -1068,23 +1062,6 @@ internal fun convertIntToEmoji(unicodeCodePoint: Int): String = try {
|
|||
"\uD83D\uDCCD"
|
||||
}
|
||||
|
||||
internal fun unicodeEmojiToBitmap(icon: Int): BitmapDescriptor {
|
||||
val unicodeEmoji = convertIntToEmoji(icon)
|
||||
val paint =
|
||||
Paint(Paint.ANTI_ALIAS_FLAG).apply {
|
||||
textSize = 64f
|
||||
color = android.graphics.Color.BLACK
|
||||
textAlign = Paint.Align.CENTER
|
||||
}
|
||||
val baseline = -paint.ascent()
|
||||
val width = (paint.measureText(unicodeEmoji) + 0.5f).toInt()
|
||||
val height = (baseline + paint.descent() + 0.5f).toInt()
|
||||
val image = createBitmap(width, height, android.graphics.Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(image)
|
||||
canvas.drawText(unicodeEmoji, width / 2f, baseline, paint)
|
||||
return BitmapDescriptorFactory.fromBitmap(image)
|
||||
}
|
||||
|
||||
@Suppress("NestedBlockDepth")
|
||||
fun Uri.getFileName(context: android.content.Context): String {
|
||||
var name = this.lastPathSegment ?: "layer_$nowMillis"
|
||||
|
|
|
|||
|
|
@ -16,15 +16,22 @@
|
|||
*/
|
||||
package org.meshtastic.app.map.component
|
||||
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import com.google.android.gms.maps.model.BitmapDescriptor
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.google.android.gms.maps.model.LatLng
|
||||
import com.google.maps.android.compose.MapsComposeExperimentalApi
|
||||
import com.google.maps.android.compose.Marker
|
||||
import com.google.maps.android.compose.rememberComposeBitmapDescriptor
|
||||
import com.google.maps.android.compose.rememberUpdatedMarkerState
|
||||
import kotlinx.coroutines.launch
|
||||
import org.meshtastic.app.map.convertIntToEmoji
|
||||
import org.meshtastic.core.model.util.GeoConstants.DEG_D
|
||||
import org.meshtastic.core.resources.Res
|
||||
import org.meshtastic.core.resources.locked
|
||||
|
|
@ -32,13 +39,13 @@ import org.meshtastic.core.ui.util.showToast
|
|||
import org.meshtastic.feature.map.BaseMapViewModel
|
||||
import org.meshtastic.proto.Waypoint
|
||||
|
||||
@OptIn(MapsComposeExperimentalApi::class)
|
||||
@Composable
|
||||
fun WaypointMarkers(
|
||||
displayableWaypoints: List<Waypoint>,
|
||||
mapFilterState: BaseMapViewModel.MapFilterState,
|
||||
myNodeNum: Int,
|
||||
isConnected: Boolean,
|
||||
unicodeEmojiToBitmapProvider: (Int) -> BitmapDescriptor,
|
||||
onEditWaypointRequest: (Waypoint) -> Unit,
|
||||
selectedWaypointId: Int? = null,
|
||||
) {
|
||||
|
|
@ -57,14 +64,16 @@ fun WaypointMarkers(
|
|||
}
|
||||
}
|
||||
|
||||
val iconCodePoint = if ((waypoint.icon ?: 0) == 0) PUSHPIN else waypoint.icon!!
|
||||
val emojiText = convertIntToEmoji(iconCodePoint)
|
||||
val icon =
|
||||
rememberComposeBitmapDescriptor(iconCodePoint) {
|
||||
Text(text = emojiText, fontSize = 32.sp, modifier = Modifier.padding(2.dp))
|
||||
}
|
||||
|
||||
Marker(
|
||||
state = markerState,
|
||||
icon =
|
||||
if ((waypoint.icon ?: 0) == 0) {
|
||||
unicodeEmojiToBitmapProvider(PUSHPIN) // Default icon (Round Pushpin)
|
||||
} else {
|
||||
unicodeEmojiToBitmapProvider(waypoint.icon!!)
|
||||
},
|
||||
icon = icon,
|
||||
title = (waypoint.name ?: "").replace('\n', ' ').replace('\b', ' '),
|
||||
snippet = (waypoint.description ?: "").replace('\n', ' ').replace('\b', ' '),
|
||||
visible = true,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
package org.meshtastic.app.ui
|
||||
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.junit4.v2.createComposeRule
|
||||
import androidx.navigation3.runtime.NavKey
|
||||
import androidx.navigation3.runtime.entryProvider
|
||||
import androidx.navigation3.runtime.rememberNavBackStack
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
*/
|
||||
package org.meshtastic.core.barcode
|
||||
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.junit4.v2.createComposeRule
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
|
|
|
|||
|
|
@ -41,8 +41,6 @@ kotlin {
|
|||
}
|
||||
androidMain.dependencies { api(libs.androidx.core.ktx) }
|
||||
|
||||
val androidHostTest by getting { dependencies { implementation(libs.robolectric) } }
|
||||
|
||||
commonTest.dependencies { implementation(libs.kotlinx.coroutines.test) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ package org.meshtastic.core.database
|
|||
|
||||
import androidx.room3.TypeConverter
|
||||
import co.touchlab.kermit.Logger
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import okio.ByteString
|
||||
import okio.ByteString.Companion.toByteString
|
||||
|
|
@ -33,10 +34,12 @@ import org.meshtastic.proto.User
|
|||
|
||||
@Suppress("TooManyFunctions")
|
||||
class Converters {
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
private val json = Json {
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
encodeDefaults = true
|
||||
exceptionsWithDebugInfo = false
|
||||
}
|
||||
|
||||
@TypeConverter fun dataFromString(value: String): DataPacket = json.decodeFromString(DataPacket.serializer(), value)
|
||||
|
|
|
|||
|
|
@ -63,9 +63,6 @@ kotlin {
|
|||
commonTest.dependencies {
|
||||
implementation(projects.core.testing)
|
||||
implementation(libs.kotlinx.coroutines.test)
|
||||
implementation(libs.turbine)
|
||||
implementation(libs.kotest.assertions)
|
||||
implementation(libs.kotest.property)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
*/
|
||||
package org.meshtastic.core.network.di
|
||||
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.koin.core.annotation.ComponentScan
|
||||
import org.koin.core.annotation.Module
|
||||
|
|
@ -24,10 +25,12 @@ import org.koin.core.annotation.Single
|
|||
@Module
|
||||
@ComponentScan("org.meshtastic.core.network")
|
||||
class CoreNetworkModule {
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@Single
|
||||
fun provideJson(): Json = Json {
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
coerceInputValues = true
|
||||
exceptionsWithDebugInfo = false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import kotlinx.coroutines.flow.first
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Semaphore
|
||||
import kotlinx.coroutines.sync.withPermit
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.koin.core.annotation.Single
|
||||
|
|
@ -62,7 +63,12 @@ class MQTTRepositoryImpl(
|
|||
}
|
||||
|
||||
private var client: MQTTClient? = null
|
||||
private val json = Json { ignoreUnknownKeys = true }
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
private val json = Json {
|
||||
ignoreUnknownKeys = true
|
||||
exceptionsWithDebugInfo = false
|
||||
}
|
||||
private val scope = CoroutineScope(dispatchers.default + SupervisorJob())
|
||||
private var clientJob: Job? = null
|
||||
private val publishSemaphore = Semaphore(20)
|
||||
|
|
@ -115,6 +121,9 @@ class MQTTRepositoryImpl(
|
|||
Logger.d { "MQTT parsed JSON payload successfully" }
|
||||
|
||||
trySend(MqttClientProxyMessage(topic = topic, text = jsonStr, retained = packet.retain))
|
||||
} catch (e: kotlinx.serialization.json.JsonDecodingException) {
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
Logger.e(e) { "Failed to parse MQTT JSON: ${e.shortMessage} (path: ${e.path})" }
|
||||
} catch (e: kotlinx.serialization.SerializationException) {
|
||||
Logger.e(e) { "Failed to parse MQTT JSON: ${e.message}" }
|
||||
} catch (e: IllegalArgumentException) {
|
||||
|
|
|
|||
|
|
@ -56,9 +56,6 @@ kotlin {
|
|||
commonTest.dependencies {
|
||||
implementation(projects.core.testing)
|
||||
implementation(libs.kotlinx.coroutines.test)
|
||||
implementation(libs.turbine)
|
||||
implementation(libs.kotest.assertions)
|
||||
implementation(libs.kotest.property)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,9 +70,6 @@ kotlin {
|
|||
implementation(projects.core.testing)
|
||||
implementation(libs.junit)
|
||||
implementation(libs.kotlinx.coroutines.test)
|
||||
implementation(libs.turbine)
|
||||
implementation(libs.kotest.assertions)
|
||||
implementation(libs.kotest.property)
|
||||
}
|
||||
|
||||
val androidHostTest by getting { dependencies { implementation(libs.androidx.test.runner) } }
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
package org.meshtastic.core.ui.component
|
||||
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.junit4.v2.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import androidx.compose.material3.Text
|
|||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.ui.test.assertDoesNotExist
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.junit4.v2.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package org.meshtastic.core.ui.util
|
|||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.test.assertIsDisplayed
|
||||
import androidx.compose.ui.test.junit4.createComposeRule
|
||||
import androidx.compose.ui.test.junit4.v2.createComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithText
|
||||
import androidx.compose.ui.test.performClick
|
||||
import org.junit.Rule
|
||||
|
|
|
|||
|
|
@ -58,11 +58,12 @@ kotlin {
|
|||
|
||||
androidMain.dependencies { implementation(libs.markdown.renderer.android) }
|
||||
|
||||
commonTest.dependencies { implementation(projects.core.testing) }
|
||||
|
||||
val androidHostTest by getting {
|
||||
dependencies {
|
||||
implementation(libs.junit)
|
||||
implementation(libs.kotlinx.coroutines.test)
|
||||
implementation(libs.androidx.compose.ui.test.junit4)
|
||||
implementation(libs.androidx.test.ext.junit)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@
|
|||
package org.meshtastic.feature.firmware.ota.dfu
|
||||
|
||||
import co.touchlab.kermit.Logger
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonDecodingException
|
||||
|
||||
private val json = Json { ignoreUnknownKeys = true }
|
||||
|
||||
|
|
@ -36,7 +38,11 @@ internal fun parseDfuZipEntries(entries: Map<String, ByteArray>): DfuZipPackage
|
|||
|
||||
val manifest =
|
||||
runCatching { json.decodeFromString<DfuManifest>(manifestBytes.decodeToString()) }
|
||||
.getOrElse { e -> throw DfuException.InvalidPackage("Failed to parse manifest.json: ${e.message}") }
|
||||
.getOrElse { e ->
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
val detail = (e as? JsonDecodingException)?.shortMessage ?: e.message
|
||||
throw DfuException.InvalidPackage("Failed to parse manifest.json: $detail")
|
||||
}
|
||||
|
||||
val entry =
|
||||
manifest.manifest.primaryEntry ?: throw DfuException.InvalidPackage("No firmware entry found in manifest.json")
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ kotlin {
|
|||
implementation(libs.junit)
|
||||
implementation(project.dependencies.platform(libs.androidx.compose.bom))
|
||||
implementation(libs.kotlinx.coroutines.test)
|
||||
implementation(libs.androidx.compose.ui.test.junit4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ osmdroid-android = "6.1.20"
|
|||
spotless = "8.4.0"
|
||||
wire = "6.2.0"
|
||||
vico = "3.1.0"
|
||||
dependency-guard = "0.5.0"
|
||||
kable = "0.42.0"
|
||||
kmqtt = "1.0.0"
|
||||
jmdns = "3.6.3"
|
||||
|
|
@ -141,7 +140,6 @@ compose-multiplatform-ui-tooling-preview = { module = "org.jetbrains.compose.ui:
|
|||
compose-multiplatform-resources = { module = "org.jetbrains.compose.components:components-resources", version.ref = "compose-multiplatform" }
|
||||
compose-multiplatform-material3 = { module = "org.jetbrains.compose.material3:material3", version.ref = "compose-multiplatform-material3" }
|
||||
|
||||
|
||||
# JetBrains Material 3 Adaptive (multiplatform — Android, Desktop, iOS)
|
||||
jetbrains-compose-material3-adaptive = { module = "org.jetbrains.compose.material3.adaptive:adaptive", version.ref = "jetbrains-adaptive" }
|
||||
jetbrains-compose-material3-adaptive-layout = { module = "org.jetbrains.compose.material3.adaptive:adaptive-layout", version.ref = "jetbrains-adaptive" }
|
||||
|
|
@ -174,7 +172,6 @@ qrcode-kotlin = { module = "io.github.g0dkar:qrcode-kotlin", version.ref = "qrco
|
|||
kotlin-gradlePlugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" }
|
||||
dokka-gradlePlugin = { module = "org.jetbrains.dokka:dokka-gradle-plugin", version.ref = "dokka" }
|
||||
|
||||
|
||||
kotlinx-collections-immutable = { module = "org.jetbrains.kotlinx:kotlinx-collections-immutable", version = "0.4.0" }
|
||||
kotlinx-atomicfu = { module = "org.jetbrains.kotlinx:atomicfu", version = "0.32.1" }
|
||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-android" }
|
||||
|
|
@ -199,13 +196,10 @@ androidx-test-ext-junit = { module = "androidx.test.ext:junit", version = "1.3.0
|
|||
androidx-test-runner = { module = "androidx.test:runner", version = "1.7.0" }
|
||||
androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version = "3.7.0" }
|
||||
junit = { module = "junit:junit", version = "4.13.2" }
|
||||
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit5" }
|
||||
junit-vintage-engine = { module = "org.junit.vintage:junit-vintage-engine", version.ref = "junit5" }
|
||||
junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher", version.ref = "junit-platform" }
|
||||
mokkery-library = { module = "dev.mokkery:mokkery-runtime", version.ref = "mokkery" }
|
||||
kotest-assertions = { module = "io.kotest:kotest-assertions-core", version.ref = "kotest" }
|
||||
kotest-property = { module = "io.kotest:kotest-property", version.ref = "kotest" }
|
||||
kotest-framework = { module = "io.kotest:kotest-framework-engine", version.ref = "kotest" }
|
||||
kotest-runner-junit6 = { module = "io.kotest:kotest-runner-junit6", version.ref = "kotest" }
|
||||
robolectric = { module = "org.robolectric:robolectric", version = "4.16.1" }
|
||||
turbine = { module = "app.cash.turbine:turbine", version.ref = "turbine" }
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue