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:
@@ -11,8 +11,8 @@ android {
|
|||||||
applicationId = "com.kawomi.githugandroid"
|
applicationId = "com.kawomi.githugandroid"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 34
|
targetSdk = 34
|
||||||
versionCode = 28
|
versionCode = 29
|
||||||
versionName = "0.1.27"
|
versionName = "0.1.28"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|||||||
@@ -123,6 +123,11 @@ private data class PaneLayout(
|
|||||||
val weights: Map<PaneId, Float>,
|
val weights: Map<PaneId, Float>,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private enum class ExerciseDetailPanel {
|
||||||
|
HINT,
|
||||||
|
SUGGESTIONS,
|
||||||
|
}
|
||||||
|
|
||||||
private fun defaultPaneLayout(): PaneLayout = PaneLayout(
|
private fun defaultPaneLayout(): PaneLayout = PaneLayout(
|
||||||
order = listOf(PaneId.EXERCISE, PaneId.TERMINAL, PaneId.VISUAL, PaneId.LEVELS),
|
order = listOf(PaneId.EXERCISE, PaneId.TERMINAL, PaneId.VISUAL, PaneId.LEVELS),
|
||||||
collapsed = emptySet(),
|
collapsed = emptySet(),
|
||||||
@@ -205,7 +210,6 @@ 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 * 1.05f).coerceAtLeast(560.dp)
|
|
||||||
val screenHeightDp = configuration.screenHeightDp
|
val screenHeightDp = configuration.screenHeightDp
|
||||||
|
|
||||||
var paneLayout by remember { mutableStateOf(defaultPaneLayout()) }
|
var paneLayout by remember { mutableStateOf(defaultPaneLayout()) }
|
||||||
@@ -216,7 +220,8 @@ fun GitHugApp() {
|
|||||||
var suppressedImeEcho by remember { mutableStateOf<String?>(null) }
|
var suppressedImeEcho by remember { mutableStateOf<String?>(null) }
|
||||||
var output by remember { mutableStateOf(listOf(runtime.startupBanner())) }
|
var output by remember { mutableStateOf(listOf(runtime.startupBanner())) }
|
||||||
var hintIndex by remember { mutableStateOf(0) }
|
var hintIndex by remember { mutableStateOf(0) }
|
||||||
var suggestionsExpanded by remember { mutableStateOf(false) }
|
var activeExerciseDetail by remember { mutableStateOf<ExerciseDetailPanel?>(null) }
|
||||||
|
var visibleHint by remember { mutableStateOf<String?>(null) }
|
||||||
var completedLevels by remember { mutableStateOf(setOf<String>()) }
|
var completedLevels by remember { mutableStateOf(setOf<String>()) }
|
||||||
var commandHistory by remember { mutableStateOf(listOf<String>()) }
|
var commandHistory by remember { mutableStateOf(listOf<String>()) }
|
||||||
var historyIndex by remember { mutableStateOf(-1) }
|
var historyIndex by remember { mutableStateOf(-1) }
|
||||||
@@ -258,13 +263,26 @@ fun GitHugApp() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val recommendedWeights = recommendedPaneWeights(
|
||||||
|
level = currentLevel,
|
||||||
|
levelCount = levels.size,
|
||||||
|
outputLineCount = output.size,
|
||||||
|
screenHeightDp = screenHeightDp,
|
||||||
|
)
|
||||||
|
val workspaceHeight = recommendedWorkspaceHeight(
|
||||||
|
paneLayout = paneLayout,
|
||||||
|
recommendedWeights = recommendedWeights,
|
||||||
|
screenHeightDp = screenHeightDp,
|
||||||
|
)
|
||||||
|
|
||||||
fun resetCurrentLevel(message: String = "Level reset.") {
|
fun resetCurrentLevel(message: String = "Level reset.") {
|
||||||
repo = runtime.prepareLevel(currentLevel)
|
repo = runtime.prepareLevel(currentLevel)
|
||||||
clearCommandInput()
|
clearCommandInput()
|
||||||
suppressedImeEcho = null
|
suppressedImeEcho = null
|
||||||
output = listOf(message)
|
output = listOf(message)
|
||||||
hintIndex = 0
|
hintIndex = 0
|
||||||
suggestionsExpanded = false
|
activeExerciseDetail = null
|
||||||
|
visibleHint = null
|
||||||
historyIndex = -1
|
historyIndex = -1
|
||||||
historyDraft = ""
|
historyDraft = ""
|
||||||
applyRecommendedPaneWeights(persist = false)
|
applyRecommendedPaneWeights(persist = false)
|
||||||
@@ -277,7 +295,8 @@ fun GitHugApp() {
|
|||||||
clearCommandInput()
|
clearCommandInput()
|
||||||
suppressedImeEcho = null
|
suppressedImeEcho = null
|
||||||
hintIndex = 0
|
hintIndex = 0
|
||||||
suggestionsExpanded = false
|
activeExerciseDetail = null
|
||||||
|
visibleHint = null
|
||||||
historyIndex = -1
|
historyIndex = -1
|
||||||
historyDraft = ""
|
historyDraft = ""
|
||||||
paneLayout = paneLayout.copy(
|
paneLayout = paneLayout.copy(
|
||||||
@@ -434,11 +453,15 @@ fun GitHugApp() {
|
|||||||
exerciseContent = {
|
exerciseContent = {
|
||||||
ExercisePane(
|
ExercisePane(
|
||||||
level = currentLevel,
|
level = currentLevel,
|
||||||
suggestionsExpanded = suggestionsExpanded,
|
visibleHint = if (activeExerciseDetail == ExerciseDetailPanel.HINT) visibleHint else null,
|
||||||
onToggleSuggestions = { suggestionsExpanded = !suggestionsExpanded },
|
suggestionsExpanded = activeExerciseDetail == ExerciseDetailPanel.SUGGESTIONS,
|
||||||
|
onToggleSuggestions = {
|
||||||
|
activeExerciseDetail = if (activeExerciseDetail == ExerciseDetailPanel.SUGGESTIONS) null else ExerciseDetailPanel.SUGGESTIONS
|
||||||
|
},
|
||||||
onHint = {
|
onHint = {
|
||||||
val hint = currentLevel.hints.getOrNull(hintIndex) ?: "No more hints for this level."
|
val hint = currentLevel.hints.getOrNull(hintIndex) ?: "No more hints for this level."
|
||||||
output = output + "hint> $hint"
|
visibleHint = hint
|
||||||
|
activeExerciseDetail = ExerciseDetailPanel.HINT
|
||||||
hintIndex = (hintIndex + 1).coerceAtMost(currentLevel.hints.size)
|
hintIndex = (hintIndex + 1).coerceAtMost(currentLevel.hints.size)
|
||||||
},
|
},
|
||||||
onReset = { resetCurrentLevel() },
|
onReset = { resetCurrentLevel() },
|
||||||
@@ -890,6 +913,7 @@ private fun VisualPane(repo: RepoState) {
|
|||||||
@Composable
|
@Composable
|
||||||
private fun ExercisePane(
|
private fun ExercisePane(
|
||||||
level: Level,
|
level: Level,
|
||||||
|
visibleHint: String?,
|
||||||
suggestionsExpanded: Boolean,
|
suggestionsExpanded: Boolean,
|
||||||
onToggleSuggestions: () -> Unit,
|
onToggleSuggestions: () -> Unit,
|
||||||
onHint: () -> Unit,
|
onHint: () -> Unit,
|
||||||
@@ -930,6 +954,10 @@ private fun ExercisePane(
|
|||||||
Text(suggestion, color = TextSecondary, fontFamily = FontFamily.Monospace)
|
Text(suggestion, color = TextSecondary, fontFamily = FontFamily.Monospace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (visibleHint != null) {
|
||||||
|
Text("Hint", color = TextPrimary, fontWeight = FontWeight.Bold)
|
||||||
|
Text(visibleHint, color = TextSecondary)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -983,7 +1011,9 @@ private fun TerminalPane(
|
|||||||
val horizontalScroll = rememberScrollState()
|
val horizontalScroll = rememberScrollState()
|
||||||
val outputVerticalScroll = rememberScrollState()
|
val outputVerticalScroll = rememberScrollState()
|
||||||
val terminalMinWidth = 80.dp * 7.2f
|
val terminalMinWidth = 80.dp * 7.2f
|
||||||
val maxOutputHeight = configuration.screenHeightDp.dp * 0.7f
|
val terminalPaneMaxHeight = configuration.screenHeightDp.dp * 0.7f
|
||||||
|
val reservedControlsHeight = 86.dp
|
||||||
|
val maxOutputHeight = (terminalPaneMaxHeight - reservedControlsHeight).coerceAtLeast(120.dp)
|
||||||
val outputLineHeight = 20.dp
|
val outputLineHeight = 20.dp
|
||||||
val desiredOutputHeight = (output.size.coerceAtLeast(6) * outputLineHeight.value).dp.coerceAtMost(maxOutputHeight)
|
val desiredOutputHeight = (output.size.coerceAtLeast(6) * outputLineHeight.value).dp.coerceAtMost(maxOutputHeight)
|
||||||
|
|
||||||
@@ -1187,6 +1217,22 @@ private fun recommendedPaneWeights(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun recommendedWorkspaceHeight(
|
||||||
|
paneLayout: PaneLayout,
|
||||||
|
recommendedWeights: Map<PaneId, Float>,
|
||||||
|
screenHeightDp: Int,
|
||||||
|
): androidx.compose.ui.unit.Dp {
|
||||||
|
val screenHeight = screenHeightDp.coerceAtLeast(560)
|
||||||
|
val dividerHeight = 18 * (paneLayout.order.size - 1)
|
||||||
|
val collapsedPaneHeight = 44 * paneLayout.collapsed.size
|
||||||
|
val expandedHeight = paneLayout.order
|
||||||
|
.filterNot { it in paneLayout.collapsed }
|
||||||
|
.sumOf { pane ->
|
||||||
|
(recommendedWeights[pane] ?: 1f * screenHeight).toInt()
|
||||||
|
}
|
||||||
|
return (expandedHeight + dividerHeight + collapsedPaneHeight).coerceAtLeast(screenHeight / 2).dp
|
||||||
|
}
|
||||||
|
|
||||||
private fun commonPrefix(values: List<String>): String {
|
private fun commonPrefix(values: List<String>): String {
|
||||||
if (values.isEmpty()) return ""
|
if (values.isEmpty()) return ""
|
||||||
var prefix = values.first()
|
var prefix = values.first()
|
||||||
|
|||||||
Reference in New Issue
Block a user