Add SDK map module and migrate map fetching to Apollo with Hilt wiring.

This includes the new sdk module, MapService + mapper implementation, Apollo provider module, Hilt app integration, and the project .gitignore update.

Made-with: Cursor
This commit is contained in:
2026-02-28 16:38:52 +01:00
parent 54092f184f
commit 6dedaf0e8b
29 changed files with 292 additions and 215 deletions

49
sdk/build.gradle.kts Normal file
View File

@@ -0,0 +1,49 @@
plugins {
alias(libs.plugins.android.library)
alias(libs.plugins.ksp)
alias(libs.plugins.apollo)
}
android {
namespace = "org.db3.airmq.sdk"
compileSdk {
version = release(36) {
minorApiLevel = 1
}
}
defaultConfig {
minSdk = 24
consumerProguardFiles("consumer-rules.pro")
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
buildFeatures {
buildConfig = true
}
}
apollo {
service("service") {
packageName.set("org.db3.airmq.sdk")
schemaFiles.from(file("../app/src/main/graphql/schema.graphqls"))
}
}
dependencies {
implementation(libs.apollo.runtime)
implementation(libs.hilt.android)
ksp(libs.hilt.compiler)
}

1
sdk/consumer-rules.pro Normal file
View File

@@ -0,0 +1 @@
# Consumer ProGuard rules for sdk module.

1
sdk/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1 @@
# Add project specific ProGuard rules here.

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest />

View File

@@ -0,0 +1,9 @@
query MapMarkers {
getMarkers {
_id
name
latitude
longitude
text
}
}

View File

@@ -0,0 +1,33 @@
package org.db3.airmq.sdk.di
import com.apollographql.apollo.ApolloClient
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
import org.db3.airmq.sdk.map.ApolloMapService
import org.db3.airmq.sdk.map.MapService
@Module
@InstallIn(SingletonComponent::class)
object SDKModule {
private const val API_URL = "https://api.airmq.cc"
@Provides
@Singleton
fun provideApolloClient(): ApolloClient {
return ApolloClient.Builder()
.serverUrl(API_URL)
.build()
}
}
@Module
@InstallIn(SingletonComponent::class)
abstract class SDKBindModule {
@Binds
@Singleton
abstract fun bindMapService(impl: ApolloMapService): MapService
}

View File

@@ -0,0 +1,21 @@
package org.db3.airmq.sdk.map
import javax.inject.Inject
import org.db3.airmq.sdk.MapMarkersQuery
import org.db3.airmq.sdk.map.domain.MapItem
class ApolloMapItemMapper @Inject constructor() {
fun toDomain(marker: MapMarkersQuery.GetMarker, index: Int): MapItem? {
val latitude = marker.latitude ?: return null
val longitude = marker.longitude ?: return null
val id = marker._id?.ifBlank { null } ?: "marker-$index"
return MapItem(
id = id,
title = marker.name?.ifBlank { null } ?: marker.text?.ifBlank { null } ?: id,
city = null,
latitude = latitude,
longitude = longitude,
isOnline = false
)
}
}

View File

@@ -0,0 +1,33 @@
package org.db3.airmq.sdk.map
import android.util.Log
import com.apollographql.apollo.ApolloClient
import javax.inject.Inject
import org.db3.airmq.sdk.MapMarkersQuery
import org.db3.airmq.sdk.map.domain.MapItem
class ApolloMapService @Inject constructor(
private val apolloClient: ApolloClient,
private val mapper: ApolloMapItemMapper
) : MapService {
override suspend fun fetchMapItems(): List<MapItem> {
Log.d(TAG, "Executing MapMarkers Apollo query")
val response = apolloClient.query(MapMarkersQuery()).execute()
response.errors?.firstOrNull()?.let { gqlError ->
Log.e(TAG, "MapMarkers Apollo query failed: ${gqlError.message}")
throw IllegalStateException(gqlError.message)
}
val mappedItems = response.data?.getMarkers
.orEmpty()
.filterNotNull()
.mapIndexedNotNull { index, marker -> mapper.toDomain(marker, index) }
Log.d(TAG, "MapMarkers Apollo query returned ${mappedItems.size} items")
return mappedItems
}
private companion object {
private const val TAG = "ApolloMapService"
}
}

View File

@@ -0,0 +1,7 @@
package org.db3.airmq.sdk.map
import org.db3.airmq.sdk.map.domain.MapItem
interface MapService {
suspend fun fetchMapItems(): List<MapItem>
}

View File

@@ -0,0 +1,10 @@
package org.db3.airmq.sdk.map.domain
data class MapItem(
val id: String,
val title: String,
val city: String?,
val latitude: Double,
val longitude: Double,
val isOnline: Boolean
)