Skip to content

Commit

Permalink
update ui: add distance
Browse files Browse the repository at this point in the history
  • Loading branch information
nqmgaming committed Jun 4, 2024
1 parent 9244130 commit 39876a5
Showing 10 changed files with 200 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.nqmgaming.searchaddresslab.core.util

import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.pow
import kotlin.math.sin
import kotlin.math.sqrt

object CalculateDistance {
fun calculateDistance(
lat1: Double,
lon1: Double,
lat2: Double,
lon2: Double
): Double {
val earthRadius = 6371.0 // radius of the earth in kilometers

val latDistance = Math.toRadians(lat2 - lat1)
val lonDistance = Math.toRadians(lon2 - lon1)

val a = sin(latDistance / 2).pow(2.0) +
cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) *
sin(lonDistance / 2).pow(2.0)

val c = 2 * atan2(sqrt(a), sqrt(1 - a))

return earthRadius * c
}
}
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ fun Response.toDomainResponse(): DomainResponse {
localityType = item.localityType,
mapView = item.mapView?.asDomainMapView(),
title = item.title,
distance = item.distance
)
}
)
Original file line number Diff line number Diff line change
@@ -8,11 +8,12 @@ import retrofit2.http.GET
import retrofit2.http.Query

interface ApiService {
@GET("autocomplete")
suspend fun getGeocode(
@GET("autosuggest")
suspend fun getAddresses(
@Query("q") q: String,
@Query("apiKey") apiKey: String = API_KEY,
// @Query("at") at: String = CURRENT_LOCATION, this is for auto suggest
// @Query("in") inCountry: String = COUNTRY_CODE
@Query("at") at: String = CURRENT_LOCATION,
@Query("in") inCountry: String = COUNTRY_CODE
): Response

}
Original file line number Diff line number Diff line change
@@ -8,5 +8,5 @@ data class Item(
val politicalView: String?,
val position: Position?,
val title: String?,

val distance: Double?,
)
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@ class HereRepositoryImpl @Inject constructor(
return flow {
emit(Resources.Loading(true))
val hereList = try {
hereApi.getGeocode(q)
hereApi.getAddresses(q)
} catch (e: IOException) {
Log.e(TAG, "Get geocodes: ${e.stackTraceToString()}")
emit(Resources.Error("An error occurred while fetching data"))
Original file line number Diff line number Diff line change
@@ -7,4 +7,5 @@ data class Item(
val mapView: MapView?,
val position: Position?,
val title: String?,
var distance: Double?,
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.nqmgaming.searchaddresslab.presentation.screen.home

import android.Manifest
import android.content.pm.PackageManager
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
@@ -32,6 +34,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.app.ActivityCompat
import androidx.navigation.NavController
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted
@@ -58,14 +61,24 @@ fun HomeScreen(
context
)

var title = remember {
val title = remember {
mutableStateOf("Permission not granted yet!")
}

LaunchedEffect(key1 = title.value) {
locationPermission.launchPermissionRequest()

if (locationPermission.status.isGranted) {
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return@LaunchedEffect
}
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
// Got last known location. In some rare situations this can be null.
if (location != null) {
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.nqmgaming.searchaddresslab.presentation.screen.search

import android.Manifest
import android.content.pm.PackageManager
import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
@@ -23,7 +25,9 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableDoubleStateOf
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -37,16 +41,24 @@ import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.unit.dp
import androidx.core.app.ActivityCompat
import androidx.hilt.navigation.compose.hiltViewModel
import com.airbnb.lottie.compose.LottieAnimation
import com.airbnb.lottie.compose.LottieCompositionSpec
import com.airbnb.lottie.compose.LottieConstants
import com.airbnb.lottie.compose.animateLottieCompositionAsState
import com.airbnb.lottie.compose.rememberLottieComposition
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.rememberPermissionState
import com.google.android.gms.location.FusedLocationProviderClient
import com.google.android.gms.location.LocationServices
import com.nqmgaming.searchaddresslab.R
import com.nqmgaming.searchaddresslab.core.util.CalculateDistance.calculateDistance
import com.nqmgaming.searchaddresslab.core.util.NetworkUtils
import com.nqmgaming.searchaddresslab.presentation.screen.search.components.AddressItem

@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun SearchScreen(
modifier: Modifier = Modifier,
@@ -88,6 +100,51 @@ fun SearchScreen(

)

val locationPermission = rememberPermissionState(
Manifest.permission.ACCESS_FINE_LOCATION
)

val fusedLocationClient: FusedLocationProviderClient =
LocationServices.getFusedLocationProviderClient(
context
)

val lat = remember {
mutableDoubleStateOf(0.0)
}
val lng = remember {
mutableDoubleStateOf(0.0)
}

LaunchedEffect(key1 = lat.doubleValue, key2 = lng.doubleValue) {
locationPermission.launchPermissionRequest()

if (locationPermission.status.isGranted) {
if (ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_FINE_LOCATION
) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(
context,
Manifest.permission.ACCESS_COARSE_LOCATION
) != PackageManager.PERMISSION_GRANTED
) {
return@LaunchedEffect
}
fusedLocationClient.lastLocation.addOnSuccessListener { location ->
// Got last known location. In some rare situations this can be null.
if (location != null) {
// Logic to handle location object
try {
lat.doubleValue = location.latitude
lng.doubleValue = location.longitude
} catch (e: Exception) {
e.printStackTrace()
}
}
}
}
}

if (networkIsConnected) {
Column(
modifier = modifier.fillMaxSize(),
@@ -157,18 +214,30 @@ fun SearchScreen(
}
),

)
)
LazyColumn(
modifier = Modifier
.fillMaxSize()
.padding(top = 8.dp)
) {
addresses.items?.let {
items(it.size) { index ->
val address = it[index]

addresses.items?.let { items ->
items.forEach { address ->
address.distance = calculateDistance(
lat1 = lat.doubleValue,
lon1 = lng.doubleValue,
lat2 = address.position?.lat ?: 0.0,
lon2 = address.position?.lng ?: 0.0
)
}

val sortedItems = items.sortedBy { address -> address.distance }

items(sortedItems.size) { index ->
val address = sortedItems[index]
AddressItem(
item = address,
query = query
query = query,
)
}
}
Original file line number Diff line number Diff line change
@@ -66,6 +66,10 @@ class SearchScreenViewModel @Inject constructor(
delay(delayMillis)
onEvent(SearchScreenEvent.OnSearch(newQuery))
}
}else{
_state.value = _state.value.copy(
addresses = Response(items = emptyList())
)
}
}

Loading

0 comments on commit 39876a5

Please sign in to comment.