From 11224b84cbfc901f075c991e2f46d103e681caa6 Mon Sep 17 00:00:00 2001 From: James Rich <2199651+jamesarich@users.noreply.github.com> Date: Thu, 22 May 2025 14:53:00 -0500 Subject: [PATCH] Refactor: Move ApiModule to flavor specific directories (#1913) --- .../java/com/geeksville/mesh/ui/NodeDetail.kt | 2 +- network/build.gradle.kts | 10 +++ .../geeksville/mesh/network/di/ApiModule.kt | 82 +++++++++++++++++++ .../mesh/network/retrofit/NoOpApiService.kt | 35 ++++++++ .../geeksville/mesh/network/di/ApiModule.kt | 0 .../mesh/network/retrofit/ApiService.kt | 4 - 6 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 network/src/fdroid/java/com/geeksville/mesh/network/di/ApiModule.kt create mode 100644 network/src/fdroid/java/com/geeksville/mesh/network/retrofit/NoOpApiService.kt rename network/src/{main => google}/java/com/geeksville/mesh/network/di/ApiModule.kt (100%) diff --git a/app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt b/app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt index 660c8fdbc..462c9a615 100644 --- a/app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt +++ b/app/src/main/java/com/geeksville/mesh/ui/NodeDetail.kt @@ -384,7 +384,7 @@ fun DeviceHardwareImage( deviceHardware: DeviceHardware, modifier: Modifier = Modifier, ) { - val hwImg = deviceHardware.images?.get(1) ?: deviceHardware.images?.get(0) ?: "unknown.svg" + val hwImg = deviceHardware.images?.getOrNull(1) ?: deviceHardware.images?.getOrNull(0) ?: "unknown.svg" val imageUrl = "https://flasher.meshtastic.org/img/devices/$hwImg" val listener = object : ImageRequest.Listener { override fun onStart(request: ImageRequest) { diff --git a/network/build.gradle.kts b/network/build.gradle.kts index 58f6b7d61..3f0f4343b 100644 --- a/network/build.gradle.kts +++ b/network/build.gradle.kts @@ -23,6 +23,16 @@ android { sourceCompatibility(JavaVersion.VERSION_17) targetCompatibility(JavaVersion.VERSION_17) } + + flavorDimensions += "default" + productFlavors { + create("fdroid") { + dimension = "default" + } + create("google") { + dimension = "default" + } + } } kotlin { diff --git a/network/src/fdroid/java/com/geeksville/mesh/network/di/ApiModule.kt b/network/src/fdroid/java/com/geeksville/mesh/network/di/ApiModule.kt new file mode 100644 index 000000000..ba4531ea4 --- /dev/null +++ b/network/src/fdroid/java/com/geeksville/mesh/network/di/ApiModule.kt @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025 Meshtastic LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.geeksville.mesh.network.di + +import android.content.Context +import coil3.ImageLoader +import coil3.disk.DiskCache +import coil3.memory.MemoryCache +import coil3.network.okhttp.OkHttpNetworkFetcherFactory +import coil3.request.crossfade +import coil3.svg.SvgDecoder +import coil3.util.DebugLogger +import coil3.util.Logger +import com.geeksville.mesh.network.BuildConfig +import com.geeksville.mesh.network.retrofit.ApiService +import com.geeksville.mesh.network.retrofit.NoOpApiService +import dagger.Binds +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import okhttp3.OkHttpClient +import javax.inject.Singleton + +private const val DISK_CACHE_PERCENT = 0.02 +private const val MEMORY_CACHE_PERCENT = 0.25 + +@InstallIn(SingletonComponent::class) +@Module +class ApiModule { + + @Provides + @Singleton + fun provideApiService(): ApiService { + return NoOpApiService() + } + + @Provides + @Singleton + fun imageLoader( + httpClient: OkHttpClient, + @ApplicationContext application: Context, + ): ImageLoader { + val sharedOkHttp = httpClient.newBuilder().build() + return ImageLoader.Builder(application) + .components { + add( + OkHttpNetworkFetcherFactory({ sharedOkHttp }) + ) + add(SvgDecoder.Factory()) + } + .memoryCache { + MemoryCache.Builder() + .maxSizePercent(application, MEMORY_CACHE_PERCENT) + .build() + } + .diskCache { + DiskCache.Builder() + .maxSizePercent(DISK_CACHE_PERCENT) + .build() + } + .logger(if (BuildConfig.DEBUG) DebugLogger(Logger.Level.Verbose) else null) + .crossfade(true) + .build() + } +} diff --git a/network/src/fdroid/java/com/geeksville/mesh/network/retrofit/NoOpApiService.kt b/network/src/fdroid/java/com/geeksville/mesh/network/retrofit/NoOpApiService.kt new file mode 100644 index 000000000..02415e080 --- /dev/null +++ b/network/src/fdroid/java/com/geeksville/mesh/network/retrofit/NoOpApiService.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Meshtastic LLC + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.geeksville.mesh.network.retrofit + +import com.geeksville.mesh.network.model.NetworkDeviceHardware +import com.geeksville.mesh.network.model.NetworkFirmwareReleases +import retrofit2.Response +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class NoOpApiService@Inject constructor() : ApiService { + override suspend fun getDeviceHardware(): Response> { + return Response.success(emptyList()) + } + + override suspend fun getFirmwareReleases(): Response { + return Response.success(NetworkFirmwareReleases(emptyList())) + } +} \ No newline at end of file diff --git a/network/src/main/java/com/geeksville/mesh/network/di/ApiModule.kt b/network/src/google/java/com/geeksville/mesh/network/di/ApiModule.kt similarity index 100% rename from network/src/main/java/com/geeksville/mesh/network/di/ApiModule.kt rename to network/src/google/java/com/geeksville/mesh/network/di/ApiModule.kt diff --git a/network/src/main/java/com/geeksville/mesh/network/retrofit/ApiService.kt b/network/src/main/java/com/geeksville/mesh/network/retrofit/ApiService.kt index 97c9c907b..daf513411 100644 --- a/network/src/main/java/com/geeksville/mesh/network/retrofit/ApiService.kt +++ b/network/src/main/java/com/geeksville/mesh/network/retrofit/ApiService.kt @@ -21,12 +21,8 @@ import com.geeksville.mesh.network.model.NetworkDeviceHardware import com.geeksville.mesh.network.model.NetworkFirmwareReleases import retrofit2.Response import retrofit2.http.GET -import retrofit2.http.Query interface ApiService { - @GET(".") - suspend fun checkDeviceRegistration(@Query("deviceId") deviceId: String): Response - @GET("resource/deviceHardware") suspend fun getDeviceHardware(): Response>