Settings
This commit is contained in:
@@ -14,8 +14,8 @@ android {
|
|||||||
applicationId = "com.kouros.navigation"
|
applicationId = "com.kouros.navigation"
|
||||||
minSdk = 33
|
minSdk = 33
|
||||||
targetSdk = 36
|
targetSdk = 36
|
||||||
versionCode = 42
|
versionCode = 43
|
||||||
versionName = "0.2.0.42"
|
versionName = "0.2.0.43"
|
||||||
base.archivesName = "navi-$versionName"
|
base.archivesName = "navi-$versionName"
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
@@ -97,9 +97,6 @@ dependencies {
|
|||||||
implementation("com.github.ticofab:android-gpx-parser:2.3.1")
|
implementation("com.github.ticofab:android-gpx-parser:2.3.1")
|
||||||
implementation(libs.androidx.navigation.compose)
|
implementation(libs.androidx.navigation.compose)
|
||||||
implementation(libs.kotlinx.serialization.json)
|
implementation(libs.kotlinx.serialization.json)
|
||||||
implementation("com.github.alorma.compose-settings:ui-tiles:2.25.0")
|
|
||||||
implementation("com.github.alorma.compose-settings:ui-tiles-extended:2.25.0")
|
|
||||||
implementation("com.github.alorma.compose-settings:ui-tiles-expressive:2.25.0")
|
|
||||||
implementation(libs.androidx.foundation.layout)
|
implementation(libs.androidx.foundation.layout)
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.androidx.junit)
|
androidTestImplementation(libs.androidx.junit)
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import androidx.compose.material3.BottomSheetScaffold
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.SheetState
|
||||||
|
import androidx.compose.material3.SheetValue
|
||||||
import androidx.compose.material3.SnackbarHost
|
import androidx.compose.material3.SnackbarHost
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -34,6 +36,7 @@ import androidx.compose.runtime.mutableDoubleStateOf
|
|||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@@ -91,7 +94,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
val routeModel = RouteModel()
|
val routeModel = RouteModel()
|
||||||
var tilt = 50.0
|
var tilt = 50.0
|
||||||
val useMock = true
|
val useMock = false
|
||||||
val type = 3 // 1 simulate 2 test 3 gpx 4 testSingle
|
val type = 3 // 1 simulate 2 test 3 gpx 4 testSingle
|
||||||
|
|
||||||
var currentIndex = 0
|
var currentIndex = 0
|
||||||
@@ -198,13 +201,12 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
val appViewModel: AppViewModel = appViewModel()
|
val appViewModel: AppViewModel = appViewModel()
|
||||||
val darkMode by appViewModel.darkMode.collectAsState()
|
val darkMode by appViewModel.darkMode.collectAsState()
|
||||||
|
val sheetPeekHeight = 250.dp
|
||||||
baseStyle = BaseStyleModel().readStyle(applicationContext, darkMode, darkMode == 1)
|
baseStyle = BaseStyleModel().readStyle(applicationContext, darkMode, darkMode == 1)
|
||||||
|
|
||||||
val scaffoldState = rememberBottomSheetScaffoldState()
|
val scaffoldState = rememberBottomSheetScaffoldState()
|
||||||
val snackbarHostState = remember { SnackbarHostState() }
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val sheetPeekHeightState = remember { mutableStateOf(256.dp) }
|
val sheetPeekHeightState = remember { mutableStateOf(sheetPeekHeight) }
|
||||||
|
|
||||||
val locationProvider = rememberDefaultLocationProvider(
|
val locationProvider = rememberDefaultLocationProvider(
|
||||||
updateInterval = 0.5.seconds, desiredAccuracy = DesiredAccuracy.Highest
|
updateInterval = 0.5.seconds, desiredAccuracy = DesiredAccuracy.Highest
|
||||||
@@ -221,7 +223,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
fun closeSheet() {
|
fun closeSheet() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
scaffoldState.bottomSheetState.partialExpand()
|
scaffoldState.bottomSheetState.partialExpand()
|
||||||
sheetPeekHeightState.value = 128.dp
|
sheetPeekHeightState.value = sheetPeekHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NavigationTheme (useDarkTheme = darkMode == 1) {
|
NavigationTheme (useDarkTheme = darkMode == 1) {
|
||||||
@@ -261,11 +263,11 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun App() {
|
fun App() {
|
||||||
//val lastRoute = NavigationUtils.getStringKeyValue(applicationContext, Constants.LAST_ROUTE)
|
val appViewModel: AppViewModel = appViewModel()
|
||||||
//if (lastRoute!!.isNotEmpty()) {
|
val lastRoute by appViewModel.lastRoute.collectAsState()
|
||||||
// routeModel.startNavigation(lastRoute, applicationContext)
|
if (lastRoute.isNotEmpty()) {
|
||||||
// routeData.value = routeModel.curRoute.routeGeoJson
|
navigationViewModel.route.value = lastRoute
|
||||||
//}
|
}
|
||||||
AppNavGraph(applicationContext = applicationContext, this)
|
AppNavGraph(applicationContext = applicationContext, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.kouros.navigation.car.map.rememberBaseStyle
|
|||||||
import com.kouros.navigation.data.StepData
|
import com.kouros.navigation.data.StepData
|
||||||
import com.kouros.navigation.ui.app.AppViewModel
|
import com.kouros.navigation.ui.app.AppViewModel
|
||||||
import com.kouros.navigation.ui.app.appViewModel
|
import com.kouros.navigation.ui.app.appViewModel
|
||||||
|
import com.kouros.navigation.utils.settingsViewModel
|
||||||
import org.maplibre.compose.camera.CameraPosition
|
import org.maplibre.compose.camera.CameraPosition
|
||||||
import org.maplibre.compose.camera.rememberCameraState
|
import org.maplibre.compose.camera.rememberCameraState
|
||||||
import org.maplibre.compose.location.LocationTrackingEffect
|
import org.maplibre.compose.location.LocationTrackingEffect
|
||||||
@@ -66,7 +67,7 @@ fun MapView(
|
|||||||
val rememberBaseStyle = rememberBaseStyle(baseStyle)
|
val rememberBaseStyle = rememberBaseStyle(baseStyle)
|
||||||
|
|
||||||
val appViewModel: AppViewModel = appViewModel()
|
val appViewModel: AppViewModel = appViewModel()
|
||||||
val showBuildings by appViewModel.threedBuilding.collectAsState()
|
val showBuildings by appViewModel.show3D.collectAsState()
|
||||||
|
|
||||||
Column {
|
Column {
|
||||||
NavigationInfo(step, nextStep)
|
NavigationInfo(step, nextStep)
|
||||||
|
|||||||
@@ -4,10 +4,13 @@ import android.content.Context
|
|||||||
import android.location.Location
|
import android.location.Location
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.foundation.text.input.TextFieldState
|
import androidx.compose.foundation.text.input.TextFieldState
|
||||||
@@ -17,6 +20,7 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
|||||||
import androidx.compose.material3.HorizontalDivider
|
import androidx.compose.material3.HorizontalDivider
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.ListItem
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SearchBar
|
import androidx.compose.material3.SearchBar
|
||||||
import androidx.compose.material3.SearchBarDefaults
|
import androidx.compose.material3.SearchBarDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
@@ -51,32 +55,36 @@ fun SearchSheet(
|
|||||||
if (search.value != null) {
|
if (search.value != null) {
|
||||||
searchResults.addAll(search.value!!)
|
searchResults.addAll(search.value!!)
|
||||||
}
|
}
|
||||||
|
val textFieldState = rememberTextFieldState()
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.wrapContentHeight()
|
||||||
|
) {
|
||||||
|
SearchBar(
|
||||||
|
textFieldState = textFieldState,
|
||||||
|
searchPlaces = emptyList(),
|
||||||
|
searchResults = searchResults,
|
||||||
|
viewModel = viewModel,
|
||||||
|
context = applicationContext,
|
||||||
|
location = location,
|
||||||
|
closeSheet = { closeSheet() }
|
||||||
|
|
||||||
Home(applicationContext, viewModel, location, closeSheet = { closeSheet() })
|
)
|
||||||
if (recentPlaces.value != null) {
|
//Home(applicationContext, viewModel, location, closeSheet = { closeSheet() })
|
||||||
val items = listOf(recentPlaces)
|
if (recentPlaces.value != null) {
|
||||||
if (items.isNotEmpty()) {
|
val items = listOf(recentPlaces)
|
||||||
RecentPlaces(recentPlaces.value!!, viewModel, applicationContext, location, closeSheet)
|
if (items.isNotEmpty()) {
|
||||||
|
RecentPlaces(
|
||||||
|
recentPlaces.value!!,
|
||||||
|
viewModel,
|
||||||
|
applicationContext,
|
||||||
|
location,
|
||||||
|
closeSheet
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if (searchResults.isNotEmpty()) {
|
|
||||||
val textFieldState = rememberTextFieldState()
|
|
||||||
val items = listOf(searchResults)
|
|
||||||
// if (items.isNotEmpty()) {
|
|
||||||
SearchBar(
|
|
||||||
textFieldState = textFieldState,
|
|
||||||
searchPlaces = emptyList<Place>(),
|
|
||||||
searchResults = searchResults,
|
|
||||||
viewModel = viewModel,
|
|
||||||
context = applicationContext,
|
|
||||||
location = location,
|
|
||||||
closeSheet = { closeSheet() }
|
|
||||||
|
|
||||||
)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -124,40 +132,44 @@ fun SearchBar(
|
|||||||
location: Location,
|
location: Location,
|
||||||
closeSheet: () -> Unit
|
closeSheet: () -> Unit
|
||||||
) {
|
) {
|
||||||
var expanded by rememberSaveable { mutableStateOf(true) }
|
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||||
SearchBar(
|
SearchBar(
|
||||||
inputField = {
|
colors = SearchBarDefaults.colors(
|
||||||
SearchBarDefaults.InputField(
|
containerColor = MaterialTheme.colorScheme.secondaryContainer
|
||||||
leadingIcon = {
|
),
|
||||||
Icon(
|
modifier = modifier,
|
||||||
painter = painterResource(id = R.drawable.search_48px),
|
inputField = {
|
||||||
"Search",
|
SearchBarDefaults.InputField(
|
||||||
modifier = Modifier.size(24.dp, 24.dp),
|
leadingIcon = {
|
||||||
)
|
Icon(
|
||||||
},
|
painter = painterResource(id = R.drawable.search_48px),
|
||||||
query = textFieldState.text.toString(),
|
"Search",
|
||||||
onQueryChange = { textFieldState.edit { replace(0, length, it) } },
|
modifier = Modifier.size(24.dp, 24.dp),
|
||||||
onSearch = {
|
)
|
||||||
searchPlaces(viewModel, location, it)
|
},
|
||||||
expanded = false
|
query = textFieldState.text.toString(),
|
||||||
},
|
onQueryChange = { textFieldState.edit { replace(0, length, it) } },
|
||||||
expanded = expanded,
|
onSearch = {
|
||||||
onExpandedChange = { expanded = it },
|
searchPlaces(viewModel, location, it)
|
||||||
placeholder = { Text(context.getString(R.string.search_action_title)) }
|
expanded = false
|
||||||
)
|
},
|
||||||
},
|
expanded = expanded,
|
||||||
expanded = expanded,
|
onExpandedChange = { expanded = it },
|
||||||
onExpandedChange = { expanded = it },
|
placeholder = { Text(context.getString(R.string.search_action_title)) }
|
||||||
) {
|
)
|
||||||
if (searchPlaces.isNotEmpty()) {
|
},
|
||||||
Text(context.getString(R.string.recent_destinations))
|
expanded = expanded,
|
||||||
RecentPlaces(searchPlaces, viewModel, context, location, closeSheet)
|
onExpandedChange = { expanded = it },
|
||||||
}
|
) {
|
||||||
if (searchResults.isNotEmpty()) {
|
if (searchPlaces.isNotEmpty()) {
|
||||||
Text("Search places")
|
Text(context.getString(R.string.recent_destinations))
|
||||||
SearchPlaces(searchResults, viewModel, context, location, closeSheet)
|
RecentPlaces(searchPlaces, viewModel, context, location, closeSheet)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (searchResults.isNotEmpty()) {
|
||||||
|
Text("Search places")
|
||||||
|
SearchPlaces(searchResults, viewModel, context, location, closeSheet)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun searchPlaces(viewModel: NavigationViewModel, location: Location, it: String) {
|
private fun searchPlaces(viewModel: NavigationViewModel, location: Location, it: String) {
|
||||||
|
|||||||
@@ -1,68 +0,0 @@
|
|||||||
package com.kouros.navigation.ui
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.navigation.NavHostController
|
|
||||||
import com.kouros.data.R
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
|
||||||
@Composable
|
|
||||||
fun SettingsScreen(navController: NavHostController, navigateBack: () -> Unit) {
|
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
|
||||||
CenterAlignedTopAppBar(
|
|
||||||
title = {
|
|
||||||
Text(
|
|
||||||
stringResource(id = R.string.settings_action_title),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = navigateBack) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(R.drawable.arrow_back_24px),
|
|
||||||
contentDescription = stringResource(id = R.string.accept_action_title),
|
|
||||||
modifier = Modifier.size(48.dp, 48.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
) { padding ->
|
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
Column(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.consumeWindowInsets(padding)
|
|
||||||
.verticalScroll(scrollState)
|
|
||||||
.padding(top = padding.calculateTopPadding()),
|
|
||||||
) {
|
|
||||||
Column(modifier = Modifier.padding(16.dp)) {
|
|
||||||
|
|
||||||
Button(onClick = { navController.navigate("display_settings") }) {
|
|
||||||
Text(stringResource(R.string.display_settings))
|
|
||||||
}
|
|
||||||
Button(onClick = { navController.navigate("nav_settings") }) {
|
|
||||||
Text(stringResource(R.string.navigation_settings))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -18,10 +18,17 @@ class AppViewModel(
|
|||||||
0
|
0
|
||||||
)
|
)
|
||||||
|
|
||||||
val threedBuilding = settingsRepository.threedBuildingFlow
|
val show3D = settingsRepository.show3DFlow
|
||||||
.stateIn(
|
.stateIn(
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
SharingStarted.Eagerly,
|
SharingStarted.Eagerly,
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val lastRoute = settingsRepository.lastRouteFlow
|
||||||
|
.stateIn(
|
||||||
|
viewModelScope,
|
||||||
|
SharingStarted.Eagerly,
|
||||||
|
""
|
||||||
|
)
|
||||||
}
|
}
|
||||||
@@ -6,9 +6,6 @@ import androidx.navigation.compose.NavHost
|
|||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.compose.rememberNavController
|
import androidx.navigation.compose.rememberNavController
|
||||||
import com.kouros.navigation.ui.MainActivity
|
import com.kouros.navigation.ui.MainActivity
|
||||||
import com.kouros.navigation.ui.settings.NavigationScreenSettings
|
|
||||||
import com.kouros.navigation.ui.SettingsScreen
|
|
||||||
import com.kouros.navigation.ui.settings.DisplaySettings
|
|
||||||
import com.kouros.navigation.ui.settings.SettingsRoute
|
import com.kouros.navigation.ui.settings.SettingsRoute
|
||||||
|
|
||||||
|
|
||||||
@@ -18,17 +15,8 @@ fun AppNavGraph(applicationContext: Context, mainActivity: MainActivity) {
|
|||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
NavHost(navController = navController, startDestination = "startScreen") {
|
NavHost(navController = navController, startDestination = "startScreen") {
|
||||||
composable("startScreen") { mainActivity.StartScreen(navController) }
|
composable("startScreen") { mainActivity.StartScreen(navController) }
|
||||||
composable("settings") { SettingsScreen(navController) { navController.popBackStack() } }
|
|
||||||
composable("settingsxx") {
|
|
||||||
SettingsRoute("display_settings", navController) { navController.popBackStack() }
|
|
||||||
}
|
|
||||||
// old
|
|
||||||
//composable("display_settings") { DisplaySettings(applicationContext) { navController.popBackStack() } }
|
|
||||||
//composable("nav_settings") { NavigationScreenSettings(applicationContext) { navController.popBackStack() } }
|
|
||||||
|
|
||||||
// new
|
|
||||||
composable("display_settings") { SettingsRoute("display_settings", navController) { navController.popBackStack() } }
|
composable("display_settings") { SettingsRoute("display_settings", navController) { navController.popBackStack() } }
|
||||||
composable("nav_settings") { SettingsRoute("nav_settings", navController) { navController.popBackStack() } }
|
composable("nav_settings") { SettingsRoute("nav_settings", navController) { navController.popBackStack() } }
|
||||||
|
composable("settings") { SettingsRoute("settings", navController) { navController.popBackStack() } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,116 @@
|
|||||||
|
package com.kouros.navigation.ui.settings
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.SegmentedButtonDefaults.Icon
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
|
import com.kouros.data.R
|
||||||
|
import com.kouros.navigation.model.SettingsViewModel
|
||||||
|
import com.kouros.navigation.ui.components.RadioButtonSingleSelection
|
||||||
|
import com.kouros.navigation.ui.components.SectionTitle
|
||||||
|
import com.kouros.navigation.ui.components.SettingSwitch
|
||||||
|
import com.kouros.navigation.ui.theme.NavigationTheme
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun DisplayScreen(viewModel: SettingsViewModel, navigateBack: () -> Unit) {
|
||||||
|
|
||||||
|
val darkMode by viewModel.darkMode.collectAsState()
|
||||||
|
val show3D by viewModel.show3D.collectAsState()
|
||||||
|
NavigationTheme(useDarkTheme = viewModel.darkMode.collectAsState().value == 1) {
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
CenterAlignedTopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
stringResource(id = R.string.display_settings),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(onClick = navigateBack) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.arrow_back_24px),
|
||||||
|
contentDescription = stringResource(id = R.string.accept_action_title),
|
||||||
|
modifier = Modifier.size(48.dp, 48.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
{ padding ->
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(top = 20.dp)
|
||||||
|
.verticalScroll(scrollState)
|
||||||
|
) {
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = stringResource(R.string.settings_action_title),
|
||||||
|
style = MaterialTheme.typography.headlineMedium
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
|
||||||
|
// Appearance
|
||||||
|
SectionTitle(stringResource(R.string.threed_building))
|
||||||
|
|
||||||
|
SettingSwitch(
|
||||||
|
title = stringResource(R.string.threed_building),
|
||||||
|
checked = show3D,
|
||||||
|
onCheckedChange = viewModel::onShow3DChanged
|
||||||
|
)
|
||||||
|
|
||||||
|
SectionTitle(stringResource(R.string.dark_mode))
|
||||||
|
|
||||||
|
val radioOptions = listOf(
|
||||||
|
stringResource(R.string.off_action_title),
|
||||||
|
stringResource(R.string.on_action_title),
|
||||||
|
stringResource(R.string.use_telephon_settings)
|
||||||
|
)
|
||||||
|
RadioButtonSingleSelection(
|
||||||
|
modifier = Modifier.padding(),
|
||||||
|
selectedOption = darkMode,
|
||||||
|
radioOptions = radioOptions,
|
||||||
|
onClick = viewModel::onDarkModeChanged
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
package com.kouros.navigation.ui.settings
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.Card
|
|
||||||
import androidx.compose.material3.CardDefaults
|
|
||||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.alorma.compose.settings.ui.SettingsCheckbox
|
|
||||||
import com.alorma.compose.settings.ui.SettingsGroup
|
|
||||||
import com.alorma.compose.settings.ui.SettingsRadioButton
|
|
||||||
import com.alorma.compose.settings.ui.base.internal.LocalSettingsTileColors
|
|
||||||
import com.alorma.compose.settings.ui.base.internal.SettingsTileDefaults
|
|
||||||
import com.kouros.data.R
|
|
||||||
import com.kouros.navigation.utils.getSettingsViewModel
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun DisplaySettings(context: Context, navigateBack: () -> Unit) {
|
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
|
||||||
CenterAlignedTopAppBar(
|
|
||||||
title = {
|
|
||||||
Text(
|
|
||||||
stringResource(id = R.string.display_settings),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = navigateBack) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(R.drawable.arrow_back_24px),
|
|
||||||
contentDescription = stringResource(id = R.string.accept_action_title),
|
|
||||||
modifier = Modifier.size(48.dp, 48.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
) { padding ->
|
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
Column(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.consumeWindowInsets(padding)
|
|
||||||
.verticalScroll(scrollState)
|
|
||||||
.padding(top = padding.calculateTopPadding()),
|
|
||||||
) {
|
|
||||||
DisplaySettings(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun DisplaySettings(context: Context) {
|
|
||||||
val settingsViewModel = getSettingsViewModel(context)
|
|
||||||
Section(title = "Anzeige") {
|
|
||||||
val state = remember {
|
|
||||||
mutableStateOf(
|
|
||||||
settingsViewModel.threedBuilding.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
SettingsCheckbox(
|
|
||||||
state = state.value,
|
|
||||||
title = { Text(text = stringResource(R.string.threed_building)) },
|
|
||||||
onCheckedChange = {
|
|
||||||
state.value = it
|
|
||||||
settingsViewModel.onThreedBuildingChanged(it)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Section(title = "Dunkles Design") {
|
|
||||||
val state = remember {
|
|
||||||
mutableIntStateOf(
|
|
||||||
settingsViewModel.darkMode.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
DarkModeData(context).darkDesign.forEach { sampleItem ->
|
|
||||||
SettingsRadioButton(
|
|
||||||
state = state.intValue == sampleItem.key,
|
|
||||||
title = { Text(text = sampleItem.title) },
|
|
||||||
onClick = {
|
|
||||||
state.intValue = sampleItem.key
|
|
||||||
settingsViewModel.onDarkModeChanged(state.intValue)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
internal fun Section(
|
|
||||||
title: String,
|
|
||||||
enabled: Boolean = true,
|
|
||||||
verticalArrangement: Arrangement.Vertical = Arrangement.spacedBy(4.dp),
|
|
||||||
content: @Composable ColumnScope.() -> Unit,
|
|
||||||
) {
|
|
||||||
SettingsGroup(
|
|
||||||
contentPadding = PaddingValues(0.dp),
|
|
||||||
verticalArrangement = verticalArrangement,
|
|
||||||
enabled = enabled,
|
|
||||||
title = { Text(text = title) },
|
|
||||||
) {
|
|
||||||
Card(
|
|
||||||
colors = CardDefaults.cardColors(
|
|
||||||
containerColor = (LocalSettingsTileColors.current
|
|
||||||
?: SettingsTileDefaults.colors()).containerColor
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
content()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
internal class DarkModeData(context: Context) {
|
|
||||||
val darkDesign =
|
|
||||||
listOf(
|
|
||||||
Item(
|
|
||||||
key = 0,
|
|
||||||
title = context.getString(R.string.off_action_title),
|
|
||||||
),
|
|
||||||
Item(
|
|
||||||
key = 1,
|
|
||||||
title = context.getString(R.string.on_action_title),
|
|
||||||
),
|
|
||||||
Item(
|
|
||||||
key = 2,
|
|
||||||
title = context.getString(R.string.use_telephon_settings),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal data class Item(
|
|
||||||
val key: Int,
|
|
||||||
val title: String,
|
|
||||||
)
|
|
||||||
@@ -0,0 +1,130 @@
|
|||||||
|
package com.kouros.navigation.ui.settings
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
|
import com.kouros.data.R
|
||||||
|
import com.kouros.navigation.data.RouteEngine
|
||||||
|
import com.kouros.navigation.model.SettingsViewModel
|
||||||
|
import com.kouros.navigation.ui.components.RadioButtonSingleSelection
|
||||||
|
import com.kouros.navigation.ui.components.SectionTitle
|
||||||
|
import com.kouros.navigation.ui.components.SettingSwitch
|
||||||
|
import com.kouros.navigation.ui.theme.NavigationTheme
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun NavigationScreen(viewModel: SettingsViewModel, navigateBack: () -> Unit) {
|
||||||
|
|
||||||
|
NavigationTheme(useDarkTheme = viewModel.darkMode.collectAsState().value == 1) {
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
CenterAlignedTopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
stringResource(id = R.string.navigation_settings),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(onClick = navigateBack) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.arrow_back_24px),
|
||||||
|
contentDescription = stringResource(id = R.string.accept_action_title),
|
||||||
|
modifier = Modifier.size(48.dp, 48.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) { padding ->
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
Column(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.consumeWindowInsets(padding)
|
||||||
|
.verticalScroll(scrollState)
|
||||||
|
.padding(top = padding.calculateTopPadding()),
|
||||||
|
) {
|
||||||
|
NavigationSettings(viewModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun NavigationSettings(viewModel: SettingsViewModel) {
|
||||||
|
val avoidMotorway by viewModel.avoidMotorway.collectAsState()
|
||||||
|
val avoidTollway by viewModel.avoidTollway.collectAsState()
|
||||||
|
val carLocation by viewModel.carLocation.collectAsState()
|
||||||
|
val routingEngine by viewModel.routingEngine.collectAsState()
|
||||||
|
val tomTomApiKey by viewModel.tomTomApiKey.collectAsState()
|
||||||
|
|
||||||
|
SettingSwitch(
|
||||||
|
title = stringResource(R.string.avoid_highways_row_title),
|
||||||
|
checked = avoidMotorway,
|
||||||
|
onCheckedChange = viewModel::onAvoidMotorway
|
||||||
|
)
|
||||||
|
|
||||||
|
SettingSwitch(
|
||||||
|
title = stringResource(R.string.avoid_tolls_row_title),
|
||||||
|
checked = avoidTollway,
|
||||||
|
onCheckedChange = viewModel::onAvoidTollway
|
||||||
|
)
|
||||||
|
|
||||||
|
SettingSwitch(
|
||||||
|
title = stringResource(R.string.use_car_location),
|
||||||
|
checked = carLocation,
|
||||||
|
onCheckedChange = viewModel::onCarLocation
|
||||||
|
)
|
||||||
|
|
||||||
|
SectionTitle(stringResource(R.string.routing_engine))
|
||||||
|
|
||||||
|
val routingEngineOptions = listOf(
|
||||||
|
stringResource(R.string.valhalla),
|
||||||
|
stringResource(R.string.osrm),
|
||||||
|
stringResource(R.string.tomtom)
|
||||||
|
)
|
||||||
|
RadioButtonSingleSelection(
|
||||||
|
modifier = Modifier.padding(),
|
||||||
|
selectedOption = routingEngine,
|
||||||
|
radioOptions = routingEngineOptions,
|
||||||
|
onClick = viewModel::onRoutingEngineChanged
|
||||||
|
)
|
||||||
|
|
||||||
|
if (routingEngine == RouteEngine.TOMTOM.ordinal) {
|
||||||
|
var key by remember { mutableStateOf(tomTomApiKey) }
|
||||||
|
TextField(
|
||||||
|
value = key,
|
||||||
|
onValueChange = {
|
||||||
|
key = it
|
||||||
|
viewModel::onTomTomApiKeyChanged
|
||||||
|
},
|
||||||
|
label = { Text(stringResource(R.string.tomtom_api_key)) },
|
||||||
|
textStyle = TextStyle(color = Color.Green, fontWeight = FontWeight.Bold),
|
||||||
|
modifier = Modifier.padding(20.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
package com.kouros.navigation.ui.settings
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.consumeWindowInsets
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.rememberScrollState
|
|
||||||
import androidx.compose.foundation.verticalScroll
|
|
||||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.mutableIntStateOf
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.alorma.compose.settings.ui.SettingsCheckbox
|
|
||||||
import com.alorma.compose.settings.ui.SettingsRadioButton
|
|
||||||
import com.kouros.data.R
|
|
||||||
import com.kouros.navigation.data.Constants
|
|
||||||
import com.kouros.navigation.data.Constants.ROUTING_ENGINE
|
|
||||||
import com.kouros.navigation.data.RouteEngine
|
|
||||||
import com.kouros.navigation.utils.NavigationUtils
|
|
||||||
import com.kouros.navigation.utils.getSettingsViewModel
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun NavigationScreenSettings(context: Context, navigateBack: () -> Unit) {
|
|
||||||
Scaffold(
|
|
||||||
topBar = {
|
|
||||||
CenterAlignedTopAppBar(
|
|
||||||
title = {
|
|
||||||
Text(
|
|
||||||
stringResource(id = R.string.navigation_settings),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = navigateBack) {
|
|
||||||
Icon(
|
|
||||||
painter = painterResource(R.drawable.arrow_back_24px),
|
|
||||||
contentDescription = stringResource(id = R.string.accept_action_title),
|
|
||||||
modifier = Modifier.size(48.dp, 48.dp),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
) { padding ->
|
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
Column(
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.consumeWindowInsets(padding)
|
|
||||||
.verticalScroll(scrollState)
|
|
||||||
.padding(top = padding.calculateTopPadding()),
|
|
||||||
) {
|
|
||||||
NavigationSettings(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun NavigationSettings(context: Context) {
|
|
||||||
val settingsViewModel = getSettingsViewModel(context)
|
|
||||||
Section(title = stringResource(id = R.string.options)) {
|
|
||||||
val avoidMotorwayState = remember {
|
|
||||||
mutableStateOf(
|
|
||||||
settingsViewModel.avoidMotorway.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
SettingsCheckbox(
|
|
||||||
state = avoidMotorwayState.value,
|
|
||||||
title = { Text(text = stringResource(id = R.string.avoid_highways_row_title)) },
|
|
||||||
onCheckedChange = {
|
|
||||||
avoidMotorwayState.value = it
|
|
||||||
settingsViewModel.onAvoidMotorway(it)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
val avoidTollwayState = remember {
|
|
||||||
mutableStateOf(
|
|
||||||
settingsViewModel.avoidTollway.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
SettingsCheckbox(
|
|
||||||
state = avoidTollwayState.value,
|
|
||||||
title = { Text(text = stringResource(id = R.string.avoid_tolls_row_title)) },
|
|
||||||
onCheckedChange = {
|
|
||||||
avoidTollwayState.value = it
|
|
||||||
settingsViewModel.onAvoidTollway(it)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
val carLocationState = remember {
|
|
||||||
mutableStateOf(
|
|
||||||
settingsViewModel.carLocation.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
SettingsCheckbox(
|
|
||||||
state = carLocationState.value,
|
|
||||||
title = { Text(text = stringResource(id = R.string.use_car_location)) },
|
|
||||||
onCheckedChange = {
|
|
||||||
carLocationState.value = it
|
|
||||||
settingsViewModel.onCarLocation(it)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Section(title = stringResource(id = R.string.routing_engine)) {
|
|
||||||
val state = remember {
|
|
||||||
mutableIntStateOf(
|
|
||||||
settingsViewModel.routingEngine.value
|
|
||||||
)
|
|
||||||
}
|
|
||||||
RoutingEngineData.engines.forEach { sampleItem ->
|
|
||||||
SettingsRadioButton(
|
|
||||||
state = state.intValue == sampleItem.key,
|
|
||||||
title = { Text(text = sampleItem.title) },
|
|
||||||
onClick = {
|
|
||||||
state.intValue = sampleItem.key
|
|
||||||
settingsViewModel.onRoutingEngineChanged(state.intValue)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal object RoutingEngineData {
|
|
||||||
val engines =
|
|
||||||
listOf(
|
|
||||||
Item(
|
|
||||||
key = 0,
|
|
||||||
title = RouteEngine.VALHALLA.toString(),
|
|
||||||
),
|
|
||||||
Item(
|
|
||||||
key = 1,
|
|
||||||
title = RouteEngine.OSRM.toString(),
|
|
||||||
),
|
|
||||||
Item(
|
|
||||||
key = 2,
|
|
||||||
title = RouteEngine.TOMTOM.toString(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@ import com.kouros.navigation.model.SettingsViewModel
|
|||||||
import com.kouros.navigation.repository.SettingsRepository
|
import com.kouros.navigation.repository.SettingsRepository
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsRoute(route: String, navController: NavHostController, function: () -> Boolean) {
|
fun SettingsRoute(route: String, navController: NavHostController, function: () -> Unit) {
|
||||||
|
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
|
|
||||||
@@ -28,10 +28,12 @@ fun SettingsRoute(route: String, navController: NavHostController, function: ()
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (route == "display_settings") {
|
if (route == "display_settings") {
|
||||||
SettingsScreen(viewModel = viewModel)
|
DisplayScreen(viewModel = viewModel, function)
|
||||||
}
|
}
|
||||||
if (route == "nav_settings") {
|
if (route == "nav_settings") {
|
||||||
SettingsScreen(viewModel = viewModel)
|
NavigationScreen (viewModel = viewModel, function)
|
||||||
|
}
|
||||||
|
if (route == "settings") {
|
||||||
|
SettingsScreen(viewModel, navController, function)
|
||||||
}
|
}
|
||||||
///DisplaySettings(context, viewModel, navController.popBackStack())
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,151 +1,72 @@
|
|||||||
package com.kouros.navigation.ui.settings
|
package com.kouros.navigation.ui.settings
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.consumeWindowInsets
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.CenterAlignedTopAppBar
|
import androidx.compose.material3.CenterAlignedTopAppBar
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.navigation.NavHostController
|
||||||
import com.kouros.data.R
|
import com.kouros.data.R
|
||||||
import com.kouros.navigation.model.SettingsViewModel
|
import com.kouros.navigation.model.SettingsViewModel
|
||||||
import com.kouros.navigation.ui.components.RadioButtonSingleSelection
|
import com.kouros.navigation.ui.theme.NavigationTheme
|
||||||
import com.kouros.navigation.ui.components.SectionTitle
|
|
||||||
import com.kouros.navigation.ui.components.SettingSwitch
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun SettingsScreen(viewModel: SettingsViewModel) {
|
fun SettingsScreen(viewModel: SettingsViewModel, navController: NavHostController, navigateBack: () -> Unit) {
|
||||||
|
NavigationTheme(useDarkTheme = viewModel.darkMode.collectAsState().value == 1) {
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
CenterAlignedTopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
stringResource(id = R.string.settings_action_title),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(onClick = navigateBack) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(R.drawable.arrow_back_24px),
|
||||||
|
contentDescription = stringResource(id = R.string.accept_action_title),
|
||||||
|
modifier = Modifier.size(48.dp, 48.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) { padding ->
|
||||||
|
val scrollState = rememberScrollState()
|
||||||
|
Column(
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.consumeWindowInsets(padding)
|
||||||
|
.verticalScroll(scrollState)
|
||||||
|
.padding(top = padding.calculateTopPadding()),
|
||||||
|
) {
|
||||||
|
Column(modifier = Modifier.padding(16.dp)) {
|
||||||
|
|
||||||
val darkMode by viewModel.darkMode.collectAsState()
|
Button(onClick = { navController.navigate("display_settings") }) {
|
||||||
val threedBuilding by viewModel.threedBuilding.collectAsState()
|
Text(stringResource(R.string.display_settings))
|
||||||
val avoidMotorway by viewModel.avoidMotorway.collectAsState()
|
}
|
||||||
val avoidTollway by viewModel.avoidTollway.collectAsState()
|
Button(onClick = { navController.navigate("nav_settings") }) {
|
||||||
val carLocation by viewModel.carLocation.collectAsState()
|
Text(stringResource(R.string.navigation_settings))
|
||||||
val routingEngine by viewModel.routingEngine.collectAsState()
|
}
|
||||||
|
}
|
||||||
Scaffold(
|
}
|
||||||
topBar = {
|
|
||||||
CenterAlignedTopAppBar(
|
|
||||||
title = {
|
|
||||||
Text(
|
|
||||||
stringResource(id = R.string.display_settings),
|
|
||||||
)
|
|
||||||
},
|
|
||||||
navigationIcon = {
|
|
||||||
// IconButton(onClick = navigateBack) {
|
|
||||||
// Icon(
|
|
||||||
// painter = painterResource(R.drawable.arrow_back_24px),
|
|
||||||
// contentDescription = stringResource(id = R.string.accept_action_title),
|
|
||||||
// modifier = Modifier.size(48.dp, 48.dp),
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
},
|
|
||||||
)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
{ padding ->
|
|
||||||
val scrollState = rememberScrollState()
|
|
||||||
Column(
|
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxSize()
|
|
||||||
.padding(top = 20.dp)
|
|
||||||
.verticalScroll(scrollState)
|
|
||||||
) {
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = stringResource(R.string.settings_action_title),
|
|
||||||
style = MaterialTheme.typography.headlineMedium
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
|
|
||||||
// Appearance
|
|
||||||
SectionTitle(stringResource(R.string.threed_building))
|
|
||||||
|
|
||||||
SettingSwitch(
|
|
||||||
title = stringResource(R.string.threed_building),
|
|
||||||
checked = threedBuilding,
|
|
||||||
onCheckedChange = viewModel::onThreedBuildingChanged
|
|
||||||
)
|
|
||||||
|
|
||||||
SectionTitle(stringResource(R.string.dark_mode))
|
|
||||||
|
|
||||||
val radioOptions = listOf(
|
|
||||||
stringResource(R.string.off_action_title),
|
|
||||||
stringResource(R.string.on_action_title),
|
|
||||||
stringResource(R.string.use_telephon_settings)
|
|
||||||
)
|
|
||||||
RadioButtonSingleSelection(
|
|
||||||
modifier = Modifier.padding(),
|
|
||||||
selectedOption = darkMode,
|
|
||||||
radioOptions = radioOptions,
|
|
||||||
onClick = viewModel::onDarkModeChanged
|
|
||||||
)
|
|
||||||
|
|
||||||
// Appearance
|
|
||||||
SectionTitle(stringResource(R.string.navigation_settings))
|
|
||||||
|
|
||||||
SettingSwitch(
|
|
||||||
title = stringResource(R.string.avoid_highways_row_title),
|
|
||||||
checked = avoidMotorway,
|
|
||||||
onCheckedChange = viewModel::onAvoidMotorway
|
|
||||||
)
|
|
||||||
|
|
||||||
SettingSwitch(
|
|
||||||
title = stringResource(R.string.avoid_tolls_row_title),
|
|
||||||
checked = avoidTollway,
|
|
||||||
onCheckedChange = viewModel::onAvoidTollway
|
|
||||||
)
|
|
||||||
|
|
||||||
SettingSwitch(
|
|
||||||
title = stringResource(R.string.use_car_location),
|
|
||||||
checked = carLocation,
|
|
||||||
onCheckedChange = viewModel::onCarLocation
|
|
||||||
)
|
|
||||||
|
|
||||||
SectionTitle(stringResource(R.string.routing_engine))
|
|
||||||
|
|
||||||
val routingEngineOptions = listOf(
|
|
||||||
stringResource(R.string.valhalla),
|
|
||||||
stringResource(R.string.osrm),
|
|
||||||
stringResource(R.string.tomtom)
|
|
||||||
)
|
|
||||||
RadioButtonSingleSelection(
|
|
||||||
modifier = Modifier.padding(),
|
|
||||||
selectedOption = routingEngine,
|
|
||||||
radioOptions = routingEngineOptions,
|
|
||||||
onClick = viewModel::onRoutingEngineChanged
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.kouros.navigation.car
|
|||||||
|
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Application
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
@@ -34,12 +33,10 @@ import com.kouros.navigation.car.navigation.RouteCarModel
|
|||||||
import com.kouros.navigation.car.screen.NavigationScreen
|
import com.kouros.navigation.car.screen.NavigationScreen
|
||||||
import com.kouros.navigation.car.screen.RequestPermissionScreen
|
import com.kouros.navigation.car.screen.RequestPermissionScreen
|
||||||
import com.kouros.navigation.car.screen.SearchScreen
|
import com.kouros.navigation.car.screen.SearchScreen
|
||||||
import com.kouros.navigation.data.Constants.CAR_LOCATION
|
|
||||||
import com.kouros.navigation.data.Constants.MAXIMAL_ROUTE_DEVIATION
|
import com.kouros.navigation.data.Constants.MAXIMAL_ROUTE_DEVIATION
|
||||||
import com.kouros.navigation.data.Constants.MAXIMAL_SNAP_CORRECTION
|
import com.kouros.navigation.data.Constants.MAXIMAL_SNAP_CORRECTION
|
||||||
import com.kouros.navigation.data.Constants.TAG
|
import com.kouros.navigation.data.Constants.TAG
|
||||||
import com.kouros.navigation.data.RouteEngine
|
import com.kouros.navigation.data.RouteEngine
|
||||||
import com.kouros.navigation.data.datastore.DataStoreManager
|
|
||||||
import com.kouros.navigation.data.osrm.OsrmRepository
|
import com.kouros.navigation.data.osrm.OsrmRepository
|
||||||
import com.kouros.navigation.data.tomtom.TomTomRepository
|
import com.kouros.navigation.data.tomtom.TomTomRepository
|
||||||
import com.kouros.navigation.data.valhalla.ValhallaRepository
|
import com.kouros.navigation.data.valhalla.ValhallaRepository
|
||||||
@@ -47,7 +44,6 @@ import com.kouros.navigation.model.NavigationViewModel
|
|||||||
import com.kouros.navigation.utils.GeoUtils.snapLocation
|
import com.kouros.navigation.utils.GeoUtils.snapLocation
|
||||||
import com.kouros.navigation.utils.NavigationUtils.getViewModel
|
import com.kouros.navigation.utils.NavigationUtils.getViewModel
|
||||||
import com.kouros.navigation.utils.getSettingsRepository
|
import com.kouros.navigation.utils.getSettingsRepository
|
||||||
import com.kouros.navigation.utils.getSettingsViewModel
|
|
||||||
import kotlinx.coroutines.awaitCancellation
|
import kotlinx.coroutines.awaitCancellation
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import com.kouros.navigation.car.map.cameraState
|
|||||||
import com.kouros.navigation.car.map.getPaddingValues
|
import com.kouros.navigation.car.map.getPaddingValues
|
||||||
import com.kouros.navigation.car.map.rememberBaseStyle
|
import com.kouros.navigation.car.map.rememberBaseStyle
|
||||||
import com.kouros.navigation.car.navigation.RouteCarModel
|
import com.kouros.navigation.car.navigation.RouteCarModel
|
||||||
import com.kouros.navigation.data.Constants.ROUTING_ENGINE
|
|
||||||
import com.kouros.navigation.data.Constants.homeVogelhart
|
import com.kouros.navigation.data.Constants.homeVogelhart
|
||||||
import com.kouros.navigation.data.ObjectBox
|
import com.kouros.navigation.data.ObjectBox
|
||||||
import com.kouros.navigation.data.RouteEngine
|
import com.kouros.navigation.data.RouteEngine
|
||||||
@@ -42,7 +41,6 @@ import com.kouros.navigation.utils.calculateTilt
|
|||||||
import com.kouros.navigation.utils.calculateZoom
|
import com.kouros.navigation.utils.calculateZoom
|
||||||
import com.kouros.navigation.utils.duration
|
import com.kouros.navigation.utils.duration
|
||||||
import com.kouros.navigation.utils.getSettingsRepository
|
import com.kouros.navigation.utils.getSettingsRepository
|
||||||
import com.kouros.navigation.utils.getSettingsViewModel
|
|
||||||
import com.kouros.navigation.utils.location
|
import com.kouros.navigation.utils.location
|
||||||
import com.kouros.navigation.utils.previewZoom
|
import com.kouros.navigation.utils.previewZoom
|
||||||
import com.kouros.navigation.utils.settingsViewModel
|
import com.kouros.navigation.utils.settingsViewModel
|
||||||
|
|||||||
@@ -22,18 +22,18 @@ class DisplaySettings(private val carContext: CarContext) : Screen(carContext) {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
settingsViewModel.threedBuilding.collect {
|
settingsViewModel.show3D.collect {
|
||||||
invalidate()
|
invalidate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onGetTemplate(): Template {
|
override fun onGetTemplate(): Template {
|
||||||
buildingToggleState = settingsViewModel.threedBuilding.value
|
buildingToggleState = settingsViewModel.show3D.value
|
||||||
val listBuilder = ItemList.Builder()
|
val listBuilder = ItemList.Builder()
|
||||||
val buildingToggle: Toggle =
|
val buildingToggle: Toggle =
|
||||||
Toggle.Builder { checked: Boolean ->
|
Toggle.Builder { checked: Boolean ->
|
||||||
settingsViewModel.onThreedBuildingChanged(checked)
|
settingsViewModel.onShow3DChanged(checked)
|
||||||
buildingToggleState = !buildingToggleState
|
buildingToggleState = !buildingToggleState
|
||||||
}.setChecked(buildingToggleState).build()
|
}.setChecked(buildingToggleState).build()
|
||||||
listBuilder.addItem(buildRowForTemplate(R.string.threed_building, buildingToggle))
|
listBuilder.addItem(buildRowForTemplate(R.string.threed_building, buildingToggle))
|
||||||
|
|||||||
@@ -38,9 +38,7 @@ import com.kouros.navigation.repository.SettingsRepository
|
|||||||
import com.kouros.navigation.utils.GeoUtils
|
import com.kouros.navigation.utils.GeoUtils
|
||||||
import com.kouros.navigation.utils.getSettingsViewModel
|
import com.kouros.navigation.utils.getSettingsViewModel
|
||||||
import com.kouros.navigation.utils.location
|
import com.kouros.navigation.utils.location
|
||||||
import kotlinx.coroutines.flow.first
|
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import java.time.Duration
|
import java.time.Duration
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ class NavigationSettings(private val carContext: CarContext, private var navigat
|
|||||||
init {
|
init {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
settingsViewModel.avoidTollway.collect {
|
settingsViewModel.avoidTollway.collect {
|
||||||
invalidate()
|
settingsViewModel.avoidMotorway.collect {
|
||||||
|
settingsViewModel.carLocation.collect {
|
||||||
|
invalidate()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,8 +102,6 @@ object Constants {
|
|||||||
|
|
||||||
//const val STYLE_DARK: String = "https://kouros-online.de/liberty_night.json"
|
//const val STYLE_DARK: String = "https://kouros-online.de/liberty_night.json"
|
||||||
|
|
||||||
const val STYLE: String = "https://tiles.openfreemap.org/styles/liberty"
|
|
||||||
const val STYLE_DARK: String = "https://tiles.openfreemap.org/styles/liberty"
|
|
||||||
const val TAG: String = "Navigation"
|
const val TAG: String = "Navigation"
|
||||||
|
|
||||||
const val CATEGORIES: String = "Categories"
|
const val CATEGORIES: String = "Categories"
|
||||||
@@ -126,21 +124,6 @@ object Constants {
|
|||||||
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)
|
||||||
|
|
||||||
const val SHARED_PREF_KEY = "NavigationPrefs"
|
|
||||||
|
|
||||||
const val SHOW_THREED_BUILDING = "Show3D"
|
|
||||||
|
|
||||||
const val DARK_MODE_SETTINGS = "DarkMode"
|
|
||||||
|
|
||||||
const val AVOID_MOTORWAY = "AvoidMotorway"
|
|
||||||
|
|
||||||
const val AVOID_TOLLWAY = "AvoidTollway"
|
|
||||||
|
|
||||||
const val CAR_LOCATION = "CarLocation"
|
|
||||||
const val ROUTING_ENGINE = "RoutingEngine"
|
|
||||||
|
|
||||||
const val LAST_ROUTE = "LastRoute"
|
|
||||||
|
|
||||||
const val NEXT_STEP_THRESHOLD = 500.0
|
const val NEXT_STEP_THRESHOLD = 500.0
|
||||||
|
|
||||||
const val MAXIMAL_SNAP_CORRECTION = 50.0
|
const val MAXIMAL_SNAP_CORRECTION = 50.0
|
||||||
|
|||||||
@@ -51,11 +51,10 @@ abstract class NavigationRepository {
|
|||||||
currentLocation: Location,
|
currentLocation: Location,
|
||||||
location: Location,
|
location: Location,
|
||||||
carOrientation: Float,
|
carOrientation: Float,
|
||||||
searchFilter: SearchFilter,
|
|
||||||
context: Context
|
context: Context
|
||||||
): Double {
|
): Double {
|
||||||
val osrm = OsrmRepository()
|
val osrm = OsrmRepository()
|
||||||
val route = osrm.getRoute(context, currentLocation, location, carOrientation, searchFilter)
|
val route = osrm.getRoute(context, currentLocation, location, carOrientation, SearchFilter())
|
||||||
val gson = GsonBuilder().serializeNulls().create()
|
val gson = GsonBuilder().serializeNulls().create()
|
||||||
val osrmJson = gson.fromJson(route, OsrmResponse::class.java)
|
val osrmJson = gson.fromJson(route, OsrmResponse::class.java)
|
||||||
if (osrmJson.routes.isEmpty()) {
|
if (osrmJson.routes.isEmpty()) {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import androidx.datastore.preferences.core.Preferences
|
|||||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
import androidx.datastore.preferences.core.intPreferencesKey
|
import androidx.datastore.preferences.core.intPreferencesKey
|
||||||
|
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||||
import androidx.datastore.preferences.preferencesDataStore
|
import androidx.datastore.preferences.preferencesDataStore
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
@@ -26,7 +27,7 @@ class DataStoreManager(private val context: Context) {
|
|||||||
// Keys
|
// Keys
|
||||||
private object PreferencesKeys {
|
private object PreferencesKeys {
|
||||||
|
|
||||||
val THREED_BUILDING = booleanPreferencesKey("Show3D")
|
val SHOW_3D = booleanPreferencesKey("Show3D")
|
||||||
|
|
||||||
val DARK_MODE = intPreferencesKey("DarkMode")
|
val DARK_MODE = intPreferencesKey("DarkMode")
|
||||||
|
|
||||||
@@ -37,13 +38,17 @@ class DataStoreManager(private val context: Context) {
|
|||||||
val CAR_LOCATION = booleanPreferencesKey("CarLocation")
|
val CAR_LOCATION = booleanPreferencesKey("CarLocation")
|
||||||
|
|
||||||
val ROUTING_ENGINE = intPreferencesKey("RoutingEngine")
|
val ROUTING_ENGINE = intPreferencesKey("RoutingEngine")
|
||||||
|
|
||||||
|
val LAST_ROUTE = stringPreferencesKey("LastRoute")
|
||||||
|
|
||||||
|
val TOMTOM_APIKEY = stringPreferencesKey("TomTomApiKey")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read values
|
// Read values
|
||||||
|
|
||||||
val threeDBuildingFlow: Flow<Boolean> =
|
val show3DFlow: Flow<Boolean> =
|
||||||
context.dataStore.data.map { preferences ->
|
context.dataStore.data.map { preferences ->
|
||||||
preferences[PreferencesKeys.THREED_BUILDING] == true
|
preferences[PreferencesKeys.SHOW_3D] == true
|
||||||
}
|
}
|
||||||
val darkModeFlow: Flow<Int> =
|
val darkModeFlow: Flow<Int> =
|
||||||
context.dataStore.data.map { preferences ->
|
context.dataStore.data.map { preferences ->
|
||||||
@@ -72,10 +77,22 @@ class DataStoreManager(private val context: Context) {
|
|||||||
?: 0
|
?: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val lastRouteFlow: Flow<String> =
|
||||||
|
context.dataStore.data.map { preferences ->
|
||||||
|
preferences[PreferencesKeys.LAST_ROUTE]
|
||||||
|
?: ""
|
||||||
|
}
|
||||||
|
|
||||||
|
val tomTomApiKeyFlow: Flow<String> =
|
||||||
|
context.dataStore.data.map { preferences ->
|
||||||
|
preferences[PreferencesKeys.TOMTOM_APIKEY]
|
||||||
|
?: ""
|
||||||
|
}
|
||||||
|
|
||||||
// Save values
|
// Save values
|
||||||
suspend fun setThreedBuilding(enabled: Boolean) {
|
suspend fun setShow3D(enabled: Boolean) {
|
||||||
context.dataStore.edit { preferences ->
|
context.dataStore.edit { preferences ->
|
||||||
preferences[PreferencesKeys.THREED_BUILDING] = enabled
|
preferences[PreferencesKeys.SHOW_3D] = enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,4 +125,16 @@ class DataStoreManager(private val context: Context) {
|
|||||||
prefs[PreferencesKeys.ROUTING_ENGINE] = mode
|
prefs[PreferencesKeys.ROUTING_ENGINE] = mode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun setLastRoute(route: String) {
|
||||||
|
context.dataStore.edit { prefs ->
|
||||||
|
prefs[PreferencesKeys.LAST_ROUTE] = route
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun setTomtomApiKey(apiKey: String) {
|
||||||
|
context.dataStore.edit { prefs ->
|
||||||
|
prefs[PreferencesKeys.TOMTOM_APIKEY] = apiKey
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,18 +6,21 @@ import com.kouros.data.R
|
|||||||
import com.kouros.navigation.data.NavigationRepository
|
import com.kouros.navigation.data.NavigationRepository
|
||||||
import com.kouros.navigation.data.SearchFilter
|
import com.kouros.navigation.data.SearchFilter
|
||||||
import com.kouros.navigation.utils.GeoUtils.calculateSquareRadius
|
import com.kouros.navigation.utils.GeoUtils.calculateSquareRadius
|
||||||
|
import com.kouros.navigation.utils.getSettingsRepository
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
|
||||||
private const val routeUrl = "https://api.tomtom.com/routing/1/calculateRoute/"
|
private const val routeUrl = "https://api.tomtom.com/routing/1/calculateRoute/"
|
||||||
|
|
||||||
const val tomtomApiKey = "678k5v6940cSXXIS5oD92qIrDgW3RBZ3"
|
//const val tomtomApiKey = "678k5v6940cSXXIS5oD92qIrDgW3RBZ3"
|
||||||
|
|
||||||
const val tomtomTrafficUrl = "https://api.tomtom.com/traffic/services/5/incidentDetails"
|
const val tomtomTrafficUrl = "https://api.tomtom.com/traffic/services/5/incidentDetails"
|
||||||
|
|
||||||
private const val tomtomFields =
|
private const val tomtomFields =
|
||||||
"{incidents{type,geometry{type,coordinates},properties{iconCategory,events{description}}}}"
|
"{incidents{type,geometry{type,coordinates},properties{iconCategory,events{description}}}}"
|
||||||
|
|
||||||
const val useAsset = true
|
const val useAsset = false
|
||||||
|
|
||||||
class TomTomRepository : NavigationRepository() {
|
class TomTomRepository : NavigationRepository() {
|
||||||
override fun getRoute(
|
override fun getRoute(
|
||||||
@@ -32,6 +35,8 @@ class TomTomRepository : NavigationRepository() {
|
|||||||
val routeJsonString = routeJson.bufferedReader().use { it.readText() }
|
val routeJsonString = routeJson.bufferedReader().use { it.readText() }
|
||||||
return routeJsonString
|
return routeJsonString
|
||||||
}
|
}
|
||||||
|
val repository = getSettingsRepository(context)
|
||||||
|
val tomtomApiKey = runBlocking { repository.tomTomApiKeyFlow.first() }
|
||||||
val url =
|
val url =
|
||||||
routeUrl + "${currentLocation.latitude},${currentLocation.longitude}:${location.latitude},${location.longitude}" +
|
routeUrl + "${currentLocation.latitude},${currentLocation.longitude}:${location.latitude},${location.longitude}" +
|
||||||
"/json?vehicleHeading=90§ionType=traffic&report=effectiveSettings&routeType=eco" +
|
"/json?vehicleHeading=90§ionType=traffic&report=effectiveSettings&routeType=eco" +
|
||||||
@@ -47,6 +52,8 @@ class TomTomRepository : NavigationRepository() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getTraffic(context: Context, location: Location, carOrientation: Float): String {
|
override fun getTraffic(context: Context, location: Location, carOrientation: Float): String {
|
||||||
|
val repository = getSettingsRepository(context)
|
||||||
|
val tomtomApiKey = runBlocking { repository.tomTomApiKeyFlow.first() }
|
||||||
val bbox = calculateSquareRadius(location.latitude, location.longitude, 15.0)
|
val bbox = calculateSquareRadius(location.latitude, location.longitude, 15.0)
|
||||||
return if (useAsset) {
|
return if (useAsset) {
|
||||||
val trafficJson = context.resources.openRawResource(R.raw.tomtom_traffic)
|
val trafficJson = context.resources.openRawResource(R.raw.tomtom_traffic)
|
||||||
|
|||||||
@@ -102,7 +102,6 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
|||||||
location,
|
location,
|
||||||
plLocation,
|
plLocation,
|
||||||
carOrientation,
|
carOrientation,
|
||||||
SearchFilter(),
|
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
place.distance = distance.toFloat()
|
place.distance = distance.toFloat()
|
||||||
@@ -135,7 +134,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
|||||||
location,
|
location,
|
||||||
plLocation,
|
plLocation,
|
||||||
carOrientation,
|
carOrientation,
|
||||||
getSearchFilter(context), context
|
context
|
||||||
)
|
)
|
||||||
place.distance = distance.toFloat()
|
place.distance = distance.toFloat()
|
||||||
}
|
}
|
||||||
@@ -164,7 +163,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
|||||||
location,
|
location,
|
||||||
plLocation,
|
plLocation,
|
||||||
carOrientation,
|
carOrientation,
|
||||||
getSearchFilter(context),
|
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
place.distance = distance.toFloat()
|
place.distance = distance.toFloat()
|
||||||
@@ -486,7 +485,6 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
|||||||
location,
|
location,
|
||||||
plLocation,
|
plLocation,
|
||||||
carOrientation,
|
carOrientation,
|
||||||
getSearchFilter(context),
|
|
||||||
context
|
context
|
||||||
)
|
)
|
||||||
place.distance = distance.toFloat()
|
place.distance = distance.toFloat()
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ open class RouteModel {
|
|||||||
)
|
)
|
||||||
if (hasLegs()) {
|
if (hasLegs()) {
|
||||||
navState = navState.copy(navigating = true)
|
navState = navState.copy(navigating = true)
|
||||||
//NavigationUtils.setStringKeyValue(context, routeString, LAST_ROUTE)
|
getSettingsViewModel(context).onLastRouteChanged(routeString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +75,7 @@ open class RouteModel {
|
|||||||
arrived = false,
|
arrived = false,
|
||||||
maneuverType = Maneuver.TYPE_UNKNOWN
|
maneuverType = Maneuver.TYPE_UNKNOWN
|
||||||
)
|
)
|
||||||
//NavigationUtils.setStringKeyValue(context, "", LAST_ROUTE)
|
getSettingsViewModel(context).onLastRouteChanged("")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateLocation(context: Context, curLocation: Location, viewModel: NavigationViewModel) {
|
fun updateLocation(context: Context, curLocation: Location, viewModel: NavigationViewModel) {
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
class SettingsViewModel(private val repository: SettingsRepository) : ViewModel() {
|
class SettingsViewModel(private val repository: SettingsRepository) : ViewModel() {
|
||||||
|
|
||||||
val threedBuilding = repository.threedBuildingFlow.stateIn(
|
val show3D = repository.show3DFlow.stateIn(
|
||||||
viewModelScope,
|
viewModelScope,
|
||||||
SharingStarted.WhileSubscribed(5_000),
|
SharingStarted.WhileSubscribed(5_000),
|
||||||
false
|
false
|
||||||
@@ -45,10 +45,21 @@ class SettingsViewModel(private val repository: SettingsRepository) : ViewModel(
|
|||||||
0
|
0
|
||||||
)
|
)
|
||||||
|
|
||||||
fun onThreedBuildingChanged(enabled: Boolean) {
|
val lastRoute = repository.lastRouteFlow.stateIn(
|
||||||
viewModelScope.launch { repository.setThreedBuilding(enabled) }
|
viewModelScope,
|
||||||
}
|
SharingStarted.WhileSubscribed(5_000),
|
||||||
|
""
|
||||||
|
)
|
||||||
|
|
||||||
|
val tomTomApiKey = repository.tomTomApiKeyFlow.stateIn(
|
||||||
|
viewModelScope,
|
||||||
|
SharingStarted.WhileSubscribed(5_000),
|
||||||
|
""
|
||||||
|
)
|
||||||
|
|
||||||
|
fun onShow3DChanged(enabled: Boolean) {
|
||||||
|
viewModelScope.launch { repository.setShow3D(enabled) }
|
||||||
|
}
|
||||||
|
|
||||||
fun onDarkModeChanged(mode: Int) {
|
fun onDarkModeChanged(mode: Int) {
|
||||||
viewModelScope.launch { repository.setDarkMode(mode) }
|
viewModelScope.launch { repository.setDarkMode(mode) }
|
||||||
@@ -69,4 +80,12 @@ class SettingsViewModel(private val repository: SettingsRepository) : ViewModel(
|
|||||||
fun onRoutingEngineChanged(mode: Int) {
|
fun onRoutingEngineChanged(mode: Int) {
|
||||||
viewModelScope.launch { repository.setRoutingEngine(mode) }
|
viewModelScope.launch { repository.setRoutingEngine(mode) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onLastRouteChanged(route: String) {
|
||||||
|
viewModelScope.launch { repository.setLastRoute(route) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onTomTomApiKeyChanged(route: String) {
|
||||||
|
viewModelScope.launch { repository.setTomTomApiKey(route) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,8 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
class SettingsRepository(
|
class SettingsRepository(
|
||||||
private val dataStoreManager: DataStoreManager
|
private val dataStoreManager: DataStoreManager
|
||||||
) {
|
) {
|
||||||
|
val show3DFlow: Flow<Boolean> =
|
||||||
val threedBuildingFlow: Flow<Boolean> =
|
dataStoreManager.show3DFlow
|
||||||
dataStoreManager.threeDBuildingFlow
|
|
||||||
val darkModeFlow: Flow<Int> =
|
val darkModeFlow: Flow<Int> =
|
||||||
dataStoreManager.darkModeFlow
|
dataStoreManager.darkModeFlow
|
||||||
|
|
||||||
@@ -24,9 +23,14 @@ class SettingsRepository(
|
|||||||
val routingEngineFlow: Flow<Int> =
|
val routingEngineFlow: Flow<Int> =
|
||||||
dataStoreManager.routingEngineFlow
|
dataStoreManager.routingEngineFlow
|
||||||
|
|
||||||
|
val lastRouteFlow: Flow<String> =
|
||||||
|
dataStoreManager.lastRouteFlow
|
||||||
|
|
||||||
suspend fun setThreedBuilding(enabled: Boolean) {
|
val tomTomApiKeyFlow: Flow<String> =
|
||||||
dataStoreManager.setThreedBuilding(enabled)
|
dataStoreManager.tomTomApiKeyFlow
|
||||||
|
|
||||||
|
suspend fun setShow3D(enabled: Boolean) {
|
||||||
|
dataStoreManager.setShow3D(enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun setDarkMode(mode: Int) {
|
suspend fun setDarkMode(mode: Int) {
|
||||||
@@ -49,4 +53,12 @@ class SettingsRepository(
|
|||||||
dataStoreManager.setRoutingEngine(mode)
|
dataStoreManager.setRoutingEngine(mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
suspend fun setLastRoute(route: String) {
|
||||||
|
dataStoreManager.setLastRoute(route)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun setTomTomApiKey(apiKey: String) {
|
||||||
|
dataStoreManager.setTomtomApiKey(apiKey)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -3,18 +3,11 @@ package com.kouros.navigation.utils
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.location.Location
|
import android.location.Location
|
||||||
import android.location.LocationManager
|
import android.location.LocationManager
|
||||||
import androidx.car.app.CarContext
|
|
||||||
import androidx.core.content.edit
|
|
||||||
import com.kouros.navigation.data.Constants.ROUTING_ENGINE
|
|
||||||
import com.kouros.navigation.data.Constants.SHARED_PREF_KEY
|
|
||||||
import com.kouros.navigation.data.RouteEngine
|
import com.kouros.navigation.data.RouteEngine
|
||||||
import com.kouros.navigation.data.datastore.DataStoreManager
|
|
||||||
import com.kouros.navigation.data.osrm.OsrmRepository
|
import com.kouros.navigation.data.osrm.OsrmRepository
|
||||||
import com.kouros.navigation.data.tomtom.TomTomRepository
|
import com.kouros.navigation.data.tomtom.TomTomRepository
|
||||||
import com.kouros.navigation.data.valhalla.ValhallaRepository
|
import com.kouros.navigation.data.valhalla.ValhallaRepository
|
||||||
import com.kouros.navigation.model.NavigationViewModel
|
import com.kouros.navigation.model.NavigationViewModel
|
||||||
import com.kouros.navigation.model.SettingsViewModel
|
|
||||||
import com.kouros.navigation.repository.SettingsRepository
|
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|||||||
@@ -36,4 +36,5 @@
|
|||||||
<string name="use_car_location">Use car location</string>
|
<string name="use_car_location">Use car location</string>
|
||||||
<string name="tomtom">TomTom\t</string>
|
<string name="tomtom">TomTom\t</string>
|
||||||
<string name="options">Options</string>
|
<string name="options">Options</string>
|
||||||
|
<string name="tomtom_api_key">TomTom ApiKey</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "9.0.0"
|
agp = "9.0.1"
|
||||||
androidSdkTurf = "6.0.1"
|
androidSdkTurf = "6.0.1"
|
||||||
gradle = "9.0.0"
|
gradle = "9.0.1"
|
||||||
koinAndroid = "4.1.1"
|
koinAndroid = "4.1.1"
|
||||||
koinAndroidxCompose = "4.1.1"
|
koinAndroidxCompose = "4.1.1"
|
||||||
koinComposeViewmodel = "4.1.1"
|
koinComposeViewmodel = "4.1.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user