Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6011cb20 authored by Ellen Poe's avatar Ellen Poe
Browse files

Merge branch 'ellenhp/nearby_filter_chips' into 'main'

Add filter chips to nearby screen

Closes #4

See merge request e/os/cardinal!26
parents f7017898 b4ddeff7
Loading
Loading
Loading
Loading
Loading
+31 −26
Original line number Diff line number Diff line
@@ -21,10 +21,8 @@ package earth.maps.cardinal.geocoding
import earth.maps.cardinal.data.GeocodeResult
import earth.maps.cardinal.data.GeocodeResult.Companion.generatePlaceId
import earth.maps.cardinal.data.LatLng
import earth.maps.cardinal.data.Place
import earth.maps.cardinal.data.LocationRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import earth.maps.cardinal.data.Place

abstract class GeocodingService(private val locationRepository: LocationRepository) {

@@ -32,9 +30,9 @@ abstract class GeocodingService(private val locationRepository: LocationReposito
     * Geocode a query string to find matching locations, returning Place objects.
     * @param query The search query (e.g., address, place name)
     * @param focusPoint Optional focus point for viewport biasing
     * @return Flow of Place objects
     * @return Place objects
     */
    suspend fun geocode(query: String, focusPoint: LatLng? = null): Flow<List<Place>> {
    suspend fun geocode(query: String, focusPoint: LatLng? = null): List<Place> {
        return convertResultsToPlaces(geocodeRaw(query, focusPoint))
    }

@@ -42,9 +40,9 @@ abstract class GeocodingService(private val locationRepository: LocationReposito
     * Reverse geocode coordinates to find address information, returning Place objects.
     * @param latitude The latitude coordinate
     * @param longitude The longitude coordinate
     * @return Flow of Place objects
     * @return Place objects
     */
    suspend fun reverseGeocode(latitude: Double, longitude: Double): Flow<List<Place>> {
    suspend fun reverseGeocode(latitude: Double, longitude: Double): List<Place> {
        return convertResultsToPlaces(reverseGeocodeRaw(latitude, longitude))
    }

@@ -52,50 +50,57 @@ abstract class GeocodingService(private val locationRepository: LocationReposito
     * Find nearby places around a given point, returning Place objects.
     * @param latitude The latitude coordinate
     * @param longitude The longitude coordinate
     * @return Flow of Place objects
     * @return Place objects
     */
    suspend fun nearby(latitude: Double, longitude: Double): Flow<List<Place>> {
        return convertResultsToPlaces(nearbyRaw(latitude, longitude))
    suspend fun nearby(latitude: Double, longitude: Double, selectedCategories: List<String>): List<Place> {
        return convertResultsToPlaces(nearbyRaw(latitude, longitude, selectedCategories))
    }

    /**
     * Converts a Flow of GeocodeResult to a Flow of Place, including deduplication.
     * @param resultsFlow The Flow of GeocodeResult to convert.
     * @return Flow of Place objects.
     * Converts a list of GeocodeResult to a list of Place, including deduplication.
     * @param results The GeocodeResults to convert.
     * @return Place objects.
     */
    protected open suspend fun convertResultsToPlaces(resultsFlow: Flow<List<GeocodeResult>>): Flow<List<Place>> {
        return resultsFlow.map { results ->
            // Deduplicate based on GeocodeResult before converting to Place
    protected open suspend fun convertResultsToPlaces(results: List<GeocodeResult>): List<Place> {
        val deduplicatedResults = deduplicateSearchResults(results)
            deduplicatedResults.map { geocodeResult ->
        return deduplicatedResults.map { geocodeResult ->
            locationRepository.createSearchResultPlace(geocodeResult)
        }
    }
    }

    /**
     * Geocode a query string to find matching locations, returning raw GeocodeResult objects.
     * @param query The search query (e.g., address, place name)
     * @param focusPoint Optional focus point for viewport biasing
     * @return Flow of raw geocoding results
     * @return Raw geocoding results
     */
    abstract suspend fun geocodeRaw(query: String, focusPoint: LatLng? = null): Flow<List<GeocodeResult>>
    abstract suspend fun geocodeRaw(
        query: String,
        focusPoint: LatLng? = null
    ): List<GeocodeResult>

    /**
     * Reverse geocode coordinates to find address information, returning raw GeocodeResult objects.
     * @param latitude The latitude coordinate
     * @param longitude The longitude coordinate
     * @return Flow of raw geocoding results
     * @return Raw geocoding results
     */
    abstract suspend fun reverseGeocodeRaw(latitude: Double, longitude: Double): Flow<List<GeocodeResult>>
    abstract suspend fun reverseGeocodeRaw(
        latitude: Double,
        longitude: Double
    ): List<GeocodeResult>

    /**
     * Find nearby places around a given point, returning raw GeocodeResult objects.
     * @param latitude The latitude coordinate
     * @param longitude The longitude coordinate
     * @return Flow of raw nearby places
     * @return Raw nearby places
     */
     abstract suspend fun nearbyRaw(latitude: Double, longitude: Double): Flow<List<GeocodeResult>>
    abstract suspend fun nearbyRaw(
        latitude: Double,
        longitude: Double,
        selectedCategories: List<String>
    ): List<GeocodeResult>
}

fun deduplicateSearchResults(results: List<GeocodeResult>): List<GeocodeResult> {
+9 −6
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import earth.maps.cardinal.data.AppPreferenceRepository
import earth.maps.cardinal.data.GeocodeResult
import earth.maps.cardinal.data.LatLng
import earth.maps.cardinal.data.LocationRepository
import kotlinx.coroutines.flow.Flow

class MultiplexedGeocodingService(
    private val appPreferenceRepository: AppPreferenceRepository,
@@ -31,7 +30,7 @@ class MultiplexedGeocodingService(
    locationRepository: LocationRepository,
) : GeocodingService(locationRepository) {

    override suspend fun geocodeRaw(query: String, focusPoint: LatLng?): Flow<List<GeocodeResult>> {
    override suspend fun geocodeRaw(query: String, focusPoint: LatLng?): List<GeocodeResult> {
        return if (appPreferenceRepository.offlineMode.value) {
            offlineGeocodingService.geocodeRaw(query, focusPoint)
        } else {
@@ -42,7 +41,7 @@ class MultiplexedGeocodingService(
    override suspend fun reverseGeocodeRaw(
        latitude: Double,
        longitude: Double
    ): Flow<List<GeocodeResult>> {
    ): List<GeocodeResult> {
        return if (appPreferenceRepository.offlineMode.value) {
            offlineGeocodingService.reverseGeocodeRaw(latitude, longitude)
        } else {
@@ -50,11 +49,15 @@ class MultiplexedGeocodingService(
        }
    }

    override suspend fun nearbyRaw(latitude: Double, longitude: Double): Flow<List<GeocodeResult>> {
    override suspend fun nearbyRaw(
        latitude: Double,
        longitude: Double,
        selectedCategories: List<String>
    ): List<GeocodeResult> {
        return if (appPreferenceRepository.offlineMode.value) {
            offlineGeocodingService.nearbyRaw(latitude, longitude)
            offlineGeocodingService.nearbyRaw(latitude, longitude, selectedCategories)
        } else {
            onlineGeocodingService.nearbyRaw(latitude, longitude)
            onlineGeocodingService.nearbyRaw(latitude, longitude, selectedCategories)
        }
    }
}
+23 −23
Original line number Diff line number Diff line
@@ -25,8 +25,6 @@ import earth.maps.cardinal.data.Address
import earth.maps.cardinal.data.GeocodeResult
import earth.maps.cardinal.data.LatLng
import earth.maps.cardinal.data.LocationRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import uniffi.cardinal_geocoder.newAirmailIndex
import java.io.File

@@ -37,8 +35,7 @@ class OfflineGeocodingService(
    private val geocoderDir = File(context.filesDir, "geocoder").apply { mkdirs() }
    private val airmailIndex = newAirmailIndex("en", geocoderDir.absolutePath)

    override suspend fun geocodeRaw(query: String, focusPoint: LatLng?): Flow<List<GeocodeResult>> =
        flow {
    override suspend fun geocodeRaw(query: String, focusPoint: LatLng?): List<GeocodeResult> {
        try {
            val results = airmailIndex.searchPhrase(query)
            val geocodeResults = results.map { poi ->
@@ -48,24 +45,27 @@ class OfflineGeocodingService(
                }
                buildResult(tagMap, poi.lat, poi.lng)
            }
                emit(geocodeResults)
            return geocodeResults
        } catch (e: Exception) {
            Log.e(TAG, "Geocode failed with exception", e)
            // If there's an error, return empty list
                emit(emptyList())
            return emptyList()
        }
    }

    override suspend fun reverseGeocodeRaw(
        latitude: Double,
        longitude: Double
    ): Flow<List<GeocodeResult>> = flow {
        emit(emptyList())
    ): List<GeocodeResult> {
        return emptyList()
    }

    override suspend fun nearbyRaw(latitude: Double, longitude: Double): Flow<List<GeocodeResult>> =
        flow {
            emit(emptyList())
    override suspend fun nearbyRaw(
        latitude: Double,
        longitude: Double,
        selectedCategories: List<String>
    ): List<GeocodeResult> {
        return emptyList()
    }

    override suspend fun beginTileProcessing() {
+58 −56
Original line number Diff line number Diff line
@@ -32,8 +32,6 @@ import io.ktor.client.plugins.logging.Logging
import io.ktor.client.request.get
import io.ktor.client.request.parameter
import io.ktor.serialization.kotlinx.json.json
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement
@@ -60,8 +58,7 @@ class PeliasGeocodingService(
        install(Logging)
    }

    override suspend fun geocodeRaw(query: String, focusPoint: LatLng?): Flow<List<GeocodeResult>> =
        flow {
    override suspend fun geocodeRaw(query: String, focusPoint: LatLng?): List<GeocodeResult> {
        try {
            Log.d(TAG, "Geocoding query: $query, focusPoint: $focusPoint")
            val config = appPreferenceRepository.peliasApiConfig.value
@@ -85,17 +82,17 @@ class PeliasGeocodingService(
            }
            Log.d(TAG, "Parsed results: ${geocodeResults.size}")

                emit(geocodeResults)
            return geocodeResults
        } catch (e: Exception) {
            Log.e(TAG, "Error during geocoding", e)
                emit(emptyList())
            return emptyList()
        }
    }

    override suspend fun reverseGeocodeRaw(
        latitude: Double,
        longitude: Double
    ): Flow<List<GeocodeResult>> = flow {
    ): List<GeocodeResult> {
        try {
            Log.d(TAG, "Reverse geocoding: $latitude, $longitude")
            val config = appPreferenceRepository.peliasApiConfig.value
@@ -116,15 +113,17 @@ class PeliasGeocodingService(
            }
            Log.d(TAG, "Parsed reverse results: ${geocodeResults.size}")

            emit(geocodeResults)
            return geocodeResults
        } catch (e: Exception) {
            Log.e(TAG, "Error during reverse geocoding", e)
            emit(emptyList())
            return emptyList()
        }
    }

    override suspend fun nearbyRaw(latitude: Double, longitude: Double): Flow<List<GeocodeResult>> =
        flow {
    override suspend fun nearbyRaw(
        latitude: Double,
        longitude: Double,
        selectedCategories: List<String>
    ): List<GeocodeResult> {
        try {
            Log.d(TAG, "Nearby: $latitude, $longitude")
            val config = appPreferenceRepository.peliasApiConfig.value
@@ -133,6 +132,9 @@ class PeliasGeocodingService(
                parameter("point.lon", longitude.toString())
                parameter("size", "50")
                parameter("layers", "venue")
                if (selectedCategories.isNotEmpty()) {
                    parameter("categories", selectedCategories.joinToString(","))
                }
                config.apiKey?.let { parameter("api_key", it) }
            }

@@ -146,10 +148,10 @@ class PeliasGeocodingService(
            }
            Log.d(TAG, "Parsed nearby results: ${geocodeResults.size}")

                emit(geocodeResults)
            return geocodeResults
        } catch (e: Exception) {
            Log.e(TAG, "Error during nearby", e)
                emit(emptyList())
            return emptyList()
        }
    }

+3 −4
Original line number Diff line number Diff line
@@ -459,10 +459,9 @@ class DirectionsViewModel @Inject constructor(
                // Use fromPlace as focus point for viewport biasing if available,
                // otherwise fall back to current viewport center
                val focusPoint = fromPlace?.latLng ?: viewportRepository.viewportCenter.value
                geocodingService.geocode(query, focusPoint).collect { results ->
                    geocodeResults.value = results

                geocodeResults.value = geocodingService.geocode(query, focusPoint)
                isSearching = false
                }
            } catch (e: Exception) {
                // Handle error
                searchError = e.message ?: "An error occurred during search"
Loading