Auto-commit after successful build: update app gameplay/UI, improve build setup

Changed files:\napp/build.gradle.kts
app/src/main/java/com/kawomi/githugandroid/GitHugApp.kt
This commit is contained in:
Joe Tretter
2026-04-22 12:42:14 -05:00
parent b80a8aca25
commit 9340d386a0
2 changed files with 57 additions and 30 deletions

View File

@@ -8,15 +8,20 @@ import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.KeyboardArrowUp
import androidx.compose.material.icons.filled.KeyboardTab
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.FilterChip
import androidx.compose.material3.FilterChipDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
@@ -28,7 +33,10 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.key
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.TextRange
@@ -74,6 +82,7 @@ fun GitHugApp() {
var mode by remember { mutableStateOf(PlayMode.CLI_ONLY) }
var repo by remember { mutableStateOf(levels.first().setup()) }
var commandInput by remember { mutableStateOf(TextFieldValue("")) }
var inputFieldVersion by remember { mutableStateOf(0) }
var output by remember { mutableStateOf(listOf("Welcome to GitHug Android.")) }
var hintIndex by remember { mutableStateOf(0) }
var completedLevels by remember { mutableStateOf(setOf<String>()) }
@@ -88,9 +97,14 @@ fun GitHugApp() {
screenScrollState.scrollTo(0)
}
fun clearCommandInput() {
commandInput = TextFieldValue(text = "", selection = TextRange.Zero)
inputFieldVersion += 1
}
fun resetCurrentLevel(message: String = "Level reset.") {
repo = currentLevel.setup()
commandInput = TextFieldValue("")
clearCommandInput()
output = listOf(message)
hintIndex = 0
historyIndex = -1
@@ -153,7 +167,7 @@ fun GitHugApp() {
val raw = commandInput.text.trim()
if (raw.isBlank()) return
commandInput = TextFieldValue("")
clearCommandInput()
if (commandHistory.lastOrNull() != raw) {
commandHistory = commandHistory + raw
@@ -181,12 +195,12 @@ fun GitHugApp() {
currentLevelIndex = nextLevelIndex
repo = nextLevel.setup()
output = listOf("Loaded level: ${nextLevel.title}")
commandInput = TextFieldValue("")
clearCommandInput()
hintIndex = 0
} else {
repo = newRepo
output = listOf("🏁 All available MVP levels completed.")
commandInput = TextFieldValue("")
clearCommandInput()
}
} else {
repo = newRepo
@@ -212,7 +226,7 @@ fun GitHugApp() {
currentLevelIndex = index
repo = levels[index].setup()
output = listOf("Loaded level: ${levels[index].title}")
commandInput = TextFieldValue("")
clearCommandInput()
hintIndex = 0
historyIndex = -1
historyDraft = ""
@@ -232,6 +246,7 @@ fun GitHugApp() {
}
TerminalPanel(
output = output,
inputFieldVersion = inputFieldVersion,
commandInput = commandInput,
onValueChange = { commandInput = it },
onRun = { runCommand() },
@@ -349,6 +364,7 @@ private fun InfoCard(title: String, content: String, modifier: Modifier = Modifi
@Composable
private fun TerminalPanel(
output: List<String>,
inputFieldVersion: Int,
commandInput: TextFieldValue,
onValueChange: (TextFieldValue) -> Unit,
onRun: () -> Unit,
@@ -359,6 +375,12 @@ private fun TerminalPanel(
onHistoryDown: () -> Unit,
modifier: Modifier = Modifier,
) {
val focusRequester = remember { FocusRequester() }
LaunchedEffect(inputFieldVersion) {
focusRequester.requestFocus()
}
Card(modifier = modifier, colors = CardDefaults.cardColors(containerColor = TerminalBackground)) {
Box(modifier = Modifier.fillMaxSize().padding(16.dp)) {
Column(verticalArrangement = Arrangement.spacedBy(6.dp)) {
@@ -390,20 +412,24 @@ private fun TerminalPanel(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold
)
BasicTextField(
value = commandInput,
onValueChange = onValueChange,
modifier = Modifier.fillMaxWidth(),
singleLine = true,
textStyle = TextStyle(color = TextPrimary, fontFamily = FontFamily.Monospace),
cursorBrush = SolidColor(Accent),
keyboardOptions = KeyboardOptions(
autoCorrect = false,
keyboardType = KeyboardType.Ascii,
imeAction = ImeAction.Done,
),
keyboardActions = KeyboardActions(onDone = { onRun() })
)
key(inputFieldVersion) {
BasicTextField(
value = commandInput,
onValueChange = onValueChange,
modifier = Modifier
.weight(1f)
.focusRequester(focusRequester),
singleLine = true,
textStyle = TextStyle(color = TextPrimary, fontFamily = FontFamily.Monospace),
cursorBrush = SolidColor(Accent),
keyboardOptions = KeyboardOptions(
autoCorrect = false,
keyboardType = KeyboardType.Ascii,
imeAction = ImeAction.Done,
),
keyboardActions = KeyboardActions(onDone = { onRun() })
)
}
}
}
}
@@ -422,17 +448,17 @@ private fun SpecialKeyBar(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
TerminalKeyButton(label = "", onClick = onTab, modifier = Modifier.weight(1.3f))
TerminalKeyButton(label = "", onClick = onCursorLeft)
TerminalKeyButton(label = "", onClick = onCursorRight)
TerminalKeyButton(label = "", onClick = onHistoryUp)
TerminalKeyButton(label = "", onClick = onHistoryDown)
TerminalKeyButton(icon = { Icon(Icons.Filled.KeyboardTab, contentDescription = "Tab") }, onClick = onTab, modifier = Modifier.weight(1.3f))
TerminalKeyButton(icon = { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Move cursor left") }, onClick = onCursorLeft)
TerminalKeyButton(icon = { Icon(Icons.AutoMirrored.Filled.ArrowForward, contentDescription = "Move cursor right") }, onClick = onCursorRight)
TerminalKeyButton(icon = { Icon(Icons.Filled.KeyboardArrowUp, contentDescription = "Previous command") }, onClick = onHistoryUp)
TerminalKeyButton(icon = { Icon(Icons.Filled.KeyboardArrowDown, contentDescription = "Next command") }, onClick = onHistoryDown)
}
}
@Composable
private fun TerminalKeyButton(
label: String,
icon: @Composable () -> Unit,
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
@@ -444,7 +470,7 @@ private fun TerminalKeyButton(
contentColor = TextPrimary
)
) {
Text(label, fontFamily = FontFamily.Monospace, fontWeight = FontWeight.Bold)
icon()
}
}