intro: add a step inviting drivers to the Matrix chat

This commit is contained in:
Seb3thehacker committed 2026-10-13 15:21:17 -07:00
1 parent e13b0618db
commit 5947bc1e63
2 files changed
+31 -3

No files matched your search

@@ -39,9 +39,9 @@ internal fun AboutLinkRows() {
) )
} }
SettingsRow( SettingsRow(
"Join the discussion on Matrix", "Join the chat on Matrix",
Modifier.clickable { GearslipLinks.open(context, GearslipLinks.MATRIX) }, Modifier.clickable { GearslipLinks.open(context, GearslipLinks.MATRIX) },
subtitle = "Questions, ideas, or a car to report", subtitle = "Talk with other drivers about cars, apps, and Gearslip",
icon = Icons.AutoMirrored.Filled.Send, icon = Icons.AutoMirrored.Filled.Send,
trailing = arrow, trailing = arrow,
) )
@@ -49,6 +49,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -134,7 +135,7 @@ internal fun introColors(): IntroColors {
) )
} }
private enum class IntroStep { WELCOME, WIRELESS, KNOBS, VOICE, GRAPHENE, THANKS, APPS, THEME, DRIVE } private enum class IntroStep { WELCOME, WIRELESS, KNOBS, VOICE, GRAPHENE, THANKS, CHAT, APPS, THEME, DRIVE }
private val Pop = CubicBezierEasing(0.3f, 1.6f, 0.5f, 1f) private val Pop = CubicBezierEasing(0.3f, 1.6f, 0.5f, 1f)
private val Rise = CubicBezierEasing(0.2f, 0.8f, 0.2f, 1f) private val Rise = CubicBezierEasing(0.2f, 0.8f, 0.2f, 1f)
@@ -191,6 +192,12 @@ fun IntroScreen(onDone: () -> Unit) {
IntroStep.THANKS -> BadgeStep(c, ::cq, ::cqSp, c.tertiaryC, "Thank you.", IntroStep.THANKS -> BadgeStep(c, ::cq, ::cqSp, c.tertiaryC, "Thank you.",
"To everyone sending usage notes: they show me which cars Gearslip works in and which " + "To everyone sending usage notes: they show me which cars Gearslip works in and which " +
"ones still fail, so I know what to fix next. Every note helps.", step) { HeartIcon(c.onTertiaryC) } "ones still fail, so I know what to fix next. Every note helps.", step) { HeartIcon(c.onTertiaryC) }
IntroStep.CHAT -> BadgeStep(c, ::cq, ::cqSp, c.primaryC, "Come say hi.",
"Gearslip has a chat room on Matrix. Talk with other drivers about cars, apps, and " +
"where Gearslip is headed.", step,
action = "Join on Matrix" to { GearslipLinks.open(context, GearslipLinks.MATRIX) },
outlined = true,
) { ChatIcon(c.onPrimaryC, c.primaryC) }
IntroStep.APPS -> BadgeStep(c, ::cq, ::cqSp, c.secondaryC, "Good company.", IntroStep.APPS -> BadgeStep(c, ::cq, ::cqSp, c.secondaryC, "Good company.",
"Free, open-source apps that work well in the car. Tap one to see it on GitHub.", step, "Free, open-source apps that work well in the car. Tap one to see it on GitHub.", step,
extra = { AppPicks(c, ::cq, ::cqSp, step) }) { StarIcon(c.onSecondaryC) } extra = { AppPicks(c, ::cq, ::cqSp, step) }) { StarIcon(c.onSecondaryC) }
@@ -726,6 +733,27 @@ internal fun ShieldIcon(color: Color, tick: Color) {
} }
} }
/** A speech bubble with three dots that pulse, like someone typing. */
@Composable
private fun ChatIcon(color: Color, dots: Color) {
val t = rememberInfiniteTransition(label = "typing")
val pulse = (0..2).map { i ->
t.animateFloat(
0.35f, 1f,
infiniteRepeatable(tween(500, easing = FastOutSlowInEasing), RepeatMode.Reverse,
initialStartOffset = androidx.compose.animation.core.StartOffset(i * 170)),
label = "dot$i",
)
}
Canvas(Modifier.fillMaxSize()) {
inIconBox {
drawRoundRect(color, Offset(4f, 7f), Size(40f, 28f), CornerRadius(10f, 10f))
drawPath(Path().apply { moveTo(12f, 33f); lineTo(10f, 43f); lineTo(22f, 33f); close() }, color)
pulse.forEachIndexed { i, a -> drawCircle(dots.copy(alpha = a.value), 3.2f, Offset(15f + i * 9f, 21f)) }
}
}
}
@Composable @Composable
internal fun HeartIcon(color: Color) { internal fun HeartIcon(color: Color) {
val beat by rememberInfiniteTransition(label = "beat").animateFloat( val beat by rememberInfiniteTransition(label = "beat").animateFloat(