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-23 11:16:52 -05:00
parent 21334203c7
commit a830d41abf
2 changed files with 43 additions and 24 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 = 22 versionCode = 24
versionName = "0.1.21" versionName = "0.1.23"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true

View File

@@ -38,8 +38,6 @@ import androidx.compose.material3.MaterialTheme
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
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.TextButton import androidx.compose.material3.TextButton
import androidx.compose.material3.darkColorScheme import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -205,7 +203,7 @@ fun GitHugApp() {
val persistedPaneLayout by paneLayoutStore.layoutFlow.collectAsState(initial = defaultPaneLayout()) val persistedPaneLayout by paneLayoutStore.layoutFlow.collectAsState(initial = defaultPaneLayout())
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val screenScrollState = rememberScrollState() val screenScrollState = rememberScrollState()
val workspaceHeight = (configuration.screenHeightDp.dp * 0.72f).coerceAtLeast(420.dp) val workspaceHeight = (configuration.screenHeightDp.dp * 1.05f).coerceAtLeast(560.dp)
var paneLayout by remember { mutableStateOf(defaultPaneLayout()) } var paneLayout by remember { mutableStateOf(defaultPaneLayout()) }
var currentLevelIndex by remember { mutableStateOf(0) } var currentLevelIndex by remember { mutableStateOf(0) }
@@ -225,11 +223,13 @@ fun GitHugApp() {
paneLayout = persistedPaneLayout paneLayout = persistedPaneLayout
} }
fun updatePaneLayout(transform: (PaneLayout) -> PaneLayout) { fun updatePaneLayout(transform: (PaneLayout) -> PaneLayout, persist: Boolean = true) {
val updated = transform(paneLayout) val updated = transform(paneLayout)
paneLayout = updated paneLayout = updated
if (persist) {
scope.launch { paneLayoutStore.save(updated) } scope.launch { paneLayoutStore.save(updated) }
} }
}
fun clearCommandInput(recreateField: Boolean = false) { fun clearCommandInput(recreateField: Boolean = false) {
commandInput = TextFieldValue(text = "", selection = TextRange.Zero) commandInput = TextFieldValue(text = "", selection = TextRange.Zero)
@@ -380,17 +380,20 @@ fun GitHugApp() {
.height(workspaceHeight), .height(workspaceHeight),
paneLayout = paneLayout, paneLayout = paneLayout,
onMovePane = { paneId, delta -> onMovePane = { paneId, delta ->
updatePaneLayout { layout -> movePane(layout, paneId, delta) } updatePaneLayout(transform = { layout -> movePane(layout, paneId, delta) })
}, },
onTogglePane = { paneId -> onTogglePane = { paneId ->
updatePaneLayout { layout -> updatePaneLayout(transform = { layout ->
val collapsed = layout.collapsed.toMutableSet() val collapsed = layout.collapsed.toMutableSet()
if (!collapsed.add(paneId)) collapsed.remove(paneId) if (!collapsed.add(paneId)) collapsed.remove(paneId)
layout.copy(collapsed = collapsed) layout.copy(collapsed = collapsed)
} })
}, },
onResize = { upper, lower, dragFraction -> onResize = { upper, lower, dragFraction ->
updatePaneLayout { layout -> resizePanes(layout, upper, lower, dragFraction) } updatePaneLayout(transform = { layout -> resizePanes(layout, upper, lower, dragFraction) }, persist = false)
},
onResizeFinished = {
scope.launch { paneLayoutStore.save(paneLayout) }
}, },
levelsContent = { levelsContent = {
LevelsPane(levels, currentLevelIndex, completedLevels) { index -> loadLevel(index) } LevelsPane(levels, currentLevelIndex, completedLevels) { index -> loadLevel(index) }
@@ -470,6 +473,7 @@ private fun PaneWorkspace(
onMovePane: (PaneId, Int) -> Unit, onMovePane: (PaneId, Int) -> Unit,
onTogglePane: (PaneId) -> Unit, onTogglePane: (PaneId) -> Unit,
onResize: (PaneId, PaneId, Float) -> Unit, onResize: (PaneId, PaneId, Float) -> Unit,
onResizeFinished: () -> Unit,
levelsContent: @Composable () -> Unit, levelsContent: @Composable () -> Unit,
visualContent: @Composable () -> Unit, visualContent: @Composable () -> Unit,
exerciseContent: @Composable () -> Unit, exerciseContent: @Composable () -> Unit,
@@ -523,6 +527,7 @@ private fun PaneWorkspace(
val fraction = deltaPx / (heightBasis * 4f) val fraction = deltaPx / (heightBasis * 4f)
onResize(upper, lower, fraction) onResize(upper, lower, fraction)
}, },
onDragFinished = onResizeFinished,
) )
} }
} }
@@ -643,6 +648,7 @@ private fun HeaderActionButton(
private fun PaneDivider( private fun PaneDivider(
enabled: Boolean, enabled: Boolean,
onDrag: (Float) -> Unit, onDrag: (Float) -> Unit,
onDragFinished: () -> Unit,
) { ) {
val dragState = rememberDraggableState { delta -> val dragState = rememberDraggableState { delta ->
if (enabled) onDrag(delta) if (enabled) onDrag(delta)
@@ -656,6 +662,7 @@ private fun PaneDivider(
state = dragState, state = dragState,
orientation = Orientation.Vertical, orientation = Orientation.Vertical,
enabled = enabled, enabled = enabled,
onDragStopped = { onDragFinished() },
), ),
contentAlignment = Alignment.Center, contentAlignment = Alignment.Center,
) { ) {
@@ -665,6 +672,13 @@ private fun PaneDivider(
.height(1.dp) .height(1.dp)
.background(if (enabled) Accent.copy(alpha = 0.45f) else PanelTertiary), .background(if (enabled) Accent.copy(alpha = 0.45f) else PanelTertiary),
) )
Text(
text = "",
color = if (enabled) Accent else TextMuted,
modifier = Modifier.align(Alignment.CenterStart).padding(start = 28.dp),
fontSize = 12.sp,
fontWeight = FontWeight.Bold,
)
} }
} }
@@ -855,6 +869,7 @@ private fun TerminalPane(
val horizontalScroll = rememberScrollState() val horizontalScroll = rememberScrollState()
val outputVerticalScroll = rememberScrollState() val outputVerticalScroll = rememberScrollState()
val terminalMinWidth = 640.dp val terminalMinWidth = 640.dp
val scope = rememberCoroutineScope()
LaunchedEffect(inputFieldVersion) { LaunchedEffect(inputFieldVersion) {
if (inputFieldVersion == 0) return@LaunchedEffect if (inputFieldVersion == 0) return@LaunchedEffect
@@ -886,7 +901,6 @@ private fun TerminalPane(
.widthIn(min = terminalMinWidth), .widthIn(min = terminalMinWidth),
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp),
) { ) {
Text("Terminal", color = TextPrimary, fontWeight = FontWeight.Bold)
Box( Box(
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
@@ -929,36 +943,41 @@ private fun TerminalPane(
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
) )
key(inputFieldVersion) { key(inputFieldVersion) {
TextField( BasicTextField(
value = commandInput, value = commandInput,
onValueChange = onValueChange, onValueChange = onValueChange,
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.focusRequester(focusRequester) .focusRequester(focusRequester)
.bringIntoViewRequester(bringIntoViewRequester)
.onFocusChanged { state -> .onFocusChanged { state ->
if (state.isFocused) { if (state.isFocused) {
keyboardController?.show() keyboardController?.show()
scope.launch {
delay(150)
bringIntoViewRequester.bringIntoView()
}
} }
}, },
singleLine = true, singleLine = true,
textStyle = TextStyle(color = TextPrimary, fontFamily = FontFamily.Monospace), textStyle = TextStyle(color = TextPrimary, fontFamily = FontFamily.Monospace),
colors = TextFieldDefaults.colors( cursorBrush = SolidColor(Accent),
focusedContainerColor = Color.Transparent,
unfocusedContainerColor = Color.Transparent,
disabledContainerColor = Color.Transparent,
cursorColor = Accent,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
disabledIndicatorColor = Color.Transparent,
focusedTextColor = TextPrimary,
unfocusedTextColor = TextPrimary,
),
keyboardOptions = KeyboardOptions( keyboardOptions = KeyboardOptions(
autoCorrect = false, autoCorrect = false,
keyboardType = KeyboardType.Ascii, keyboardType = KeyboardType.Ascii,
imeAction = ImeAction.Done, imeAction = ImeAction.Done,
), ),
keyboardActions = KeyboardActions(onDone = { submitCommand() }), keyboardActions = KeyboardActions(onDone = { submitCommand() }),
decorationBox = { innerTextField ->
Box(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
contentAlignment = Alignment.CenterStart,
) {
innerTextField()
}
},
) )
} }
} }