mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
Refactor: Only show advanced and app settings for local node (#4290)
Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
parent
d8c7a51a84
commit
71628cac84
2 changed files with 172 additions and 167 deletions
|
|
@ -276,177 +276,180 @@ fun SettingsScreen(
|
|||
|
||||
val context = LocalContext.current
|
||||
|
||||
TitledCard(title = stringResource(Res.string.app_settings), modifier = Modifier.padding(top = 16.dp)) {
|
||||
if (state.analyticsAvailable) {
|
||||
val allowed by viewModel.analyticsAllowedFlow.collectAsStateWithLifecycle(false)
|
||||
SwitchListItem(
|
||||
text = stringResource(Res.string.analytics_okay),
|
||||
checked = allowed,
|
||||
leadingIcon = Icons.Default.BugReport,
|
||||
onClick = { viewModel.toggleAnalyticsAllowed() },
|
||||
)
|
||||
}
|
||||
if (state.isLocal) {
|
||||
TitledCard(title = stringResource(Res.string.app_settings), modifier = Modifier.padding(top = 16.dp)) {
|
||||
if (state.analyticsAvailable) {
|
||||
val allowed by viewModel.analyticsAllowedFlow.collectAsStateWithLifecycle(false)
|
||||
SwitchListItem(
|
||||
text = stringResource(Res.string.analytics_okay),
|
||||
checked = allowed,
|
||||
leadingIcon = Icons.Default.BugReport,
|
||||
onClick = { viewModel.toggleAnalyticsAllowed() },
|
||||
)
|
||||
}
|
||||
|
||||
val locationPermissionsState =
|
||||
rememberMultiplePermissionsState(permissions = listOf(Manifest.permission.ACCESS_FINE_LOCATION))
|
||||
val isGpsDisabled = context.gpsDisabled()
|
||||
val provideLocation by settingsViewModel.provideLocation.collectAsStateWithLifecycle()
|
||||
val locationPermissionsState =
|
||||
rememberMultiplePermissionsState(permissions = listOf(Manifest.permission.ACCESS_FINE_LOCATION))
|
||||
val isGpsDisabled = context.gpsDisabled()
|
||||
val provideLocation by settingsViewModel.provideLocation.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(provideLocation, locationPermissionsState.allPermissionsGranted, isGpsDisabled) {
|
||||
if (provideLocation) {
|
||||
if (locationPermissionsState.allPermissionsGranted) {
|
||||
if (!isGpsDisabled) {
|
||||
settingsViewModel.meshService?.startProvideLocation()
|
||||
LaunchedEffect(provideLocation, locationPermissionsState.allPermissionsGranted, isGpsDisabled) {
|
||||
if (provideLocation) {
|
||||
if (locationPermissionsState.allPermissionsGranted) {
|
||||
if (!isGpsDisabled) {
|
||||
settingsViewModel.meshService?.startProvideLocation()
|
||||
} else {
|
||||
context.showToast(Res.string.location_disabled)
|
||||
}
|
||||
} else {
|
||||
context.showToast(Res.string.location_disabled)
|
||||
// Request permissions if not granted and user wants to provide location
|
||||
locationPermissionsState.launchMultiplePermissionRequest()
|
||||
}
|
||||
} else {
|
||||
// Request permissions if not granted and user wants to provide location
|
||||
locationPermissionsState.launchMultiplePermissionRequest()
|
||||
settingsViewModel.meshService?.stopProvideLocation()
|
||||
}
|
||||
} else {
|
||||
settingsViewModel.meshService?.stopProvideLocation()
|
||||
}
|
||||
}
|
||||
|
||||
SwitchListItem(
|
||||
text = stringResource(Res.string.provide_location_to_mesh),
|
||||
leadingIcon = Icons.Rounded.LocationOn,
|
||||
enabled = !isGpsDisabled,
|
||||
checked = provideLocation,
|
||||
onClick = { settingsViewModel.setProvideLocation(!provideLocation) },
|
||||
)
|
||||
SwitchListItem(
|
||||
text = stringResource(Res.string.provide_location_to_mesh),
|
||||
leadingIcon = Icons.Rounded.LocationOn,
|
||||
enabled = !isGpsDisabled,
|
||||
checked = provideLocation,
|
||||
onClick = { settingsViewModel.setProvideLocation(!provideLocation) },
|
||||
)
|
||||
|
||||
val settingsLauncher =
|
||||
rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) {}
|
||||
val settingsLauncher =
|
||||
rememberLauncherForActivityResult(
|
||||
contract = ActivityResultContracts.StartActivityForResult(),
|
||||
) {}
|
||||
|
||||
// On Android 12 and below, system app settings for language are not available. Use the in-app language
|
||||
// picker for these devices.
|
||||
val useInAppLangPicker = Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
|
||||
ListItem(
|
||||
text = stringResource(Res.string.preferences_language),
|
||||
leadingIcon = Icons.Rounded.Language,
|
||||
trailingIcon = if (useInAppLangPicker) null else Icons.AutoMirrored.Rounded.KeyboardArrowRight,
|
||||
) {
|
||||
if (useInAppLangPicker) {
|
||||
showLanguagePickerDialog = true
|
||||
} else {
|
||||
val intent = Intent(ACTION_APP_LOCALE_SETTINGS, "package:${context.packageName}".toUri())
|
||||
if (intent.resolveActivity(context.packageManager) != null) {
|
||||
settingsLauncher.launch(intent)
|
||||
} else {
|
||||
// Fall back to the in-app picker
|
||||
// On Android 12 and below, system app settings for language are not available. Use the in-app
|
||||
// language
|
||||
// picker for these devices.
|
||||
val useInAppLangPicker = Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
|
||||
ListItem(
|
||||
text = stringResource(Res.string.preferences_language),
|
||||
leadingIcon = Icons.Rounded.Language,
|
||||
trailingIcon = if (useInAppLangPicker) null else Icons.AutoMirrored.Rounded.KeyboardArrowRight,
|
||||
) {
|
||||
if (useInAppLangPicker) {
|
||||
showLanguagePickerDialog = true
|
||||
} else {
|
||||
val intent = Intent(ACTION_APP_LOCALE_SETTINGS, "package:${context.packageName}".toUri())
|
||||
if (intent.resolveActivity(context.packageManager) != null) {
|
||||
settingsLauncher.launch(intent)
|
||||
} else {
|
||||
// Fall back to the in-app picker
|
||||
showLanguagePickerDialog = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ListItem(
|
||||
text = stringResource(Res.string.theme),
|
||||
leadingIcon = Icons.Rounded.FormatPaint,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
showThemePickerDialog = true
|
||||
}
|
||||
|
||||
ListItem(
|
||||
text = "Message Filter",
|
||||
leadingIcon = Icons.Rounded.FilterList,
|
||||
trailingIcon = Icons.AutoMirrored.Rounded.KeyboardArrowRight,
|
||||
) {
|
||||
onNavigate(SettingsRoutes.FilterSettings)
|
||||
}
|
||||
|
||||
// Node DB cache limit (App setting)
|
||||
val cacheLimit = settingsViewModel.dbCacheLimit.collectAsStateWithLifecycle().value
|
||||
val cacheItems = remember {
|
||||
(DatabaseConstants.MIN_CACHE_LIMIT..DatabaseConstants.MAX_CACHE_LIMIT).map {
|
||||
it.toLong() to it.toString()
|
||||
ListItem(
|
||||
text = stringResource(Res.string.theme),
|
||||
leadingIcon = Icons.Rounded.FormatPaint,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
showThemePickerDialog = true
|
||||
}
|
||||
}
|
||||
DropDownPreference(
|
||||
title = stringResource(Res.string.device_db_cache_limit),
|
||||
enabled = true,
|
||||
items = cacheItems,
|
||||
selectedItem = cacheLimit.toLong(),
|
||||
onItemSelected = { selected -> settingsViewModel.setDbCacheLimit(selected.toInt()) },
|
||||
summary = stringResource(Res.string.device_db_cache_limit_summary),
|
||||
)
|
||||
|
||||
val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
|
||||
val nodeName = ourNode?.user?.shortName ?: ""
|
||||
|
||||
val exportRangeTestLauncher =
|
||||
rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == RESULT_OK) {
|
||||
it.data?.data?.let { uri -> settingsViewModel.saveDataCsv(uri) }
|
||||
ListItem(
|
||||
text = "Message Filter",
|
||||
leadingIcon = Icons.Rounded.FilterList,
|
||||
trailingIcon = Icons.AutoMirrored.Rounded.KeyboardArrowRight,
|
||||
) {
|
||||
onNavigate(SettingsRoutes.FilterSettings)
|
||||
} // Node DB cache limit (App setting)
|
||||
val cacheLimit = settingsViewModel.dbCacheLimit.collectAsStateWithLifecycle().value
|
||||
val cacheItems = remember {
|
||||
(DatabaseConstants.MIN_CACHE_LIMIT..DatabaseConstants.MAX_CACHE_LIMIT).map {
|
||||
it.toLong() to it.toString()
|
||||
}
|
||||
}
|
||||
ListItem(
|
||||
text = stringResource(Res.string.save_rangetest),
|
||||
leadingIcon = Icons.Rounded.Output,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
val intent =
|
||||
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "application/csv"
|
||||
putExtra(Intent.EXTRA_TITLE, "Meshtastic_rangetest_${nodeName}_$timestamp.csv")
|
||||
}
|
||||
exportRangeTestLauncher.launch(intent)
|
||||
}
|
||||
DropDownPreference(
|
||||
title = stringResource(Res.string.device_db_cache_limit),
|
||||
enabled = true,
|
||||
items = cacheItems,
|
||||
selectedItem = cacheLimit.toLong(),
|
||||
onItemSelected = { selected -> settingsViewModel.setDbCacheLimit(selected.toInt()) },
|
||||
summary = stringResource(Res.string.device_db_cache_limit_summary),
|
||||
)
|
||||
|
||||
val exportDataLauncher =
|
||||
rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == RESULT_OK) {
|
||||
it.data?.data?.let { uri -> settingsViewModel.saveDataCsv(uri) }
|
||||
val timestamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US).format(Date())
|
||||
val nodeName = ourNode?.user?.shortName ?: ""
|
||||
|
||||
val exportRangeTestLauncher =
|
||||
rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == RESULT_OK) {
|
||||
it.data?.data?.let { uri -> settingsViewModel.saveDataCsv(uri) }
|
||||
}
|
||||
}
|
||||
ListItem(
|
||||
text = stringResource(Res.string.save_rangetest),
|
||||
leadingIcon = Icons.Rounded.Output,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
val intent =
|
||||
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "application/csv"
|
||||
putExtra(Intent.EXTRA_TITLE, "Meshtastic_rangetest_${nodeName}_$timestamp.csv")
|
||||
}
|
||||
exportRangeTestLauncher.launch(intent)
|
||||
}
|
||||
ListItem(
|
||||
text = stringResource(Res.string.export_data_csv),
|
||||
leadingIcon = Icons.Rounded.Output,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
val intent =
|
||||
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "application/csv"
|
||||
putExtra(Intent.EXTRA_TITLE, "Meshtastic_datalog_${nodeName}_$timestamp.csv")
|
||||
|
||||
val exportDataLauncher =
|
||||
rememberLauncherForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
if (it.resultCode == RESULT_OK) {
|
||||
it.data?.data?.let { uri -> settingsViewModel.saveDataCsv(uri) }
|
||||
}
|
||||
}
|
||||
exportDataLauncher.launch(intent)
|
||||
}
|
||||
ListItem(
|
||||
text = stringResource(Res.string.export_data_csv),
|
||||
leadingIcon = Icons.Rounded.Output,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
val intent =
|
||||
Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
||||
addCategory(Intent.CATEGORY_OPENABLE)
|
||||
type = "application/csv"
|
||||
putExtra(Intent.EXTRA_TITLE, "Meshtastic_datalog_${nodeName}_$timestamp.csv")
|
||||
}
|
||||
exportDataLauncher.launch(intent)
|
||||
}
|
||||
|
||||
ListItem(
|
||||
text = stringResource(Res.string.intro_show),
|
||||
leadingIcon = Icons.Rounded.WavingHand,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
settingsViewModel.showAppIntro()
|
||||
}
|
||||
ListItem(
|
||||
text = stringResource(Res.string.intro_show),
|
||||
leadingIcon = Icons.Rounded.WavingHand,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
settingsViewModel.showAppIntro()
|
||||
}
|
||||
|
||||
ListItem(
|
||||
text = stringResource(Res.string.system_settings),
|
||||
leadingIcon = Icons.Rounded.AppSettingsAlt,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intent.data = Uri.fromParts("package", context.packageName, null)
|
||||
settingsLauncher.launch(intent)
|
||||
}
|
||||
ListItem(
|
||||
text = stringResource(Res.string.system_settings),
|
||||
leadingIcon = Icons.Rounded.AppSettingsAlt,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
intent.data = Uri.fromParts("package", context.packageName, null)
|
||||
settingsLauncher.launch(intent)
|
||||
}
|
||||
|
||||
ListItem(
|
||||
text = stringResource(Res.string.acknowledgements),
|
||||
leadingIcon = Icons.Rounded.Info,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
onNavigate(SettingsRoutes.About)
|
||||
}
|
||||
ListItem(
|
||||
text = stringResource(Res.string.acknowledgements),
|
||||
leadingIcon = Icons.Rounded.Info,
|
||||
trailingIcon = null,
|
||||
) {
|
||||
onNavigate(SettingsRoutes.About)
|
||||
}
|
||||
|
||||
AppVersionButton(
|
||||
excludedModulesUnlocked = excludedModulesUnlocked,
|
||||
appVersionName = settingsViewModel.appVersionName,
|
||||
) {
|
||||
settingsViewModel.unlockExcludedModules()
|
||||
AppVersionButton(
|
||||
excludedModulesUnlocked = excludedModulesUnlocked,
|
||||
appVersionName = settingsViewModel.appVersionName,
|
||||
) {
|
||||
settingsViewModel.unlockExcludedModules()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -206,33 +206,35 @@ fun RadioConfigItemList(
|
|||
}
|
||||
}
|
||||
|
||||
TitledCard(title = stringResource(Res.string.advanced_title), modifier = Modifier.padding(top = 16.dp)) {
|
||||
if (isManaged) {
|
||||
ManagedMessage()
|
||||
}
|
||||
if (state.isLocal) {
|
||||
TitledCard(title = stringResource(Res.string.advanced_title), modifier = Modifier.padding(top = 16.dp)) {
|
||||
if (isManaged) {
|
||||
ManagedMessage()
|
||||
}
|
||||
|
||||
if (isOtaCapable) {
|
||||
ListItem(
|
||||
text = stringResource(Res.string.firmware_update_title),
|
||||
leadingIcon = Icons.Rounded.SystemUpdate,
|
||||
enabled = enabled,
|
||||
onClick = { onNavigate(FirmwareRoutes.FirmwareUpdate) },
|
||||
)
|
||||
}
|
||||
|
||||
if (isOtaCapable && state.isLocal) {
|
||||
ListItem(
|
||||
text = stringResource(Res.string.firmware_update_title),
|
||||
leadingIcon = Icons.Rounded.SystemUpdate,
|
||||
text = stringResource(Res.string.clean_node_database_title),
|
||||
leadingIcon = Icons.Rounded.CleaningServices,
|
||||
enabled = enabled,
|
||||
onClick = { onNavigate(FirmwareRoutes.FirmwareUpdate) },
|
||||
onClick = { onNavigate(SettingsRoutes.CleanNodeDb) },
|
||||
)
|
||||
|
||||
ListItem(
|
||||
text = stringResource(Res.string.debug_panel),
|
||||
leadingIcon = Icons.Rounded.BugReport,
|
||||
enabled = enabled,
|
||||
onClick = { onNavigate(SettingsRoutes.DebugPanel) },
|
||||
)
|
||||
}
|
||||
|
||||
ListItem(
|
||||
text = stringResource(Res.string.clean_node_database_title),
|
||||
leadingIcon = Icons.Rounded.CleaningServices,
|
||||
enabled = enabled,
|
||||
onClick = { onNavigate(SettingsRoutes.CleanNodeDb) },
|
||||
)
|
||||
|
||||
ListItem(
|
||||
text = stringResource(Res.string.debug_panel),
|
||||
leadingIcon = Icons.Rounded.BugReport,
|
||||
enabled = enabled,
|
||||
onClick = { onNavigate(SettingsRoutes.DebugPanel) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue