Make manual level selection responsive
This commit is contained in:
@@ -20,8 +20,8 @@ android {
|
||||
applicationId = "solutions.tretter.githugandroid"
|
||||
minSdk = 26
|
||||
targetSdk = 35
|
||||
versionCode = 175
|
||||
versionName = "0.1.174"
|
||||
versionCode = 176
|
||||
versionName = "0.1.175"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.compose.ui.test.junit4.createEmptyComposeRule
|
||||
import androidx.compose.ui.test.onNodeWithTag
|
||||
import androidx.compose.ui.test.performClick
|
||||
import androidx.compose.ui.test.performImeAction
|
||||
import androidx.compose.ui.test.performScrollTo
|
||||
import androidx.compose.ui.test.performTextClearance
|
||||
import androidx.compose.ui.test.performTextInput
|
||||
import androidx.test.core.app.ActivityScenario
|
||||
@@ -62,6 +63,21 @@ class GitRepositoryRuntimeInstrumentedTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun selectingLevelFromLevelsPaneUpdatesExerciseImmediately() {
|
||||
launchFreshApp().use {
|
||||
composeRule.onNodeWithTag("level-submodule")
|
||||
.performScrollTo()
|
||||
.performClick()
|
||||
|
||||
composeRule.waitUntil(timeoutMillis = 1_500) {
|
||||
composeRule.onAllNodes(hasText(submoduleLevel().title, substring = true))
|
||||
.fetchSemanticsNodes()
|
||||
.isNotEmpty()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun launchFreshApp(): ActivityScenario<MainActivity> {
|
||||
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||
File(context.filesDir, "githug-sandboxes").deleteRecursively()
|
||||
|
||||
@@ -34,8 +34,10 @@ import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.text.TextRange
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
@Composable
|
||||
fun GitHugApp() {
|
||||
@@ -73,6 +75,8 @@ fun GitHugApp() {
|
||||
var historyIndex by remember { mutableStateOf(-1) }
|
||||
var historyDraft by remember { mutableStateOf("") }
|
||||
var hasRestoredProgress by remember { mutableStateOf(false) }
|
||||
var isPreparingLevel by remember { mutableStateOf(false) }
|
||||
var levelLoadRequestId by remember { mutableStateOf(0) }
|
||||
var editorState by remember { mutableStateOf<TextEditorState?>(null) }
|
||||
var gitMessageEditorState by remember { mutableStateOf<GitMessageEditorState?>(null) }
|
||||
var manPageState by remember { mutableStateOf<ManPageState?>(null) }
|
||||
@@ -233,11 +237,14 @@ fun GitHugApp() {
|
||||
index: Int,
|
||||
message: List<String> = listOf("Loaded level: ${levels[index].title}"),
|
||||
keepSuppressedImeEcho: Boolean = false,
|
||||
prepareInBackground: Boolean = false,
|
||||
) {
|
||||
AppLog.d("GitHugApp", "Loading level index=$index id=${levels[index].id} title=${levels[index].title}")
|
||||
val level = levels[index]
|
||||
val requestId = levelLoadRequestId + 1
|
||||
levelLoadRequestId = requestId
|
||||
AppLog.d("GitHugApp", "Loading level index=$index id=${level.id} title=${level.title} background=$prepareInBackground")
|
||||
currentLevelIndex = index
|
||||
repo = runtime.prepareLevel(levels[index])
|
||||
output = message
|
||||
output = if (prepareInBackground) listOf("Preparing level: ${level.title}") else message
|
||||
clearCommandInput(recreateField = true)
|
||||
if (!keepSuppressedImeEcho) {
|
||||
suppressedImeEcho = null
|
||||
@@ -250,10 +257,29 @@ fun GitHugApp() {
|
||||
editorState = null
|
||||
gitMessageEditorState = null
|
||||
manPageState = null
|
||||
if (prepareInBackground) {
|
||||
isPreparingLevel = true
|
||||
repo = RepoState()
|
||||
scope.launch {
|
||||
val preparedRepo = withContext(Dispatchers.Default) {
|
||||
runtime.prepareLevel(level)
|
||||
}
|
||||
if (levelLoadRequestId == requestId) {
|
||||
AppLog.d("GitHugApp", "Prepared level index=$index id=${level.id}")
|
||||
repo = preparedRepo
|
||||
output = message
|
||||
isPreparingLevel = false
|
||||
clearCommandInput(recreateField = true)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
isPreparingLevel = false
|
||||
repo = runtime.prepareLevel(level)
|
||||
}
|
||||
paneLayout = paneLayout.copy(
|
||||
weights = paneLayout.weights + recommendedPaneWeights(
|
||||
heights = recommendedPaneHeights(
|
||||
level = levels[index],
|
||||
level = level,
|
||||
levelCount = levels.size,
|
||||
outputLineCount = 1,
|
||||
screenHeightDp = screenHeightDp,
|
||||
@@ -457,6 +483,12 @@ fun GitHugApp() {
|
||||
val submittedText = commandInput.text
|
||||
val raw = submittedText.trim()
|
||||
if (raw.isBlank()) return
|
||||
if (isPreparingLevel) {
|
||||
output = output + "Still preparing ${currentLevel.title}. Try again in a moment."
|
||||
clearCommandInput(recreateField = true)
|
||||
applyRecommendedPaneWeights(persist = false, outputLineCount = terminalOutputLineCount(output))
|
||||
return
|
||||
}
|
||||
val isInteractiveInput = repo.interactiveAddSession != null
|
||||
|
||||
showHelpOverlay = false
|
||||
@@ -560,7 +592,9 @@ fun GitHugApp() {
|
||||
})
|
||||
},
|
||||
levelsContent = {
|
||||
LevelsPane(levels, currentLevelIndex, completedLevels) { index -> loadLevel(index) }
|
||||
LevelsPane(levels, currentLevelIndex, completedLevels) { index ->
|
||||
loadLevel(index, prepareInBackground = true)
|
||||
}
|
||||
},
|
||||
visualContent = { VisualPane(repo) },
|
||||
exerciseContent = {
|
||||
|
||||
Reference in New Issue
Block a user