From 5da6bf94345a0e4a0eefd60c7a6b563522a018fe Mon Sep 17 00:00:00 2001 From: SHIYI <3401187804@qq.com> Date: Sun, 9 Mar 2025 17:35:43 +0800 Subject: [PATCH 1/2] repair code --- .github/workflows/main.yml | 2 +- app/build.gradle.kts | 4 +- app/proguard-rules.pro | 4 +- .../com/example/unscramble/MainActivity.kt | 3 +- .../com/example/unscramble/ui/GameScreen.kt | 56 ++++----- .../com/example/unscramble/ui/GameUiState.kt | 22 +--- .../example/unscramble/ui/GameViewModel.kt | 107 +++++------------- .../com/example/unscramble/ui/theme/Theme.kt | 16 +++ 8 files changed, 83 insertions(+), 131 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 379df0a..9309143 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -25,5 +25,5 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v3 - - name: Build project and run local and device tests + - name: Build project run: ./gradlew :app:assembleDebug diff --git a/app/build.gradle.kts b/app/build.gradle.kts index cd22dca..df95f35 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -72,10 +72,8 @@ dependencies { implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.core:core-ktx:1.15.0") implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.8.7") - implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7") + debugImplementation("androidx.compose.ui:ui-test-manifest") debugImplementation("androidx.compose.ui:ui-tooling") - - testImplementation("junit:junit:4.13.2") } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 481bb43..2f9dc5a 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -1,6 +1,6 @@ # Add project specific ProGuard rules here. # You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. +# proguardFiles setting in build.gradle.kts. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html @@ -18,4 +18,4 @@ # If you keep the line number information, uncomment this to # hide the original source file name. -#-renamesourcefileattribute SourceFile \ No newline at end of file +#-renamesourcefileattribute SourceFile diff --git a/app/src/main/java/com/example/unscramble/MainActivity.kt b/app/src/main/java/com/example/unscramble/MainActivity.kt index 555e5de..b932acd 100644 --- a/app/src/main/java/com/example/unscramble/MainActivity.kt +++ b/app/src/main/java/com/example/unscramble/MainActivity.kt @@ -24,6 +24,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.Surface import androidx.compose.ui.Modifier import com.example.unscramble.ui.GameScreen +import com.example.unscramble.ui.GameViewModel import com.example.unscramble.ui.theme.UnscrambleTheme class MainActivity : ComponentActivity() { @@ -35,7 +36,7 @@ class MainActivity : ComponentActivity() { Surface( modifier = Modifier.fillMaxSize(), ) { - GameScreen() + GameScreen(GameViewModel) } } } diff --git a/app/src/main/java/com/example/unscramble/ui/GameScreen.kt b/app/src/main/java/com/example/unscramble/ui/GameScreen.kt index 215e6c3..037df63 100644 --- a/app/src/main/java/com/example/unscramble/ui/GameScreen.kt +++ b/app/src/main/java/com/example/unscramble/ui/GameScreen.kt @@ -15,6 +15,7 @@ */ package com.example.unscramble.ui +import android.R.attr.label import android.app.Activity import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -41,8 +42,9 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable +import androidx.compose.runtime.Recomposer import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue +import androidx.compose.runtime.internal.isLiveLiteralsEnabled import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip @@ -54,15 +56,15 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import androidx.lifecycle.viewmodel.compose.viewModel import com.example.unscramble.R import com.example.unscramble.ui.theme.UnscrambleTheme @Composable -fun GameScreen(gameViewModel: GameViewModel = viewModel()) { - val gameUiState by gameViewModel.uiState.collectAsState() +fun GameScreen( + gameViewModel: GameViewModel +) { val mediumPadding = dimensionResource(R.dimen.padding_medium) - + val gameUiState = gameViewModel.uiState.collectAsState() Column( modifier = Modifier .statusBarsPadding() @@ -78,16 +80,16 @@ fun GameScreen(gameViewModel: GameViewModel = viewModel()) { style = typography.titleLarge, ) GameLayout( - onUserGuessChanged = { gameViewModel.updateUserGuess(it) }, - wordCount = gameUiState.currentWordCount, userGuess = gameViewModel.userGuess, + onUserGuessChanged = { gameViewModel.updateUserGuess(it) }, onKeyboardDone = { gameViewModel.checkUserGuess() }, - currentScrambledWord = gameUiState.currentScrambledWord, - isGuessWrong = gameUiState.isGuessedWordWrong, + currentScrambledWord = gameUiState.value.currentScrambledWord, modifier = Modifier .fillMaxWidth() .wrapContentHeight() - .padding(mediumPadding) + .padding(mediumPadding), + isGuessWrong = gameUiState.value.isGuessedWordWrong, + wordCount = gameUiState.value.currentWordCount, ) Column( modifier = Modifier @@ -116,16 +118,15 @@ fun GameScreen(gameViewModel: GameViewModel = viewModel()) { fontSize = 16.sp ) } + if (gameUiState.value.isGameOver) { + FinalScoreDialog( + score = gameUiState.value.score, + onPlayAgain = { gameViewModel.resetGame() } + ) + } } - GameStatus(score = gameUiState.score, modifier = Modifier.padding(20.dp)) - - if (gameUiState.isGameOver) { - FinalScoreDialog( - score = gameUiState.score, - onPlayAgain = { gameViewModel.resetGame() } - ) - } + GameStatus(score = gameUiState.value.score, modifier = Modifier.padding(20.dp)) } } @@ -139,22 +140,19 @@ fun GameStatus(score: Int, modifier: Modifier = Modifier) { style = typography.headlineMedium, modifier = Modifier.padding(8.dp) ) - } } @Composable fun GameLayout( - currentScrambledWord: String, wordCount: Int, - isGuessWrong: Boolean, + isGuessWrong : Boolean, userGuess: String, onUserGuessChanged: (String) -> Unit, onKeyboardDone: () -> Unit, - modifier: Modifier = Modifier -) { + currentScrambledWord: String, + modifier: Modifier = Modifier) { val mediumPadding = dimensionResource(R.dimen.padding_medium) - Card( modifier = modifier, elevation = CardDefaults.cardElevation(defaultElevation = 5.dp) @@ -170,13 +168,15 @@ fun GameLayout( .background(colorScheme.surfaceTint) .padding(horizontal = 10.dp, vertical = 4.dp) .align(alignment = Alignment.End), - text = stringResource(R.string.word_count, wordCount), + text = stringResource(R.string.word_count,wordCount ), style = typography.titleMedium, color = colorScheme.onPrimary ) Text( text = currentScrambledWord, - style = typography.displayMedium + style = typography.displayMedium, + fontSize = 45.sp, + modifier = Modifier.align(Alignment.CenterHorizontally) ) Text( text = stringResource(R.string.instructions), @@ -206,7 +206,7 @@ fun GameLayout( imeAction = ImeAction.Done ), keyboardActions = KeyboardActions( - onDone = { onKeyboardDone() } + onDone = { onKeyboardDone } ) ) } @@ -254,6 +254,6 @@ private fun FinalScoreDialog( @Composable fun GameScreenPreview() { UnscrambleTheme { - GameScreen() + GameScreen(GameViewModel) } } diff --git a/app/src/main/java/com/example/unscramble/ui/GameUiState.kt b/app/src/main/java/com/example/unscramble/ui/GameUiState.kt index 613399c..3e26284 100644 --- a/app/src/main/java/com/example/unscramble/ui/GameUiState.kt +++ b/app/src/main/java/com/example/unscramble/ui/GameUiState.kt @@ -1,27 +1,9 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ package com.example.unscramble.ui -/** - * Data class that represents the game UI state - */ data class GameUiState( val currentScrambledWord: String = "", - val currentWordCount: Int = 1, - val score: Int = 0, val isGuessedWordWrong: Boolean = false, + val score: Int = 0, + val currentWordCount: Int = 1, val isGameOver: Boolean = false ) diff --git a/app/src/main/java/com/example/unscramble/ui/GameViewModel.kt b/app/src/main/java/com/example/unscramble/ui/GameViewModel.kt index 7a6ca0e..d2093de 100644 --- a/app/src/main/java/com/example/unscramble/ui/GameViewModel.kt +++ b/app/src/main/java/com/example/unscramble/ui/GameViewModel.kt @@ -1,19 +1,3 @@ -/* - * Copyright (C) 2023 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package com.example.unscramble.ui import androidx.compose.runtime.getValue @@ -28,49 +12,45 @@ import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.update -/** - * ViewModel containing the app data and methods to process the data - */ -class GameViewModel : ViewModel() { - - // Game UI state +object GameViewModel : ViewModel() { + var userGuess by mutableStateOf("") private val _uiState = MutableStateFlow(GameUiState()) val uiState: StateFlow = _uiState.asStateFlow() - - var userGuess by mutableStateOf("") - private set - - // Set of words used in the game - private var usedWords: MutableSet = mutableSetOf() private lateinit var currentWord: String + private var usedWords: MutableSet = mutableSetOf() - init { - resetGame() + private fun pickRandomWordAndShuffle(): String { + // Continue picking up a new random word until you get one that hasn't been used before + currentWord = allWords.random() + if (usedWords.contains(currentWord)) { + return pickRandomWordAndShuffle() + } else { + usedWords.add(currentWord) + return shuffleCurrentWord(currentWord) + } + } + + private fun shuffleCurrentWord(word: String): String { + val tempWord = word.toCharArray() + // Scramble the word + tempWord.shuffle() + while (String(tempWord) == word) { + tempWord.shuffle() + } + return String(tempWord) } - /* - * Re-initializes the game data to restart the game. - */ fun resetGame() { usedWords.clear() _uiState.value = GameUiState(currentScrambledWord = pickRandomWordAndShuffle()) } - /* - * Update the user's guess - */ - fun updateUserGuess(guessedWord: String){ + fun updateUserGuess(guessedWord: String) { userGuess = guessedWord } - /* - * Checks if the user's guess is correct. - * Increases the score accordingly. - */ fun checkUserGuess() { if (userGuess.equals(currentWord, ignoreCase = true)) { - // User's guess is correct, increase the score - // and call updateGameState() to prepare the game for next round val updatedScore = _uiState.value.score.plus(SCORE_INCREASE) updateGameState(updatedScore) } else { @@ -82,23 +62,9 @@ class GameViewModel : ViewModel() { // Reset user guess updateUserGuess("") } - - /* - * Skip to next word - */ - fun skipWord() { - updateGameState(_uiState.value.score) - // Reset user guess - updateUserGuess("") - } - - /* - * Picks a new currentWord and currentScrambledWord and updates UiState according to - * current game state. - */ private fun updateGameState(updatedScore: Int) { if (usedWords.size == MAX_NO_OF_WORDS){ - //Last round in the game, update isGameOver to true, don't pick a new word + //Last round in the game _uiState.update { currentState -> currentState.copy( isGuessedWordWrong = false, @@ -119,24 +85,13 @@ class GameViewModel : ViewModel() { } } - private fun shuffleCurrentWord(word: String): String { - val tempWord = word.toCharArray() - // Scramble the word - tempWord.shuffle() - while (String(tempWord) == word) { - tempWord.shuffle() - } - return String(tempWord) + fun skipWord() { + updateGameState(_uiState.value.score) + // Reset user guess + updateUserGuess("") } - private fun pickRandomWordAndShuffle(): String { - // Continue picking up a new random word until you get one that hasn't been used before - currentWord = allWords.random() - return if (usedWords.contains(currentWord)) { - pickRandomWordAndShuffle() - } else { - usedWords.add(currentWord) - shuffleCurrentWord(currentWord) - } + init { + resetGame() } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/example/unscramble/ui/theme/Theme.kt b/app/src/main/java/com/example/unscramble/ui/theme/Theme.kt index 2abd759..5755bf9 100644 --- a/app/src/main/java/com/example/unscramble/ui/theme/Theme.kt +++ b/app/src/main/java/com/example/unscramble/ui/theme/Theme.kt @@ -16,6 +16,7 @@ package com.example.unscramble.ui.theme +import android.app.Activity import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme @@ -24,7 +25,11 @@ import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.SideEffect +import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalView +import androidx.core.view.WindowCompat private val LightColors = lightColorScheme( primary = md_theme_light_primary, @@ -108,6 +113,17 @@ fun UnscrambleTheme( else -> LightColors } + val view = LocalView.current + if (!view.isInEditMode) { + SideEffect { + val window = (view.context as Activity).window + window.statusBarColor = colorScheme.primary.toArgb() + WindowCompat + .getInsetsController(window, view) + .isAppearanceLightStatusBars = darkTheme + } + } + MaterialTheme( colorScheme = colorScheme, typography = Typography, From be4b40c1db72624ebd91d0b61d1ee62bf9195463 Mon Sep 17 00:00:00 2001 From: SHIYI <3401187804@qq.com> Date: Sun, 9 Mar 2025 17:37:48 +0800 Subject: [PATCH 2/2] repair import --- app/src/main/java/com/example/unscramble/ui/GameScreen.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/com/example/unscramble/ui/GameScreen.kt b/app/src/main/java/com/example/unscramble/ui/GameScreen.kt index 037df63..bb0c7f4 100644 --- a/app/src/main/java/com/example/unscramble/ui/GameScreen.kt +++ b/app/src/main/java/com/example/unscramble/ui/GameScreen.kt @@ -15,7 +15,6 @@ */ package com.example.unscramble.ui -import android.R.attr.label import android.app.Activity import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -42,9 +41,7 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.Recomposer import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.internal.isLiveLiteralsEnabled import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip