From afd05ad8c03b25a870c1cf6627343b453dfa7da8 Mon Sep 17 00:00:00 2001 From: Seb3thehacker Date: Thu, 5 Nov 2026 17:14:28 -0800 Subject: [PATCH] Car settings match the phone's: voice settings under Sound and voice, switches for on and off, screen fixes together under Screen, and one lyrics setup for everyone --- .../seb3thehacker/gearslip/car/CarSettings.kt | 9 - .../gearslip/car/CarSettingsScreen.kt | 479 ++++++++---------- .../seb3thehacker/gearslip/media/Lyrics.kt | 20 +- .../gearslip/ui/HomeCarSettings.kt | 14 +- gearslip/src/main/res/values-ar/strings.xml | 4 - gearslip/src/main/res/values-cs/strings.xml | 4 - gearslip/src/main/res/values-da/strings.xml | 2 - gearslip/src/main/res/values-de/strings.xml | 4 - gearslip/src/main/res/values-es/strings.xml | 4 - gearslip/src/main/res/values-fr/strings.xml | 4 - gearslip/src/main/res/values-it/strings.xml | 4 - gearslip/src/main/res/values-ja/strings.xml | 4 - gearslip/src/main/res/values-ko/strings.xml | 4 - gearslip/src/main/res/values-nl/strings.xml | 4 - gearslip/src/main/res/values-pl/strings.xml | 4 - .../src/main/res/values-pt-rBR/strings.xml | 4 - gearslip/src/main/res/values-ro/strings.xml | 4 - gearslip/src/main/res/values-ru/strings.xml | 4 - gearslip/src/main/res/values-sv/strings.xml | 4 - gearslip/src/main/res/values-tr/strings.xml | 4 - gearslip/src/main/res/values-uk/strings.xml | 4 - .../src/main/res/values-zh-rCN/strings.xml | 4 - gearslip/src/main/res/values/strings.xml | 10 +- 23 files changed, 224 insertions(+), 378 deletions(-) diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarSettings.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarSettings.kt index 08ec1dd..b0befa2 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarSettings.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarSettings.kt @@ -68,7 +68,6 @@ private const val KEY_LOCATION_WARNING = "car_location_warning" private const val KEY_AUTOPLAY = "car_autoplay" private const val KEY_PLAYER_TITLE = "car_player_title" private const val KEY_PLAYER_LEFT = "car_player_left" - private const val KEY_MORE_LYRICS = "car_more_lyrics" private const val KEY_THEME = "car_app_theme" private const val KEY_UI_THEME = "car_ui_theme" private const val KEY_DARK_STYLE = "car_dark_style" @@ -114,7 +113,6 @@ private const val KEY_CLUSTER_VIDEO = "cluster_video_enabled" private val autoplayFlow = MutableStateFlow(false) private val playerTitleFlow = MutableStateFlow(false) private val playerLeftFlow = MutableStateFlow(false) - private val moreLyricsFlow = MutableStateFlow(true) private val themeFlow = MutableStateFlow(AppTheme.PHONE) val appTheme: StateFlow = themeFlow private val darkStyleFlow = MutableStateFlow(DarkStyle.BLACK) @@ -245,7 +243,6 @@ private const val KEY_CLUSTER_VIDEO = "cluster_video_enabled" val playerLeft: StateFlow = playerLeftFlow /** Lyrics from BetterLyrics and KuGou as well as LRCLIB; off sends song details to LRCLIB only. */ - val moreLyrics: StateFlow = moreLyricsFlow val scale: StateFlow = scaleFlow @@ -398,7 +395,6 @@ private const val KEY_CLUSTER_VIDEO = "cluster_video_enabled" autoplayFlow.value = AppSettings.getString(app, KEY_AUTOPLAY, "false") == "true" playerTitleFlow.value = AppSettings.getString(app, KEY_PLAYER_TITLE, "false") == "true" playerLeftFlow.value = AppSettings.getString(app, KEY_PLAYER_LEFT, "false") == "true" - moreLyricsFlow.value = AppSettings.getString(app, KEY_MORE_LYRICS, "true") == "true" pipeAudioFlow.value = AppSettings.getString(app, KEY_PIPE_AUDIO, "true") == "true" // Until the driver sets it, on for USB audio and off for Bluetooth, where the map app's // own voice already reaches the car. @@ -490,11 +486,6 @@ private const val KEY_CLUSTER_VIDEO = "cluster_video_enabled" AppSettings.putString(app, KEY_PLAYER_LEFT, on.toString()) } - fun setMoreLyrics(on: Boolean) { - moreLyricsFlow.value = on - AppSettings.putString(app, KEY_MORE_LYRICS, on.toString()) - } - fun setAutoplay(on: Boolean) { autoplayFlow.value = on AppSettings.putString(app, KEY_AUTOPLAY, on.toString()) diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarSettingsScreen.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarSettingsScreen.kt index af19f12..f87d3fc 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarSettingsScreen.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/car/CarSettingsScreen.kt @@ -32,7 +32,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.produceState import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -45,9 +44,6 @@ import app.seb3thehacker.gearslip.car.theme.GsColors import app.seb3thehacker.gearslip.car.theme.GsIconBox import app.seb3thehacker.gearslip.car.theme.GsThemes import app.seb3thehacker.gearslip.AppSettings -import app.seb3thehacker.gearslip.ui.CertSummary -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext /** * Settings that make sense while sitting in the car. The web page URL is edited here, with the @@ -73,7 +69,6 @@ fun CarSettingsScreen() { val autoplay by CarSettings.autoplay.collectAsState() val playerTitle by CarSettings.playerTitle.collectAsState() val playerLeft by CarSettings.playerLeft.collectAsState() - val moreLyrics by CarSettings.moreLyrics.collectAsState() val theme by CarSettings.appTheme.collectAsState() val uiTheme by CarSettings.uiTheme.collectAsState() val darkStyle by CarSettings.darkStyle.collectAsState() @@ -85,12 +80,9 @@ fun CarSettingsScreen() { val display by CarEnvironment.display.collectAsState() val vehicle by CarEnvironment.vehicle.collectAsState() val context = LocalContext.current - val cert by produceState(null) { - value = withContext(Dispatchers.Default) { CertSummary.read(context) } - } // A rail of the groups down the left, and the chosen group's settings beside it: five short - // lists instead of one long scroll. + // lists instead of one long scroll. The groups and their order match Settings on the phone. var chosen by androidx.compose.runtime.saveable.rememberSaveable { androidx.compose.runtime.mutableIntStateOf(0) } val listState = androidx.compose.foundation.lazy.rememberLazyListState() androidx.compose.runtime.LaunchedEffect(chosen) { listState.scrollToItem(0) } @@ -104,259 +96,180 @@ fun CarSettingsScreen() { contentPadding = PaddingValues(horizontal = 24.dp, vertical = 16.dp), verticalArrangement = Arrangement.spacedBy(20.dp), ) { - var section: Int - section = 0 - if (section == chosen) item { Group(stringResource(R.string.car_group_screen)) } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_open_on_connect), - listOf(CarSettings.HOME to stringResource(R.string.choice_open_home)) + CarApps.shown(launcher, LauncherMode.canCall(context)).map { it.id to stringResource(it.labelRes) }, - open, - ) { CarSettings.setOpenOnConnect(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_size), - listOf(1f to stringResource(R.string.choice_size_normal), 1.25f to stringResource(R.string.choice_size_large), 1.5f to stringResource(R.string.choice_size_xlarge)), - scale, - ) { CarSettings.setScale(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_app_theme), - listOf(AppTheme.PHONE to stringResource(R.string.choice_theme_phone), AppTheme.LIGHT to stringResource(R.string.choice_theme_light), AppTheme.DARK to stringResource(R.string.choice_theme_dark)), - theme, - ) { CarSettings.setAppTheme(it) } - } - - if (section == chosen && theme != AppTheme.LIGHT) item { - ChoiceRow( - stringResource(R.string.car_dark_mode), - listOf( - DarkStyle.BLACK to stringResource(R.string.choice_dark_black), - DarkStyle.BLACK_COLOUR to stringResource(R.string.choice_dark_black_colour), - DarkStyle.DEEP_COLOUR to stringResource(R.string.choice_dark_deep_colour), - DarkStyle.GREY to stringResource(R.string.choice_dark_grey), - ), - darkStyle, - ) { CarSettings.setDarkStyle(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.carset_theme), - GsThemes.builtIn.map { it.id to it.name }, - uiTheme, - ) { CarSettings.setUiTheme(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_map_day_night), - listOf(NightMode.AUTO to stringResource(R.string.choice_auto), NightMode.DAY to stringResource(R.string.choice_night_day), NightMode.NIGHT to stringResource(R.string.choice_night_night)), - night, - ) { CarSettings.setNightMode(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_units), - listOf(Units.AUTO to stringResource(R.string.choice_auto), Units.IMPERIAL to stringResource(R.string.carset_imperial), Units.METRIC to stringResource(R.string.carset_metric)), - units, - ) { CarSettings.setUnits(it) } - } - - // For a head unit that reports the wrong size and stretches the picture (issue #12). - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.carset_screen_size), - listOf(null).plus(SCREEN_PRESETS).plus(screenSize).distinct() - .map { it to (it?.toString() ?: stringResource(R.string.screen_from_car)) }, - screenSize, - ) { CarSettings.setScreenSize(it) } - } - - if (section == chosen && screenSize != null) item { - ChoiceRow( - stringResource(R.string.carset_fit), - listOf(ScreenFit.CROP to stringResource(R.string.screen_crop), ScreenFit.SQUASH to stringResource(R.string.screen_squash)), - screenFit, - ) { CarSettings.setScreenFit(it) } - } - - section = 1 - if (section == chosen) item { Group(stringResource(R.string.car_group_nav_bar)) } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_nav_bar), - listOf( - NavBarMode.SHOW to stringResource(R.string.choice_nav_show), - NavBarMode.HIDE_NAVIGATING to stringResource(R.string.choice_nav_hide_navigating), - NavBarMode.HIDE to stringResource(R.string.choice_nav_hide), - ), - navBar, - ) { CarSettings.setNavBarMode(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_player_nav_bar), - listOf(false to stringResource(R.string.car_skip_buttons), true to stringResource(R.string.car_song_title)), - playerTitle, - ) { CarSettings.setPlayerTitle(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_player_beside_map), - listOf(false to stringResource(R.string.car_right), true to stringResource(R.string.car_left)), - playerLeft, - ) { CarSettings.setPlayerLeft(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_autoplay), - listOf(false to stringResource(R.string.off), true to stringResource(R.string.on)), - autoplay, - ) { CarSettings.setAutoplay(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.carset_lyrics_from), - listOf(false to "LRCLIB", true to stringResource(R.string.carset_more_sources)), - moreLyrics, - ) { CarSettings.setMoreLyrics(it) } - } - - section = 2 - if (section == chosen) item { Group(stringResource(R.string.car_group_sound)) } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_audio), - listOf(false to stringResource(R.string.guide_audio_bluetooth), true to stringResource(R.string.guide_audio_usb)), - pipeAudio, - ) { CarSettings.setPipeAudio(it) } - } - - if (section == chosen) item { - Text( - stringResource(R.string.carset_audio_note), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - - section = 3 - if (section == chosen) item { Group(stringResource(R.string.car_group_warnings)) } - - if (section == chosen && !pipeAudio) item { - ChoiceRow( - stringResource(R.string.car_warn_bluetooth), - listOf(false to stringResource(R.string.off), true to stringResource(R.string.on)), - bluetoothWarning, - ) { CarSettings.setBluetoothWarning(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_warn_location), - listOf(false to stringResource(R.string.off), true to stringResource(R.string.on)), - locationWarning, - ) { CarSettings.setLocationWarning(it) } - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_spoken_directions), - listOf(false to stringResource(R.string.off), true to stringResource(R.string.on)), - speakDirections, - ) { CarSettings.setSpeakDirections(it) } - } - - if (section == chosen) item { - Text( - stringResource(R.string.carset_directions_note), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - - if (section == chosen && speakDirections) item { - ChoiceRow( - stringResource(R.string.car_directions_over_music), - listOf(false to stringResource(R.string.off), true to stringResource(R.string.on)), - directionsOverMusic, - ) { CarSettings.setDirectionsOverMusic(it) } - } - - if (section == chosen && speakDirections) item { - Text( - stringResource(R.string.car_directions_over_music_note), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - ) - } - - if (section == chosen) item { - ExperimentalFeatureRow( - title = stringResource(R.string.car_phone_speech), - description = stringResource(R.string.carset_phone_speech_note), - checked = systemSpeech, - ) { CarSettings.setSystemSpeech(it) } - } - - section = 4 - if (section == chosen) item { Group(stringResource(R.string.car_group_more)) } - - if (section == chosen) item { - WebPageSetting() - } - - if (section == chosen) item { - ScreenFit(vehicle) - } - - if (section == chosen) item { - ChoiceRow( - stringResource(R.string.car_experimental), - listOf(false to stringResource(R.string.carset_hide), true to stringResource(R.string.carset_show)), - experimentalFeatures, - ) { CarSettings.setExperimentalFeaturesEnabled(it) } - } - - if (section == chosen && experimentalFeatures) item { - ExperimentalFeaturesList(carSensors, adaptiveVideo, clusterVideo) - } - - if (section == chosen) item { - Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { - Text(stringResource(R.string.settings_connection), style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.primary) - Info(stringResource(R.string.carset_phone), "${Build.MANUFACTURER} ${Build.MODEL}") - Info(stringResource(R.string.carset_vehicle), vehicle.ifEmpty { "-" }) - Info(stringResource(R.string.carset_video), display.ifEmpty { "-" }) - Info(stringResource(R.string.settings_certificate), cert?.headline ?: stringResource(R.string.cert_checking)) + when (chosen) { + 0 -> { + item { Group(stringResource(R.string.car_group_screen)) } + item { + ChoiceRow( + stringResource(R.string.car_open_on_connect), + listOf(CarSettings.HOME to stringResource(R.string.choice_open_home)) + CarApps.shown(launcher, LauncherMode.canCall(context)).map { it.id to stringResource(it.labelRes) }, + open, + ) { CarSettings.setOpenOnConnect(it) } + } + item { + ChoiceRow( + stringResource(R.string.car_size), + listOf(1f to stringResource(R.string.choice_size_normal), 1.25f to stringResource(R.string.choice_size_large), 1.5f to stringResource(R.string.choice_size_xlarge)), + scale, + ) { CarSettings.setScale(it) } + } + item { + ChoiceRow( + stringResource(R.string.car_app_theme), + listOf(AppTheme.PHONE to stringResource(R.string.choice_theme_phone), AppTheme.LIGHT to stringResource(R.string.choice_theme_light), AppTheme.DARK to stringResource(R.string.choice_theme_dark)), + theme, + ) { CarSettings.setAppTheme(it) } + } + if (theme != AppTheme.LIGHT) item { + ChoiceRow( + stringResource(R.string.car_dark_mode), + listOf( + DarkStyle.BLACK to stringResource(R.string.choice_dark_black), + DarkStyle.BLACK_COLOUR to stringResource(R.string.choice_dark_black_colour), + DarkStyle.DEEP_COLOUR to stringResource(R.string.choice_dark_deep_colour), + DarkStyle.GREY to stringResource(R.string.choice_dark_grey), + ), + darkStyle, + ) { CarSettings.setDarkStyle(it) } + } + item { + ChoiceRow( + stringResource(R.string.car_buttons), + GsThemes.builtIn.map { it.id to it.name }, + uiTheme, + ) { CarSettings.setUiTheme(it) } + } + item { + ChoiceRow( + stringResource(R.string.car_map_day_night), + listOf(NightMode.AUTO to stringResource(R.string.choice_auto), NightMode.DAY to stringResource(R.string.choice_night_day), NightMode.NIGHT to stringResource(R.string.choice_night_night)), + night, + ) { CarSettings.setNightMode(it) } + } + item { + ChoiceRow( + stringResource(R.string.car_units), + listOf(Units.AUTO to stringResource(R.string.choice_auto), Units.IMPERIAL to stringResource(R.string.carset_imperial), Units.METRIC to stringResource(R.string.carset_metric)), + units, + ) { CarSettings.setUnits(it) } + } + // Fixes for a head unit that gets its own screen wrong (issue #12), together + // and last, since most cars never need them. + item { SubGroup(stringResource(R.string.carset_advanced)) } + item { + ChoiceRow( + stringResource(R.string.carset_screen_size), + listOf(null).plus(SCREEN_PRESETS).plus(screenSize).distinct() + .map { it to (it?.toString() ?: stringResource(R.string.screen_from_car)) }, + screenSize, + ) { CarSettings.setScreenSize(it) } + } + if (screenSize != null) item { + ChoiceRow( + stringResource(R.string.carset_fit), + listOf(ScreenFit.CROP to stringResource(R.string.screen_crop), ScreenFit.SQUASH to stringResource(R.string.screen_squash)), + screenFit, + ) { CarSettings.setScreenFit(it) } + } + item { ScreenFit(vehicle) } } - } - - if (section == chosen) item { - Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { - Text(stringResource(R.string.settings_about), style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.primary) - Info(stringResource(R.string.carset_version), app.seb3thehacker.gearslip.BuildConfig.VERSION_NAME) - Info(stringResource(R.string.carset_build), app.seb3thehacker.gearslip.BuildConfig.VERSION_CODE.toString()) - ExperimentalFeatureRow( - stringResource(R.string.carset_whats_new_after), - stringResource(R.string.carset_whats_new_after_sub), - whatsNew, - ) { CarSettings.setWhatsNewAfterUpdates(it) } - GsButton(onClick = CarSettings::openWhatsNew, tone = GsTone.Tonal, modifier = Modifier.height(56.dp)) { - Text(stringResource(R.string.settings_whats_new), style = MaterialTheme.typography.titleMedium) + 1 -> { + item { Group(stringResource(R.string.car_group_nav_bar)) } + item { + ChoiceRow( + stringResource(R.string.car_nav_bar), + listOf( + NavBarMode.SHOW to stringResource(R.string.choice_nav_show), + NavBarMode.HIDE_NAVIGATING to stringResource(R.string.choice_nav_hide_navigating), + NavBarMode.HIDE to stringResource(R.string.choice_nav_hide), + ), + navBar, + ) { CarSettings.setNavBarMode(it) } + } + item { + ChoiceRow( + stringResource(R.string.car_player_nav_bar), + listOf(false to stringResource(R.string.car_skip_buttons), true to stringResource(R.string.car_song_title)), + playerTitle, + ) { CarSettings.setPlayerTitle(it) } + } + item { + ChoiceRow( + stringResource(R.string.car_player_beside_map), + listOf(false to stringResource(R.string.car_right), true to stringResource(R.string.car_left)), + playerLeft, + ) { CarSettings.setPlayerLeft(it) } + } + item { Note(stringResource(R.string.car_player_beside_map_note)) } + item { + SwitchRow(stringResource(R.string.car_autoplay), stringResource(R.string.car_autoplay_note), autoplay) { CarSettings.setAutoplay(it) } + } + } + 2 -> { + item { Group(stringResource(R.string.car_group_sound)) } + item { + ChoiceRow( + stringResource(R.string.car_audio), + listOf(false to stringResource(R.string.guide_audio_bluetooth), true to stringResource(R.string.guide_audio_usb)), + pipeAudio, + ) { CarSettings.setPipeAudio(it) } + } + item { Note(stringResource(R.string.carset_audio_note)) } + item { + SwitchRow(stringResource(R.string.car_spoken_directions), stringResource(R.string.carset_directions_note), speakDirections) { CarSettings.setSpeakDirections(it) } + } + if (speakDirections) item { + SwitchRow(stringResource(R.string.car_directions_over_music), stringResource(R.string.car_directions_over_music_note), directionsOverMusic) { CarSettings.setDirectionsOverMusic(it) } + } + item { + SwitchRow(stringResource(R.string.car_phone_speech), stringResource(R.string.carset_phone_speech_note), systemSpeech) { CarSettings.setSystemSpeech(it) } + } + } + 3 -> { + item { Group(stringResource(R.string.car_group_warnings)) } + if (!pipeAudio) item { + SwitchRow(stringResource(R.string.car_warn_bluetooth), null, bluetoothWarning) { CarSettings.setBluetoothWarning(it) } + } + item { + SwitchRow(stringResource(R.string.car_warn_location), null, locationWarning) { CarSettings.setLocationWarning(it) } + } + } + else -> { + item { Group(stringResource(R.string.car_group_more)) } + item { WebPageSetting() } + item { + SwitchRow(stringResource(R.string.car_experimental), stringResource(R.string.car_experimental_note), experimentalFeatures) { CarSettings.setExperimentalFeaturesEnabled(it) } + } + if (experimentalFeatures) item { + Column(verticalArrangement = Arrangement.spacedBy(10.dp)) { + SubGroup(stringResource(R.string.carset_experimental_heading)) + ExperimentalFeaturesList(carSensors, adaptiveVideo, clusterVideo) + } + } + item { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + SubGroup(stringResource(R.string.settings_connection)) + // The certificate is managed on the phone, which shows it in full. + val none = stringResource(R.string.status_idle) + Info(stringResource(R.string.carset_phone), "${Build.MANUFACTURER} ${Build.MODEL}") + Info(stringResource(R.string.carset_vehicle), vehicle.ifEmpty { none }) + Info(stringResource(R.string.carset_video), display.ifEmpty { none }) + } + } + item { + Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { + SubGroup(stringResource(R.string.settings_about)) + Info(stringResource(R.string.carset_version), app.seb3thehacker.gearslip.BuildConfig.VERSION_NAME) + Info(stringResource(R.string.carset_build), app.seb3thehacker.gearslip.BuildConfig.VERSION_CODE.toString()) + SwitchRow( + stringResource(R.string.carset_whats_new_after), + stringResource(R.string.carset_whats_new_after_sub), + whatsNew, + ) { CarSettings.setWhatsNewAfterUpdates(it) } + GsButton(onClick = CarSettings::openWhatsNew, tone = GsTone.Tonal, modifier = Modifier.height(56.dp)) { + Text(stringResource(R.string.settings_whats_new), style = MaterialTheme.typography.titleMedium) + } + } } } } @@ -364,6 +277,18 @@ fun CarSettingsScreen() { } } +/** A heading inside a group, for a few settings that belong together. */ +@Composable +private fun SubGroup(title: String) { + Text(title, style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.primary) +} + +/** What a setting above it does, in a sentence or two. */ +@Composable +private fun Note(text: String) { + Text(text, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant) +} + @Composable private fun ChoiceRow(title: String, options: List>, selected: T, onSelect: (T) -> Unit) { // On a wide screen the name sits beside its choices, which halves how far there is to scroll. @@ -451,7 +376,16 @@ private fun ChoiceButtons(options: List>, selected: T, onSel else GsColors(scheme.surfaceContainerHigh, scheme.onSurface), latched = on, ) { - Text(label, style = MaterialTheme.typography.titleMedium, fontWeight = if (on) FontWeight.Bold else FontWeight.Normal) + // Centred however many lines it takes: "Black and colour" wrapped to the left. + Text( + label, + style = MaterialTheme.typography.titleMedium, + fontWeight = if (on) FontWeight.Bold else FontWeight.Normal, + textAlign = androidx.compose.ui.text.style.TextAlign.Center, + maxLines = 2, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.padding(horizontal = 8.dp), + ) } } } @@ -469,17 +403,17 @@ private fun ExperimentalFeaturesList(carSensors: Boolean, adaptiveVideo: Boolean Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(10.dp), ) { - ExperimentalFeatureRow( + SwitchRow( title = stringResource(R.string.car_vehicle_data), description = stringResource(R.string.carset_vehicle_data_note), checked = carSensors, ) { CarSettings.setCarSensorsEnabled(it) } - ExperimentalFeatureRow( + SwitchRow( title = stringResource(R.string.car_adaptive_video), description = stringResource(R.string.carset_adaptive_note), checked = adaptiveVideo, ) { CarSettings.setAdaptiveVideoEnabled(it) } - ExperimentalFeatureRow( + SwitchRow( title = stringResource(R.string.car_cluster_video), description = stringResource(R.string.car_cluster_video_note), checked = clusterVideo, @@ -488,9 +422,9 @@ private fun ExperimentalFeaturesList(carSensors: Boolean, adaptiveVideo: Boolean } @Composable -private fun ExperimentalFeatureRow( +private fun SwitchRow( title: String, - description: String, + description: String?, checked: Boolean, warning: Boolean = false, onCheckedChange: (Boolean) -> Unit, @@ -508,7 +442,7 @@ private fun ExperimentalFeatureRow( ) { Column(Modifier.weight(1f)) { Text(title, style = MaterialTheme.typography.titleMedium) - Text( + if (description != null) Text( description, style = MaterialTheme.typography.bodySmall, color = if (warning) MaterialTheme.colorScheme.error else MaterialTheme.colorScheme.onSurfaceVariant, @@ -589,7 +523,7 @@ private fun ScreenFit(vehicle: String) { } Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { - Text(stringResource(R.string.carset_screen_fit), style = MaterialTheme.typography.titleMedium, color = MaterialTheme.colorScheme.primary) + Text(stringResource(R.string.carset_screen_fit), style = MaterialTheme.typography.titleMedium) Stepper(stringResource(R.string.carset_top), insets.top) { change(insets.copy(top = (insets.top + it).coerceAtLeast(0))) } Stepper(stringResource(R.string.carset_bottom), insets.bottom) { change(insets.copy(bottom = (insets.bottom + it).coerceAtLeast(0))) } Text( @@ -597,14 +531,15 @@ private fun ScreenFit(vehicle: String) { style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, ) - GsButton( + // With no car to name, a greyed-out button only said what couldn't be done. + if (known) GsButton( onClick = { val ok = app.seb3thehacker.gearslip.VehicleProfiles.saveInsets(context, vehicle, insets) saved = if (ok) context.getString(R.string.carset_saved_to, vehicle) else context.getString(R.string.carset_save_failed) }, - enabled = known, modifier = Modifier.fillMaxWidth().height(56.dp), - ) { Text(if (known) stringResource(R.string.carset_save_vehicle) else stringResource(R.string.carset_no_profile)) } + ) { Text(stringResource(R.string.carset_save_vehicle)) } + else Note(stringResource(R.string.carset_fit_needs_car)) saved?.let { Text(it, style = MaterialTheme.typography.bodyMedium) } } } diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/media/Lyrics.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/media/Lyrics.kt index aea80c4..76e78e8 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/media/Lyrics.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/media/Lyrics.kt @@ -4,7 +4,6 @@ import android.content.Context import android.util.Base64 import android.util.Xml import app.seb3thehacker.gearslip.GearslipLog -import app.seb3thehacker.gearslip.car.CarSettings import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async @@ -48,8 +47,7 @@ class LyricsResult(val lines: List, val synced: Boolean, val source: * * Media apps almost never publish lyrics in their session metadata, so these are the only general * source. Each lookup sends the track's title, artist, album and length to these services, which - * is why it happens only when the driver opens the lyrics view, never in the background. With - * [CarSettings.moreLyrics] off, only LRCLIB is asked. + * is why it happens only when the driver opens the lyrics view, never in the background. * * Results are cached twice over: in memory for the life of the process, and on disk under the * cache directory so a song looked up on a past drive doesn't need the network again on this one. @@ -79,13 +77,12 @@ object Lyrics { private class Source(val name: String, val best: Int, val lookup: () -> LyricsResult?) private fun sources(title: String, artist: String, album: String, durationMs: Long): List { - val more = CarSettings.moreLyrics.value val seconds = (durationMs / 1000).toInt() - return buildList { - if (more) add(Source("BetterLyrics", BEST) { betterLyrics(title, artist, album, seconds) }) - add(Source("LRCLIB", 2) { exact(title, artist, album, durationMs) ?: search(title, artist) }) - if (more) add(Source("KuGou", 2) { kuGou(title, artist, album, seconds) }) - } + return listOf( + Source("BetterLyrics", BEST) { betterLyrics(title, artist, album, seconds) }, + Source("LRCLIB", 2) { exact(title, artist, album, durationMs) ?: search(title, artist) }, + Source("KuGou", 2) { kuGou(title, artist, album, seconds) }, + ) } private fun key(title: String, artist: String, album: String, durationMs: Long) = "$title|$artist|$album|$durationMs" @@ -93,8 +90,7 @@ object Lyrics { suspend fun find(context: Context, title: String, artist: String, album: String, durationMs: Long): LyricsResult? { if (title.isBlank()) return null val key = key(title, artist, album, durationMs) - // A miss with only LRCLIB isn't a miss once more sources are on, so the mode is part of it. - val memoryKey = "${CarSettings.moreLyrics.value}|$key" + val memoryKey = key synchronized(cache) { if (cache.containsKey(memoryKey)) return cache[memoryKey] } val fromDisk = withContext(Dispatchers.IO) { readDisk(context, key) } @@ -129,7 +125,7 @@ object Lyrics { withContext(Dispatchers.IO) { writeDisk(context, key, better ?: current, System.currentTimeMillis()) } if (better == null) return null GearslipLog.i("lyrics: replaced ${current.source.ifEmpty { "cached" }} lyrics with ${better.source}'s") - synchronized(cache) { cache["${CarSettings.moreLyrics.value}|$key"] = better } + synchronized(cache) { cache[key] = better } return better } diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/HomeCarSettings.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/HomeCarSettings.kt index 87543a8..57fc0c1 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/HomeCarSettings.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/HomeCarSettings.kt @@ -228,7 +228,6 @@ private fun GroupRows(group: CarGroup) { val autoplay by CarSettings.autoplay.collectAsState() val playerTitle by CarSettings.playerTitle.collectAsState() val playerLeft by CarSettings.playerLeft.collectAsState() - val moreLyrics by CarSettings.moreLyrics.collectAsState() val theme by CarSettings.appTheme.collectAsState() val uiTheme by CarSettings.uiTheme.collectAsState() val darkStyle by CarSettings.darkStyle.collectAsState() @@ -263,16 +262,9 @@ private fun GroupRows(group: CarGroup) { SettingsDivider() Choice(stringResource(R.string.car_player_nav_bar), listOf(false to stringResource(R.string.car_skip_buttons), true to stringResource(R.string.car_song_title)), playerTitle, CarSettings::setPlayerTitle) SettingsDivider() - Choice(stringResource(R.string.car_player_beside_map), listOf(false to stringResource(R.string.car_right), true to stringResource(R.string.car_left)), playerLeft, CarSettings::setPlayerLeft) + Choice(stringResource(R.string.car_player_beside_map), listOf(false to stringResource(R.string.car_right), true to stringResource(R.string.car_left)), playerLeft, CarSettings::setPlayerLeft, note = stringResource(R.string.car_player_beside_map_note)) SettingsDivider() - Toggle(stringResource(R.string.car_autoplay), autoplay, CarSettings::setAutoplay) - SettingsDivider() - Toggle( - stringResource(R.string.car_more_lyrics), - moreLyrics, - CarSettings::setMoreLyrics, - note = stringResource(R.string.car_more_lyrics_note), - ) + Toggle(stringResource(R.string.car_autoplay), autoplay, CarSettings::setAutoplay, note = stringResource(R.string.car_autoplay_note)) } CarGroup.SOUND -> { Toggle( @@ -309,7 +301,7 @@ private fun GroupRows(group: CarGroup) { CarGroup.MORE -> { WebPageRow() SettingsDivider() - Toggle(stringResource(R.string.car_experimental), experimental, CarSettings::setExperimentalFeaturesEnabled) + Toggle(stringResource(R.string.car_experimental), experimental, CarSettings::setExperimentalFeaturesEnabled, note = stringResource(R.string.car_experimental_note)) if (experimental) { SettingsDivider() Toggle( diff --git a/gearslip/src/main/res/values-ar/strings.xml b/gearslip/src/main/res/values-ar/strings.xml index ada635f..3f50bf6 100644 --- a/gearslip/src/main/res/values-ar/strings.xml +++ b/gearslip/src/main/res/values-ar/strings.xml @@ -200,8 +200,6 @@ يمين يسار التشغيل التلقائي عند الاتصال - مصادر أكثر لكلمات الأغاني - يسأل أيضًا BetterLyrics وKuGou، فيحصلان على اسم الأغنية والفنان. عند الإيقاف يسأل LRCLIB فقط. الإرشادات الصوتية أوقفها إذا كان صوت تطبيق الخرائط نفسه يُسمع في السيارة بالفعل. استخدام التعرّف على الكلام في الهاتف @@ -433,8 +431,6 @@ ملاءمة الشاشة متوقف مفعّل - الكلمات من - مصادر أكثر إخفاء إظهار الهاتف diff --git a/gearslip/src/main/res/values-cs/strings.xml b/gearslip/src/main/res/values-cs/strings.xml index fa7cb2a..53a4ba9 100644 --- a/gearslip/src/main/res/values-cs/strings.xml +++ b/gearslip/src/main/res/values-cs/strings.xml @@ -200,8 +200,6 @@ Vpravo Vlevo Přehrát po připojení - Více zdrojů textů - Ptá se také BetterLyrics a KuGou, které pak dostanou název a interpreta skladby. Vypnuto se ptá jen LRCLIB. Hlasové pokyny Vypněte je, pokud hlas vaší mapové aplikace už v autě hraje. Používat rozpoznávání řeči telefonu @@ -431,8 +429,6 @@ Přizpůsobit obrazovce Vyp. Zap. - Texty z - Více zdrojů Skrýt Zobrazit Telefon diff --git a/gearslip/src/main/res/values-da/strings.xml b/gearslip/src/main/res/values-da/strings.xml index e95b77a..2e1b3e1 100644 --- a/gearslip/src/main/res/values-da/strings.xml +++ b/gearslip/src/main/res/values-da/strings.xml @@ -187,8 +187,6 @@ Højre Venstre Autoplay på forbindelse - Flere tekstkilder - Spørg også BetterLyrics og KuGou, som derefter får sangens navn og kunstner. Ellers spørges kun LRCLIB. Import Talte rutevejledniger Slå det fra, hvis dit navigations programs egen stemme allerede spiller i bilen. diff --git a/gearslip/src/main/res/values-de/strings.xml b/gearslip/src/main/res/values-de/strings.xml index 2844f2e..c8a84a7 100644 --- a/gearslip/src/main/res/values-de/strings.xml +++ b/gearslip/src/main/res/values-de/strings.xml @@ -11,8 +11,6 @@ An Bildschirm anpassen Aus An - Songtexte von - Weitere Quellen Ausblenden Anzeigen Handy @@ -510,8 +508,6 @@ Rechts Links Automatisch abspielen beim Verbinden - Weitere Songtext-Quellen - Fragt außerdem bei BetterLyrics und KuGou an, die dabei Titel und Interpret des Songs erfahren. Bei „Aus“ wird nur LRCLIB gefragt. Gesprochene Navigationsansagen Schalte das aus, wenn die Sprachansage deiner Karten-App bereits im Auto zu hören ist. Spracherkennung des Handys verwenden diff --git a/gearslip/src/main/res/values-es/strings.xml b/gearslip/src/main/res/values-es/strings.xml index 5b26991..c98442b 100644 --- a/gearslip/src/main/res/values-es/strings.xml +++ b/gearslip/src/main/res/values-es/strings.xml @@ -109,8 +109,6 @@ Bien Izquierda Autoplay en conexión - Más fuentes de letras - También pregunta BetterLyrics y KuGou, que luego consigue el nombre y artista de la canción. Fuera pide LRCLIB sólo. Instrucciones descritas Apágalo si la propia voz de su aplicación de mapa ya juega en el coche. Use el reconocimiento del discurso del teléfono @@ -300,8 +298,6 @@ Ajuste a la pantalla Fuera On - Letras de - Más fuentes Oculto Show Teléfono diff --git a/gearslip/src/main/res/values-fr/strings.xml b/gearslip/src/main/res/values-fr/strings.xml index cac5c71..4e6f68a 100644 --- a/gearslip/src/main/res/values-fr/strings.xml +++ b/gearslip/src/main/res/values-fr/strings.xml @@ -200,8 +200,6 @@ Droite Gauche Lecture auto à la connexion - Plus de sources de paroles - Interroge aussi BetterLyrics et KuGou, qui reçoivent alors le titre et l’artiste du morceau. Désactivé, seul LRCLIB est interrogé. Guidage vocal Désactivez-le si la voix de votre appli de navigation passe déjà dans la voiture. Utiliser la reconnaissance vocale du téléphone @@ -430,8 +428,6 @@ Ajuster à l’écran Désactivé Activé - Paroles depuis - Plus de sources Masquer Afficher Téléphone diff --git a/gearslip/src/main/res/values-it/strings.xml b/gearslip/src/main/res/values-it/strings.xml index 3d4941d..dc8b932 100644 --- a/gearslip/src/main/res/values-it/strings.xml +++ b/gearslip/src/main/res/values-it/strings.xml @@ -200,8 +200,6 @@ Destra Sinistra Riproduci alla connessione - Più fonti per i testi - Chiede anche a BetterLyrics e KuGou, che ricevono così titolo e artista del brano. Se disattivato, chiede solo a LRCLIB. Indicazioni vocali Disattivale se la voce della tua app di navigazione si sente già in auto. Usa il riconoscimento vocale del telefono @@ -430,8 +428,6 @@ Adatta allo schermo Off On - Testi da - Più fonti Nascondi Mostra Telefono diff --git a/gearslip/src/main/res/values-ja/strings.xml b/gearslip/src/main/res/values-ja/strings.xml index 775d95b..5938ea9 100644 --- a/gearslip/src/main/res/values-ja/strings.xml +++ b/gearslip/src/main/res/values-ja/strings.xml @@ -200,8 +200,6 @@ 右 左 接続時に自動再生 - 歌詞の取得元を増やす - BetterLyrics と KuGou にも問い合わせ、曲名とアーティスト名が送られます。オフにすると LRCLIB のみに問い合わせます。 音声案内 地図アプリ自身の音声がすでに車で流れている場合はオフにしてください。 スマートフォンの音声認識を使う @@ -428,8 +426,6 @@ 画面に合わせる オフ オン - 歌詞の取得元 - 取得元を増やす 隠す 表示 電話 diff --git a/gearslip/src/main/res/values-ko/strings.xml b/gearslip/src/main/res/values-ko/strings.xml index ea2d22b..729f49a 100644 --- a/gearslip/src/main/res/values-ko/strings.xml +++ b/gearslip/src/main/res/values-ko/strings.xml @@ -200,8 +200,6 @@ 오른쪽 왼쪽 연결 시 자동 재생 - 가사 출처 더 보기 - BetterLyrics와 KuGou에도 요청하며, 이때 노래 제목과 아티스트가 전달됩니다. 끄면 LRCLIB에만 요청합니다. 음성 안내 지도 앱 자체의 음성이 이미 차량에서 나온다면 끄세요. 휴대전화의 음성 인식 사용 @@ -428,8 +426,6 @@ 화면에 맞추기 끄기 켜기 - 가사 출처 - 출처 더 보기 숨기기 표시 휴대전화 diff --git a/gearslip/src/main/res/values-nl/strings.xml b/gearslip/src/main/res/values-nl/strings.xml index 9381f58..d068b93 100644 --- a/gearslip/src/main/res/values-nl/strings.xml +++ b/gearslip/src/main/res/values-nl/strings.xml @@ -200,8 +200,6 @@ Rechts Links Automatisch afspelen bij verbinden - Meer songtekstbronnen - Vraagt ook BetterLyrics en KuGou, die dan de titel en artiest van het nummer krijgen. Uit vraagt alleen LRCLIB. Gesproken aanwijzingen Zet dit uit als de stem van je kaarten-app al in de auto klinkt. Spraakherkenning van de telefoon gebruiken @@ -429,8 +427,6 @@ Passend maken voor het scherm Uit Aan - Songteksten van - Meer bronnen Verbergen Tonen Telefoon diff --git a/gearslip/src/main/res/values-pl/strings.xml b/gearslip/src/main/res/values-pl/strings.xml index 979c09a..448ccdb 100644 --- a/gearslip/src/main/res/values-pl/strings.xml +++ b/gearslip/src/main/res/values-pl/strings.xml @@ -200,8 +200,6 @@ Prawo Lewo Odtwarzaj po połączeniu - Więcej źródeł tekstów - Pyta też BetterLyrics i KuGou, które dostają wtedy tytuł i wykonawcę utworu. Po wyłączeniu pyta tylko LRCLIB. Wskazówki głosowe Wyłącz, jeśli głos twojej aplikacji z mapami już gra w samochodzie. Używaj rozpoznawania mowy telefonu @@ -431,8 +429,6 @@ Dopasuj do ekranu Wył. Wł. - Teksty z - Więcej źródeł Ukryj Pokaż Telefon diff --git a/gearslip/src/main/res/values-pt-rBR/strings.xml b/gearslip/src/main/res/values-pt-rBR/strings.xml index b113c67..32a039b 100644 --- a/gearslip/src/main/res/values-pt-rBR/strings.xml +++ b/gearslip/src/main/res/values-pt-rBR/strings.xml @@ -200,8 +200,6 @@ Direita Esquerda Tocar ao conectar - Mais fontes de letras - Também consulta o BetterLyrics e o KuGou, que recebem o nome e o artista da música. Desativado, consulta só o LRCLIB. Instruções faladas Desative se a voz do seu app de mapas já toca no carro. Usar o reconhecimento de voz do celular @@ -430,8 +428,6 @@ Ajustar à tela Desativado Ativado - Letras de - Mais fontes Ocultar Mostrar Celular diff --git a/gearslip/src/main/res/values-ro/strings.xml b/gearslip/src/main/res/values-ro/strings.xml index e854b04..063ad13 100644 --- a/gearslip/src/main/res/values-ro/strings.xml +++ b/gearslip/src/main/res/values-ro/strings.xml @@ -188,8 +188,6 @@ Dreapta Stânga Redare automată la conectare - Alte surse de versuri - De asemenea, interoghează BetterLyrics și KuGou, care obțin apoi numele melodiei și al artistului. Opțiunea „Oprit” interoghează doar LRCLIB. Instrucțiuni vocale Dezactivează dacă vocea aplicației de hărți se aude deja în mașină. Folosește funcția de recunoaștere vocală a telefonului @@ -378,8 +376,6 @@ Ajustare la ecran Oprit Pornit - Versuri din - Alte surse Ascunde Afișează Telefon diff --git a/gearslip/src/main/res/values-ru/strings.xml b/gearslip/src/main/res/values-ru/strings.xml index e923084..5212c6f 100644 --- a/gearslip/src/main/res/values-ru/strings.xml +++ b/gearslip/src/main/res/values-ru/strings.xml @@ -200,8 +200,6 @@ Справа Слева Воспроизводить при подключении - Больше источников текстов - Также спрашивает BetterLyrics и KuGou, которые тогда получают название и исполнителя песни. Если выключено, спрашивает только LRCLIB. Голосовые подсказки Выключите, если голос вашего навигатора уже звучит в машине. Распознавание речи телефона @@ -431,8 +429,6 @@ Подогнать под экран Выкл. Вкл. - Тексты из - Больше источников Скрыть Показать Телефон diff --git a/gearslip/src/main/res/values-sv/strings.xml b/gearslip/src/main/res/values-sv/strings.xml index 40973ec..bc30fd6 100644 --- a/gearslip/src/main/res/values-sv/strings.xml +++ b/gearslip/src/main/res/values-sv/strings.xml @@ -200,8 +200,6 @@ Höger Vänster Spela upp vid anslutning - Fler källor för låttexter - Frågar även BetterLyrics och KuGou, som då får låtens namn och artist. Av frågar bara LRCLIB. Röstvägledning Stäng av den om kartappens egen röst redan hörs i bilen. Använd telefonens taligenkänning @@ -429,8 +427,6 @@ Anpassa till skärmen Av På - Låttexter från - Fler källor Dölj Visa Telefon diff --git a/gearslip/src/main/res/values-tr/strings.xml b/gearslip/src/main/res/values-tr/strings.xml index dd0b7f8..1333ce6 100644 --- a/gearslip/src/main/res/values-tr/strings.xml +++ b/gearslip/src/main/res/values-tr/strings.xml @@ -200,8 +200,6 @@ Sağ Sol Bağlanınca çal - Daha fazla şarkı sözü kaynağı - BetterLyrics ve KuGou’ya da sorar; bunlar şarkının adını ve sanatçısını alır. Kapalıyken yalnızca LRCLIB’ye sorar. Sesli yol tarifi Harita uygulamanızın kendi sesi araçta zaten çalıyorsa kapatın. Telefonun konuşma tanımasını kullan @@ -429,8 +427,6 @@ Ekrana sığdır Kapalı Açık - Sözlerin kaynağı - Daha fazla kaynak Gizle Göster Telefon diff --git a/gearslip/src/main/res/values-uk/strings.xml b/gearslip/src/main/res/values-uk/strings.xml index 8d05571..491536b 100644 --- a/gearslip/src/main/res/values-uk/strings.xml +++ b/gearslip/src/main/res/values-uk/strings.xml @@ -200,8 +200,6 @@ Праворуч Ліворуч Відтворювати під час підключення - Більше джерел текстів - Також питає BetterLyrics і KuGou, які тоді отримують назву й виконавця пісні. Якщо вимкнено, питає лише LRCLIB. Голосові підказки Вимкніть, якщо голос вашого навігатора вже звучить в авто. Розпізнавання мовлення телефона @@ -431,8 +429,6 @@ Припасувати до екрана Вимк. Увімк. - Тексти з - Більше джерел Сховати Показати Телефон diff --git a/gearslip/src/main/res/values-zh-rCN/strings.xml b/gearslip/src/main/res/values-zh-rCN/strings.xml index 635de5c..63b81b6 100644 --- a/gearslip/src/main/res/values-zh-rCN/strings.xml +++ b/gearslip/src/main/res/values-zh-rCN/strings.xml @@ -200,8 +200,6 @@ 右 左 连接时自动播放 - 更多歌词来源 - 同时查询 BetterLyrics 和 KuGou,它们会收到歌曲名和歌手。关闭后只查询 LRCLIB。 语音导航 如果地图应用自己的语音已经在车上播放,请关闭此项。 使用手机的语音识别 @@ -428,8 +426,6 @@ 适应屏幕 关 开 - 歌词来源 - 更多来源 隐藏 显示 手机 diff --git a/gearslip/src/main/res/values/strings.xml b/gearslip/src/main/res/values/strings.xml index a4a9192..f9c3788 100644 --- a/gearslip/src/main/res/values/strings.xml +++ b/gearslip/src/main/res/values/strings.xml @@ -206,11 +206,11 @@ Skip buttons Song title Player beside the map + The side of the map the player docks to when you tap its dock button. Right Left Autoplay on connect - More lyrics sources - Also asks BetterLyrics and KuGou, which then get the song\'s name and artist. Off asks LRCLIB only. + Picks the music up where it stopped once the car connects. Spoken directions Turn it off if your map app\'s own voice already plays in the car. Use the phone\'s speech recognition @@ -218,6 +218,10 @@ Warn when Bluetooth isn\'t connected Warn when location is off Experimental features + Features still in testing. They may not work in every car. + Experimental + Advanced + Connect to a car to save this fit for it. Vehicle data Adds a Vehicle data tile: a live dump of the car\'s sensors. The field names are guesses until you\'ve watched one change. Adaptive video quality @@ -462,8 +466,6 @@ Fit to the screen Off On - Lyrics from - More sources Hide Show Phone