Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- **Where was I that day?**: New feature on the dashboard to look up the car's position and activity at any past date and time. Shows map, location breadcrumb (country/region/city), car state (driving/charging/parked), state-specific details, and weather. Tapping a driving or charging card navigates to the corresponding detail screen.
- **Line chart visual revamp**: Smooth cubic Bezier curves, gradient fills, dashed grid lines, vertical crosshair, glowing indicators, animated entrance, and theme-aware tooltips.
- **Battery heater overlay**: Grafana-style orange annotation bands on drive detail Power and Battery charts highlighting battery pre-heating periods.
- **Speed distribution histogram**: Drive details now include a speed histogram showing the percentage of time spent in each speed bucket (10 km/h or 5 mph).

## [1.2.3] - 2026-03-08

### Added
Expand Down
50 changes: 50 additions & 0 deletions app/src/main/java/com/matedroid/ui/navigation/NavGraph.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import java.net.URLDecoder
import java.net.URLEncoder
import java.nio.charset.StandardCharsets
import com.matedroid.ui.screens.updates.SoftwareVersionsScreen
import com.matedroid.ui.screens.wherewasi.WhereWasIScreen
import com.matedroid.domain.model.YearFilter
import kotlinx.coroutines.launch

Expand Down Expand Up @@ -154,6 +155,14 @@ sealed class Screen(val route: String) {
return "stats/$carId/countries/$countryCode/regions?${params.joinToString("&")}"
}
}
data object WhereWasI : Screen("wherewasi/{carId}?timestamp={timestamp}&exteriorColor={exteriorColor}") {
fun createRoute(carId: Int, timestamp: String, exteriorColor: String? = null): String {
val encodedTimestamp = URLEncoder.encode(timestamp, StandardCharsets.UTF_8.toString())
val params = mutableListOf("timestamp=$encodedTimestamp")
if (exteriorColor != null) params.add("exteriorColor=$exteriorColor")
return "wherewasi/$carId?${params.joinToString("&")}"
}
}
}

@Composable
Expand Down Expand Up @@ -267,6 +276,9 @@ fun NavGraph(
},
onNavigateToCurrentCharge = { carId, exteriorColor ->
navController.navigate(Screen.CurrentCharge.createRoute(carId, exteriorColor))
},
onNavigateToWhereWasI = { carId, timestamp, exteriorColor ->
navController.navigate(Screen.WhereWasI.createRoute(carId, timestamp, exteriorColor))
}
)
}
Expand Down Expand Up @@ -567,5 +579,43 @@ fun NavGraph(
onNavigateBack = { navController.popBackStack() }
)
}

composable(
route = Screen.WhereWasI.route,
arguments = listOf(
navArgument("carId") { type = NavType.IntType },
navArgument("timestamp") {
type = NavType.StringType
defaultValue = ""
},
navArgument("exteriorColor") {
type = NavType.StringType
nullable = true
defaultValue = null
}
)
) { backStackEntry ->
val carId = backStackEntry.arguments?.getInt("carId") ?: return@composable
val timestamp = backStackEntry.arguments?.getString("timestamp")?.let {
URLDecoder.decode(it, StandardCharsets.UTF_8.toString())
} ?: return@composable
val exteriorColor = backStackEntry.arguments?.getString("exteriorColor")

WhereWasIScreen(
carId = carId,
targetTimestamp = timestamp,
exteriorColor = exteriorColor,
onNavigateBack = { navController.popBackStack() },
onNavigateToDriveDetail = { driveId ->
navController.navigate(Screen.DriveDetail.createRoute(carId, driveId, exteriorColor))
},
onNavigateToChargeDetail = { chargeId ->
navController.navigate(Screen.ChargeDetail.createRoute(carId, chargeId, exteriorColor))
},
onNavigateToCountriesVisited = {
navController.navigate(Screen.CountriesVisited.createRoute(carId, exteriorColor))
}
)
}
}
}
Loading
Loading