diff --git a/.idea/androidTestResultsUserPreferences.xml b/.idea/androidTestResultsUserPreferences.xml
index 0ad17ea..058a49f 100644
--- a/.idea/androidTestResultsUserPreferences.xml
+++ b/.idea/androidTestResultsUserPreferences.xml
@@ -543,6 +543,19 @@
+
+
+
+
+
+
+
@@ -595,6 +608,19 @@
+
+
+
+
+
+
+
@@ -636,6 +662,19 @@
+
+
+
+
+
+
+
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index 0fc3113..69e8615 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 0ad17cb..773fe0f 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,7 +1,6 @@
-
-
+
diff --git a/app/.gitignore b/app/.gitignore
index 42afabf..c9bc8fa 100644
--- a/app/.gitignore
+++ b/app/.gitignore
@@ -1 +1,2 @@
-/build
\ No newline at end of file
+/build
+../.idea/androidTestResultsUserPreferences.xml
\ No newline at end of file
diff --git a/app/src/androidTest/java/com/marcopla/flashcards/data/FlashCardRepositoryTest.kt b/app/src/androidTest/java/com/marcopla/flashcards/data/FlashCardRepositoryTest.kt
index fd48328..a53bd13 100644
--- a/app/src/androidTest/java/com/marcopla/flashcards/data/FlashCardRepositoryTest.kt
+++ b/app/src/androidTest/java/com/marcopla/flashcards/data/FlashCardRepositoryTest.kt
@@ -121,7 +121,7 @@ class FlashCardRepositoryTest {
}
@Test
- fun whenAddingResult_thenIsSaved() {
+ fun whenAddingResult_thenIsSaved() = runTest {
val quizResult = QuizResult(
FlashCard("Engels", "English"),
"Dutch",
@@ -130,7 +130,7 @@ class FlashCardRepositoryTest {
repository.addResult(quizResult)
- val currentResults = repository.getCurrentResults()
+ val currentResults = repository.getCurrentResults().first()
assertEquals(listOf(quizResult), currentResults)
}
}
diff --git a/app/src/androidTest/java/com/marcopla/flashcards/presentation/add/AddScreenRobot.kt b/app/src/androidTest/java/com/marcopla/flashcards/presentation/add/AddScreenRobot.kt
index 0c63246..7a729ce 100644
--- a/app/src/androidTest/java/com/marcopla/flashcards/presentation/add/AddScreenRobot.kt
+++ b/app/src/androidTest/java/com/marcopla/flashcards/presentation/add/AddScreenRobot.kt
@@ -1,13 +1,18 @@
package com.marcopla.flashcards.presentation.add
import androidx.activity.ComponentActivity
-import androidx.compose.ui.test.*
+import androidx.compose.ui.test.assertIsDisplayed
+import androidx.compose.ui.test.assertIsFocused
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
+import androidx.compose.ui.test.onNodeWithContentDescription
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.performTextInput
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.marcopla.flashcards.R
import com.marcopla.flashcards.data.repository.FlashCardRepository
import com.marcopla.flashcards.domain.usecase.AddUseCase
-import com.marcopla.flashcards.presentation.screen.add.AddScreen
+import com.marcopla.flashcards.presentation.screen.add.AddRoute
import com.marcopla.flashcards.presentation.screen.add.AddViewModel
import com.marcopla.testing_shared.TestFlashCardRepository
@@ -19,9 +24,8 @@ fun launchAddScreen(
repository: FlashCardRepository = TestFlashCardRepository(),
block: AddScreenRobot.() -> Unit
): AddScreenRobot {
- composeRule.setContent {
- AddScreen(viewModel = AddViewModel(AddUseCase(repository)))
- }
+ val viewModel = AddViewModel(AddUseCase(repository))
+ composeRule.setContent { AddRoute(viewModel = viewModel) }
return AddScreenRobot(composeRule).apply(block)
}
diff --git a/app/src/androidTest/java/com/marcopla/flashcards/presentation/carousel/CarouselRobot.kt b/app/src/androidTest/java/com/marcopla/flashcards/presentation/carousel/CarouselRobot.kt
index e3c6a42..e086c37 100644
--- a/app/src/androidTest/java/com/marcopla/flashcards/presentation/carousel/CarouselRobot.kt
+++ b/app/src/androidTest/java/com/marcopla/flashcards/presentation/carousel/CarouselRobot.kt
@@ -1,15 +1,19 @@
package com.marcopla.flashcards.presentation.carousel
import androidx.activity.ComponentActivity
-import androidx.compose.ui.test.*
+import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
+import androidx.compose.ui.test.onNodeWithContentDescription
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.performTextInput
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.marcopla.flashcards.R
import com.marcopla.flashcards.data.model.FlashCard
import com.marcopla.flashcards.data.repository.FlashCardRepositoryImpl
import com.marcopla.flashcards.domain.usecase.LoadUseCase
import com.marcopla.flashcards.domain.usecase.SubmitQuizUseCase
-import com.marcopla.flashcards.presentation.screen.carousel.CarouselScreen
+import com.marcopla.flashcards.presentation.screen.carousel.CarouselRoute
import com.marcopla.flashcards.presentation.screen.carousel.CarouselViewModel
import com.marcopla.testing_shared.FakeFlashCardDao
@@ -21,15 +25,12 @@ fun launchCarouselScreen(
flashCards: List,
block: CarouselScreenRobot.() -> Unit
): CarouselScreenRobot {
- composeRule.setContent {
- val repository = FlashCardRepositoryImpl(FakeFlashCardDao(flashCards))
- CarouselScreen(
- viewModel = CarouselViewModel(
- LoadUseCase(repository),
- SubmitQuizUseCase(repository)
- )
- ) {}
- }
+ val repository = FlashCardRepositoryImpl(FakeFlashCardDao(flashCards))
+ val viewModel = CarouselViewModel(
+ LoadUseCase(repository),
+ SubmitQuizUseCase(repository)
+ )
+ composeRule.setContent { CarouselRoute(viewModel) {} }
return CarouselScreenRobot(composeRule).apply(block)
}
diff --git a/app/src/androidTest/java/com/marcopla/flashcards/presentation/edit/EditScreenRobot.kt b/app/src/androidTest/java/com/marcopla/flashcards/presentation/edit/EditScreenRobot.kt
index e582798..ef5c5d6 100644
--- a/app/src/androidTest/java/com/marcopla/flashcards/presentation/edit/EditScreenRobot.kt
+++ b/app/src/androidTest/java/com/marcopla/flashcards/presentation/edit/EditScreenRobot.kt
@@ -1,8 +1,12 @@
package com.marcopla.flashcards.presentation.edit
import androidx.activity.ComponentActivity
-import androidx.compose.ui.test.*
+import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
+import androidx.compose.ui.test.onNodeWithContentDescription
+import androidx.compose.ui.test.onNodeWithText
+import androidx.compose.ui.test.performClick
+import androidx.compose.ui.test.performTextInput
import androidx.lifecycle.SavedStateHandle
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.marcopla.flashcards.R
@@ -13,7 +17,7 @@ import com.marcopla.flashcards.domain.usecase.DeleteUseCase
import com.marcopla.flashcards.domain.usecase.EditUseCase
import com.marcopla.flashcards.domain.usecase.LoadUseCase
import com.marcopla.flashcards.presentation.navigation.FLASH_CARD_ID_ARG_KEY
-import com.marcopla.flashcards.presentation.screen.edit.EditScreen
+import com.marcopla.flashcards.presentation.screen.edit.EditRoute
import com.marcopla.flashcards.presentation.screen.edit.EditViewModel
import com.marcopla.testing_shared.FakeFlashCardDao
import com.marcopla.testing_shared.TestFlashCardRepository
@@ -27,19 +31,16 @@ fun launchEditScreenFor(
flashCardRepository: FlashCardRepository = TestFlashCardRepository(),
block: EditScreenRobot.() -> Unit
): EditScreenRobot {
+ val viewModel = EditViewModel(
+ SavedStateHandle(mapOf(FLASH_CARD_ID_ARG_KEY to selectedFlashCard.id)),
+ EditUseCase(flashCardRepository),
+ LoadUseCase(
+ FlashCardRepositoryImpl(FakeFlashCardDao(listOf(selectedFlashCard)))
+ ),
+ DeleteUseCase(TestFlashCardRepository())
+ )
composeRule.setContent {
- EditScreen(
- viewModel = EditViewModel(
- SavedStateHandle(mapOf(FLASH_CARD_ID_ARG_KEY to selectedFlashCard.id)),
- EditUseCase(flashCardRepository),
- LoadUseCase(
- FlashCardRepositoryImpl(FakeFlashCardDao(listOf(selectedFlashCard)))
- ),
- DeleteUseCase(TestFlashCardRepository())
- ),
- onFlashCardEdited = {},
- onFlashCardDeleted = {}
- )
+ EditRoute(viewModel) {}
}
return EditScreenRobot(composeRule).apply(block)
}
diff --git a/app/src/androidTest/java/com/marcopla/flashcards/presentation/home/HomeScreenRobot.kt b/app/src/androidTest/java/com/marcopla/flashcards/presentation/home/HomeScreenRobot.kt
index 08160e9..d08bd2a 100644
--- a/app/src/androidTest/java/com/marcopla/flashcards/presentation/home/HomeScreenRobot.kt
+++ b/app/src/androidTest/java/com/marcopla/flashcards/presentation/home/HomeScreenRobot.kt
@@ -8,24 +8,20 @@ import androidx.compose.ui.test.onNodeWithText
import androidx.test.ext.junit.rules.ActivityScenarioRule
import com.marcopla.flashcards.R
import com.marcopla.flashcards.data.model.FlashCard
-import com.marcopla.flashcards.data.repository.FlashCardRepositoryImpl
-import com.marcopla.flashcards.domain.usecase.LoadUseCase
import com.marcopla.flashcards.presentation.screen.home.HomeScreen
-import com.marcopla.flashcards.presentation.screen.home.HomeViewModel
-import com.marcopla.testing_shared.FakeFlashCardDao
+import com.marcopla.flashcards.presentation.screen.home.HomeScreenState
typealias ComponentActivityTestRule =
AndroidComposeTestRule, ComponentActivity>
suspend fun launchHomeScreen(
rule: ComponentActivityTestRule,
- flashCards: List = emptyList(),
+ screenState: HomeScreenState,
block: suspend HomeScreenRobot.() -> Unit
): HomeScreenRobot {
- val repository = FlashCardRepositoryImpl(FakeFlashCardDao(flashCards))
rule.setContent {
HomeScreen(
- viewModel = HomeViewModel(LoadUseCase(repository)),
+ screenState = screenState,
onNavigateToAddScreen = {},
onItemClicked = {},
onNavigateToCarouselScreen = {}
diff --git a/app/src/androidTest/java/com/marcopla/flashcards/presentation/home/HomeScreenTest.kt b/app/src/androidTest/java/com/marcopla/flashcards/presentation/home/HomeScreenTest.kt
index 1bb05ca..a79a031 100644
--- a/app/src/androidTest/java/com/marcopla/flashcards/presentation/home/HomeScreenTest.kt
+++ b/app/src/androidTest/java/com/marcopla/flashcards/presentation/home/HomeScreenTest.kt
@@ -3,6 +3,7 @@ package com.marcopla.flashcards.presentation.home
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import com.marcopla.flashcards.data.model.FlashCard
+import com.marcopla.flashcards.presentation.screen.home.HomeScreenState
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.runTest
import org.junit.Rule
@@ -16,7 +17,7 @@ class HomeScreenTest {
@Test
fun homeScreen_whenGettingEmptyState_thenShowEmptyMessage() = runTest {
- launchHomeScreen(composeRule, emptyList()) {
+ launchHomeScreen(composeRule, HomeScreenState.Empty) {
// Do nothing
} verify {
emptyMessageIsDisplayed()
@@ -31,7 +32,7 @@ class HomeScreenTest {
FlashCard(frontText = "front3", backText = "back3")
)
- launchHomeScreen(composeRule, flashCards) {
+ launchHomeScreen(composeRule, HomeScreenState.Cards(flashCards)) {
// Do nothing
} verify {
listOfFlashCardsIsDisplayed(flashCards)
@@ -40,7 +41,7 @@ class HomeScreenTest {
@Test
fun homeScreen_whenNoFlashCards_thenDoNotShowCarouselButton() = runTest {
- launchHomeScreen(composeRule, emptyList()) {
+ launchHomeScreen(composeRule, HomeScreenState.Empty) {
// Empty
} verify {
carouselButtonIsNotDisplayed()
diff --git a/app/src/main/java/com/marcopla/flashcards/data/repository/FlashCardRepository.kt b/app/src/main/java/com/marcopla/flashcards/data/repository/FlashCardRepository.kt
index 63eef51..69a7989 100644
--- a/app/src/main/java/com/marcopla/flashcards/data/repository/FlashCardRepository.kt
+++ b/app/src/main/java/com/marcopla/flashcards/data/repository/FlashCardRepository.kt
@@ -19,7 +19,7 @@ interface FlashCardRepository {
fun addResult(quizResult: QuizResult)
- fun getCurrentResults(): List
+ fun getCurrentResults(): Flow>
fun clearResults()
}
\ No newline at end of file
diff --git a/app/src/main/java/com/marcopla/flashcards/data/repository/FlashCardRepositoryImpl.kt b/app/src/main/java/com/marcopla/flashcards/data/repository/FlashCardRepositoryImpl.kt
index 6b28c06..6daaaba 100644
--- a/app/src/main/java/com/marcopla/flashcards/data/repository/FlashCardRepositoryImpl.kt
+++ b/app/src/main/java/com/marcopla/flashcards/data/repository/FlashCardRepositoryImpl.kt
@@ -5,6 +5,7 @@ import com.marcopla.flashcards.data.datasource.FlashCardDao
import com.marcopla.flashcards.data.model.FlashCard
import com.marcopla.flashcards.data.model.QuizResult
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.flow
class FlashCardRepositoryImpl(
private val flashCardDao: FlashCardDao
@@ -49,8 +50,8 @@ class FlashCardRepositoryImpl(
* Get the stored results for this session.
* Note: results are currently just saved in memory.
*/
- override fun getCurrentResults(): List {
- return currentResults
+ override fun getCurrentResults(): Flow> {
+ return flow { emit(currentResults) }
}
override fun clearResults() {
diff --git a/app/src/main/java/com/marcopla/flashcards/domain/usecase/LoadResultsUseCase.kt b/app/src/main/java/com/marcopla/flashcards/domain/usecase/LoadResultsUseCase.kt
index 52ca374..11bc0f1 100644
--- a/app/src/main/java/com/marcopla/flashcards/domain/usecase/LoadResultsUseCase.kt
+++ b/app/src/main/java/com/marcopla/flashcards/domain/usecase/LoadResultsUseCase.kt
@@ -3,11 +3,12 @@ package com.marcopla.flashcards.domain.usecase
import com.marcopla.flashcards.data.model.QuizResult
import com.marcopla.flashcards.data.repository.FlashCardRepository
import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
// TODO: Currently the results are stored only in memory. Would be better to store them on disk.
class LoadResultsUseCase @Inject constructor(private val repository: FlashCardRepository) {
- operator fun invoke(): List {
+ operator fun invoke(): Flow> {
return repository.getCurrentResults()
}
diff --git a/app/src/main/java/com/marcopla/flashcards/presentation/navigation/AppNavHost.kt b/app/src/main/java/com/marcopla/flashcards/presentation/navigation/AppNavHost.kt
index c0f086f..bc59832 100644
--- a/app/src/main/java/com/marcopla/flashcards/presentation/navigation/AppNavHost.kt
+++ b/app/src/main/java/com/marcopla/flashcards/presentation/navigation/AppNavHost.kt
@@ -6,11 +6,11 @@ import androidx.navigation.NavType
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.navArgument
-import com.marcopla.flashcards.presentation.screen.add.AddScreen
-import com.marcopla.flashcards.presentation.screen.carousel.CarouselScreen
-import com.marcopla.flashcards.presentation.screen.edit.EditScreen
-import com.marcopla.flashcards.presentation.screen.home.HomeScreen
-import com.marcopla.flashcards.presentation.screen.result.ResultsScreen
+import com.marcopla.flashcards.presentation.screen.add.AddRoute
+import com.marcopla.flashcards.presentation.screen.carousel.CarouselRoute
+import com.marcopla.flashcards.presentation.screen.edit.EditRoute
+import com.marcopla.flashcards.presentation.screen.home.HomeRoute
+import com.marcopla.flashcards.presentation.screen.result.ResultsRoute
@Composable
fun AppNavHost(
@@ -21,7 +21,7 @@ fun AppNavHost(
startDestination = Routes.HOME_SCREEN
) {
composable(Routes.HOME_SCREEN) {
- HomeScreen(
+ HomeRoute(
onNavigateToAddScreen = {
navController.navigate(Routes.ADD_SCREEN)
},
@@ -34,34 +34,31 @@ fun AppNavHost(
)
}
composable(Routes.ADD_SCREEN) {
- AddScreen()
+ AddRoute()
}
composable(
- "${Routes.EDIT_SCREEN}/{$FLASH_CARD_ID_ARG_KEY}",
+ route = "${Routes.EDIT_SCREEN}/{$FLASH_CARD_ID_ARG_KEY}",
arguments = listOf(
navArgument(FLASH_CARD_ID_ARG_KEY) {
type = NavType.IntType
}
)
) {
- EditScreen(
- onFlashCardEdited = {
- navController.popBackStack(Routes.HOME_SCREEN, false)
- },
- onFlashCardDeleted = {
+ EditRoute(
+ onPopBackStack = {
navController.popBackStack(Routes.HOME_SCREEN, false)
}
)
}
composable(Routes.CAROUSEL_SCREEN) {
- CarouselScreen(
+ CarouselRoute(
onLastFlashCardPlayed = {
navController.navigate(Routes.RESULT_SCREEN)
}
)
}
composable(Routes.RESULT_SCREEN) {
- ResultsScreen(
+ ResultsRoute(
onDoneClicked = {
navController.popBackStack(Routes.HOME_SCREEN, false)
}
diff --git a/app/src/main/java/com/marcopla/flashcards/presentation/screen/add/AddScreen.kt b/app/src/main/java/com/marcopla/flashcards/presentation/screen/add/AddScreen.kt
index 6bc4664..d25bd2d 100644
--- a/app/src/main/java/com/marcopla/flashcards/presentation/screen/add/AddScreen.kt
+++ b/app/src/main/java/com/marcopla/flashcards/presentation/screen/add/AddScreen.kt
@@ -17,32 +17,50 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.marcopla.flashcards.R
-@OptIn(ExperimentalLayoutApi::class)
@Composable
-fun AddScreen(
- modifier: Modifier = Modifier,
- viewModel: AddViewModel = hiltViewModel()
-) {
+fun AddRoute(viewModel: AddViewModel = hiltViewModel()) {
+ val infoTextState = viewModel.infoTextState.value
val scaffoldState = rememberScaffoldState()
HandleInfoTextEffect(
- viewModel.infoTextState.value.messageStringRes,
+ infoTextState.messageStringRes,
scaffoldState.snackbarHostState
)
+ AddScreen(
+ frontTextState = viewModel.frontTextState.value,
+ backTextState = viewModel.backTextState.value,
+ addScreenState = viewModel.addScreenState.value,
+ onSubmitClick = {
+ viewModel.attemptSubmit(
+ frontText = viewModel.frontTextState.value.text,
+ backText = viewModel.backTextState.value.text
+ )
+ },
+ onFrontTextValueChange = { frontInput -> viewModel.updateFrontText(frontInput) },
+ onBackTextValueChange = { backInput -> viewModel.updateBackText(backInput) },
+ scaffoldState = scaffoldState
+ )
+}
+
+@OptIn(ExperimentalLayoutApi::class)
+@Composable
+fun AddScreen(
+ frontTextState: FrontTextState,
+ backTextState: BackTextState,
+ addScreenState: AddScreenState,
+ onSubmitClick: () -> Unit,
+ onFrontTextValueChange: (String) -> Unit,
+ onBackTextValueChange: (String) -> Unit,
+ scaffoldState: ScaffoldState,
+ modifier: Modifier = Modifier
+) {
Scaffold(
scaffoldState = scaffoldState,
topBar = {
TopAppBar(title = { Text(stringResource(R.string.addScreenTitle)) })
},
floatingActionButton = {
- FloatingActionButton(
- onClick = {
- viewModel.attemptSubmit(
- frontText = viewModel.frontTextState.value.text,
- backText = viewModel.backTextState.value.text
- )
- }
- ) {
+ FloatingActionButton(onClick = onSubmitClick) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = stringResource(R.string.addCardButton)
@@ -52,16 +70,16 @@ fun AddScreen(
) { paddingValues: PaddingValues ->
Column(modifier = modifier.padding(4.dp).consumeWindowInsets(paddingValues)) {
FontTextField(
- value = viewModel.frontTextState.value.text,
- isError = viewModel.frontTextState.value.showError,
- isFocused = viewModel.addScreenState.value == AddScreenState.SUCCESSFUL_SAVE,
- onValueChange = { frontInput -> viewModel.updateFrontText(frontInput) }
+ value = frontTextState.text,
+ isError = frontTextState.showError,
+ isFocused = addScreenState == AddScreenState.SUCCESSFUL_SAVE,
+ onValueChange = onFrontTextValueChange
)
Spacer(modifier = Modifier.height(8.dp))
BackTextField(
- value = viewModel.backTextState.value.text,
- isError = viewModel.backTextState.value.showError,
- onValueChange = { backInput -> viewModel.updateBackText(backInput) }
+ value = backTextState.text,
+ isError = backTextState.showError,
+ onValueChange = onBackTextValueChange
)
}
}
@@ -114,7 +132,7 @@ private fun BackTextField(
}
@Composable
-private fun HandleInfoTextEffect(
+fun HandleInfoTextEffect(
infoTextStringRes: Int?,
snackbarHostState: SnackbarHostState
) {
@@ -123,4 +141,4 @@ private fun HandleInfoTextEffect(
LaunchedEffect(infoTextStringRes) {
snackbarHostState.showSnackbar(infoText)
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/marcopla/flashcards/presentation/screen/carousel/CarouselScreen.kt b/app/src/main/java/com/marcopla/flashcards/presentation/screen/carousel/CarouselScreen.kt
index a5c10f5..ef25506 100644
--- a/app/src/main/java/com/marcopla/flashcards/presentation/screen/carousel/CarouselScreen.kt
+++ b/app/src/main/java/com/marcopla/flashcards/presentation/screen/carousel/CarouselScreen.kt
@@ -13,24 +13,37 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.marcopla.flashcards.R
-@OptIn(ExperimentalLayoutApi::class)
@Composable
-fun CarouselScreen(
- modifier: Modifier = Modifier,
+fun CarouselRoute(
viewModel: CarouselViewModel = hiltViewModel(),
onLastFlashCardPlayed: () -> Unit
) {
- LaunchedEffect(key1 = Unit) {
- viewModel.loadFlashCards()
- }
-
- val screenState = viewModel.screenState
- if (screenState.value == CarouselScreenState.Finished) {
+ val screenState = viewModel.screenState.value
+ if (screenState == CarouselScreenState.Finished) {
LaunchedEffect(key1 = Unit) {
onLastFlashCardPlayed()
}
}
+ CarouselScreen(
+ screenState = screenState,
+ onSubmitClicked = {
+ viewModel.submit(viewModel.guessInput.value)
+ },
+ guessInputState = viewModel.guessInput.value,
+ onGuessInputChange = viewModel::updateGuessInput
+ )
+}
+
+@OptIn(ExperimentalLayoutApi::class)
+@Composable
+fun CarouselScreen(
+ screenState: CarouselScreenState,
+ onSubmitClicked: () -> Unit,
+ guessInputState: String,
+ onGuessInputChange: (String) -> Unit,
+ modifier: Modifier = Modifier
+) {
Scaffold(
topBar = {
TopAppBar(
@@ -40,9 +53,7 @@ fun CarouselScreen(
)
},
floatingActionButton = {
- FloatingActionButton(onClick = {
- viewModel.submit(viewModel.guessInput.value)
- }) {
+ FloatingActionButton(onClick = onSubmitClicked) {
Icon(imageVector = Icons.Default.Done, stringResource(id = R.string.nextButton))
}
}
@@ -52,10 +63,10 @@ fun CarouselScreen(
.padding(4.dp)
.consumeWindowInsets(it)
) {
- Prompt(screenState.value)
+ Prompt(screenState)
Guess(
- value = viewModel.guessInput.value,
- onValueChange = viewModel::updateGuessInput
+ value = guessInputState,
+ onValueChange = onGuessInputChange
)
}
}
@@ -94,4 +105,4 @@ private fun Prompt(screenState: CarouselScreenState) {
}
}
Text(text = promptText)
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/marcopla/flashcards/presentation/screen/carousel/CarouselViewModel.kt b/app/src/main/java/com/marcopla/flashcards/presentation/screen/carousel/CarouselViewModel.kt
index 62acca1..bdc2cea 100644
--- a/app/src/main/java/com/marcopla/flashcards/presentation/screen/carousel/CarouselViewModel.kt
+++ b/app/src/main/java/com/marcopla/flashcards/presentation/screen/carousel/CarouselViewModel.kt
@@ -30,7 +30,11 @@ class CarouselViewModel @Inject constructor(
private val isLastFlashCard: Boolean
get() = currentFlashCardIndex >= flashCards.size - 1
- fun loadFlashCards() {
+ init {
+ loadFlashCards()
+ }
+
+ private fun loadFlashCards() {
viewModelScope.launch {
flashCards = loadUseCase.loadAll().first()
_screenState.value = CarouselScreenState.Initial(flashCards[0])
diff --git a/app/src/main/java/com/marcopla/flashcards/presentation/screen/edit/EditScreen.kt b/app/src/main/java/com/marcopla/flashcards/presentation/screen/edit/EditScreen.kt
index 191e71d..8213a3b 100644
--- a/app/src/main/java/com/marcopla/flashcards/presentation/screen/edit/EditScreen.kt
+++ b/app/src/main/java/com/marcopla/flashcards/presentation/screen/edit/EditScreen.kt
@@ -16,33 +16,64 @@ import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.marcopla.flashcards.R
+@Composable
+fun EditRoute(
+ viewModel: EditViewModel = hiltViewModel(),
+ onPopBackStack: () -> Unit
+) {
+ if (viewModel.shouldShowDeleteConfirmation.value) {
+ DeleteConfirmationDialog(
+ onConfirmationClick = viewModel::delete,
+ onCancelClick = viewModel::hideDeleteConfirmationDialog,
+ onDismissRequest = viewModel::hideDeleteConfirmationDialog
+ )
+ }
+
+ EditScreen(
+ onFlashCardEdited = onPopBackStack,
+ onFlashCardDeleted = {
+ viewModel.hideDeleteConfirmationDialog()
+ onPopBackStack()
+ },
+ editScreenState = viewModel.screenState.value,
+ onReset = viewModel::reset,
+ onShowDeleteConfirmationDialog = viewModel::showDeleteConfirmationDialog,
+ onSubmit = {
+ viewModel.attemptSubmit(
+ viewModel.frontTextState.value.text,
+ viewModel.backTextState.value.text
+ )
+ },
+ frontTextState = viewModel.frontTextState.value,
+ onFrontTextValueChange = viewModel::updateFrontText,
+ backTextState = viewModel.backTextState.value,
+ onBackTextValueChange = viewModel::updateBackText
+ )
+}
+
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun EditScreen(
onFlashCardEdited: () -> Unit,
onFlashCardDeleted: () -> Unit,
- modifier: Modifier = Modifier,
- viewModel: EditViewModel = hiltViewModel()
+ editScreenState: EditScreenState,
+ onReset: () -> Unit,
+ onShowDeleteConfirmationDialog: () -> Unit,
+ onSubmit: () -> Unit,
+ frontTextState: EditFrontTextState,
+ onFrontTextValueChange: (String) -> Unit,
+ backTextState: EditBackTextState,
+ onBackTextValueChange: (String) -> Unit,
+ modifier: Modifier = Modifier
) {
val scaffoldState = rememberScaffoldState()
HandleScreenState(
- viewModel.screenState.value,
+ editScreenState,
scaffoldState,
onFlashCardEdited,
- onFlashCardDeleted = {
- viewModel.hideDeleteConfirmationDialog()
- onFlashCardDeleted()
- }
+ onFlashCardDeleted
)
- if (viewModel.shouldShowDeleteConfirmation.value) {
- DeleteConfirmationDialog(
- onConfirmationClick = { viewModel.delete() },
- onCancelClick = { viewModel.hideDeleteConfirmationDialog() },
- onDismissRequest = { viewModel.hideDeleteConfirmationDialog() }
- )
- }
-
Scaffold(
scaffoldState = scaffoldState,
topBar = {
@@ -51,17 +82,15 @@ fun EditScreen(
Text(text = stringResource(R.string.editScreenTitle))
},
actions = {
- if (viewModel.screenState.value == EditScreenState.Editing) {
+ if (editScreenState == EditScreenState.Editing) {
Icon(
- modifier = Modifier.clickable(onClick = viewModel::reset),
+ modifier = Modifier.clickable(onClick = onReset),
imageVector = Icons.Default.Refresh,
contentDescription = stringResource(id = R.string.resetButton)
)
} else {
Icon(
- modifier = Modifier.clickable {
- viewModel.showDeleteConfirmationDialog()
- },
+ modifier = Modifier.clickable(onClick = onShowDeleteConfirmationDialog),
imageVector = Icons.Default.Delete,
contentDescription = stringResource(R.string.deleteButton)
)
@@ -70,12 +99,7 @@ fun EditScreen(
)
},
floatingActionButton = {
- FloatingActionButton(onClick = {
- viewModel.attemptSubmit(
- viewModel.frontTextState.value.text,
- viewModel.backTextState.value.text
- )
- }) {
+ FloatingActionButton(onClick = onSubmit) {
Icon(
imageVector = Icons.Default.Edit,
contentDescription = stringResource(R.string.editButton)
@@ -83,11 +107,6 @@ fun EditScreen(
}
}
) {
- // TODO: Consider using Flows and call collectAsStateWithLifecycle here.
- LaunchedEffect(key1 = Unit) {
- viewModel.initState()
- }
-
Column(
modifier = modifier
.padding(4.dp)
@@ -100,10 +119,10 @@ fun EditScreen(
.semantics {
contentDescription = frontTextContentDescription
},
- value = viewModel.frontTextState.value.text,
+ value = frontTextState.text,
label = { Text(stringResource(R.string.frontTextFieldLabel)) },
- isError = viewModel.frontTextState.value.showError,
- onValueChange = viewModel::updateFrontText
+ isError = frontTextState.showError,
+ onValueChange = onFrontTextValueChange
)
Spacer(modifier = Modifier.height(8.dp))
@@ -115,10 +134,10 @@ fun EditScreen(
.semantics {
contentDescription = backTextContentDescription
},
- value = viewModel.backTextState.value.text,
+ value = backTextState.text,
label = { Text(stringResource(R.string.backTextFieldLabel)) },
- isError = viewModel.backTextState.value.showError,
- onValueChange = viewModel::updateBackText
+ isError = backTextState.showError,
+ onValueChange = onBackTextValueChange
)
}
}
@@ -151,7 +170,7 @@ private fun HandleScreenState(
}
@Composable
-private fun DeleteConfirmationDialog(
+fun DeleteConfirmationDialog(
onConfirmationClick: () -> Unit,
onCancelClick: () -> Unit,
onDismissRequest: () -> Unit,
diff --git a/app/src/main/java/com/marcopla/flashcards/presentation/screen/edit/EditViewModel.kt b/app/src/main/java/com/marcopla/flashcards/presentation/screen/edit/EditViewModel.kt
index 77da895..8e9139b 100644
--- a/app/src/main/java/com/marcopla/flashcards/presentation/screen/edit/EditViewModel.kt
+++ b/app/src/main/java/com/marcopla/flashcards/presentation/screen/edit/EditViewModel.kt
@@ -40,7 +40,11 @@ class EditViewModel @Inject constructor(
private val flashCardId: Int by lazy { checkNotNull(savedStateHandle[FLASH_CARD_ID_ARG_KEY]) }
- fun initState() {
+ init {
+ initializeFlashCard()
+ }
+
+ private fun initializeFlashCard() {
viewModelScope.launch {
val flashCard = loadFlashCardUseCase.loadById(flashCardId)
_frontTextState.value = _frontTextState.value.copy(text = flashCard.frontText)
diff --git a/app/src/main/java/com/marcopla/flashcards/presentation/screen/home/HomeScreen.kt b/app/src/main/java/com/marcopla/flashcards/presentation/screen/home/HomeScreen.kt
index 75917eb..5bff620 100644
--- a/app/src/main/java/com/marcopla/flashcards/presentation/screen/home/HomeScreen.kt
+++ b/app/src/main/java/com/marcopla/flashcards/presentation/screen/home/HomeScreen.kt
@@ -25,14 +25,29 @@ import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@Composable
-fun HomeScreen(
+fun HomeRoute(
onNavigateToAddScreen: () -> Unit,
onItemClicked: (Int) -> Unit,
onNavigateToCarouselScreen: () -> Unit,
- modifier: Modifier = Modifier,
viewModel: HomeViewModel = hiltViewModel()
) {
val screenState: HomeScreenState by viewModel.homeScreenState.collectAsStateWithLifecycle()
+ HomeScreen(
+ screenState = screenState,
+ onNavigateToAddScreen = onNavigateToAddScreen,
+ onItemClicked = onItemClicked,
+ onNavigateToCarouselScreen = onNavigateToCarouselScreen
+ )
+}
+
+@Composable
+fun HomeScreen(
+ screenState: HomeScreenState,
+ onNavigateToAddScreen: () -> Unit,
+ onItemClicked: (Int) -> Unit,
+ onNavigateToCarouselScreen: () -> Unit,
+ modifier: Modifier = Modifier
+) {
Scaffold(
topBar = {
TopAppBar(
@@ -157,4 +172,4 @@ private fun CardsList(
}
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/main/java/com/marcopla/flashcards/presentation/screen/result/ResultViewModel.kt b/app/src/main/java/com/marcopla/flashcards/presentation/screen/result/ResultViewModel.kt
index 31f4e2c..63c8e6e 100644
--- a/app/src/main/java/com/marcopla/flashcards/presentation/screen/result/ResultViewModel.kt
+++ b/app/src/main/java/com/marcopla/flashcards/presentation/screen/result/ResultViewModel.kt
@@ -1,19 +1,24 @@
package com.marcopla.flashcards.presentation.screen.result
-import androidx.compose.runtime.State
-import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
import com.marcopla.flashcards.data.model.QuizResult
import com.marcopla.flashcards.domain.usecase.LoadResultsUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.stateIn
@HiltViewModel
class ResultViewModel @Inject constructor(
private val loadResults: LoadResultsUseCase
) : ViewModel() {
- private val _results = mutableStateOf(loadResults())
- val results: State> = _results
+ val results: StateFlow> = loadResults().stateIn(
+ scope = viewModelScope,
+ started = SharingStarted.WhileSubscribed(5_000),
+ initialValue = emptyList()
+ )
fun clearResults() {
loadResults.clearAll()
diff --git a/app/src/main/java/com/marcopla/flashcards/presentation/screen/result/ResultsScreen.kt b/app/src/main/java/com/marcopla/flashcards/presentation/screen/result/ResultsScreen.kt
index dcbac0e..c6d44c2 100644
--- a/app/src/main/java/com/marcopla/flashcards/presentation/screen/result/ResultsScreen.kt
+++ b/app/src/main/java/com/marcopla/flashcards/presentation/screen/result/ResultsScreen.kt
@@ -7,6 +7,7 @@ import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
@@ -14,14 +15,32 @@ import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
+import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.marcopla.flashcards.R
+import com.marcopla.flashcards.data.model.QuizResult
+import kotlinx.collections.immutable.ImmutableList
+import kotlinx.collections.immutable.toImmutableList
+
+@Composable
+fun ResultsRoute(
+ onDoneClicked: () -> Unit,
+ viewModel: ResultViewModel = hiltViewModel()
+) {
+ val results: List by viewModel.results.collectAsStateWithLifecycle()
+ ResultsScreen(
+ onDoneClicked = onDoneClicked,
+ results = results.toImmutableList(),
+ clearResults = { viewModel.clearResults() }
+ )
+}
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun ResultsScreen(
- modifier: Modifier = Modifier,
- viewModel: ResultViewModel = hiltViewModel(),
- onDoneClicked: () -> Unit
+ onDoneClicked: () -> Unit,
+ results: ImmutableList,
+ clearResults: () -> Unit,
+ modifier: Modifier = Modifier
) {
Scaffold(topBar = {
TopAppBar(title = { Text(stringResource(R.string.results)) })
@@ -34,9 +53,9 @@ fun ResultsScreen(
horizontalAlignment = Alignment.CenterHorizontally
) {
LazyColumn {
- items(viewModel.results.value.size) { index ->
+ items(results.size) { index ->
ResultItem(
- quizResult = viewModel.results.value[index]
+ quizResult = results[index]
)
}
}
@@ -45,11 +64,11 @@ fun ResultsScreen(
modifier = Modifier.semantics { contentDescription = buttonText },
onClick = {
onDoneClicked()
- viewModel.clearResults()
+ clearResults()
}
) {
Text(buttonText)
}
}
}
-}
\ No newline at end of file
+}
diff --git a/app/src/test/java/com/marcopla/flashcards/domain/usecase/SubmitQuizUseCaseTest.kt b/app/src/test/java/com/marcopla/flashcards/domain/usecase/SubmitQuizUseCaseTest.kt
index b46e145..6c6214e 100644
--- a/app/src/test/java/com/marcopla/flashcards/domain/usecase/SubmitQuizUseCaseTest.kt
+++ b/app/src/test/java/com/marcopla/flashcards/domain/usecase/SubmitQuizUseCaseTest.kt
@@ -2,31 +2,36 @@ package com.marcopla.flashcards.domain.usecase
import com.marcopla.flashcards.data.model.FlashCard
import com.marcopla.testing_shared.TestFlashCardRepository
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertFalse
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.params.ParameterizedTest
import org.junit.jupiter.params.provider.ValueSource
+@OptIn(ExperimentalCoroutinesApi::class)
class SubmitQuizUseCaseTest {
@ParameterizedTest
@ValueSource(strings = ["", " ", " "])
- fun whenSubmittingBlankGuess_thenAddWrongResult_andReturnWrongValidation(blankGuess: String) {
- val repository = TestFlashCardRepository()
- val submitQuizUseCase = SubmitQuizUseCase(repository)
+ fun whenSubmittingBlankGuess_thenAddWrongResult_andReturnWrongValidation(blankGuess: String) =
+ runTest {
+ val repository = TestFlashCardRepository()
+ val submitQuizUseCase = SubmitQuizUseCase(repository)
- val isValidationCorrect = submitQuizUseCase.invoke(
- FlashCard("Engels", "English"),
- blankGuess
- )
+ val isValidationCorrect = submitQuizUseCase.invoke(
+ FlashCard("Engels", "English"),
+ blankGuess
+ )
- val quizResult = repository.getCurrentResults().first()
- assertFalse(quizResult.isCorrect)
- assertFalse(isValidationCorrect)
- }
+ val quizResult = repository.getCurrentResults().first().first()
+ assertFalse(quizResult.isCorrect)
+ assertFalse(isValidationCorrect)
+ }
@Test
- fun whenSubmittingWrongGuess_thenAddWrongResult_andReturnWrongValidation() {
+ fun whenSubmittingWrongGuess_thenAddWrongResult_andReturnWrongValidation() = runTest {
val repository = TestFlashCardRepository()
val submitQuizUseCase = SubmitQuizUseCase(repository)
@@ -35,13 +40,13 @@ class SubmitQuizUseCaseTest {
":wrongGuess:"
)
- val quizResult = repository.getCurrentResults().first()
+ val quizResult = repository.getCurrentResults().first().first()
assertFalse(quizResult.isCorrect)
assertFalse(isValidationCorrect)
}
@Test
- fun whenSubmittingCorrectGuess_thenAddCorrectResult_andReturnCorrectValidation() {
+ fun whenSubmittingCorrectGuess_thenAddCorrectResult_andReturnCorrectValidation() = runTest {
val repository = TestFlashCardRepository()
val submitQuizUseCase = SubmitQuizUseCase(repository)
@@ -50,7 +55,7 @@ class SubmitQuizUseCaseTest {
"English"
)
- val quizResult = repository.getCurrentResults().first()
+ val quizResult = repository.getCurrentResults().first().first()
assertTrue(quizResult.isCorrect)
assertTrue(isValidationCorrect)
}
diff --git a/app/src/test/java/com/marcopla/flashcards/presentation/carousel/CarouselViewModelTest.kt b/app/src/test/java/com/marcopla/flashcards/presentation/carousel/CarouselViewModelTest.kt
index e7cf3e2..0910895 100644
--- a/app/src/test/java/com/marcopla/flashcards/presentation/carousel/CarouselViewModelTest.kt
+++ b/app/src/test/java/com/marcopla/flashcards/presentation/carousel/CarouselViewModelTest.kt
@@ -9,6 +9,8 @@ import com.marcopla.flashcards.presentation.screen.carousel.CarouselScreenState
import com.marcopla.flashcards.presentation.screen.carousel.CarouselViewModel
import com.marcopla.testing_shared.FakeFlashCardDao
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
@@ -34,7 +36,6 @@ class CarouselViewModelTest {
LoadUseCase(repository),
SubmitQuizUseCase(repository)
)
- viewModel.loadFlashCards()
viewModel.submit(emptyUserGuess)
@@ -59,8 +60,6 @@ class CarouselViewModelTest {
SubmitQuizUseCase(repository)
)
- viewModel.loadFlashCards()
-
assertEquals(
CarouselScreenState.Initial(
listOf(
@@ -86,7 +85,6 @@ class CarouselViewModelTest {
LoadUseCase(repository),
SubmitQuizUseCase(repository)
)
- viewModel.loadFlashCards()
viewModel.submit("wrong guess")
@@ -110,7 +108,6 @@ class CarouselViewModelTest {
LoadUseCase(repository),
SubmitQuizUseCase(repository)
)
- viewModel.loadFlashCards()
viewModel.submit("English")
@@ -134,7 +131,6 @@ class CarouselViewModelTest {
LoadUseCase(repository),
SubmitQuizUseCase(repository)
)
- viewModel.loadFlashCards()
viewModel.submit("English")
viewModel.submit("Dutch")
@@ -156,7 +152,6 @@ class CarouselViewModelTest {
LoadUseCase(repository),
SubmitQuizUseCase(repository)
)
- viewModel.loadFlashCards()
viewModel.updateGuessInput(":guess:")
viewModel.submit(":guess:")
@@ -165,7 +160,7 @@ class CarouselViewModelTest {
}
@Test
- fun whenFinished_allFlashCardsWereProcessed() {
+ fun whenFinished_allFlashCardsWereProcessed() = runTest {
val storedFlashCards = listOf(
FlashCard("Engels", "English"),
FlashCard("Nederlands", "Dutch"),
@@ -176,12 +171,11 @@ class CarouselViewModelTest {
LoadUseCase(repository),
SubmitQuizUseCase(repository)
)
- viewModel.loadFlashCards()
repeat(storedFlashCards.size) {
viewModel.submit(":guess:")
}
- assertEquals(storedFlashCards.size, repository.getCurrentResults().size)
+ assertEquals(storedFlashCards.size, repository.getCurrentResults().first().size)
}
}
\ No newline at end of file
diff --git a/app/src/test/java/com/marcopla/flashcards/presentation/result/ResultViewModelTest.kt b/app/src/test/java/com/marcopla/flashcards/presentation/result/ResultViewModelTest.kt
index b43f4b9..1f9aea1 100644
--- a/app/src/test/java/com/marcopla/flashcards/presentation/result/ResultViewModelTest.kt
+++ b/app/src/test/java/com/marcopla/flashcards/presentation/result/ResultViewModelTest.kt
@@ -1,17 +1,25 @@
package com.marcopla.flashcards.presentation.result
+import com.marcopla.flashcards.MainDispatcherExtension
import com.marcopla.flashcards.data.model.FlashCard
import com.marcopla.flashcards.data.model.QuizResult
import com.marcopla.flashcards.data.repository.FlashCardRepositoryImpl
import com.marcopla.flashcards.domain.usecase.LoadResultsUseCase
import com.marcopla.flashcards.presentation.screen.result.ResultViewModel
import com.marcopla.testing_shared.FakeFlashCardDao
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runTest
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
+import org.junit.jupiter.api.extension.ExtendWith
+@OptIn(ExperimentalCoroutinesApi::class)
+@ExtendWith(MainDispatcherExtension::class)
class ResultViewModelTest {
@Test
- fun whenResultsAreLoaded_thenEmitResults() {
+ fun whenResultsAreLoaded_thenEmitResults() = runTest {
val storedResults = listOf(
QuizResult(FlashCard("Engels", "English"), "English", true),
QuizResult(FlashCard("Nederlands", "Dutch"), "", false),
@@ -21,7 +29,9 @@ class ResultViewModelTest {
storedResults.forEach { addResult(it) }
}
val viewModel = ResultViewModel(LoadResultsUseCase(repository))
+ val collectJob = launch(UnconfinedTestDispatcher()) { viewModel.results.collect {} }
assertEquals(storedResults, viewModel.results.value)
+ collectJob.cancel()
}
}
\ No newline at end of file
diff --git a/app/testing/src/main/java/com/marcopla/testing_shared/DuplicateFlashCardRepository.kt b/app/testing/src/main/java/com/marcopla/testing_shared/DuplicateFlashCardRepository.kt
index 2d4b545..ea9122b 100644
--- a/app/testing/src/main/java/com/marcopla/testing_shared/DuplicateFlashCardRepository.kt
+++ b/app/testing/src/main/java/com/marcopla/testing_shared/DuplicateFlashCardRepository.kt
@@ -31,7 +31,7 @@ class DuplicateFlashCardRepository : FlashCardRepository {
TODO("Not yet implemented")
}
- override fun getCurrentResults(): List {
+ override fun getCurrentResults(): Flow> {
TODO("Not yet implemented")
}
diff --git a/app/testing/src/main/java/com/marcopla/testing_shared/TestFlashCardRepository.kt b/app/testing/src/main/java/com/marcopla/testing_shared/TestFlashCardRepository.kt
index 9b21c56..20c7241 100644
--- a/app/testing/src/main/java/com/marcopla/testing_shared/TestFlashCardRepository.kt
+++ b/app/testing/src/main/java/com/marcopla/testing_shared/TestFlashCardRepository.kt
@@ -41,8 +41,8 @@ class TestFlashCardRepository : FlashCardRepository {
currentResults.add(quizResult)
}
- override fun getCurrentResults(): List {
- return currentResults
+ override fun getCurrentResults(): Flow> {
+ return flow { emit(currentResults) }
}
override fun clearResults() {