diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/GearslipApp.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/GearslipApp.kt index f31fb5f..b130b68 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/GearslipApp.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/GearslipApp.kt @@ -108,26 +108,23 @@ fun GearslipApp(onDisconnect: () -> Unit, onRequestCallScreening: () -> Unit) { Screen.INTRO -> IntroScreen(onDone = { screen = introReturn }) Screen.HOME -> HomeScreen( onOpenSettings = { settingsAtUsageNotes = false; screen = Screen.SETTINGS }, - onOpenWhatsNew = { backTo = Screen.HOME; screen = Screen.WHATS_NEW }, onOpenHelp = { backTo = Screen.HOME; screen = Screen.HELP }, onOpenUsageNotes = { settingsAtUsageNotes = true; screen = Screen.SETTINGS }, + onOpenCarPreview = { backTo = Screen.HOME; screen = Screen.CAR_PREVIEW }, + onOpenLogs = { backTo = Screen.HOME; screen = Screen.LOGS }, onDisconnect = onDisconnect, ) Screen.WHATS_NEW -> WhatsNewScreen(onBack = { screen = backTo }) - Screen.LOGS -> LogsScreen(onBack = { screen = Screen.SETTINGS }) + Screen.LOGS -> LogsScreen(onBack = { screen = backTo }) Screen.SETTINGS -> SettingsScreen( onBack = { screen = Screen.HOME }, onOpenRecommendedApps = { settingsAtUsageNotes = false; screen = Screen.RECOMMENDED_APPS }, onOpenWhatsNew = { settingsAtUsageNotes = false; backTo = Screen.SETTINGS; screen = Screen.WHATS_NEW }, - onOpenHelp = { settingsAtUsageNotes = false; backTo = Screen.SETTINGS; screen = Screen.HELP }, - onOpenCarPreview = { settingsAtUsageNotes = false; screen = Screen.CAR_PREVIEW }, - onOpenLogs = { settingsAtUsageNotes = false; screen = Screen.LOGS }, onReplayTutorial = { screen = Screen.SETUP_GUIDE }, - onReplayIntro = { Intro.replay(context); introReturn = Screen.SETTINGS; screen = Screen.INTRO }, atUsageNotes = settingsAtUsageNotes, ) Screen.RECOMMENDED_APPS -> RecommendedAppsScreen(onBack = { screen = Screen.SETTINGS }) - Screen.CAR_PREVIEW -> CarPreviewScreen(onBack = { screen = Screen.SETTINGS }) + Screen.CAR_PREVIEW -> CarPreviewScreen(onBack = { screen = backTo }) Screen.HELP -> HelpScreen( onBack = { screen = backTo }, onRequestCallScreening = onRequestCallScreening, diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/HomeScreen.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/HomeScreen.kt index 4abde51..aab9325 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/HomeScreen.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/HomeScreen.kt @@ -5,6 +5,7 @@ import app.seb3thehacker.gearslip.speech.SpeechModels import androidx.compose.material3.LinearProgressIndicator import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -27,6 +28,8 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight +import androidx.compose.material.icons.automirrored.filled.List +import androidx.compose.material.icons.automirrored.filled.Send import androidx.compose.material.icons.filled.Info import androidx.compose.material.icons.filled.Send import androidx.compose.material.icons.filled.List @@ -60,9 +63,10 @@ import app.seb3thehacker.gearslip.stats.WorkedPrompt @Composable fun HomeScreen( onOpenSettings: () -> Unit, - onOpenWhatsNew: () -> Unit, onOpenHelp: () -> Unit, onOpenUsageNotes: () -> Unit, + onOpenCarPreview: () -> Unit, + onOpenLogs: () -> Unit, onDisconnect: () -> Unit, ) { val status by SessionStatus.state.collectAsStateWithLifecycle() @@ -125,21 +129,11 @@ fun HomeScreen( // Sits at the bottom, where a thumb reaches it. Column(Modifier.padding(vertical = 16.dp)) { - SettingsCard { - SettingsRow( - "What's new in ${Intro.release}", - Modifier.clickable(onClick = onOpenWhatsNew), - icon = Icons.Filled.Star, - trailing = { Arrow() }, - ) - SettingsDivider() - SettingsRow( - "Which cars work", - Modifier.clickable(onClick = onOpenHelp), - subtitle = "Most do. See which ones, and what to set up first", - icon = Icons.Filled.Info, - trailing = { Arrow() }, - ) + Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) { + HomeShortcut(Icons.Filled.Info, "Help", onOpenHelp, Modifier.weight(1f)) + // The preview draws the car screen on the phone, so it waits until no car is using it. + if (!live) HomeShortcut(Icons.Filled.PlayArrow, "Preview", onOpenCarPreview, Modifier.weight(1f)) + HomeShortcut(Icons.AutoMirrored.Filled.List, "Logs", onOpenLogs, Modifier.weight(1f)) } if (live) { Spacer(Modifier.height(16.dp)) @@ -157,6 +151,27 @@ fun HomeScreen( } } +/** One of Home's shortcuts at the bottom: an icon over a one-word label, small enough that all fit in a row. */ +@Composable +private fun HomeShortcut(icon: androidx.compose.ui.graphics.vector.ImageVector, label: String, onClick: () -> Unit, modifier: Modifier = Modifier) { + Surface( + onClick = onClick, + modifier = modifier.heightIn(min = 64.dp), + shape = MaterialTheme.shapes.large, + color = MaterialTheme.colorScheme.secondaryContainer, + contentColor = MaterialTheme.colorScheme.onSecondaryContainer, + ) { + Column( + Modifier.padding(vertical = 10.dp, horizontal = 4.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(4.dp), + ) { + Icon(icon, contentDescription = null, modifier = Modifier.size(22.dp)) + Text(label, style = MaterialTheme.typography.labelMedium, maxLines = 1) + } + } +} + /** Bluetooth audio is chosen, but the phone isn't connected to the car. See [BluetoothAudioCheck]. */ @Composable private fun BluetoothMissingCard() { diff --git a/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/SettingsScreen.kt b/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/SettingsScreen.kt index db61df6..30a0574 100644 --- a/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/SettingsScreen.kt +++ b/gearslip/src/main/java/app/seb3thehacker/gearslip/ui/SettingsScreen.kt @@ -80,11 +80,7 @@ fun SettingsScreen( onBack: () -> Unit, onOpenRecommendedApps: () -> Unit, onOpenWhatsNew: () -> Unit, - onOpenHelp: () -> Unit, - onOpenCarPreview: () -> Unit, - onOpenLogs: () -> Unit, onReplayTutorial: () -> Unit, - onReplayIntro: () -> Unit, atUsageNotes: Boolean = false, ) { val scroll = rememberScrollState() @@ -119,12 +115,20 @@ fun SettingsScreen( verticalArrangement = Arrangement.spacedBy(24.dp), ) { Spacer(Modifier.height(0.dp)) + SettingsSection { + SettingsRow( + "What's new", + Modifier.clickable(onClick = onOpenWhatsNew), + subtitle = "Version ${BuildConfig.VERSION_NAME}", + icon = Icons.Filled.Star, + trailing = { Arrow() }, + ) + } SettingsSection( "Support Gearslip", footer = "Gearslip is free, with no ads and no tracking. Your support keeps it going.", ) { DonateRows() } ConnectionSection() - HelpSection(onOpenHelp, onOpenCarPreview, onOpenLogs) CarAudioSection() CarScreenSection() VoiceModelSection() @@ -136,7 +140,8 @@ fun SettingsScreen( ) { UsageStatsRows() } SettingsSection("Updates") { UpdateRow() } CertificateSection() - AboutSection(onOpenWhatsNew, onReplayTutorial, onReplayIntro) + AboutSection(onReplayTutorial) + if (BuildConfig.DEBUG) DebugSection() Spacer(Modifier.height(16.dp)) } } @@ -149,26 +154,10 @@ private fun Arrow() = Icon( tint = MaterialTheme.colorScheme.onSurfaceVariant, ) -/** What's new, the replays, and where Gearslip lives outside the app. */ +/** The setup guide replay, and where Gearslip lives outside the app. */ @Composable -private fun AboutSection(onOpenWhatsNew: () -> Unit, onReplayTutorial: () -> Unit, onReplayIntro: () -> Unit) { +private fun AboutSection(onReplayTutorial: () -> Unit) { SettingsSection("About") { - SettingsRow( - "What's new", - Modifier.clickable(onClick = onOpenWhatsNew), - subtitle = "Version ${BuildConfig.VERSION_NAME}", - icon = Icons.Filled.Star, - trailing = { Arrow() }, - ) - SettingsDivider() - SettingsRow( - "Replay the ${Intro.release} intro", - Modifier.clickable(onClick = onReplayIntro), - subtitle = "What's in this release, in a few taps", - icon = Icons.Filled.Star, - trailing = { Arrow() }, - ) - SettingsDivider() SettingsRow( "Replay the setup guide", Modifier.clickable(onClick = onReplayTutorial), @@ -200,48 +189,17 @@ private fun ConnectionSection() { } } -/** Connection help, and the tools for checking what Gearslip does. */ +/** Tools for testing a debug build; release builds never show this section. */ @Composable -private fun HelpSection(onOpenHelp: () -> Unit, onOpenCarPreview: () -> Unit, onOpenLogs: () -> Unit) { +private fun DebugSection() { val context = LocalContext.current - val status by SessionStatus.state.collectAsState() - val live = status.phase == SessionStatus.Phase.CONNECTING || status.phase == SessionStatus.Phase.PROJECTING - SettingsSection("Help and tools") { + SettingsSection("Debug build") { SettingsRow( - "Connection help", - Modifier.clickable(onClick = onOpenHelp), - subtitle = "Which cars work, and what to set up first", - icon = Icons.Filled.Info, - trailing = { Arrow() }, + "Send a test message", + Modifier.clickable { TestMessage.post(context) }, + subtitle = "Posts a message notification to read on the car", + icon = Icons.AutoMirrored.Filled.Send, ) - // The preview draws the car screen on the phone, so it waits until no car is using it. - if (!live) { - SettingsDivider() - SettingsRow( - "Car preview", - Modifier.clickable(onClick = onOpenCarPreview), - subtitle = "See the car screen on your phone", - icon = Icons.Filled.PlayArrow, - trailing = { Arrow() }, - ) - } - SettingsDivider() - SettingsRow( - "Live logs", - Modifier.clickable(onClick = onOpenLogs), - subtitle = "What Gearslip and the car are saying to each other", - icon = Icons.AutoMirrored.Filled.List, - trailing = { Arrow() }, - ) - if (BuildConfig.DEBUG) { - SettingsDivider() - SettingsRow( - "Send a test message", - Modifier.clickable { TestMessage.post(context) }, - subtitle = "Debug builds only. Posts a message notification to read on the car", - icon = Icons.AutoMirrored.Filled.Send, - ) - } } }