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

@@ -11,8 +11,8 @@ android {
applicationId = "com.kawomi.githugandroid" applicationId = "com.kawomi.githugandroid"
minSdk = 26 minSdk = 26
targetSdk = 34 targetSdk = 34
versionCode = 2 versionCode = 4
versionName = "0.1.1" versionName = "0.1.3"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@@ -70,6 +70,7 @@ dependencies {
implementation("androidx.compose.ui:ui-graphics") implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.foundation:foundation") implementation("androidx.compose.foundation:foundation")
implementation("androidx.compose.material:material-icons-extended")
implementation("androidx.compose.material3:material3:1.2.1") implementation("androidx.compose.material3:material3:1.2.1")
implementation("com.google.android.material:material:1.12.0") implementation("com.google.android.material:material:1.12.0")

View File

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