mirror of
https://github.com/twinksoftware/Gearslip.git
synced 2026-11-10 16:02:25 +01:00
home: Help, Preview and Logs in one row at the bottom, and What's new tops Settings
Small labelled buttons pinned at the bottom of Home, so cards above can't push them out of sight. Help and tools leaves Settings, Connection help (the same page as Help) goes, What's new moves to the top of Settings, the intro replay goes, and the debug build's test message gets its own section there.
This commit is contained in:
1 parent
55c25fe967
commit
ef006dc695
3 files changed
+55
-85
No files matched your search
@@ -108,26 +108,23 @@ fun GearslipApp(onDisconnect: () -> Unit, onRequestCallScreening: () -> Unit) {
|
|||||||
Screen.INTRO -> IntroScreen(onDone = { screen = introReturn })
|
Screen.INTRO -> IntroScreen(onDone = { screen = introReturn })
|
||||||
Screen.HOME -> HomeScreen(
|
Screen.HOME -> HomeScreen(
|
||||||
onOpenSettings = { settingsAtUsageNotes = false; screen = Screen.SETTINGS },
|
onOpenSettings = { settingsAtUsageNotes = false; screen = Screen.SETTINGS },
|
||||||
onOpenWhatsNew = { backTo = Screen.HOME; screen = Screen.WHATS_NEW },
|
|
||||||
onOpenHelp = { backTo = Screen.HOME; screen = Screen.HELP },
|
onOpenHelp = { backTo = Screen.HOME; screen = Screen.HELP },
|
||||||
onOpenUsageNotes = { settingsAtUsageNotes = true; screen = Screen.SETTINGS },
|
onOpenUsageNotes = { settingsAtUsageNotes = true; screen = Screen.SETTINGS },
|
||||||
|
onOpenCarPreview = { backTo = Screen.HOME; screen = Screen.CAR_PREVIEW },
|
||||||
|
onOpenLogs = { backTo = Screen.HOME; screen = Screen.LOGS },
|
||||||
onDisconnect = onDisconnect,
|
onDisconnect = onDisconnect,
|
||||||
)
|
)
|
||||||
Screen.WHATS_NEW -> WhatsNewScreen(onBack = { screen = backTo })
|
Screen.WHATS_NEW -> WhatsNewScreen(onBack = { screen = backTo })
|
||||||
Screen.LOGS -> LogsScreen(onBack = { screen = Screen.SETTINGS })
|
Screen.LOGS -> LogsScreen(onBack = { screen = backTo })
|
||||||
Screen.SETTINGS -> SettingsScreen(
|
Screen.SETTINGS -> SettingsScreen(
|
||||||
onBack = { screen = Screen.HOME },
|
onBack = { screen = Screen.HOME },
|
||||||
onOpenRecommendedApps = { settingsAtUsageNotes = false; screen = Screen.RECOMMENDED_APPS },
|
onOpenRecommendedApps = { settingsAtUsageNotes = false; screen = Screen.RECOMMENDED_APPS },
|
||||||
onOpenWhatsNew = { settingsAtUsageNotes = false; backTo = Screen.SETTINGS; screen = Screen.WHATS_NEW },
|
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 },
|
onReplayTutorial = { screen = Screen.SETUP_GUIDE },
|
||||||
onReplayIntro = { Intro.replay(context); introReturn = Screen.SETTINGS; screen = Screen.INTRO },
|
|
||||||
atUsageNotes = settingsAtUsageNotes,
|
atUsageNotes = settingsAtUsageNotes,
|
||||||
)
|
)
|
||||||
Screen.RECOMMENDED_APPS -> RecommendedAppsScreen(onBack = { screen = Screen.SETTINGS })
|
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(
|
Screen.HELP -> HelpScreen(
|
||||||
onBack = { screen = backTo },
|
onBack = { screen = backTo },
|
||||||
onRequestCallScreening = onRequestCallScreening,
|
onRequestCallScreening = onRequestCallScreening,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import app.seb3thehacker.gearslip.speech.SpeechModels
|
|||||||
import androidx.compose.material3.LinearProgressIndicator
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
@@ -27,6 +28,8 @@ import androidx.compose.foundation.rememberScrollState
|
|||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.automirrored.filled.KeyboardArrowRight
|
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.Info
|
||||||
import androidx.compose.material.icons.filled.Send
|
import androidx.compose.material.icons.filled.Send
|
||||||
import androidx.compose.material.icons.filled.List
|
import androidx.compose.material.icons.filled.List
|
||||||
@@ -60,9 +63,10 @@ import app.seb3thehacker.gearslip.stats.WorkedPrompt
|
|||||||
@Composable
|
@Composable
|
||||||
fun HomeScreen(
|
fun HomeScreen(
|
||||||
onOpenSettings: () -> Unit,
|
onOpenSettings: () -> Unit,
|
||||||
onOpenWhatsNew: () -> Unit,
|
|
||||||
onOpenHelp: () -> Unit,
|
onOpenHelp: () -> Unit,
|
||||||
onOpenUsageNotes: () -> Unit,
|
onOpenUsageNotes: () -> Unit,
|
||||||
|
onOpenCarPreview: () -> Unit,
|
||||||
|
onOpenLogs: () -> Unit,
|
||||||
onDisconnect: () -> Unit,
|
onDisconnect: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val status by SessionStatus.state.collectAsStateWithLifecycle()
|
val status by SessionStatus.state.collectAsStateWithLifecycle()
|
||||||
@@ -125,21 +129,11 @@ fun HomeScreen(
|
|||||||
|
|
||||||
// Sits at the bottom, where a thumb reaches it.
|
// Sits at the bottom, where a thumb reaches it.
|
||||||
Column(Modifier.padding(vertical = 16.dp)) {
|
Column(Modifier.padding(vertical = 16.dp)) {
|
||||||
SettingsCard {
|
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
SettingsRow(
|
HomeShortcut(Icons.Filled.Info, "Help", onOpenHelp, Modifier.weight(1f))
|
||||||
"What's new in ${Intro.release}",
|
// The preview draws the car screen on the phone, so it waits until no car is using it.
|
||||||
Modifier.clickable(onClick = onOpenWhatsNew),
|
if (!live) HomeShortcut(Icons.Filled.PlayArrow, "Preview", onOpenCarPreview, Modifier.weight(1f))
|
||||||
icon = Icons.Filled.Star,
|
HomeShortcut(Icons.AutoMirrored.Filled.List, "Logs", onOpenLogs, Modifier.weight(1f))
|
||||||
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() },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if (live) {
|
if (live) {
|
||||||
Spacer(Modifier.height(16.dp))
|
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]. */
|
/** Bluetooth audio is chosen, but the phone isn't connected to the car. See [BluetoothAudioCheck]. */
|
||||||
@Composable
|
@Composable
|
||||||
private fun BluetoothMissingCard() {
|
private fun BluetoothMissingCard() {
|
||||||
|
|||||||
@@ -80,11 +80,7 @@ fun SettingsScreen(
|
|||||||
onBack: () -> Unit,
|
onBack: () -> Unit,
|
||||||
onOpenRecommendedApps: () -> Unit,
|
onOpenRecommendedApps: () -> Unit,
|
||||||
onOpenWhatsNew: () -> Unit,
|
onOpenWhatsNew: () -> Unit,
|
||||||
onOpenHelp: () -> Unit,
|
|
||||||
onOpenCarPreview: () -> Unit,
|
|
||||||
onOpenLogs: () -> Unit,
|
|
||||||
onReplayTutorial: () -> Unit,
|
onReplayTutorial: () -> Unit,
|
||||||
onReplayIntro: () -> Unit,
|
|
||||||
atUsageNotes: Boolean = false,
|
atUsageNotes: Boolean = false,
|
||||||
) {
|
) {
|
||||||
val scroll = rememberScrollState()
|
val scroll = rememberScrollState()
|
||||||
@@ -119,12 +115,20 @@ fun SettingsScreen(
|
|||||||
verticalArrangement = Arrangement.spacedBy(24.dp),
|
verticalArrangement = Arrangement.spacedBy(24.dp),
|
||||||
) {
|
) {
|
||||||
Spacer(Modifier.height(0.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(
|
SettingsSection(
|
||||||
"Support Gearslip",
|
"Support Gearslip",
|
||||||
footer = "Gearslip is free, with no ads and no tracking. Your support keeps it going.",
|
footer = "Gearslip is free, with no ads and no tracking. Your support keeps it going.",
|
||||||
) { DonateRows() }
|
) { DonateRows() }
|
||||||
ConnectionSection()
|
ConnectionSection()
|
||||||
HelpSection(onOpenHelp, onOpenCarPreview, onOpenLogs)
|
|
||||||
CarAudioSection()
|
CarAudioSection()
|
||||||
CarScreenSection()
|
CarScreenSection()
|
||||||
VoiceModelSection()
|
VoiceModelSection()
|
||||||
@@ -136,7 +140,8 @@ fun SettingsScreen(
|
|||||||
) { UsageStatsRows() }
|
) { UsageStatsRows() }
|
||||||
SettingsSection("Updates") { UpdateRow() }
|
SettingsSection("Updates") { UpdateRow() }
|
||||||
CertificateSection()
|
CertificateSection()
|
||||||
AboutSection(onOpenWhatsNew, onReplayTutorial, onReplayIntro)
|
AboutSection(onReplayTutorial)
|
||||||
|
if (BuildConfig.DEBUG) DebugSection()
|
||||||
Spacer(Modifier.height(16.dp))
|
Spacer(Modifier.height(16.dp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,26 +154,10 @@ private fun Arrow() = Icon(
|
|||||||
tint = MaterialTheme.colorScheme.onSurfaceVariant,
|
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
|
@Composable
|
||||||
private fun AboutSection(onOpenWhatsNew: () -> Unit, onReplayTutorial: () -> Unit, onReplayIntro: () -> Unit) {
|
private fun AboutSection(onReplayTutorial: () -> Unit) {
|
||||||
SettingsSection("About") {
|
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(
|
SettingsRow(
|
||||||
"Replay the setup guide",
|
"Replay the setup guide",
|
||||||
Modifier.clickable(onClick = onReplayTutorial),
|
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
|
@Composable
|
||||||
private fun HelpSection(onOpenHelp: () -> Unit, onOpenCarPreview: () -> Unit, onOpenLogs: () -> Unit) {
|
private fun DebugSection() {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val status by SessionStatus.state.collectAsState()
|
SettingsSection("Debug build") {
|
||||||
val live = status.phase == SessionStatus.Phase.CONNECTING || status.phase == SessionStatus.Phase.PROJECTING
|
|
||||||
SettingsSection("Help and tools") {
|
|
||||||
SettingsRow(
|
SettingsRow(
|
||||||
"Connection help",
|
"Send a test message",
|
||||||
Modifier.clickable(onClick = onOpenHelp),
|
Modifier.clickable { TestMessage.post(context) },
|
||||||
subtitle = "Which cars work, and what to set up first",
|
subtitle = "Posts a message notification to read on the car",
|
||||||
icon = Icons.Filled.Info,
|
icon = Icons.AutoMirrored.Filled.Send,
|
||||||
trailing = { Arrow() },
|
|
||||||
)
|
)
|
||||||
// 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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user