Settings
This commit is contained in:
@@ -14,8 +14,8 @@ android {
|
||||
applicationId = "com.kouros.navigation"
|
||||
minSdk = 33
|
||||
targetSdk = 36
|
||||
versionCode = 42
|
||||
versionName = "0.2.0.42"
|
||||
versionCode = 43
|
||||
versionName = "0.2.0.43"
|
||||
base.archivesName = "navi-$versionName"
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
@@ -97,9 +97,6 @@ dependencies {
|
||||
implementation("com.github.ticofab:android-gpx-parser:2.3.1")
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
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)
|
||||
testImplementation(libs.junit)
|
||||
androidTestImplementation(libs.androidx.junit)
|
||||
|
||||
@@ -22,6 +22,8 @@ import androidx.compose.material3.BottomSheetScaffold
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.SheetState
|
||||
import androidx.compose.material3.SheetValue
|
||||
import androidx.compose.material3.SnackbarHost
|
||||
import androidx.compose.material3.SnackbarHostState
|
||||
import androidx.compose.material3.Text
|
||||
@@ -34,6 +36,7 @@ import androidx.compose.runtime.mutableDoubleStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -91,7 +94,7 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
val routeModel = RouteModel()
|
||||
var tilt = 50.0
|
||||
val useMock = true
|
||||
val useMock = false
|
||||
val type = 3 // 1 simulate 2 test 3 gpx 4 testSingle
|
||||
|
||||
var currentIndex = 0
|
||||
@@ -198,13 +201,12 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
val appViewModel: AppViewModel = appViewModel()
|
||||
val darkMode by appViewModel.darkMode.collectAsState()
|
||||
|
||||
val sheetPeekHeight = 250.dp
|
||||
baseStyle = BaseStyleModel().readStyle(applicationContext, darkMode, darkMode == 1)
|
||||
|
||||
val scaffoldState = rememberBottomSheetScaffoldState()
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
val scope = rememberCoroutineScope()
|
||||
val sheetPeekHeightState = remember { mutableStateOf(256.dp) }
|
||||
val sheetPeekHeightState = remember { mutableStateOf(sheetPeekHeight) }
|
||||
|
||||
val locationProvider = rememberDefaultLocationProvider(
|
||||
updateInterval = 0.5.seconds, desiredAccuracy = DesiredAccuracy.Highest
|
||||
@@ -221,7 +223,7 @@ class MainActivity : ComponentActivity() {
|
||||
fun closeSheet() {
|
||||
scope.launch {
|
||||
scaffoldState.bottomSheetState.partialExpand()
|
||||
sheetPeekHeightState.value = 128.dp
|
||||
sheetPeekHeightState.value = sheetPeekHeight
|
||||
}
|
||||
}
|
||||
NavigationTheme (useDarkTheme = darkMode == 1) {
|
||||
@@ -261,11 +263,11 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
@Composable
|
||||
fun App() {
|
||||
//val lastRoute = NavigationUtils.getStringKeyValue(applicationContext, Constants.LAST_ROUTE)
|
||||
//if (lastRoute!!.isNotEmpty()) {
|
||||
// routeModel.startNavigation(lastRoute, applicationContext)
|
||||
// routeData.value = routeModel.curRoute.routeGeoJson
|
||||
//}
|
||||
val appViewModel: AppViewModel = appViewModel()
|
||||
val lastRoute by appViewModel.lastRoute.collectAsState()
|
||||
if (lastRoute.isNotEmpty()) {
|
||||
navigationViewModel.route.value = lastRoute
|
||||
}
|
||||
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.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.rememberCameraState
|
||||
import org.maplibre.compose.location.LocationTrackingEffect
|
||||
@@ -66,7 +67,7 @@ fun MapView(
|
||||
val rememberBaseStyle = rememberBaseStyle(baseStyle)
|
||||
|
||||
val appViewModel: AppViewModel = appViewModel()
|
||||
val showBuildings by appViewModel.threedBuilding.collectAsState()
|
||||
val showBuildings by appViewModel.show3D.collectAsState()
|
||||
|
||||
Column {
|
||||
NavigationInfo(step, nextStep)
|
||||
|
||||
@@ -4,10 +4,13 @@ import android.content.Context
|
||||
import android.location.Location
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
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.Icon
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.SearchBar
|
||||
import androidx.compose.material3.SearchBarDefaults
|
||||
import androidx.compose.material3.Text
|
||||
@@ -51,21 +55,15 @@ fun SearchSheet(
|
||||
if (search.value != null) {
|
||||
searchResults.addAll(search.value!!)
|
||||
}
|
||||
|
||||
Home(applicationContext, viewModel, location, closeSheet = { closeSheet() })
|
||||
if (recentPlaces.value != null) {
|
||||
val items = listOf(recentPlaces)
|
||||
if (items.isNotEmpty()) {
|
||||
RecentPlaces(recentPlaces.value!!, viewModel, applicationContext, location, closeSheet)
|
||||
}
|
||||
}
|
||||
// if (searchResults.isNotEmpty()) {
|
||||
val textFieldState = rememberTextFieldState()
|
||||
val items = listOf(searchResults)
|
||||
// if (items.isNotEmpty()) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight()
|
||||
) {
|
||||
SearchBar(
|
||||
textFieldState = textFieldState,
|
||||
searchPlaces = emptyList<Place>(),
|
||||
searchPlaces = emptyList(),
|
||||
searchResults = searchResults,
|
||||
viewModel = viewModel,
|
||||
context = applicationContext,
|
||||
@@ -73,10 +71,20 @@ fun SearchSheet(
|
||||
closeSheet = { closeSheet() }
|
||||
|
||||
)
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//Home(applicationContext, viewModel, location, closeSheet = { closeSheet() })
|
||||
if (recentPlaces.value != null) {
|
||||
val items = listOf(recentPlaces)
|
||||
if (items.isNotEmpty()) {
|
||||
RecentPlaces(
|
||||
recentPlaces.value!!,
|
||||
viewModel,
|
||||
applicationContext,
|
||||
location,
|
||||
closeSheet
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@@ -124,8 +132,12 @@ fun SearchBar(
|
||||
location: Location,
|
||||
closeSheet: () -> Unit
|
||||
) {
|
||||
var expanded by rememberSaveable { mutableStateOf(true) }
|
||||
var expanded by rememberSaveable { mutableStateOf(false) }
|
||||
SearchBar(
|
||||
colors = SearchBarDefaults.colors(
|
||||
containerColor = MaterialTheme.colorScheme.secondaryContainer
|
||||
),
|
||||
modifier = modifier,
|
||||
inputField = {
|
||||
SearchBarDefaults.InputField(
|
||||
leadingIcon = {
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
val threedBuilding = settingsRepository.threedBuildingFlow
|
||||
val show3D = settingsRepository.show3DFlow
|
||||
.stateIn(
|
||||
viewModelScope,
|
||||
SharingStarted.Eagerly,
|
||||
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.rememberNavController
|
||||
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
|
||||
|
||||
|
||||
@@ -18,17 +15,8 @@ fun AppNavGraph(applicationContext: Context, mainActivity: MainActivity) {
|
||||
val navController = rememberNavController()
|
||||
NavHost(navController = navController, startDestination = "startScreen") {
|
||||
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("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
|
||||
|
||||
@Composable
|
||||
fun SettingsRoute(route: String, navController: NavHostController, function: () -> Boolean) {
|
||||
fun SettingsRoute(route: String, navController: NavHostController, function: () -> Unit) {
|
||||
|
||||
val context = LocalContext.current
|
||||
|
||||
@@ -28,10 +28,12 @@ fun SettingsRoute(route: String, navController: NavHostController, function: ()
|
||||
}
|
||||
)
|
||||
if (route == "display_settings") {
|
||||
SettingsScreen(viewModel = viewModel)
|
||||
DisplayScreen(viewModel = viewModel, function)
|
||||
}
|
||||
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
|
||||
|
||||
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.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.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
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 SettingsScreen(viewModel: SettingsViewModel) {
|
||||
|
||||
val darkMode by viewModel.darkMode.collectAsState()
|
||||
val threedBuilding by viewModel.threedBuilding.collectAsState()
|
||||
val avoidMotorway by viewModel.avoidMotorway.collectAsState()
|
||||
val avoidTollway by viewModel.avoidTollway.collectAsState()
|
||||
val carLocation by viewModel.carLocation.collectAsState()
|
||||
val routingEngine by viewModel.routingEngine.collectAsState()
|
||||
|
||||
fun SettingsScreen(viewModel: SettingsViewModel, navController: NavHostController, navigateBack: () -> Unit) {
|
||||
NavigationTheme(useDarkTheme = viewModel.darkMode.collectAsState().value == 1) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
CenterAlignedTopAppBar(
|
||||
title = {
|
||||
Text(
|
||||
stringResource(id = R.string.display_settings),
|
||||
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),
|
||||
// )
|
||||
// }
|
||||
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 ->
|
||||
) { padding ->
|
||||
val scrollState = rememberScrollState()
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(top = 20.dp)
|
||||
modifier =
|
||||
Modifier
|
||||
.consumeWindowInsets(padding)
|
||||
.verticalScroll(scrollState)
|
||||
.padding(top = padding.calculateTopPadding()),
|
||||
) {
|
||||
Column(modifier = Modifier.padding(16.dp)) {
|
||||
|
||||
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
|
||||
)
|
||||
Button(onClick = { navController.navigate("display_settings") }) {
|
||||
Text(stringResource(R.string.display_settings))
|
||||
}
|
||||
Button(onClick = { navController.navigate("nav_settings") }) {
|
||||
Text(stringResource(R.string.navigation_settings))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package com.kouros.navigation.car
|
||||
|
||||
import android.Manifest
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
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.RequestPermissionScreen
|
||||
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_SNAP_CORRECTION
|
||||
import com.kouros.navigation.data.Constants.TAG
|
||||
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.tomtom.TomTomRepository
|
||||
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.NavigationUtils.getViewModel
|
||||
import com.kouros.navigation.utils.getSettingsRepository
|
||||
import com.kouros.navigation.utils.getSettingsViewModel
|
||||
import kotlinx.coroutines.awaitCancellation
|
||||
import kotlinx.coroutines.flow.first
|
||||
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.rememberBaseStyle
|
||||
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.ObjectBox
|
||||
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.duration
|
||||
import com.kouros.navigation.utils.getSettingsRepository
|
||||
import com.kouros.navigation.utils.getSettingsViewModel
|
||||
import com.kouros.navigation.utils.location
|
||||
import com.kouros.navigation.utils.previewZoom
|
||||
import com.kouros.navigation.utils.settingsViewModel
|
||||
|
||||
@@ -22,18 +22,18 @@ class DisplaySettings(private val carContext: CarContext) : Screen(carContext) {
|
||||
|
||||
init {
|
||||
lifecycleScope.launch {
|
||||
settingsViewModel.threedBuilding.collect {
|
||||
settingsViewModel.show3D.collect {
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGetTemplate(): Template {
|
||||
buildingToggleState = settingsViewModel.threedBuilding.value
|
||||
buildingToggleState = settingsViewModel.show3D.value
|
||||
val listBuilder = ItemList.Builder()
|
||||
val buildingToggle: Toggle =
|
||||
Toggle.Builder { checked: Boolean ->
|
||||
settingsViewModel.onThreedBuildingChanged(checked)
|
||||
settingsViewModel.onShow3DChanged(checked)
|
||||
buildingToggleState = !buildingToggleState
|
||||
}.setChecked(buildingToggleState).build()
|
||||
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.getSettingsViewModel
|
||||
import com.kouros.navigation.utils.location
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.time.Duration
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
|
||||
@@ -30,10 +30,14 @@ class NavigationSettings(private val carContext: CarContext, private var navigat
|
||||
init {
|
||||
lifecycleScope.launch {
|
||||
settingsViewModel.avoidTollway.collect {
|
||||
settingsViewModel.avoidMotorway.collect {
|
||||
settingsViewModel.carLocation.collect {
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onGetTemplate(): Template {
|
||||
motorWayToggleState = settingsViewModel.avoidMotorway.value
|
||||
|
||||
@@ -102,8 +102,6 @@ object Constants {
|
||||
|
||||
//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 CATEGORIES: String = "Categories"
|
||||
@@ -126,21 +124,6 @@ object Constants {
|
||||
val homeVogelhart = location(11.5793748, 48.185749)
|
||||
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 MAXIMAL_SNAP_CORRECTION = 50.0
|
||||
|
||||
@@ -51,11 +51,10 @@ abstract class NavigationRepository {
|
||||
currentLocation: Location,
|
||||
location: Location,
|
||||
carOrientation: Float,
|
||||
searchFilter: SearchFilter,
|
||||
context: Context
|
||||
): Double {
|
||||
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 osrmJson = gson.fromJson(route, OsrmResponse::class.java)
|
||||
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.edit
|
||||
import androidx.datastore.preferences.core.intPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
@@ -26,7 +27,7 @@ class DataStoreManager(private val context: Context) {
|
||||
// Keys
|
||||
private object PreferencesKeys {
|
||||
|
||||
val THREED_BUILDING = booleanPreferencesKey("Show3D")
|
||||
val SHOW_3D = booleanPreferencesKey("Show3D")
|
||||
|
||||
val DARK_MODE = intPreferencesKey("DarkMode")
|
||||
|
||||
@@ -37,13 +38,17 @@ class DataStoreManager(private val context: Context) {
|
||||
val CAR_LOCATION = booleanPreferencesKey("CarLocation")
|
||||
|
||||
val ROUTING_ENGINE = intPreferencesKey("RoutingEngine")
|
||||
|
||||
val LAST_ROUTE = stringPreferencesKey("LastRoute")
|
||||
|
||||
val TOMTOM_APIKEY = stringPreferencesKey("TomTomApiKey")
|
||||
}
|
||||
|
||||
// Read values
|
||||
|
||||
val threeDBuildingFlow: Flow<Boolean> =
|
||||
val show3DFlow: Flow<Boolean> =
|
||||
context.dataStore.data.map { preferences ->
|
||||
preferences[PreferencesKeys.THREED_BUILDING] == true
|
||||
preferences[PreferencesKeys.SHOW_3D] == true
|
||||
}
|
||||
val darkModeFlow: Flow<Int> =
|
||||
context.dataStore.data.map { preferences ->
|
||||
@@ -72,10 +77,22 @@ class DataStoreManager(private val context: Context) {
|
||||
?: 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
|
||||
suspend fun setThreedBuilding(enabled: Boolean) {
|
||||
suspend fun setShow3D(enabled: Boolean) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
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.SearchFilter
|
||||
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/"
|
||||
|
||||
const val tomtomApiKey = "678k5v6940cSXXIS5oD92qIrDgW3RBZ3"
|
||||
//const val tomtomApiKey = "678k5v6940cSXXIS5oD92qIrDgW3RBZ3"
|
||||
|
||||
const val tomtomTrafficUrl = "https://api.tomtom.com/traffic/services/5/incidentDetails"
|
||||
|
||||
private const val tomtomFields =
|
||||
"{incidents{type,geometry{type,coordinates},properties{iconCategory,events{description}}}}"
|
||||
|
||||
const val useAsset = true
|
||||
const val useAsset = false
|
||||
|
||||
class TomTomRepository : NavigationRepository() {
|
||||
override fun getRoute(
|
||||
@@ -32,6 +35,8 @@ class TomTomRepository : NavigationRepository() {
|
||||
val routeJsonString = routeJson.bufferedReader().use { it.readText() }
|
||||
return routeJsonString
|
||||
}
|
||||
val repository = getSettingsRepository(context)
|
||||
val tomtomApiKey = runBlocking { repository.tomTomApiKeyFlow.first() }
|
||||
val url =
|
||||
routeUrl + "${currentLocation.latitude},${currentLocation.longitude}:${location.latitude},${location.longitude}" +
|
||||
"/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 {
|
||||
val repository = getSettingsRepository(context)
|
||||
val tomtomApiKey = runBlocking { repository.tomTomApiKeyFlow.first() }
|
||||
val bbox = calculateSquareRadius(location.latitude, location.longitude, 15.0)
|
||||
return if (useAsset) {
|
||||
val trafficJson = context.resources.openRawResource(R.raw.tomtom_traffic)
|
||||
|
||||
@@ -102,7 +102,6 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
location,
|
||||
plLocation,
|
||||
carOrientation,
|
||||
SearchFilter(),
|
||||
context
|
||||
)
|
||||
place.distance = distance.toFloat()
|
||||
@@ -135,7 +134,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
location,
|
||||
plLocation,
|
||||
carOrientation,
|
||||
getSearchFilter(context), context
|
||||
context
|
||||
)
|
||||
place.distance = distance.toFloat()
|
||||
}
|
||||
@@ -164,7 +163,7 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
location,
|
||||
plLocation,
|
||||
carOrientation,
|
||||
getSearchFilter(context),
|
||||
|
||||
context
|
||||
)
|
||||
place.distance = distance.toFloat()
|
||||
@@ -486,7 +485,6 @@ class NavigationViewModel(private val repository: NavigationRepository) : ViewMo
|
||||
location,
|
||||
plLocation,
|
||||
carOrientation,
|
||||
getSearchFilter(context),
|
||||
context
|
||||
)
|
||||
place.distance = distance.toFloat()
|
||||
|
||||
@@ -60,7 +60,7 @@ open class RouteModel {
|
||||
)
|
||||
if (hasLegs()) {
|
||||
navState = navState.copy(navigating = true)
|
||||
//NavigationUtils.setStringKeyValue(context, routeString, LAST_ROUTE)
|
||||
getSettingsViewModel(context).onLastRouteChanged(routeString)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ open class RouteModel {
|
||||
arrived = false,
|
||||
maneuverType = Maneuver.TYPE_UNKNOWN
|
||||
)
|
||||
//NavigationUtils.setStringKeyValue(context, "", LAST_ROUTE)
|
||||
getSettingsViewModel(context).onLastRouteChanged("")
|
||||
}
|
||||
|
||||
fun updateLocation(context: Context, curLocation: Location, viewModel: NavigationViewModel) {
|
||||
|
||||
@@ -9,7 +9,7 @@ import kotlinx.coroutines.launch
|
||||
|
||||
class SettingsViewModel(private val repository: SettingsRepository) : ViewModel() {
|
||||
|
||||
val threedBuilding = repository.threedBuildingFlow.stateIn(
|
||||
val show3D = repository.show3DFlow.stateIn(
|
||||
viewModelScope,
|
||||
SharingStarted.WhileSubscribed(5_000),
|
||||
false
|
||||
@@ -45,10 +45,21 @@ class SettingsViewModel(private val repository: SettingsRepository) : ViewModel(
|
||||
0
|
||||
)
|
||||
|
||||
fun onThreedBuildingChanged(enabled: Boolean) {
|
||||
viewModelScope.launch { repository.setThreedBuilding(enabled) }
|
||||
}
|
||||
val lastRoute = repository.lastRouteFlow.stateIn(
|
||||
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) {
|
||||
viewModelScope.launch { repository.setDarkMode(mode) }
|
||||
@@ -69,4 +80,12 @@ class SettingsViewModel(private val repository: SettingsRepository) : ViewModel(
|
||||
fun onRoutingEngineChanged(mode: Int) {
|
||||
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(
|
||||
private val dataStoreManager: DataStoreManager
|
||||
) {
|
||||
|
||||
val threedBuildingFlow: Flow<Boolean> =
|
||||
dataStoreManager.threeDBuildingFlow
|
||||
val show3DFlow: Flow<Boolean> =
|
||||
dataStoreManager.show3DFlow
|
||||
val darkModeFlow: Flow<Int> =
|
||||
dataStoreManager.darkModeFlow
|
||||
|
||||
@@ -24,9 +23,14 @@ class SettingsRepository(
|
||||
val routingEngineFlow: Flow<Int> =
|
||||
dataStoreManager.routingEngineFlow
|
||||
|
||||
val lastRouteFlow: Flow<String> =
|
||||
dataStoreManager.lastRouteFlow
|
||||
|
||||
suspend fun setThreedBuilding(enabled: Boolean) {
|
||||
dataStoreManager.setThreedBuilding(enabled)
|
||||
val tomTomApiKeyFlow: Flow<String> =
|
||||
dataStoreManager.tomTomApiKeyFlow
|
||||
|
||||
suspend fun setShow3D(enabled: Boolean) {
|
||||
dataStoreManager.setShow3D(enabled)
|
||||
}
|
||||
|
||||
suspend fun setDarkMode(mode: Int) {
|
||||
@@ -49,4 +53,12 @@ class SettingsRepository(
|
||||
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.location.Location
|
||||
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.datastore.DataStoreManager
|
||||
import com.kouros.navigation.data.osrm.OsrmRepository
|
||||
import com.kouros.navigation.data.tomtom.TomTomRepository
|
||||
import com.kouros.navigation.data.valhalla.ValhallaRepository
|
||||
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.runBlocking
|
||||
import java.time.LocalDateTime
|
||||
|
||||
@@ -36,4 +36,5 @@
|
||||
<string name="use_car_location">Use car location</string>
|
||||
<string name="tomtom">TomTom\t</string>
|
||||
<string name="options">Options</string>
|
||||
<string name="tomtom_api_key">TomTom ApiKey</string>
|
||||
</resources>
|
||||
@@ -1,7 +1,7 @@
|
||||
[versions]
|
||||
agp = "9.0.0"
|
||||
agp = "9.0.1"
|
||||
androidSdkTurf = "6.0.1"
|
||||
gradle = "9.0.0"
|
||||
gradle = "9.0.1"
|
||||
koinAndroid = "4.1.1"
|
||||
koinAndroidxCompose = "4.1.1"
|
||||
koinComposeViewmodel = "4.1.1"
|
||||
|
||||
Reference in New Issue
Block a user