Auto-commit after successful build: update app gameplay/UI, improve build setup
Changed files:\napp/build.gradle.kts app/src/main/java/solutions/tretter/githugandroid/GameProgressStore.kt app/src/main/java/solutions/tretter/githugandroid/GitHugApp.kt
This commit is contained in:
@@ -11,8 +11,8 @@ android {
|
||||
applicationId = "solutions.tretter.githugandroid"
|
||||
minSdk = 26
|
||||
targetSdk = 34
|
||||
versionCode = 64
|
||||
versionName = "0.1.63"
|
||||
versionCode = 67
|
||||
versionName = "0.1.66"
|
||||
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
package solutions.tretter.githugandroid
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.emptyPreferences
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStoreFile
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.catch
|
||||
import kotlinx.coroutines.flow.map
|
||||
import java.io.IOException
|
||||
|
||||
class GameProgressStore(private val context: Context) {
|
||||
private val dataStore = PreferenceDataStoreFactory.create(
|
||||
produceFile = { context.preferencesDataStoreFile("game_progress_preferences") }
|
||||
)
|
||||
|
||||
private val completedLevelsKey = stringPreferencesKey("completed_levels")
|
||||
|
||||
val completedLevelsFlow: Flow<Set<String>> = dataStore.data
|
||||
.catch { error ->
|
||||
if (error is IOException) emit(emptyPreferences()) else throw error
|
||||
}
|
||||
.map { preferences ->
|
||||
preferences[completedLevelsKey]
|
||||
?.split(',')
|
||||
?.map { it.trim() }
|
||||
?.filter { it.isNotEmpty() }
|
||||
?.toSet()
|
||||
?: emptySet()
|
||||
}
|
||||
|
||||
suspend fun saveCompletedLevels(completedLevels: Set<String>) {
|
||||
dataStore.edit { preferences ->
|
||||
preferences[completedLevelsKey] = completedLevels.joinToString(",")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,9 @@ fun GitHugApp() {
|
||||
val levels = remember { sampleLevels() }
|
||||
val runtime = remember(context) { GitRepositoryRuntime(context.applicationContext) }
|
||||
val paneLayoutStore = remember(context) { PaneLayoutStore(context.applicationContext) }
|
||||
val gameProgressStore = remember(context) { GameProgressStore(context.applicationContext) }
|
||||
val persistedPaneLayout by paneLayoutStore.layoutFlow.collectAsState(initial = defaultPaneLayout())
|
||||
val persistedCompletedLevels by gameProgressStore.completedLevelsFlow.collectAsState(initial = emptySet())
|
||||
val scope = rememberCoroutineScope()
|
||||
val screenScrollState = rememberScrollState()
|
||||
val screenHeightDp = configuration.screenHeightDp
|
||||
@@ -57,6 +59,7 @@ fun GitHugApp() {
|
||||
var commandHistory by remember { mutableStateOf(listOf<String>()) }
|
||||
var historyIndex by remember { mutableStateOf(-1) }
|
||||
var historyDraft by remember { mutableStateOf("") }
|
||||
var hasRestoredProgress by remember { mutableStateOf(false) }
|
||||
val currentLevel = levels[currentLevelIndex]
|
||||
|
||||
LaunchedEffect(persistedPaneLayout) {
|
||||
@@ -78,6 +81,45 @@ fun GitHugApp() {
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(persistedCompletedLevels) {
|
||||
completedLevels = persistedCompletedLevels
|
||||
if (!hasRestoredProgress) {
|
||||
hasRestoredProgress = true
|
||||
val firstIncompleteIndex = levels.indexOfFirst { it.id !in persistedCompletedLevels }
|
||||
val resumeIndex = firstIncompleteIndex.takeIf { it >= 0 } ?: levels.lastIndex
|
||||
currentLevelIndex = resumeIndex
|
||||
repo = runtime.prepareLevel(levels[resumeIndex])
|
||||
output = listOf(
|
||||
if (persistedCompletedLevels.size == levels.size) {
|
||||
"🏁 All Githug levels completed."
|
||||
} else if (persistedCompletedLevels.isEmpty()) {
|
||||
runtime.startupBanner()
|
||||
} else {
|
||||
"Resumed at level: ${levels[resumeIndex].title}"
|
||||
}
|
||||
)
|
||||
commandInput = TextFieldValue(text = "", selection = TextRange.Zero)
|
||||
suppressedImeEcho = null
|
||||
hintIndex = 0
|
||||
activeExerciseDetail = null
|
||||
visibleHint = null
|
||||
historyIndex = -1
|
||||
historyDraft = ""
|
||||
paneLayout = paneLayout.copy(
|
||||
weights = paneLayout.weights + recommendedPaneWeights(
|
||||
heights = recommendedPaneHeights(
|
||||
level = levels[resumeIndex],
|
||||
levelCount = levels.size,
|
||||
outputLineCount = 1,
|
||||
screenHeightDp = screenHeightDp,
|
||||
suggestionsVisible = false,
|
||||
visibleHint = null,
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun applyRecommendedPaneWeights(persist: Boolean = true) {
|
||||
updatePaneLayout(
|
||||
transform = { layout ->
|
||||
@@ -230,10 +272,12 @@ fun GitHugApp() {
|
||||
}
|
||||
}
|
||||
if (solvedAfterCommand && !wasAlreadyCompleted) {
|
||||
completedLevels = completedLevels + currentLevel.id
|
||||
val hasNextLevel = currentLevelIndex < levels.lastIndex
|
||||
if (hasNextLevel) {
|
||||
loadLevel(currentLevelIndex + 1)
|
||||
val updatedCompletedLevels = completedLevels + currentLevel.id
|
||||
completedLevels = updatedCompletedLevels
|
||||
scope.launch { gameProgressStore.saveCompletedLevels(updatedCompletedLevels) }
|
||||
val nextLevelIndex = levels.indexOfFirst { it.id !in updatedCompletedLevels }
|
||||
if (nextLevelIndex >= 0) {
|
||||
loadLevel(nextLevelIndex)
|
||||
} else {
|
||||
repo = newRepo
|
||||
output = listOf("🏁 All Githug levels completed.")
|
||||
|
||||
Reference in New Issue
Block a user