Add terminal input onboarding bubble
This commit is contained in:
@@ -19,8 +19,8 @@ android {
|
|||||||
applicationId = "solutions.tretter.githugandroid"
|
applicationId = "solutions.tretter.githugandroid"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 113
|
versionCode = 114
|
||||||
versionName = "0.1.112"
|
versionName = "0.1.113"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ fun GitHugApp() {
|
|||||||
var gitMessageEditorState by remember { mutableStateOf<GitMessageEditorState?>(null) }
|
var gitMessageEditorState by remember { mutableStateOf<GitMessageEditorState?>(null) }
|
||||||
var manPageState by remember { mutableStateOf<ManPageState?>(null) }
|
var manPageState by remember { mutableStateOf<ManPageState?>(null) }
|
||||||
var solvedCelebrationTitle by remember { mutableStateOf<String?>(null) }
|
var solvedCelebrationTitle by remember { mutableStateOf<String?>(null) }
|
||||||
|
var showTerminalInputHint by remember { mutableStateOf(true) }
|
||||||
val currentLevel = levels[currentLevelIndex]
|
val currentLevel = levels[currentLevelIndex]
|
||||||
|
|
||||||
LaunchedEffect(solvedCelebrationTitle) {
|
LaunchedEffect(solvedCelebrationTitle) {
|
||||||
@@ -412,6 +413,7 @@ fun GitHugApp() {
|
|||||||
val raw = submittedText.trim()
|
val raw = submittedText.trim()
|
||||||
if (raw.isBlank()) return
|
if (raw.isBlank()) return
|
||||||
|
|
||||||
|
showTerminalInputHint = false
|
||||||
suppressedImeEcho = submittedText
|
suppressedImeEcho = submittedText
|
||||||
clearCommandInput(recreateField = true)
|
clearCommandInput(recreateField = true)
|
||||||
|
|
||||||
@@ -509,6 +511,8 @@ fun GitHugApp() {
|
|||||||
output = output,
|
output = output,
|
||||||
inputFieldVersion = inputFieldVersion,
|
inputFieldVersion = inputFieldVersion,
|
||||||
commandInput = commandInput,
|
commandInput = commandInput,
|
||||||
|
showInputHint = showTerminalInputHint,
|
||||||
|
onInputHintDismiss = { showTerminalInputHint = false },
|
||||||
onValueChange = {
|
onValueChange = {
|
||||||
val blockedEcho = suppressedImeEcho
|
val blockedEcho = suppressedImeEcho
|
||||||
if (blockedEcho != null && commandInput.text.isEmpty()) {
|
if (blockedEcho != null && commandInput.text.isEmpty()) {
|
||||||
@@ -518,6 +522,9 @@ fun GitHugApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
suppressedImeEcho = null
|
suppressedImeEcho = null
|
||||||
|
if (it.text.isNotEmpty()) {
|
||||||
|
showTerminalInputHint = false
|
||||||
|
}
|
||||||
commandInput = it
|
commandInput = it
|
||||||
},
|
},
|
||||||
onRun = { runCommand() },
|
onRun = { runCommand() },
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package solutions.tretter.githugandroid
|
package solutions.tretter.githugandroid
|
||||||
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.Canvas
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.horizontalScroll
|
import androidx.compose.foundation.horizontalScroll
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
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.focusRequester
|
||||||
import androidx.compose.ui.focus.onFocusChanged
|
import androidx.compose.ui.focus.onFocusChanged
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.Path
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.platform.LocalConfiguration
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
import androidx.compose.ui.platform.LocalFocusManager
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
@@ -57,6 +59,8 @@ fun TerminalPane(
|
|||||||
output: List<String>,
|
output: List<String>,
|
||||||
inputFieldVersion: Int,
|
inputFieldVersion: Int,
|
||||||
commandInput: TextFieldValue,
|
commandInput: TextFieldValue,
|
||||||
|
showInputHint: Boolean,
|
||||||
|
onInputHintDismiss: () -> Unit,
|
||||||
onValueChange: (TextFieldValue) -> Unit,
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
onRun: () -> Unit,
|
onRun: () -> Unit,
|
||||||
onTab: () -> Unit,
|
onTab: () -> Unit,
|
||||||
@@ -150,6 +154,9 @@ fun TerminalPane(
|
|||||||
onHistoryDown = onHistoryDown,
|
onHistoryDown = onHistoryDown,
|
||||||
onInsertText = { insertLiteral(it) },
|
onInsertText = { insertLiteral(it) },
|
||||||
)
|
)
|
||||||
|
if (showInputHint) {
|
||||||
|
TerminalInputHintBubble()
|
||||||
|
}
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
@@ -171,6 +178,7 @@ fun TerminalPane(
|
|||||||
onValueChange = onValueChange,
|
onValueChange = onValueChange,
|
||||||
focusRequester = focusRequester,
|
focusRequester = focusRequester,
|
||||||
keyboardController = keyboardController,
|
keyboardController = keyboardController,
|
||||||
|
onFocused = onInputHintDismiss,
|
||||||
onSubmit = { submitCommand() },
|
onSubmit = { submitCommand() },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -186,6 +194,7 @@ private fun RowScope.TerminalInputField(
|
|||||||
onValueChange: (TextFieldValue) -> Unit,
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
focusRequester: FocusRequester,
|
focusRequester: FocusRequester,
|
||||||
keyboardController: androidx.compose.ui.platform.SoftwareKeyboardController?,
|
keyboardController: androidx.compose.ui.platform.SoftwareKeyboardController?,
|
||||||
|
onFocused: () -> Unit,
|
||||||
onSubmit: () -> Unit,
|
onSubmit: () -> Unit,
|
||||||
) {
|
) {
|
||||||
key(inputFieldVersion) {
|
key(inputFieldVersion) {
|
||||||
@@ -197,6 +206,7 @@ private fun RowScope.TerminalInputField(
|
|||||||
.focusRequester(focusRequester)
|
.focusRequester(focusRequester)
|
||||||
.onFocusChanged { state ->
|
.onFocusChanged { state ->
|
||||||
if (state.isFocused) {
|
if (state.isFocused) {
|
||||||
|
onFocused()
|
||||||
keyboardController?.show()
|
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
|
@Composable
|
||||||
private fun SpecialKeyBar(
|
private fun SpecialKeyBar(
|
||||||
onTab: () -> Unit,
|
onTab: () -> Unit,
|
||||||
|
|||||||
Reference in New Issue
Block a user