chore: KMP audit — commonize code, centralize utilities, eliminate dead abstractions (#5133)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
James Rich 2026-04-14 21:17:50 -05:00 committed by GitHub
parent 50ade01e55
commit 72b981f73b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
132 changed files with 2186 additions and 916 deletions

View file

@ -51,6 +51,7 @@ import coil3.annotation.ExperimentalCoilApi
import coil3.compose.setSingletonImageLoaderFactory
import coil3.disk.DiskCache
import coil3.memory.MemoryCache
import coil3.network.DeDupeConcurrentRequestStrategy
import coil3.network.ktor3.KtorNetworkFetcherFactory
import coil3.request.crossfade
import coil3.svg.SvgDecoder
@ -62,7 +63,7 @@ import org.jetbrains.compose.resources.decodeToSvgPainter
import org.koin.compose.koinInject
import org.koin.core.context.startKoin
import org.meshtastic.core.common.BuildConfigProvider
import org.meshtastic.core.common.util.MeshtasticUri
import org.meshtastic.core.common.util.CommonUri
import org.meshtastic.core.database.desktopDataDir
import org.meshtastic.core.navigation.MultiBackstack
import org.meshtastic.core.navigation.SettingsRoute
@ -130,7 +131,7 @@ private fun ApplicationScope.DeepLinkHandler(args: Array<String>, uiViewModel: U
arg.startsWith("http://meshtastic.org") ||
arg.startsWith("https://meshtastic.org")
) {
uiViewModel.handleDeepLink(MeshtasticUri(arg)) {
uiViewModel.handleDeepLink(CommonUri.parse(arg)) {
Logger.e { "Invalid Meshtastic URI passed via args: $arg" }
}
}
@ -141,7 +142,7 @@ private fun ApplicationScope.DeepLinkHandler(args: Array<String>, uiViewModel: U
if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.APP_OPEN_URI)) {
Desktop.getDesktop().setOpenURIHandler { event ->
val uriStr = event.uri.toString()
uiViewModel.handleDeepLink(MeshtasticUri(uriStr)) { Logger.e { "Invalid URI from OS: $uriStr" } }
uiViewModel.handleDeepLink(CommonUri.parse(uriStr)) { Logger.e { "Invalid URI from OS: $uriStr" } }
}
}
}
@ -304,7 +305,12 @@ private fun CoilImageLoaderSetup() {
val cacheDir = desktopDataDir() + "/image_cache_v3"
ImageLoader.Builder(context)
.components {
add(KtorNetworkFetcherFactory(httpClient = httpClient))
add(
KtorNetworkFetcherFactory(
httpClient = httpClient,
concurrentRequestStrategy = DeDupeConcurrentRequestStrategy(),
),
)
// Render SVGs to a bitmap on Desktop to avoid Skiko vector rendering artifacts
// that show up as solid/black hardware images.
add(SvgDecoder.Factory(renderToBitmap = true))

View file

@ -14,18 +14,22 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
@file:Suppress("ktlint:standard:no-unused-imports") // Koin KSP-generated extension functions require aliased imports
@file:Suppress(
"ktlint:standard:no-unused-imports",
) // Koin K2 compiler plugin generates aliased module extensions referenced in desktopModule()
package org.meshtastic.desktop.di
// Generated Koin module extensions from core KMP modules
import io.ktor.client.HttpClient
import io.ktor.client.engine.java.Java
import io.ktor.client.plugins.DefaultRequest
import io.ktor.client.plugins.HttpRequestRetry
import io.ktor.client.plugins.HttpTimeout
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
import io.ktor.client.plugins.logging.LogLevel
import io.ktor.client.plugins.logging.Logging
import io.ktor.client.request.url
import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json
import org.koin.dsl.module
@ -183,6 +187,7 @@ private fun desktopPlatformStubsModule() = module {
single<HttpClient> {
HttpClient(Java) {
install(ContentNegotiation) { json(get<Json>()) }
install(DefaultRequest) { url(HttpClientDefaults.API_BASE_URL) }
install(HttpTimeout) {
requestTimeoutMillis = HttpClientDefaults.TIMEOUT_MS
connectTimeoutMillis = HttpClientDefaults.TIMEOUT_MS
@ -195,7 +200,7 @@ private fun desktopPlatformStubsModule() = module {
if (DesktopBuildConfig.IS_DEBUG) {
install(Logging) {
logger = KermitHttpLogger
level = LogLevel.HEADERS
level = LogLevel.BODY
}
}
}