Stopover and Legs, ManeuverType

This commit is contained in:
Dimitris
2026-04-01 16:24:51 +02:00
parent 6838ad09c4
commit 52f8dec2e6
28 changed files with 208 additions and 281 deletions
+2 -2
View File
@@ -17,8 +17,8 @@ android {
applicationId = "com.kouros.navigation" applicationId = "com.kouros.navigation"
minSdk = 33 minSdk = 33
targetSdk = 36 targetSdk = 36
versionCode = 87 versionCode = 90
versionName = "0.2.0.87" versionName = "0.2.3.90"
base.archivesName = "navi-$versionName" base.archivesName = "navi-$versionName"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }
@@ -179,7 +179,7 @@ fun Categories(
modifier = Modifier.horizontalScroll(scrollState) modifier = Modifier.horizontalScroll(scrollState)
) { ) {
Button(onClick = { Button(onClick = {
val places = viewModel.loadRecentPlace(applicationContext) val places = viewModel.loadRecentPlaces(applicationContext)
val toLocation = location(places.first()!!.longitude, places.first()!!.latitude) val toLocation = location(places.first()!!.longitude, places.first()!!.latitude)
viewModel.loadRoute(applicationContext, location, listOf(toLocation), 0F) viewModel.loadRoute(applicationContext, location, listOf(toLocation), 0F)
closeSheet() closeSheet()
@@ -116,7 +116,7 @@ fun Home(
) { ) {
Row(horizontalArrangement = Arrangement.SpaceBetween) { Row(horizontalArrangement = Arrangement.SpaceBetween) {
Button(onClick = { Button(onClick = {
val places = viewModel.loadRecentPlace(applicationContext) val places = viewModel.loadRecentPlaces(applicationContext)
val toLocation = location(places.first()!!.longitude, places.first()!!.latitude) val toLocation = location(places.first()!!.longitude, places.first()!!.latitude)
viewModel.loadRoute(applicationContext, location, listOf(toLocation), 0F) viewModel.loadRoute(applicationContext, location, listOf(toLocation), 0F)
closeSheet() closeSheet()
@@ -104,6 +104,10 @@ internal class ClusterSession : Session(), NavigationListener {
} }
override fun recalcRoute(destination: Place) {
}
companion object { companion object {
val TAG: String = ClusterSession::class.java.getSimpleName() val TAG: String = ClusterSession::class.java.getSimpleName()
} }
@@ -475,26 +475,27 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
val streetName = routeModel.currentStep().street val streetName = routeModel.currentStep().street
val currentDate = LocalDateTime.now(ZoneOffset.UTC) val currentDate = LocalDateTime.now(ZoneOffset.UTC)
snapLocation(location, streetName) if (snapLocation(location, streetName)) {
checkTraffic(currentDate, location) checkTraffic(currentDate, location)
updateSpeedCamera(location) updateSpeedCamera(location)
checkRoute(currentDate, location) checkRoute(currentDate, location)
updateNavigationScreen() updateNavigationScreen()
checkArrival() checkArrival()
} }
}
/** /**
* Updates the surface renderer with snapped location and street name. * Updates the surface renderer with snapped location and street name.
* Checks if maximal route deviation is exceeded and reroutes if needed. * Checks if maximal route deviation is exceeded and reroutes if needed.
*/ */
private fun snapLocation(location: Location, streetName: String) { private fun snapLocation(location: Location, streetName: String) : Boolean {
val snappedLocation = snapLocation(location, routeModel.route.maneuverLocations()) val snappedLocation = snapLocation(location, routeModel.route.maneuverLocations())
val distance = location.distanceTo(snappedLocation) val distance = location.distanceTo(snappedLocation)
when { when {
distance > MAXIMAL_ROUTE_DEVIATION -> { distance > MAXIMAL_ROUTE_DEVIATION -> {
stopNavigation() stopNavigation()
navigationScreen.calculateNewRoute(routeModel.navState.destination) navigationScreen.calculateNewRoute(routeModel.navState.destination)
return false
} }
distance < MAXIMAL_SNAP_CORRECTION -> { distance < MAXIMAL_SNAP_CORRECTION -> {
@@ -505,6 +506,7 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
surfaceRenderer.updateLocation(location, streetName) surfaceRenderer.updateLocation(location, streetName)
} }
} }
return true
} }
/** /**
@@ -616,7 +618,6 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
navigationScreen.navigationType = NavigationType.VIEW navigationScreen.navigationType = NavigationType.VIEW
if (notificationActive) if (notificationActive)
notificationManager.stopNotificationService() notificationManager.stopNotificationService()
Log.d(TAG, "end stopNavigation")
} }
override fun updateTrip(trip: Trip) { override fun updateTrip(trip: Trip) {
@@ -625,6 +626,19 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
} }
} }
/**
* Recalculates a route for the specified place.
*/
override fun recalcRoute(destination: Place) {
val destination = location(destination.longitude, destination.latitude)
navigationViewModel.loadRoute(
carContext,
surfaceRenderer.lastLocation,
listOf(destination),
surfaceRenderer.carOrientation
)
}
/** /**
* Handle guidance audio * Handle guidance audio
* Called when user wants to hear the step-by-step instructions * Called when user wants to hear the step-by-step instructions
@@ -646,6 +660,7 @@ class NavigationSession : Session(), NavigationListener, NavigationObserverCallb
* Starts navigation and invalidates the screen. * Starts navigation and invalidates the screen.
*/ */
override fun onRouteReceived(route: String) { override fun onRouteReceived(route: String) {
Log.d(TAG, "onRouteReceived")
if (route.isNotEmpty()) { if (route.isNotEmpty()) {
this.route = route this.route = route
if (routeModel.isNavigating()) { if (routeModel.isNavigating()) {
@@ -31,7 +31,7 @@ import com.kouros.navigation.car.map.getPaddingValues
import com.kouros.navigation.car.navigation.RouteCarModel import com.kouros.navigation.car.navigation.RouteCarModel
import com.kouros.navigation.data.Constants.TAG import com.kouros.navigation.data.Constants.TAG
import com.kouros.navigation.data.Constants.TILT import com.kouros.navigation.data.Constants.TILT
import com.kouros.navigation.data.Constants.homeVogelhart import com.kouros.navigation.data.DarkMode
import com.kouros.navigation.data.RouteEngine import com.kouros.navigation.data.RouteEngine
import com.kouros.navigation.data.ViewStyle import com.kouros.navigation.data.ViewStyle
import com.kouros.navigation.model.BaseStyleModel import com.kouros.navigation.model.BaseStyleModel
@@ -59,7 +59,7 @@ import java.time.LocalDateTime
*/ */
class SurfaceRenderer( class SurfaceRenderer(
private var carContext: CarContext, private var carContext: CarContext,
private var lifecycle: Lifecycle, lifecycle: Lifecycle,
//private var routeModel: RouteCarModel, //private var routeModel: RouteCarModel,
private var viewModelStoreOwner: ViewModelStoreOwner private var viewModelStoreOwner: ViewModelStoreOwner
) : DefaultLifecycleObserver { ) : DefaultLifecycleObserver {
@@ -74,10 +74,6 @@ class SurfaceRenderer(
val cameraPosition = MutableLiveData( val cameraPosition = MutableLiveData(
CameraPosition( CameraPosition(
zoom = 16.0, zoom = 16.0,
target = Position(
latitude = homeVogelhart.latitude,
longitude = homeVogelhart.longitude
)
) )
) )
@@ -164,7 +160,7 @@ class SurfaceRenderer(
lifecycleOwner = CustomLifecycleOwner() lifecycleOwner = CustomLifecycleOwner()
lifecycleOwner.performRestore(null) lifecycleOwner.performRestore(null)
// technically, we only really need any one of these instead of all 3 // technically, we only really need any one of these instead of all 3
// i add them to be consistent with the actual lifecycle. // add them to be consistent with the actual lifecycle.
lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_CREATE) lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_CREATE)
lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_START) lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_START)
lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_RESUME) lifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_RESUME)
@@ -251,10 +247,6 @@ class SurfaceRenderer(
speed.value = 0F speed.value = 0F
} }
fun onBaseStyleStateUpdated(style: BaseStyle) {
}
/** /**
* Composable function that renders the map and navigation UI. * Composable function that renders the map and navigation UI.
* Observes various LiveData sources and updates the map accordingly. * Observes various LiveData sources and updates the map accordingly.
@@ -272,7 +264,8 @@ class SurfaceRenderer(
val paddingValues = getPaddingValues(height, viewStyle) val paddingValues = getPaddingValues(height, viewStyle)
val cameraState = cameraState(paddingValues, position, tilt) val cameraState = cameraState(paddingValues, position, tilt)
val baseStyle = BaseStyleModel().readStyle(carContext, darkMode, carContext.isDarkMode) val baseStyle = BaseStyleModel().readStyle(carContext, darkMode, carContext.isDarkMode)
val dark = darkMode == 1 || darkMode == 2 && carContext.isDarkMode val dark = darkMode == DarkMode.DARK.ordinal
|| (darkMode == DarkMode.USE_CAR.ordinal && carContext.isDarkMode)
MapLibre( MapLibre(
cameraState, cameraState,
@@ -334,7 +327,6 @@ class SurfaceRenderer(
} }
override fun onCreate(owner: LifecycleOwner) { override fun onCreate(owner: LifecycleOwner) {
style.observe(owner, ::onBaseStyleStateUpdated)
Log.i(TAG, "SurfaceRenderer created") Log.i(TAG, "SurfaceRenderer created")
carContext.getCarService(AppManager::class.java) carContext.getCarService(AppManager::class.java)
.setSurfaceCallback(mSurfaceCallback) .setSurfaceCallback(mSurfaceCallback)
@@ -499,18 +491,6 @@ class SurfaceRenderer(
} }
} }
/**
* Updates car location from the connected car system.
* Only updates location when using OSRM routing engine.
*/
fun updateCarLocation(location: Location, streetName: String) {
val repository = getSettingsRepository(carContext)
val routingEngine = runBlocking { repository.routingEngineFlow.first() }
if (routingEngine == RouteEngine.OSRM.ordinal) {
updateLocation(location, streetName)
}
}
/** /**
* Updates current speed for display. * Updates current speed for display.
*/ */
@@ -146,10 +146,10 @@ fun RouteLayer(routeData: String?, trafficData: Map<String, String>) {
interpolate( interpolate(
type = exponential(1.2f), type = exponential(1.2f),
input = zoom(), input = zoom(),
5 to const(0.4.dp), 5 to const(0.7.dp),
6 to const(0.7.dp), 6 to const(1.0.dp),
7 to const(1.75.dp), 7 to const(2.4.dp),
20 to const(22.dp), 20 to const(26.dp),
), ),
) )
} }
@@ -3,6 +3,7 @@ package com.kouros.navigation.car.navigation
import android.text.SpannableString import android.text.SpannableString
import android.text.SpannableStringBuilder import android.text.SpannableStringBuilder
import android.text.Spanned import android.text.Spanned
import android.util.Log
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.car.app.AppManager import androidx.car.app.AppManager
import androidx.car.app.CarContext import androidx.car.app.CarContext
@@ -54,7 +55,7 @@ class RouteCarModel : RouteModel() {
val step = val step =
Step.Builder(currentStepCueWithImage) Step.Builder(currentStepCueWithImage)
step.setRoad(navState.destination.street!!) step.setRoad(navState.destination.street)
if (stepData.lane.isNotEmpty()) { if (stepData.lane.isNotEmpty()) {
val lanesAdded = addLanes(carContext, step, stepData) val lanesAdded = addLanes(carContext, step, stepData)
if (lanesAdded) { if (lanesAdded) {
@@ -16,4 +16,6 @@ interface NavigationListener {
fun updateTrip(trip: Trip) fun updateTrip(trip: Trip)
fun navigateToPlace(place: Place) fun navigateToPlace(place: Place)
fun recalcRoute(destination: Place)
} }
@@ -2,6 +2,7 @@ package com.kouros.navigation.car.screen
import android.os.CountDownTimer import android.os.CountDownTimer
import android.os.Handler import android.os.Handler
import android.util.Log
import androidx.car.app.CarContext import androidx.car.app.CarContext
import androidx.car.app.Screen import androidx.car.app.Screen
import androidx.car.app.model.Action import androidx.car.app.model.Action
@@ -32,6 +33,7 @@ import com.kouros.data.R
import com.kouros.navigation.car.SurfaceRenderer import com.kouros.navigation.car.SurfaceRenderer
import com.kouros.navigation.car.screen.settings.SettingsScreen import com.kouros.navigation.car.screen.settings.SettingsScreen
import com.kouros.navigation.data.Constants import com.kouros.navigation.data.Constants
import com.kouros.navigation.data.Constants.TAG
import com.kouros.navigation.data.Place import com.kouros.navigation.data.Place
import com.kouros.navigation.data.ViewStyle import com.kouros.navigation.data.ViewStyle
import com.kouros.navigation.model.NavigationViewModel import com.kouros.navigation.model.NavigationViewModel
@@ -471,25 +473,14 @@ open class NavigationScreen(
override fun onTick(millisUntilFinished: Long) {} override fun onTick(millisUntilFinished: Long) {}
override fun onFinish() { override fun onFinish() {
navigationType = NavigationType.NAVIGATION navigationType = NavigationType.NAVIGATION
reRoute(destination) listener.recalcRoute(destination)
} }
} }
reRouteTimer?.start() reRouteTimer?.start()
} }
} }
/**
* Re-requests a route for the specified place.
*/
fun reRoute(place: Place) {
val destination = location(place.longitude, place.latitude)
navigationViewModel.loadRoute(
carContext,
surfaceRenderer.lastLocation,
listOf(destination),
surfaceRenderer.carOrientation
)
}
/** /**
* Updates navigation state with the current location, checks for arrival, and traffic updates. * Updates navigation state with the current location, checks for arrival, and traffic updates.
@@ -6,7 +6,7 @@ val NavigationColorLight = Color(0xFF17A119)
val NavigationColorDark = Color(0xFF4EDE10) val NavigationColorDark = Color(0xFF4EDE10)
val RouteColor = Color(0xFF05692D) val RouteColor = Color(0xFF195D02)
val SpeedColor = Color(0xFF262525) val SpeedColor = Color(0xFF262525)
@@ -17,9 +17,11 @@
package com.kouros.navigation.data package com.kouros.navigation.data
import android.net.Uri import android.net.Uri
import com.google.gson.annotations.Expose
import com.kouros.navigation.data.route.Lane import com.kouros.navigation.data.route.Lane
import com.kouros.navigation.utils.location import com.kouros.navigation.utils.location
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
data class Category( data class Category(
val id: String, val id: String,
@@ -27,6 +29,7 @@ data class Category(
) )
data class Places( data class Places(
val places: List<Place>, val places: List<Place>,
) )
@@ -41,11 +44,15 @@ data class Place(
var postalCode: String = "", var postalCode: String = "",
var city: String = "", var city: String = "",
var street: String = "", var street: String = "",
@Transient
var distance: Float = 0F, var distance: Float = 0F,
//var avatar: Uri? = null, //var avatar: Uri? = null,
var lastDate: Long = 0, var lastDate: Long = 0,
@Transient
var routeIndex: Int = 0, var routeIndex: Int = 0,
@Transient
var route: String = "", var route: String = "",
@Transient
var stopOver: Boolean = false, var stopOver: Boolean = false,
) )
@@ -113,8 +120,6 @@ object Constants {
const val CHARGING_STATION: String ="charging_station" const val CHARGING_STATION: String ="charging_station"
val categories = listOf("Tankstelle", "Apotheke", "Ladestationen")
/** The initial location to use as an anchor for searches. */ /** The initial location to use as an anchor for searches. */
val homeVogelhart = location(11.5793748, 48.185749) val homeVogelhart = location(11.5793748, 48.185749)
val homeHohenwaldeck = location( 11.594322, 48.1164817) val homeHohenwaldeck = location( 11.594322, 48.1164817)
@@ -158,6 +163,10 @@ enum class RouteEngine {
VALHALLA, OSRM, TOMTOM VALHALLA, OSRM, TOMTOM
} }
enum class DarkMode {
LIGHT, DARK, USE_CAR
}
enum class EngineType { enum class EngineType {
COMBUSTION, ELECTRIC COMBUSTION, ELECTRIC
} }
@@ -3,67 +3,67 @@ package com.kouros.navigation.data.route
import android.location.Location import android.location.Location
data class Maneuver( data class Maneuver(
val bearingBefore : Int = 0, val bearingBefore: Int = 0,
val bearingAfter : Int = 0, val bearingAfter: Int = 0,
val type: Int = 0, val type: Int = 0,
val waypoints: List<List<Double>>, val waypoints: List<List<Double>>,
val location: Location, val location: Location,
val exit: Int = 0, val exit: Int = 0,
val street: String = "", val street: String = "",
val message: String = "", val message: String = "",
val pointIndex : Int = 0, val pointIndex: Int = 0,
) )
enum class ManeuverType { enum class ManeuverType(val value: Int) {
TYPE_UNKNOWN, TYPE_UNKNOWN(0),
TYPE_DEPART, TYPE_DEPART(1),
TYPE_NAME_CHANGE, TYPE_NAME_CHANGE(2),
TYPE_KEEP_LEFT, TYPE_KEEP_LEFT(3),
TYPE_KEEP_RIGHT, TYPE_KEEP_RIGHT(4),
TYPE_TURN_SLIGHT_LEFT, TYPE_TURN_SLIGHT_LEFT(5),
TYPE_TURN_SLIGHT_RIGHT, TYPE_TURN_SLIGHT_RIGHT(6),
TYPE_TURN_NORMAL_LEFT, TYPE_TURN_NORMAL_LEFT(7),
TYPE_TURN_NORMAL_RIGHT, TYPE_TURN_NORMAL_RIGHT(8),
TYPE_TURN_SHARP_LEFT, TYPE_TURN_SHARP_LEFT(9),
TYPE_TURN_SHARP_RIGHT, TYPE_TURN_SHARP_RIGHT(10),
TYPE_U_TURN_LEFT, TYPE_U_TURN_LEFT(11),
TYPE_U_TURN_RIGHT, TYPE_U_TURN_RIGHT(12),
TYPE_ON_RAMP_SLIGHT_LEFT, TYPE_ON_RAMP_SLIGHT_LEFT(13),
TYPE_ON_RAMP_SLIGHT_RIGHT, TYPE_ON_RAMP_SLIGHT_RIGHT(14),
TYPE_ON_RAMP_NORMAL_LEFT, TYPE_ON_RAMP_NORMAL_LEFT(15),
TYPE_ON_RAMP_NORMAL_RIGHT, TYPE_ON_RAMP_NORMAL_RIGHT(16),
TYPE_ON_RAMP_SHARP_LEFT, TYPE_ON_RAMP_SHARP_LEFT(17),
TYPE_ON_RAMP_SHARP_RIGHT, TYPE_ON_RAMP_SHARP_RIGHT(18),
TYPE_ON_RAMP_U_TURN_LEFT, TYPE_ON_RAMP_U_TURN_LEFT(19),
TYPE_ON_RAMP_U_TURN_RIGHT, TYPE_ON_RAMP_U_TURN_RIGHT(20),
TYPE_OFF_RAMP_SLIGHT_LEFT, TYPE_OFF_RAMP_SLIGHT_LEFT(21),
TYPE_OFF_RAMP_SLIGHT_RIGHT, TYPE_OFF_RAMP_SLIGHT_RIGHT(22),
TYPE_OFF_RAMP_NORMAL_LEFT, TYPE_OFF_RAMP_NORMAL_LEFT(23),
TYPE_OFF_RAMP_NORMAL_RIGHT, TYPE_OFF_RAMP_NORMAL_RIGHT(24),
TYPE_FORK_LEFT, TYPE_FORK_LEFT(25),
TYPE_FORK_RIGHT, TYPE_FORK_RIGHT(26),
TYPE_MERGE_LEFT, TYPE_MERGE_LEFT(27),
TYPE_MERGE_RIGHT, TYPE_MERGE_RIGHT(28),
TYPE_MERGE_SIDE_UNSPECIFIED, TYPE_MERGE_SIDE_UNSPECIFIED (29),
TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW, TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW (32),
TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE, TYPE_ROUNDABOUT_ENTER_AND_EXIT_CW_WITH_ANGLE(33),
TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW, TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW(34),
TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE, TYPE_ROUNDABOUT_ENTER_AND_EXIT_CCW_WITH_ANGLE(35),
TYPE_STRAIGHT, TYPE_STRAIGHT(36),
TYPE_FERRY_BOAT, TYPE_FERRY_BOAT (37),
TYPE_FERRY_TRAIN, TYPE_FERRY_TRAIN (38),
TYPE_DESTINATION, TYPE_DESTINATION (39),
TYPE_DESTINATION_STRAIGHT, TYPE_DESTINATION_STRAIGHT (40),
TYPE_DESTINATION_LEFT, TYPE_DESTINATION_LEFT(41),
TYPE_DESTINATION_RIGHT, TYPE_DESTINATION_RIGHT(42),
TYPE_ROUNDABOUT_ENTER_CW, TYPE_ROUNDABOUT_ENTER_CW(43),
TYPE_ROUNDABOUT_EXIT_CW, TYPE_ROUNDABOUT_EXIT_CW(44),
TYPE_ROUNDABOUT_ENTER_CCW, TYPE_ROUNDABOUT_ENTER_CCW(45),
TYPE_ROUNDABOUT_EXIT_CCW, TYPE_ROUNDABOUT_EXIT_CCW(46),
TYPE_FERRY_BOAT_LEFT, TYPE_FERRY_BOAT_LEFT(47),
TYPE_FERRY_BOAT_RIGHT, TYPE_FERRY_BOAT_RIGHT(48),
TYPE_FERRY_TRAIN_LEFT, TYPE_FERRY_TRAIN_LEFT(49),
TYPE_FERRY_TRAIN_RIGHT, TYPE_FERRY_TRAIN_RIGHT(50),
TYPE_WAYPOINT_RIGHT, TYPE_WAYPOINT_RIGHT(51),
TYPE_WAYPOINT_LEFT TYPE_WAYPOINT_LEFT(52),
} }
@@ -1,5 +0,0 @@
package com.kouros.navigation.data.tomtom
data class Cause(
val mainCauseCode: Int
)
@@ -1,10 +0,0 @@
package com.kouros.navigation.data.tomtom
import com.google.gson.annotations.SerializedName
data class Events (
@SerializedName("description" ) var description : String? = null
)
@@ -1,12 +0,0 @@
package com.kouros.navigation.data.tomtom
import com.google.gson.annotations.SerializedName
data class Features (
@SerializedName("type" ) var type : String? = null,
@SerializedName("properties" ) var properties : Properties? = Properties(),
@SerializedName("geometry" ) var geometry : Geometry? = Geometry()
)
@@ -1,11 +0,0 @@
package com.kouros.navigation.data.tomtom
import com.google.gson.annotations.SerializedName
data class Geometry (
@SerializedName("type" ) var type : String? = null,
@SerializedName("coordinates" ) var coordinates : List<List<Double>> = arrayListOf()
)
@@ -1,12 +0,0 @@
package com.kouros.navigation.data.tomtom
import com.google.gson.annotations.SerializedName
data class Incidents (
@SerializedName("type" ) var type : String? = null,
@SerializedName("properties" ) var properties : Properties? = Properties(),
@SerializedName("geometry" ) var geometry : Geometry? = Geometry()
)
@@ -1,11 +0,0 @@
package com.kouros.navigation.data.tomtom
import com.google.gson.annotations.SerializedName
data class Properties (
@SerializedName("iconCategory" ) var iconCategory : Int? = null,
@SerializedName("events" ) var events : ArrayList<Events> = arrayListOf()
)
@@ -142,79 +142,79 @@ class TomTomRoute {
var newType = 0 var newType = 0
when (type) { when (type) {
"DEPART" -> { "DEPART" -> {
newType = ManeuverType.TYPE_DEPART.ordinal newType = ManeuverType.TYPE_DEPART.value
} }
"ARRIVE" -> { "ARRIVE" -> {
newType = ManeuverType.TYPE_DESTINATION.ordinal newType = ManeuverType.TYPE_DESTINATION.value
} }
"ARRIVE_LEFT" -> { "ARRIVE_LEFT" -> {
newType = ManeuverType.TYPE_DESTINATION_LEFT.ordinal newType = ManeuverType.TYPE_DESTINATION_LEFT.value
} }
"ARRIVE_RIGHT" -> { "ARRIVE_RIGHT" -> {
newType = ManeuverType.TYPE_DESTINATION_RIGHT.ordinal newType = ManeuverType.TYPE_DESTINATION_RIGHT.value
} }
"STRAIGHT", "FOLLOW" -> { "STRAIGHT", "FOLLOW" -> {
newType = ManeuverType.TYPE_STRAIGHT.ordinal newType = ManeuverType.TYPE_STRAIGHT.value
} }
"KEEP_RIGHT" -> { "KEEP_RIGHT" -> {
newType = ManeuverType.TYPE_KEEP_RIGHT.ordinal newType = ManeuverType.TYPE_KEEP_RIGHT.value
} }
"BEAR_RIGHT" -> { "BEAR_RIGHT" -> {
newType = ManeuverType.TYPE_TURN_SLIGHT_RIGHT.ordinal newType = ManeuverType.TYPE_TURN_SLIGHT_RIGHT.value
} }
"BEAR_LEFT" -> { "BEAR_LEFT" -> {
newType = ManeuverType.TYPE_TURN_SLIGHT_LEFT.ordinal newType = ManeuverType.TYPE_TURN_SLIGHT_LEFT.value
} }
"KEEP_LEFT" -> { "KEEP_LEFT" -> {
newType = ManeuverType.TYPE_KEEP_LEFT.ordinal newType = ManeuverType.TYPE_KEEP_LEFT.value
} }
"TURN_LEFT" -> { "TURN_LEFT" -> {
newType = ManeuverType.TYPE_TURN_NORMAL_LEFT.ordinal newType = ManeuverType.TYPE_TURN_NORMAL_LEFT.value
} }
"TURN_RIGHT" -> { "TURN_RIGHT" -> {
newType = ManeuverType.TYPE_TURN_NORMAL_RIGHT.ordinal newType = ManeuverType.TYPE_TURN_NORMAL_RIGHT.value
} }
"SHARP_LEFT" -> { "SHARP_LEFT" -> {
newType = ManeuverType.TYPE_TURN_SHARP_LEFT.ordinal newType = ManeuverType.TYPE_TURN_SHARP_LEFT.value
} }
"SHARP_RIGHT" -> { "SHARP_RIGHT" -> {
newType = ManeuverType.TYPE_TURN_SHARP_RIGHT.ordinal newType = ManeuverType.TYPE_TURN_SHARP_RIGHT.value
} }
"ROUNDABOUT_RIGHT", "ROUNDABOUT_CROSS" -> { "ROUNDABOUT_RIGHT", "ROUNDABOUT_CROSS" -> {
newType = ManeuverType.TYPE_ROUNDABOUT_ENTER_CCW.ordinal newType = ManeuverType.TYPE_ROUNDABOUT_ENTER_CCW.value
} }
"ROUNDABOUT_LEFT" -> { "ROUNDABOUT_LEFT" -> {
newType = ManeuverType.TYPE_ROUNDABOUT_ENTER_CW.ordinal newType = ManeuverType.TYPE_ROUNDABOUT_ENTER_CW.value
} }
"MAKE_UTURN", "TRY_MAKE_UTURN" -> { "MAKE_UTURN", "TRY_MAKE_UTURN" -> {
newType = ManeuverType.TYPE_U_TURN_LEFT.ordinal newType = ManeuverType.TYPE_U_TURN_LEFT.value
} }
"ENTER_MOTORWAY" -> { "ENTER_MOTORWAY" -> {
newType = ManeuverType.TYPE_MERGE_LEFT.ordinal newType = ManeuverType.TYPE_MERGE_LEFT.value
} }
"TAKE_EXIT" -> { "TAKE_EXIT" -> {
newType = ManeuverType.TYPE_TURN_SLIGHT_RIGHT.ordinal newType = ManeuverType.TYPE_TURN_SLIGHT_RIGHT.value
} }
"WAYPOINT_RIGHT" -> { "WAYPOINT_RIGHT" -> {
newType = ManeuverType.TYPE_WAYPOINT_RIGHT.ordinal newType = ManeuverType.TYPE_WAYPOINT_RIGHT.value
} }
} }
return newType return newType
@@ -1,12 +0,0 @@
package com.kouros.navigation.data.tomtom
import com.google.gson.annotations.SerializedName
data class Traffic (
//@SerializedName("incidents" ) var incidents : ArrayList<Incidents> = arrayListOf()
@SerializedName("type" ) var type : String = "",
@SerializedName("features" ) var features : ArrayList<Features> = arrayListOf()
)
@@ -1,6 +0,0 @@
package com.kouros.navigation.data.tomtom
data class TrafficData (
var traffic : Traffic ,
var trafficData: String = ""
)
@@ -19,64 +19,64 @@ class IconMapper {
fun maneuverIcon(routeManeuverType: Int): Int { fun maneuverIcon(routeManeuverType: Int): Int {
var currentTurnIcon = R.drawable.ic_turn_name_change var currentTurnIcon = R.drawable.ic_turn_name_change
when (routeManeuverType) { when (routeManeuverType) {
ManeuverType.TYPE_STRAIGHT.ordinal -> { ManeuverType.TYPE_STRAIGHT.value -> {
currentTurnIcon = R.drawable.ic_turn_name_change currentTurnIcon = R.drawable.ic_turn_name_change
} }
ManeuverType.TYPE_DESTINATION.ordinal, ManeuverType.TYPE_DESTINATION.value,
ManeuverType.TYPE_DESTINATION_RIGHT.ordinal, ManeuverType.TYPE_DESTINATION_RIGHT.value,
ManeuverType.TYPE_DESTINATION_LEFT.ordinal, ManeuverType.TYPE_DESTINATION_LEFT.value,
ManeuverType.TYPE_DESTINATION_STRAIGHT.ordinal ManeuverType.TYPE_DESTINATION_STRAIGHT.value
-> { -> {
currentTurnIcon = R.drawable.ic_turn_destination currentTurnIcon = R.drawable.ic_turn_destination
} }
ManeuverType.TYPE_TURN_NORMAL_RIGHT.ordinal -> { ManeuverType.TYPE_TURN_NORMAL_RIGHT.value -> {
currentTurnIcon = R.drawable.ic_turn_normal_right currentTurnIcon = R.drawable.ic_turn_normal_right
} }
ManeuverType.TYPE_TURN_NORMAL_LEFT.ordinal -> { ManeuverType.TYPE_TURN_NORMAL_LEFT.value -> {
currentTurnIcon = R.drawable.ic_turn_normal_left currentTurnIcon = R.drawable.ic_turn_normal_left
} }
ManeuverType.TYPE_OFF_RAMP_SLIGHT_RIGHT.ordinal -> { ManeuverType.TYPE_OFF_RAMP_SLIGHT_RIGHT.value -> {
currentTurnIcon = R.drawable.ic_turn_slight_right currentTurnIcon = R.drawable.ic_turn_slight_right
} }
ManeuverType.TYPE_TURN_SLIGHT_RIGHT.ordinal -> { ManeuverType.TYPE_TURN_SLIGHT_RIGHT.value -> {
currentTurnIcon = R.drawable.ic_turn_slight_right currentTurnIcon = R.drawable.ic_turn_slight_right
} }
ManeuverType.TYPE_KEEP_RIGHT.ordinal -> { ManeuverType.TYPE_KEEP_RIGHT.value -> {
currentTurnIcon = R.drawable.ic_turn_name_change currentTurnIcon = R.drawable.ic_turn_name_change
} }
ManeuverType.TYPE_KEEP_LEFT.ordinal -> { ManeuverType.TYPE_KEEP_LEFT.value -> {
currentTurnIcon = R.drawable.ic_turn_name_change currentTurnIcon = R.drawable.ic_turn_name_change
} }
ManeuverType.TYPE_ROUNDABOUT_ENTER_CCW.ordinal -> { ManeuverType.TYPE_ROUNDABOUT_ENTER_CCW.value -> {
currentTurnIcon = R.drawable.ic_roundabout_ccw currentTurnIcon = R.drawable.ic_roundabout_ccw
} }
ManeuverType.TYPE_ROUNDABOUT_EXIT_CCW.ordinal -> { ManeuverType.TYPE_ROUNDABOUT_EXIT_CCW.value -> {
currentTurnIcon = R.drawable.ic_roundabout_ccw currentTurnIcon = R.drawable.ic_roundabout_ccw
} }
ManeuverType.TYPE_U_TURN_LEFT.ordinal -> { ManeuverType.TYPE_U_TURN_LEFT.value -> {
currentTurnIcon = R.drawable.ic_turn_u_turn_left currentTurnIcon = R.drawable.ic_turn_u_turn_left
} }
ManeuverType.TYPE_U_TURN_RIGHT.ordinal -> { ManeuverType.TYPE_U_TURN_RIGHT.value -> {
currentTurnIcon = R.drawable.ic_turn_u_turn_right currentTurnIcon = R.drawable.ic_turn_u_turn_right
} }
ManeuverType.TYPE_MERGE_LEFT.ordinal -> { ManeuverType.TYPE_MERGE_LEFT.value -> {
currentTurnIcon = R.drawable.ic_turn_merge_symmetrical currentTurnIcon = R.drawable.ic_turn_merge_symmetrical
} }
ManeuverType.TYPE_WAYPOINT_RIGHT.ordinal -> { ManeuverType.TYPE_WAYPOINT_RIGHT.value -> {
currentTurnIcon = R.drawable.ic_turn_destination currentTurnIcon = R.drawable.ic_turn_destination
} }
} }
@@ -87,8 +87,8 @@ class IconMapper {
val laneDirection = when (direction.lowercase(Locale.getDefault())) { val laneDirection = when (direction.lowercase(Locale.getDefault())) {
"left_straight" -> { "left_straight" -> {
when (stepData.currentManeuverType) { when (stepData.currentManeuverType) {
ManeuverType.TYPE_TURN_NORMAL_LEFT.ordinal -> LaneDirection.SHAPE_NORMAL_LEFT ManeuverType.TYPE_TURN_NORMAL_LEFT.value -> LaneDirection.SHAPE_NORMAL_LEFT
ManeuverType.TYPE_STRAIGHT.ordinal -> LaneDirection.SHAPE_STRAIGHT ManeuverType.TYPE_STRAIGHT.value -> LaneDirection.SHAPE_STRAIGHT
else else
-> LaneDirection.SHAPE_UNKNOWN -> LaneDirection.SHAPE_UNKNOWN
} }
@@ -96,7 +96,7 @@ class IconMapper {
"left" -> { "left" -> {
when (stepData.currentManeuverType) { when (stepData.currentManeuverType) {
ManeuverType.TYPE_TURN_NORMAL_LEFT.ordinal -> LaneDirection.SHAPE_NORMAL_LEFT ManeuverType.TYPE_TURN_NORMAL_LEFT.value -> LaneDirection.SHAPE_NORMAL_LEFT
else else
-> LaneDirection.SHAPE_UNKNOWN -> LaneDirection.SHAPE_UNKNOWN
} }
@@ -104,9 +104,9 @@ class IconMapper {
"straight" -> { "straight" -> {
when (stepData.currentManeuverType) { when (stepData.currentManeuverType) {
ManeuverType.TYPE_STRAIGHT.ordinal -> LaneDirection.SHAPE_STRAIGHT ManeuverType.TYPE_STRAIGHT.value -> LaneDirection.SHAPE_STRAIGHT
ManeuverType.TYPE_KEEP_LEFT.ordinal -> LaneDirection.SHAPE_STRAIGHT ManeuverType.TYPE_KEEP_LEFT.value -> LaneDirection.SHAPE_STRAIGHT
ManeuverType.TYPE_KEEP_RIGHT.ordinal -> LaneDirection.SHAPE_STRAIGHT ManeuverType.TYPE_KEEP_RIGHT.value -> LaneDirection.SHAPE_STRAIGHT
else else
-> LaneDirection.SHAPE_UNKNOWN -> LaneDirection.SHAPE_UNKNOWN
} }
@@ -114,7 +114,7 @@ class IconMapper {
"right" -> { "right" -> {
when (stepData.currentManeuverType) { when (stepData.currentManeuverType) {
ManeuverType.TYPE_TURN_NORMAL_RIGHT.ordinal -> LaneDirection.SHAPE_NORMAL_RIGHT ManeuverType.TYPE_TURN_NORMAL_RIGHT.value -> LaneDirection.SHAPE_NORMAL_RIGHT
else else
-> LaneDirection.SHAPE_UNKNOWN -> LaneDirection.SHAPE_UNKNOWN
} }
@@ -122,8 +122,8 @@ class IconMapper {
"right_straight" -> { "right_straight" -> {
when (stepData.currentManeuverType) { when (stepData.currentManeuverType) {
ManeuverType.TYPE_TURN_NORMAL_RIGHT.ordinal -> LaneDirection.SHAPE_NORMAL_RIGHT ManeuverType.TYPE_TURN_NORMAL_RIGHT.value -> LaneDirection.SHAPE_NORMAL_RIGHT
ManeuverType.TYPE_STRAIGHT.ordinal -> LaneDirection.SHAPE_STRAIGHT ManeuverType.TYPE_STRAIGHT.value -> LaneDirection.SHAPE_STRAIGHT
else else
-> LaneDirection.SHAPE_UNKNOWN -> LaneDirection.SHAPE_UNKNOWN
} }
@@ -131,8 +131,8 @@ class IconMapper {
"left_slight", "slight_left" -> { "left_slight", "slight_left" -> {
when (stepData.currentManeuverType) { when (stepData.currentManeuverType) {
ManeuverType.TYPE_TURN_NORMAL_LEFT.ordinal -> LaneDirection.SHAPE_SLIGHT_LEFT ManeuverType.TYPE_TURN_NORMAL_LEFT.value -> LaneDirection.SHAPE_SLIGHT_LEFT
ManeuverType.TYPE_KEEP_LEFT.ordinal -> LaneDirection.SHAPE_SLIGHT_LEFT ManeuverType.TYPE_KEEP_LEFT.value -> LaneDirection.SHAPE_SLIGHT_LEFT
else else
-> LaneDirection.SHAPE_UNKNOWN -> LaneDirection.SHAPE_UNKNOWN
} }
@@ -140,8 +140,8 @@ class IconMapper {
"right_slight", "slight_right" -> { "right_slight", "slight_right" -> {
when (stepData.currentManeuverType) { when (stepData.currentManeuverType) {
ManeuverType.TYPE_TURN_SLIGHT_RIGHT.ordinal -> LaneDirection.SHAPE_NORMAL_RIGHT ManeuverType.TYPE_TURN_SLIGHT_RIGHT.value -> LaneDirection.SHAPE_NORMAL_RIGHT
ManeuverType.TYPE_KEEP_RIGHT.ordinal -> LaneDirection.SHAPE_SLIGHT_RIGHT ManeuverType.TYPE_KEEP_RIGHT.value -> LaneDirection.SHAPE_SLIGHT_RIGHT
else else
-> LaneDirection.SHAPE_UNKNOWN -> LaneDirection.SHAPE_UNKNOWN
} }
@@ -213,8 +213,8 @@ class IconMapper {
return when (direction) { return when (direction) {
"left_straight" -> { "left_straight" -> {
when (stepData.currentManeuverType) { when (stepData.currentManeuverType) {
ManeuverType.TYPE_TURN_NORMAL_LEFT.ordinal -> "left_o_straight_x" ManeuverType.TYPE_TURN_NORMAL_LEFT.value -> "left_o_straight_x"
ManeuverType.TYPE_STRAIGHT.ordinal -> "left_x_straight_o" ManeuverType.TYPE_STRAIGHT.value -> "left_x_straight_o"
else else
-> "left_x_straight_x" -> "left_x_straight_x"
} }
@@ -222,29 +222,29 @@ class IconMapper {
"right_straight" -> { "right_straight" -> {
when (stepData.currentManeuverType) { when (stepData.currentManeuverType) {
ManeuverType.TYPE_TURN_NORMAL_RIGHT.ordinal -> "right_x_straight_x" ManeuverType.TYPE_TURN_NORMAL_RIGHT.value -> "right_x_straight_x"
ManeuverType.TYPE_STRAIGHT.ordinal -> "right_x_straight_o" ManeuverType.TYPE_STRAIGHT.value -> "right_x_straight_o"
ManeuverType.TYPE_TURN_SLIGHT_RIGHT.ordinal -> "right_o_straight_o" ManeuverType.TYPE_TURN_SLIGHT_RIGHT.value -> "right_o_straight_o"
else else
-> "right_x_straight_x" -> "right_x_straight_x"
} }
} }
"right" -> if (stepData.currentManeuverType == ManeuverType.TYPE_TURN_NORMAL_RIGHT.ordinal) "${direction}_o" else "${direction}_x" "right" -> if (stepData.currentManeuverType == ManeuverType.TYPE_TURN_NORMAL_RIGHT.value) "${direction}_o" else "${direction}_x"
"left" -> if (stepData.currentManeuverType == ManeuverType.TYPE_TURN_NORMAL_LEFT.ordinal) "${direction}_o" else "${direction}_x" "left" -> if (stepData.currentManeuverType == ManeuverType.TYPE_TURN_NORMAL_LEFT.value) "${direction}_o" else "${direction}_x"
"straight" -> if (stepData.currentManeuverType == ManeuverType.TYPE_STRAIGHT.ordinal "straight" -> if (stepData.currentManeuverType == ManeuverType.TYPE_STRAIGHT.value
|| stepData.currentManeuverType == ManeuverType.TYPE_KEEP_LEFT.ordinal || stepData.currentManeuverType == ManeuverType.TYPE_KEEP_LEFT.value
|| stepData.currentManeuverType == ManeuverType.TYPE_KEEP_RIGHT.ordinal || stepData.currentManeuverType == ManeuverType.TYPE_KEEP_RIGHT.value
) "${direction}_o" else "${direction}_x" ) "${direction}_o" else "${direction}_x"
"right_slight", "slight_right" -> if (stepData.currentManeuverType == ManeuverType.TYPE_TURN_SLIGHT_RIGHT.ordinal "right_slight", "slight_right" -> if (stepData.currentManeuverType == ManeuverType.TYPE_TURN_SLIGHT_RIGHT.value
|| stepData.currentManeuverType == ManeuverType.TYPE_TURN_NORMAL_RIGHT.ordinal || stepData.currentManeuverType == ManeuverType.TYPE_TURN_NORMAL_RIGHT.value
|| stepData.currentManeuverType == ManeuverType.TYPE_KEEP_RIGHT.ordinal || stepData.currentManeuverType == ManeuverType.TYPE_KEEP_RIGHT.value
) "slight_right_o" else "slight_right_x" ) "slight_right_o" else "slight_right_x"
"left_slight", "slight_left" -> if (stepData.currentManeuverType == ManeuverType.TYPE_TURN_SLIGHT_LEFT.ordinal "left_slight", "slight_left" -> if (stepData.currentManeuverType == ManeuverType.TYPE_TURN_SLIGHT_LEFT.value
|| stepData.currentManeuverType == ManeuverType.TYPE_TURN_NORMAL_LEFT.ordinal || stepData.currentManeuverType == ManeuverType.TYPE_TURN_NORMAL_LEFT.value
|| stepData.currentManeuverType == ManeuverType.TYPE_KEEP_LEFT.ordinal || stepData.currentManeuverType == ManeuverType.TYPE_KEEP_LEFT.value
) "slight_left_o" else "slight_left_x" ) "slight_left_o" else "slight_left_x"
else -> { else -> {
@@ -3,7 +3,6 @@ package com.kouros.navigation.model
//import com.kouros.navigation.data.Preferences.boxStore //import com.kouros.navigation.data.Preferences.boxStore
import android.content.Context import android.content.Context
import android.location.Location import android.location.Location
import android.util.Log
import androidx.compose.runtime.snapshots.SnapshotStateList import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.toMutableStateList import androidx.compose.runtime.toMutableStateList
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
@@ -27,6 +26,7 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.maplibre.geojson.FeatureCollection import org.maplibre.geojson.FeatureCollection
import java.lang.reflect.Modifier
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.ZoneOffset import java.time.ZoneOffset
@@ -101,6 +101,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
MutableLiveData() MutableLiveData()
} }
val gson: com.google.gson.Gson = GsonBuilder().create()
/** /**
* Loads all recent places from Preferences and calculates distances. * Loads all recent places from Preferences and calculates distances.
@@ -111,14 +112,14 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
try { try {
val settingsRepository = getSettingsRepository(context) val settingsRepository = getSettingsRepository(context)
val rp = settingsRepository.recentPlacesFlow.first() val rp = settingsRepository.recentPlacesFlow.first()
val gson = GsonBuilder().serializeNulls().create()
val places = gson.fromJson(rp, Places::class.java) val places = gson.fromJson(rp, Places::class.java)
val pl = mutableListOf<Place>() val pl = mutableListOf<Place>()
var id: Long = 0 var id: Long = 0
if (rp.isNotEmpty()) { if (rp.isNotEmpty()) {
for (place in places.places) { for (place in places.places) {
if (place.category.equals(Constants.RECENT) if (place.category == Constants.RECENT
|| place.category.equals(Constants.FAVORITES)) { || place.category == Constants.FAVORITES
) {
val plLocation = location(place.longitude, place.latitude) val plLocation = location(place.longitude, place.latitude)
if (place.latitude != 0.0) { if (place.latitude != 0.0) {
val distance = val distance =
@@ -289,7 +290,6 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
var sortedList: List<SearchResult> var sortedList: List<SearchResult>
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val placesJson = repository.searchPlaces(search, location) val placesJson = repository.searchPlaces(search, location)
val gson = GsonBuilder().serializeNulls().create()
val places = gson.fromJson(placesJson, Search::class.java) val places = gson.fromJson(placesJson, Search::class.java)
val distPlaces = mutableListOf<SearchResult>() val distPlaces = mutableListOf<SearchResult>()
places.forEach { places.forEach {
@@ -314,7 +314,6 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
val placesJson = repository.searchPlaces(search, location) val placesJson = repository.searchPlaces(search, location)
if (placesJson.isNotEmpty()) { if (placesJson.isNotEmpty()) {
val gson = GsonBuilder().serializeNulls().create()
val places = gson.fromJson(placesJson, Search::class.java) val places = gson.fromJson(placesJson, Search::class.java)
val distPlaces = mutableListOf<SearchResult>() val distPlaces = mutableListOf<SearchResult>()
places.forEach { places.forEach {
@@ -434,7 +433,6 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
try { try {
val places = mutableListOf<Place>() val places = mutableListOf<Place>()
val gson = GsonBuilder().serializeNulls().create()
val settingsRepository = getSettingsRepository(context) val settingsRepository = getSettingsRepository(context)
val rp = settingsRepository.recentPlacesFlow.first() val rp = settingsRepository.recentPlacesFlow.first()
var id: Long = 0 var id: Long = 0
@@ -444,6 +442,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
for (curPlace in recentPlaces) { for (curPlace in recentPlaces) {
if (curPlace.name != place.name || curPlace.category != place.category) { if (curPlace.name != place.name || curPlace.category != place.category) {
curPlace.id = id curPlace.id = id
curPlace.route = ""
places.add(curPlace) places.add(curPlace)
id += 1 id += 1
} }
@@ -451,6 +450,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
} }
val current = LocalDateTime.now(ZoneOffset.UTC) val current = LocalDateTime.now(ZoneOffset.UTC)
place.lastDate = current.atZone(ZoneOffset.UTC).toEpochSecond() place.lastDate = current.atZone(ZoneOffset.UTC).toEpochSecond()
place.route = ""
places.add(place) places.add(place)
settingsRepository.setRecentPlaces(gson.toJson(Places(places))) settingsRepository.setRecentPlaces(gson.toJson(Places(places)))
} catch (e: Exception) { } catch (e: Exception) {
@@ -473,7 +473,6 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
fun deletePlace(context: Context, place: Place) { fun deletePlace(context: Context, place: Place) {
viewModelScope.launch(Dispatchers.IO) { viewModelScope.launch(Dispatchers.IO) {
try { try {
val gson = GsonBuilder().serializeNulls().create()
val settingsRepository = getSettingsRepository(context) val settingsRepository = getSettingsRepository(context)
val rp = settingsRepository.recentPlacesFlow.first() val rp = settingsRepository.recentPlacesFlow.first()
val places = mutableListOf<Place>() val places = mutableListOf<Place>()
@@ -482,6 +481,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
gson.fromJson(rp, Places::class.java).places.sortedBy { it.lastDate } gson.fromJson(rp, Places::class.java).places.sortedBy { it.lastDate }
for (curPlace in rPlaces) { for (curPlace in rPlaces) {
if (curPlace.name != place.name || curPlace.category != place.category) { if (curPlace.name != place.name || curPlace.category != place.category) {
curPlace.route = ""
places.add(curPlace) places.add(curPlace)
} }
} }
@@ -511,12 +511,11 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
* Loads recent places as Compose SnapshotStateList. * Loads recent places as Compose SnapshotStateList.
* @return SnapshotStateList of recent places * @return SnapshotStateList of recent places
*/ */
fun loadRecentPlace(context: Context): SnapshotStateList<Place?> { fun loadRecentPlaces(context: Context): SnapshotStateList<Place?> {
val pl = mutableListOf<Place>() val pl = mutableListOf<Place>()
val settingsRepository = getSettingsRepository(context) val settingsRepository = getSettingsRepository(context)
val rp = runBlocking { settingsRepository.recentPlacesFlow.first() } val rp = runBlocking { settingsRepository.recentPlacesFlow.first() }
if (rp.isNotEmpty()) { if (rp.isNotEmpty()) {
val gson = GsonBuilder().serializeNulls().create()
val recentPlaces = gson.fromJson(rp, Places::class.java).places.sortedBy { it.lastDate } val recentPlaces = gson.fromJson(rp, Places::class.java).places.sortedBy { it.lastDate }
for (place in recentPlaces) { for (place in recentPlaces) {
if (place.category == Constants.RECENT) { if (place.category == Constants.RECENT) {
@@ -1,5 +1,6 @@
package com.kouros.navigation.repository package com.kouros.navigation.repository
import android.util.Log
import com.kouros.navigation.data.datastore.DataStoreManager import com.kouros.navigation.data.datastore.DataStoreManager
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -147,7 +147,7 @@ fun duration(
if (updateDuration.toMillis().absoluteValue < 1000) { if (updateDuration.toMillis().absoluteValue < 1000) {
2.seconds 2.seconds
} else { } else {
((updateDuration!!.toMillis().absoluteValue * 1.2).toDuration(DurationUnit.MILLISECONDS)) ((updateDuration!!.toMillis().absoluteValue * 1.8).toDuration(DurationUnit.MILLISECONDS))
} }
} }
return cameraDuration return cameraDuration
+14 -10
View File
@@ -15,7 +15,7 @@ junitVersion = "1.3.0"
espressoCore = "3.7.0" espressoCore = "3.7.0"
kotlinxSerializationJson = "1.10.0" kotlinxSerializationJson = "1.10.0"
lifecycleRuntimeKtx = "2.10.0" lifecycleRuntimeKtx = "2.10.0"
composeBom = "2026.03.00" composeBom = "2026.03.01"
appcompat = "1.7.1" appcompat = "1.7.1"
material = "1.13.0" material = "1.13.0"
carApp = "1.7.0" carApp = "1.7.0"
@@ -26,27 +26,29 @@ mockitoKotlin = "6.3.0"
rules = "1.7.0" rules = "1.7.0"
runner = "1.7.0" runner = "1.7.0"
material3 = "1.4.0" material3 = "1.4.0"
runtimeLivedata = "1.10.5" runtimeLivedata = "1.10.6"
foundation = "1.10.5" foundation = "1.10.6"
maplibre-compose = "0.12.1" maplibre-compose = "0.12.1"
playServicesLocation = "21.3.0" playServicesLocation = "21.3.0"
runtime = "1.10.5" runtime = "1.10.6"
accompanist = "0.37.3" accompanist = "0.37.3"
uiVersion = "1.10.5" uiVersion = "1.10.6"
uiText = "1.10.5" uiText = "1.10.6"
navigationCompose = "2.9.7" navigationCompose = "2.9.7"
uiToolingPreview = "1.10.5" uiToolingPreview = "1.10.6"
uiTooling = "1.10.5" uiTooling = "1.10.6"
material3WindowSizeClass = "1.4.0" material3WindowSizeClass = "1.4.0"
uiGraphics = "1.10.5" uiGraphics = "1.10.6"
window = "1.5.1" window = "1.5.1"
foundationLayout = "1.10.5" foundationLayout = "1.10.6"
datastorePreferences = "1.2.1" datastorePreferences = "1.2.1"
datastoreCore = "1.2.1" datastoreCore = "1.2.1"
monitor = "1.8.0" monitor = "1.8.0"
robolectric = "4.16.1" robolectric = "4.16.1"
truth = "1.4.5" truth = "1.4.5"
testCore = "1.7.0" testCore = "1.7.0"
archCoreTesting = "2.2.0"
kotlinxCoroutinesTest = "1.10.1"
[libraries] [libraries]
android-gpx-parser = { module = "com.github.ticofab:android-gpx-parser", version.ref = "androidGpxParser" } android-gpx-parser = { module = "com.github.ticofab:android-gpx-parser", version.ref = "androidGpxParser" }
@@ -98,6 +100,8 @@ androidx-monitor = { group = "androidx.test", name = "monitor", version.ref = "m
robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" } robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
google-truth = { module = "com.google.truth:truth", version.ref = "truth" } google-truth = { module = "com.google.truth:truth", version.ref = "truth" }
androidx-test-core = { module = "androidx.test:core", version.ref = "testCore" } androidx-test-core = { module = "androidx.test:core", version.ref = "testCore" }
androidx-arch-core-testing = { module = "androidx.arch.core:core-testing", version.ref = "archCoreTesting" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinxCoroutinesTest" }
[plugins] [plugins]
android-application = { id = "com.android.application", version.ref = "agp" } android-application = { id = "com.android.application", version.ref = "agp" }