Expand manpage and terminal output sizing
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 = 159
|
versionCode = 160
|
||||||
versionName = "0.1.158"
|
versionName = "0.1.159"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
|
|||||||
@@ -186,7 +186,10 @@ fun GitHugApp() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun applyRecommendedPaneWeights(persist: Boolean = true) {
|
fun applyRecommendedPaneWeights(
|
||||||
|
persist: Boolean = true,
|
||||||
|
outputLineCount: Int = terminalOutputLineCount(output),
|
||||||
|
) {
|
||||||
updatePaneLayout(
|
updatePaneLayout(
|
||||||
transform = { layout ->
|
transform = { layout ->
|
||||||
layout.copy(
|
layout.copy(
|
||||||
@@ -194,7 +197,7 @@ fun GitHugApp() {
|
|||||||
heights = recommendedPaneHeights(
|
heights = recommendedPaneHeights(
|
||||||
level = currentLevel,
|
level = currentLevel,
|
||||||
levelCount = levels.size,
|
levelCount = levels.size,
|
||||||
outputLineCount = output.size,
|
outputLineCount = outputLineCount,
|
||||||
screenHeightDp = screenHeightDp,
|
screenHeightDp = screenHeightDp,
|
||||||
suggestionsVisible = activeExerciseDetail == ExerciseDetailPanel.SUGGESTIONS,
|
suggestionsVisible = activeExerciseDetail == ExerciseDetailPanel.SUGGESTIONS,
|
||||||
visibleHint = visibleHint,
|
visibleHint = visibleHint,
|
||||||
@@ -223,7 +226,7 @@ fun GitHugApp() {
|
|||||||
editorState = null
|
editorState = null
|
||||||
gitMessageEditorState = null
|
gitMessageEditorState = null
|
||||||
manPageState = null
|
manPageState = null
|
||||||
applyRecommendedPaneWeights(persist = false)
|
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(listOf(message)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadLevel(
|
fun loadLevel(
|
||||||
@@ -307,7 +310,9 @@ fun GitHugApp() {
|
|||||||
|
|
||||||
val replacement = if (matches.size == 1) matches.first() else commonPrefix(matches)
|
val replacement = if (matches.size == 1) matches.first() else commonPrefix(matches)
|
||||||
if (replacement == token && matches.size > 1) {
|
if (replacement == token && matches.size > 1) {
|
||||||
output = output + "completion> ${matches.joinToString(" ")}"
|
val newOutput = output + "completion> ${matches.joinToString(" ")}"
|
||||||
|
output = newOutput
|
||||||
|
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(newOutput))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,15 +358,17 @@ fun GitHugApp() {
|
|||||||
AppLog.d("GitHugApp", "All levels completed")
|
AppLog.d("GitHugApp", "All levels completed")
|
||||||
scope.launch { persistProgress(updatedCompletedLevels, levels.lastOrNull()?.id) }
|
scope.launch { persistProgress(updatedCompletedLevels, levels.lastOrNull()?.id) }
|
||||||
repo = newRepo
|
repo = newRepo
|
||||||
output = newOutput + listOf("🏁 All Githug levels completed.")
|
val completedOutput = newOutput + listOf("🏁 All Githug levels completed.")
|
||||||
|
output = completedOutput
|
||||||
clearCommandInput()
|
clearCommandInput()
|
||||||
suppressedImeEcho = null
|
suppressedImeEcho = null
|
||||||
|
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(completedOutput))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AppLog.d("GitHugApp", "Staying on level=${levelForResult.id}")
|
AppLog.d("GitHugApp", "Staying on level=${levelForResult.id}")
|
||||||
repo = newRepo
|
repo = newRepo
|
||||||
output = newOutput
|
output = newOutput
|
||||||
applyRecommendedPaneWeights(persist = false)
|
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(newOutput))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -372,7 +379,7 @@ fun GitHugApp() {
|
|||||||
} else {
|
} else {
|
||||||
runtime.readEditorFile(currentLevel, repo, path)
|
runtime.readEditorFile(currentLevel, repo, path)
|
||||||
}
|
}
|
||||||
output = buildList {
|
val newOutput = buildList {
|
||||||
addAll(output)
|
addAll(output)
|
||||||
add("$ ${invocation.command}")
|
add("$ ${invocation.command}")
|
||||||
addAll(lines)
|
addAll(lines)
|
||||||
@@ -380,6 +387,7 @@ fun GitHugApp() {
|
|||||||
add("Opened ${invocation.editor} editor${if (path.isBlank()) "" else " for $path"}")
|
add("Opened ${invocation.editor} editor${if (path.isBlank()) "" else " for $path"}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
output = newOutput
|
||||||
if (lines.isEmpty()) {
|
if (lines.isEmpty()) {
|
||||||
editorState = TextEditorState(
|
editorState = TextEditorState(
|
||||||
editor = invocation.editor,
|
editor = invocation.editor,
|
||||||
@@ -389,18 +397,19 @@ fun GitHugApp() {
|
|||||||
saveAsPath = path,
|
saveAsPath = path,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
applyRecommendedPaneWeights(persist = false)
|
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(newOutput))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openManPage(invocation: GitHelpInvocation) {
|
fun openManPage(invocation: GitHelpInvocation) {
|
||||||
val content = runtime.gitManPage(currentLevel, repo, invocation.topic)
|
val content = runtime.gitManPage(currentLevel, repo, invocation.topic)
|
||||||
output = buildList {
|
val newOutput = buildList {
|
||||||
addAll(output)
|
addAll(output)
|
||||||
add("$ ${invocation.command}")
|
add("$ ${invocation.command}")
|
||||||
add("Opened git help viewer for ${invocation.topic}")
|
add("Opened git help viewer for ${invocation.topic}")
|
||||||
}
|
}
|
||||||
|
output = newOutput
|
||||||
manPageState = ManPageState(topic = invocation.topic, content = content)
|
manPageState = ManPageState(topic = invocation.topic, content = content)
|
||||||
applyRecommendedPaneWeights(persist = false)
|
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(newOutput))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openGitMessageEditor(invocation: GitEditorInvocation) {
|
fun openGitMessageEditor(invocation: GitEditorInvocation) {
|
||||||
@@ -410,16 +419,17 @@ fun GitHugApp() {
|
|||||||
GitEditorCommandKind.PATCH_HUNK -> "Opened Git patch editor"
|
GitEditorCommandKind.PATCH_HUNK -> "Opened Git patch editor"
|
||||||
else -> "Opened Git message editor"
|
else -> "Opened Git message editor"
|
||||||
}
|
}
|
||||||
output = buildList {
|
val newOutput = buildList {
|
||||||
addAll(output)
|
addAll(output)
|
||||||
add("$ ${invocation.command}")
|
add("$ ${invocation.command}")
|
||||||
add(openedMessage)
|
add(openedMessage)
|
||||||
}
|
}
|
||||||
|
output = newOutput
|
||||||
gitMessageEditorState = GitMessageEditorState(
|
gitMessageEditorState = GitMessageEditorState(
|
||||||
invocation = invocation.copy(initialContent = initialContent),
|
invocation = invocation.copy(initialContent = initialContent),
|
||||||
content = initialContent,
|
content = initialContent,
|
||||||
)
|
)
|
||||||
applyRecommendedPaneWeights(persist = false)
|
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(newOutput))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveEditor() {
|
fun saveEditor() {
|
||||||
@@ -490,7 +500,9 @@ fun GitHugApp() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun showCommandHelp() {
|
fun showCommandHelp() {
|
||||||
output = output + runtime.commandReferenceLines()
|
val newOutput = output + runtime.commandReferenceLines()
|
||||||
|
output = newOutput
|
||||||
|
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(newOutput))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun registerHeaderTap() {
|
fun registerHeaderTap() {
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ import androidx.compose.ui.unit.IntSize
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import androidx.compose.ui.window.DialogProperties
|
||||||
|
|
||||||
data class ManPageState(
|
data class ManPageState(
|
||||||
val topic: String,
|
val topic: String,
|
||||||
@@ -131,7 +132,10 @@ fun ManPageDialog(
|
|||||||
horizontalScrollState.animateScrollTo(horizontalTarget)
|
horizontalScrollState.animateScrollTo(horizontalTarget)
|
||||||
}
|
}
|
||||||
|
|
||||||
Dialog(onDismissRequest = onClose) {
|
Dialog(
|
||||||
|
onDismissRequest = onClose,
|
||||||
|
properties = DialogProperties(usePlatformDefaultWidth = false),
|
||||||
|
) {
|
||||||
Surface(
|
Surface(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ fun recommendedPaneHeights(
|
|||||||
val suggestionsLines = if (suggestionsVisible) level.commandSuggestions.size + 1 else 0
|
val suggestionsLines = if (suggestionsVisible) level.commandSuggestions.size + 1 else 0
|
||||||
val hintLines = visibleHint?.let { (it.length / 42).coerceAtLeast(1) + 1 } ?: 0
|
val hintLines = visibleHint?.let { (it.length / 42).coerceAtLeast(1) + 1 } ?: 0
|
||||||
val exerciseHeight = (120 + descriptionLines * 24 + suggestionsLines * 22 + hintLines * 22).coerceAtLeast(180)
|
val exerciseHeight = (120 + descriptionLines * 24 + suggestionsLines * 22 + hintLines * 22).coerceAtLeast(180)
|
||||||
val terminalHeight = (170 + outputLineCount.coerceAtLeast(1) * 20).coerceAtMost((screenHeight * 0.7f).toInt())
|
val terminalHeight = (170 + outputLineCount.coerceAtLeast(1) * 24).coerceAtMost((screenHeight * 0.8f).toInt() + 140)
|
||||||
val visualHeight = (screenHeight * 0.24f).toInt().coerceAtLeast(170)
|
val visualHeight = (screenHeight * 0.24f).toInt().coerceAtLeast(170)
|
||||||
|
|
||||||
return mapOf(
|
return mapOf(
|
||||||
|
|||||||
@@ -55,6 +55,10 @@ import androidx.compose.ui.text.input.TextFieldValue
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
|
||||||
|
fun terminalOutputDisplayLines(output: List<String>): List<String> = output.flatMap { line -> line.lines() }
|
||||||
|
|
||||||
|
fun terminalOutputLineCount(output: List<String>): Int = terminalOutputDisplayLines(output).size.coerceAtLeast(1)
|
||||||
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
@OptIn(ExperimentalFoundationApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun TerminalPane(
|
fun TerminalPane(
|
||||||
@@ -78,12 +82,11 @@ fun TerminalPane(
|
|||||||
val outputHorizontalScroll = rememberScrollState()
|
val outputHorizontalScroll = rememberScrollState()
|
||||||
val outputVerticalScroll = rememberScrollState()
|
val outputVerticalScroll = rememberScrollState()
|
||||||
val terminalMinWidth = 80.dp * 7.2f
|
val terminalMinWidth = 80.dp * 7.2f
|
||||||
val terminalPaneMaxHeight = configuration.screenHeightDp.dp * 0.7f
|
val displayOutput = remember(output) { terminalOutputDisplayLines(output) }
|
||||||
val reservedControlsHeight = 86.dp
|
val maxOutputHeight = (configuration.screenHeightDp.dp * 0.8f).coerceAtLeast(120.dp)
|
||||||
val maxOutputHeight = (terminalPaneMaxHeight - reservedControlsHeight).coerceAtLeast(120.dp)
|
val outputLineHeight = 24.dp
|
||||||
val outputLineHeight = 20.dp
|
val hasOutput = displayOutput.isNotEmpty()
|
||||||
val hasOutput = output.isNotEmpty()
|
val desiredOutputHeight = (16 + displayOutput.size.coerceAtLeast(1) * outputLineHeight.value)
|
||||||
val desiredOutputHeight = (output.size.coerceAtLeast(1) * outputLineHeight.value)
|
|
||||||
.dp
|
.dp
|
||||||
.coerceAtLeast(48.dp)
|
.coerceAtLeast(48.dp)
|
||||||
.coerceAtMost(maxOutputHeight)
|
.coerceAtMost(maxOutputHeight)
|
||||||
@@ -93,7 +96,7 @@ fun TerminalPane(
|
|||||||
focusRequester.requestFocus()
|
focusRequester.requestFocus()
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(output.size) {
|
LaunchedEffect(displayOutput.size) {
|
||||||
outputVerticalScroll.animateScrollTo(outputVerticalScroll.maxValue)
|
outputVerticalScroll.animateScrollTo(outputVerticalScroll.maxValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,7 +143,7 @@ fun TerminalPane(
|
|||||||
modifier = Modifier.widthIn(min = terminalMinWidth),
|
modifier = Modifier.widthIn(min = terminalMinWidth),
|
||||||
verticalArrangement = Arrangement.spacedBy(4.dp),
|
verticalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
) {
|
) {
|
||||||
output.forEach { line ->
|
displayOutput.forEach { line ->
|
||||||
Text(
|
Text(
|
||||||
text = line,
|
text = line,
|
||||||
color = if (line.startsWith("✔") || line.startsWith("🏁")) Success else TextSecondary,
|
color = if (line.startsWith("✔") || line.startsWith("🏁")) Success else TextSecondary,
|
||||||
|
|||||||
Reference in New Issue
Block a user