Add terminal input onboarding bubble

This commit is contained in:
Joe Tretter
2026-05-05 19:54:33 -05:00
parent 9d09eb1385
commit 344ff99f0a
3 changed files with 60 additions and 2 deletions

View File

@@ -19,8 +19,8 @@ android {
applicationId = "solutions.tretter.githugandroid"
minSdk = 26
targetSdk = 35
versionCode = 113
versionName = "0.1.112"
versionCode = 114
versionName = "0.1.113"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true

View File

@@ -77,6 +77,7 @@ fun GitHugApp() {
var gitMessageEditorState by remember { mutableStateOf<GitMessageEditorState?>(null) }
var manPageState by remember { mutableStateOf<ManPageState?>(null) }
var solvedCelebrationTitle by remember { mutableStateOf<String?>(null) }
var showTerminalInputHint by remember { mutableStateOf(true) }
val currentLevel = levels[currentLevelIndex]
LaunchedEffect(solvedCelebrationTitle) {
@@ -412,6 +413,7 @@ fun GitHugApp() {
val raw = submittedText.trim()
if (raw.isBlank()) return
showTerminalInputHint = false
suppressedImeEcho = submittedText
clearCommandInput(recreateField = true)
@@ -509,6 +511,8 @@ fun GitHugApp() {
output = output,
inputFieldVersion = inputFieldVersion,
commandInput = commandInput,
showInputHint = showTerminalInputHint,
onInputHintDismiss = { showTerminalInputHint = false },
onValueChange = {
val blockedEcho = suppressedImeEcho
if (blockedEcho != null && commandInput.text.isEmpty()) {
@@ -518,6 +522,9 @@ fun GitHugApp() {
}
}
suppressedImeEcho = null
if (it.text.isNotEmpty()) {
showTerminalInputHint = false
}
commandInput = it
},
onRun = { runCommand() },

View File

@@ -1,6 +1,7 @@
package solutions.tretter.githugandroid
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement
@@ -37,6 +38,7 @@ import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalFocusManager
@@ -57,6 +59,8 @@ fun TerminalPane(
output: List<String>,
inputFieldVersion: Int,
commandInput: TextFieldValue,
showInputHint: Boolean,
onInputHintDismiss: () -> Unit,
onValueChange: (TextFieldValue) -> Unit,
onRun: () -> Unit,
onTab: () -> Unit,
@@ -150,6 +154,9 @@ fun TerminalPane(
onHistoryDown = onHistoryDown,
onInsertText = { insertLiteral(it) },
)
if (showInputHint) {
TerminalInputHintBubble()
}
Row(
modifier = Modifier
.fillMaxWidth()
@@ -171,6 +178,7 @@ fun TerminalPane(
onValueChange = onValueChange,
focusRequester = focusRequester,
keyboardController = keyboardController,
onFocused = onInputHintDismiss,
onSubmit = { submitCommand() },
)
}
@@ -186,6 +194,7 @@ private fun RowScope.TerminalInputField(
onValueChange: (TextFieldValue) -> Unit,
focusRequester: FocusRequester,
keyboardController: androidx.compose.ui.platform.SoftwareKeyboardController?,
onFocused: () -> Unit,
onSubmit: () -> Unit,
) {
key(inputFieldVersion) {
@@ -197,6 +206,7 @@ private fun RowScope.TerminalInputField(
.focusRequester(focusRequester)
.onFocusChanged { state ->
if (state.isFocused) {
onFocused()
keyboardController?.show()
}
},
@@ -237,6 +247,47 @@ private fun RowScope.TerminalInputField(
}
}
@Composable
private fun TerminalInputHintBubble() {
val bubbleColor = Color(0xFFFFF1A8)
Column(
modifier = Modifier
.fillMaxWidth()
.padding(start = 46.dp, end = 14.dp),
horizontalAlignment = Alignment.Start,
) {
Box(
modifier = Modifier
.background(bubbleColor, RoundedCornerShape(18.dp))
.padding(horizontal = 14.dp, vertical = 10.dp),
) {
Text(
text = "Tap here to enter a command",
color = Color(0xFF161000),
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Bold,
fontSize = 14.sp,
)
}
Canvas(
modifier = Modifier
.padding(start = 26.dp)
.width(26.dp)
.height(13.dp),
) {
drawPath(
path = Path().apply {
moveTo(0f, 0f)
lineTo(size.width, 0f)
lineTo(size.width * 0.25f, size.height)
close()
},
color = bubbleColor,
)
}
}
}
@Composable
private fun SpecialKeyBar(
onTab: () -> Unit,