From 2b39f873b3ff1bf614e5f8a091f4b9e5ae5407fa Mon Sep 17 00:00:00 2001 From: Pedro Javier Date: Tue, 11 Aug 2026 08:51:44 +0200 Subject: [PATCH] Gasolinera app --- .../java/com/example/prueba/MainActivity.kt | 97 ++++++++++--------- .../java/com/example/prueba/MainScreen.kt | 21 ++-- .../prueba/data/GasStationRepository.kt | 3 +- 3 files changed, 61 insertions(+), 60 deletions(-) diff --git a/app/src/main/java/com/example/prueba/MainActivity.kt b/app/src/main/java/com/example/prueba/MainActivity.kt index cb850ad..aec3036 100644 --- a/app/src/main/java/com/example/prueba/MainActivity.kt +++ b/app/src/main/java/com/example/prueba/MainActivity.kt @@ -1,7 +1,6 @@ package com.example.prueba import android.Manifest -import android.annotation.SuppressLint import android.content.Intent import android.content.pm.PackageManager import android.location.Geocoder @@ -28,7 +27,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp import androidx.core.content.ContextCompat import com.example.prueba.data.GasStationInfo import com.example.prueba.data.GasStationRepository @@ -74,7 +72,6 @@ fun GasStationApp(repository: GasStationRepository) { var destinationQuery by remember { mutableStateOf("") } var isRouteActive by remember { mutableStateOf(false) } - var isReserveFilterActive by remember { mutableStateOf(false) } var destinationLocation by remember { mutableStateOf(null) } var hasPermission by remember { @@ -96,6 +93,7 @@ fun GasStationApp(repository: GasStationRepository) { withContext(Dispatchers.IO) { try { val geocoder = Geocoder(context, Locale.getDefault()) + @Suppress("DEPRECATION") val addresses = geocoder.getFromLocation(location.latitude, location.longitude, 1) if (!addresses.isNullOrEmpty()) { val address = addresses[0] @@ -107,29 +105,14 @@ fun GasStationApp(repository: GasStationRepository) { } } - LaunchedEffect(hasPermission, destinationLocation, selectedTab, isReserveFilterActive) { + // Registro del rastreador de GPS (Se ejecuta solo al inicio o si cambia el permiso) + LaunchedEffect(hasPermission) { if (hasPermission) { - val loc = lastLocation ?: LocationStorage.getLastLocation(context) - loc?.let { - // Primero recta para rapidez - stations = repository.getCheapestAndNearest( - userLocation = it, - maxDistanceKm = if (isReserveFilterActive) 40.0 else null, - destinationLocation = if (isRouteActive) destinationLocation else null, - getRealDistances = false - ) - // Luego real para precisión - scope.launch { - stations = repository.getCheapestAndNearest( - userLocation = it, - maxDistanceKm = if (isReserveFilterActive) 40.0 else null, - destinationLocation = if (isRouteActive) destinationLocation else null, - getRealDistances = true - ) - } - } - if (selectedTab == 0) isLoading = true + val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context) + // Cargar ubicación inicial guardada para no empezar de cero + LocationStorage.getLastLocation(context)?.let { lastLocation = it } + val locationRequest = LocationRequest.Builder(Priority.PRIORITY_HIGH_ACCURACY, 15000) .setMinUpdateDistanceMeters(500f) .build() @@ -139,24 +122,10 @@ fun GasStationApp(repository: GasStationRepository) { val location = result.lastLocation ?: return lastLocation = location LocationStorage.saveLocation(context, location) - if (selectedTab == 0) { - scope.launch { - updateAddress(location) - stations = repository.getCheapestAndNearest( - userLocation = location, - maxDistanceKm = if (isReserveFilterActive) 40.0 else null, - destinationLocation = if (isRouteActive) destinationLocation else null, - getRealDistances = true - ) - isLoading = false - } - } else { - isLoading = false - } + scope.launch { updateAddress(location) } } } - val fusedLocationClient = LocationServices.getFusedLocationProviderClient(context) try { if (ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, android.os.Looper.getMainLooper()) @@ -167,6 +136,36 @@ fun GasStationApp(repository: GasStationRepository) { } } + // Actualizador de la lista de gasolineras (Reacciona al movimiento del GPS) + LaunchedEffect(hasPermission, destinationLocation, selectedTab, isRouteActive, lastLocation) { + if (hasPermission) { + val loc = lastLocation ?: LocationStorage.getLastLocation(context) + + loc?.let { + if (selectedTab == 0) { + // 1. Carga ultra-rápida (recta) + stations = repository.getCheapestAndNearest( + userLocation = it, + destinationLocation = if (isRouteActive) destinationLocation else null, + getRealDistances = false + ) + + // 2. Carga de precisión (carretera) + val realStations = repository.getCheapestAndNearest( + userLocation = it, + destinationLocation = if (isRouteActive) destinationLocation else null, + getRealDistances = true + ) + if (realStations.isNotEmpty()) { + stations = realStations + } + isLoading = false + } + } + if (selectedTab == 0 && stations.isEmpty()) isLoading = true + } + } + Scaffold( modifier = Modifier.fillMaxSize(), topBar = { @@ -187,6 +186,7 @@ fun GasStationApp(repository: GasStationRepository) { withContext(Dispatchers.IO) { try { val geocoder = Geocoder(context, Locale.getDefault()) + @Suppress("DEPRECATION") val results = geocoder.getFromLocationName(destinationQuery, 1) if (!results.isNullOrEmpty()) { destinationLocation = android.location.Location("").apply { @@ -257,8 +257,8 @@ fun GasStationApp(repository: GasStationRepository) { scope.launch { stations = repository.getCheapestAndNearest( userLocation = loc, forceRefresh = true, - maxDistanceKm = if (isReserveFilterActive) 40.0 else null, - destinationLocation = if (isRouteActive) destinationLocation else null + destinationLocation = if (isRouteActive) destinationLocation else null, + getRealDistances = true ) isRefreshing = false } @@ -269,7 +269,7 @@ fun GasStationApp(repository: GasStationRepository) { if (isLoading && stations.isEmpty()) { CircularProgressIndicator(modifier = Modifier.align(Alignment.Center)) } else if (stations.isEmpty()) { - Text(if (isReserveFilterActive) "No hay nada a menos de 40km" else "Sin resultados", modifier = Modifier.align(Alignment.Center)) + Text("Sin resultados", modifier = Modifier.align(Alignment.Center)) } else { GasStationList(stations = stations, onLogClick = { showFuelDialog = it }) } @@ -454,10 +454,15 @@ fun GasStationItem(station: GasStationInfo, onClick: () -> Unit, onLogClick: () Text(text = "Premium: $premium €/L", style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.secondary, fontWeight = FontWeight.Medium) } } - Button(onClick = onLogClick, contentPadding = PaddingValues(horizontal = 12.dp, vertical = 4.dp), shape = MaterialTheme.shapes.small) { - Icon(Icons.Default.Add, null, modifier = Modifier.size(16.dp)) - Spacer(modifier = Modifier.width(4.dp)) - Text("Registrar") + FilledTonalIconButton( + onClick = onLogClick, + modifier = Modifier.size(40.dp) + ) { + Icon( + imageVector = Icons.Default.Add, + contentDescription = "Registrar repostaje", + modifier = Modifier.size(24.dp) + ) } } } diff --git a/app/src/main/java/com/example/prueba/MainScreen.kt b/app/src/main/java/com/example/prueba/MainScreen.kt index ded714d..8b96cc0 100644 --- a/app/src/main/java/com/example/prueba/MainScreen.kt +++ b/app/src/main/java/com/example/prueba/MainScreen.kt @@ -24,7 +24,6 @@ class MainScreen(carContext: CarContext) : Screen(carContext) { private var gasStations: List = emptyList() private var currentAddress: String? = null private var isLoading = true - private var isReserveFilterActive = false private val repository = GasStationRepository() init { @@ -54,17 +53,13 @@ class MainScreen(carContext: CarContext) : Screen(carContext) { LocationStorage.getLastLocation(carContext)?.let { lastLoc -> lifecycleScope.launch { updateAddress(lastLoc) - // Primero recta gasStations = repository.getCheapestAndNearest( userLocation = lastLoc, - maxDistanceKm = if (isReserveFilterActive) 40.0 else null, getRealDistances = false ) invalidate() - // Luego real gasStations = repository.getCheapestAndNearest( userLocation = lastLoc, - maxDistanceKm = if (isReserveFilterActive) 40.0 else null, getRealDistances = true ) invalidate() @@ -85,12 +80,15 @@ class MainScreen(carContext: CarContext) : Screen(carContext) { gasStations = repository.getCheapestAndNearest( userLocation = location, forceRefresh = forceRefresh, - maxDistanceKm = if (isReserveFilterActive) 40.0 else null, getRealDistances = true ) isLoading = false invalidate() } + if (forceRefresh) { + fusedLocationClient.removeLocationUpdates(this) + fetchLocationAndGasStations(false) + } } } @@ -100,13 +98,12 @@ class MainScreen(carContext: CarContext) : Screen(carContext) { override fun onGetTemplate(): Template { val listBuilder = ItemList.Builder() - val reserveAction = Action.Builder() - .setTitle(if (isReserveFilterActive) "Todo" else "Reserva") + val refreshAction = Action.Builder() + .setTitle("Refrescar") .setOnClickListener { - isReserveFilterActive = !isReserveFilterActive isLoading = true invalidate() - fetchLocationAndGasStations(forceRefresh = false) + fetchLocationAndGasStations(forceRefresh = true) } .build() @@ -119,7 +116,7 @@ class MainScreen(carContext: CarContext) : Screen(carContext) { if (gasStations.isEmpty()) { return MessageTemplate.Builder("Sin resultados") - .setHeader(Header.Builder().setTitle("Gasolineras").addEndHeaderAction(reserveAction).build()) + .setHeader(Header.Builder().setTitle("Gasolineras").addEndHeaderAction(refreshAction).build()) .addAction(Action.Builder().setTitle("Reintentar").setOnClickListener { isLoading = true invalidate() @@ -180,7 +177,7 @@ class MainScreen(carContext: CarContext) : Screen(carContext) { .setHeader( Header.Builder() .setTitle(currentAddress ?: "Gasolineras Diésel") - .addEndHeaderAction(reserveAction) + .addEndHeaderAction(refreshAction) .build() ) .build() diff --git a/app/src/main/java/com/example/prueba/data/GasStationRepository.kt b/app/src/main/java/com/example/prueba/data/GasStationRepository.kt index 983cae7..42b0fcb 100644 --- a/app/src/main/java/com/example/prueba/data/GasStationRepository.kt +++ b/app/src/main/java/com/example/prueba/data/GasStationRepository.kt @@ -25,7 +25,6 @@ class GasStationRepository { suspend fun getCheapestAndNearest( userLocation: Location, forceRefresh: Boolean = false, - maxDistanceKm: Double? = null, destinationLocation: Location? = null, getRealDistances: Boolean = false ): List { @@ -75,7 +74,7 @@ class GasStationRepository { } ?: emptyList() // Radio máximo: 30km si es local, 400km si hay destino (ruta larga) - val finalMaxDist = maxDistanceKm ?: if (destinationLocation == null) 30.0 else 400.0 + val finalMaxDist = if (destinationLocation == null) 30.0 else 400.0 val filtered = allStations.filter { (it.distance / 1000.0) <= finalMaxDist }