Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import com.example.android.architecture.blueprints.todoapp.HiltTestActivity
import com.example.android.architecture.blueprints.todoapp.R
import com.example.android.architecture.blueprints.todoapp.TodoDestinationsArgs.USER_MESSAGE_ARG
import com.example.android.architecture.blueprints.todoapp.TodoTheme
import com.example.android.architecture.blueprints.todoapp.data.TaskRepository
import dagger.hilt.android.testing.HiltAndroidRule
Expand Down Expand Up @@ -255,12 +256,14 @@ class TasksScreenTest {

private fun setContent() {
composeTestRule.setContent {
// Creating SavedStateHandle manually since we're not actually in a
// NavHost in this test
val savedStateHandle = SavedStateHandle.createHandle(null, null)
savedStateHandle[USER_MESSAGE_ARG] = R.string.successfully_added_task_message
TodoTheme {
Surface {
TasksScreen(
viewModel = TasksViewModel(repository, SavedStateHandle()),
userMessage = R.string.successfully_added_task_message,
onUserMessageDisplayed = { },
viewModel = TasksViewModel(repository, savedStateHandle),
onAddTask = { },
onTaskClick = { },
openDrawer = { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,9 @@ fun TodoNavGraph(
arguments = listOf(
navArgument(USER_MESSAGE_ARG) { type = NavType.IntType; defaultValue = 0 }
)
) { entry ->
) {
AppModalDrawer(drawerState, currentRoute, navActions) {
TasksScreen(
userMessage = entry.arguments?.getInt(USER_MESSAGE_ARG)!!,
onUserMessageDisplayed = { entry.arguments?.putInt(USER_MESSAGE_ARG, 0) },
onAddTask = { navActions.navigateToAddEditTask(R.string.add_task, null) },
onTaskClick = { task -> navActions.navigateToTaskDetail(task.id) },
openDrawer = { coroutineScope.launch { drawerState.open() } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.dimensionResource
Expand All @@ -66,10 +65,8 @@ import com.example.android.architecture.blueprints.todoapp.util.TasksTopAppBar

@Composable
fun TasksScreen(
@StringRes userMessage: Int,
onAddTask: () -> Unit,
onTaskClick: (Task) -> Unit,
onUserMessageDisplayed: () -> Unit,
openDrawer: () -> Unit,
modifier: Modifier = Modifier,
viewModel: TasksViewModel = hiltViewModel(),
Expand All @@ -95,6 +92,7 @@ fun TasksScreen(
}
) { paddingValues ->
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val userMessageResultCode by viewModel.userMessageResultCode.collectAsStateWithLifecycle()

TasksContent(
loading = uiState.isLoading,
Expand All @@ -118,11 +116,9 @@ fun TasksScreen(
}

// Check if there's a userMessage to show to the user
val currentOnUserMessageDisplayed by rememberUpdatedState(onUserMessageDisplayed)
LaunchedEffect(userMessage) {
if (userMessage != 0) {
viewModel.showEditResultMessage(userMessage)
currentOnUserMessageDisplayed()
LaunchedEffect(userMessageResultCode) {
if (userMessageResultCode != 0) {
viewModel.showEditResultMessage(userMessageResultCode)
}
}
Comment on lines +119 to 123

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The LaunchedEffect is now keyed by userMessageResultCode. Ensure that userMessageResultCode is properly updated and distinct to avoid unnecessary recompositions. If the same userMessageResultCode is emitted consecutively, the LaunchedEffect block will not be re-executed, which might lead to the message not being displayed if it was previously dismissed.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The message will be displayed because the userMessageResultCode will be set to 0 after one message is displayed, then the next one will also be displayed because the code will be different from 0.

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import com.example.android.architecture.blueprints.todoapp.ADD_EDIT_RESULT_OK
import com.example.android.architecture.blueprints.todoapp.DELETE_RESULT_OK
import com.example.android.architecture.blueprints.todoapp.EDIT_RESULT_OK
import com.example.android.architecture.blueprints.todoapp.R
import com.example.android.architecture.blueprints.todoapp.TodoDestinationsArgs.USER_MESSAGE_ARG
import com.example.android.architecture.blueprints.todoapp.data.Task
import com.example.android.architecture.blueprints.todoapp.data.TaskRepository
import com.example.android.architecture.blueprints.todoapp.tasks.TasksFilterType.ACTIVE_TASKS
Expand Down Expand Up @@ -60,6 +61,8 @@ class TasksViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle
) : ViewModel() {

var userMessageResultCode = savedStateHandle.getStateFlow(USER_MESSAGE_ARG, 0)

private val _savedFilterType =
savedStateHandle.getStateFlow(TASKS_FILTER_SAVED_STATE_KEY, ALL_TASKS)

Expand Down Expand Up @@ -131,6 +134,7 @@ class TasksViewModel @Inject constructor(

fun snackbarMessageShown() {
_userMessage.value = null
savedStateHandle[USER_MESSAGE_ARG] = 0
}

private fun showSnackbarMessage(message: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,22 @@ class TasksViewModelTest {
.isEqualTo(R.string.successfully_deleted_task_message)
}

@Test
fun snackbarMessageShownOnlyOnce() = runTest {
// When a snackbar message is set
tasksViewModel.showEditResultMessage(DELETE_RESULT_OK)

// The snackbar is updated
assertThat(tasksViewModel.uiState.first().userMessage)
.isEqualTo(R.string.successfully_deleted_task_message)

// When the UI has displayed the message
tasksViewModel.snackbarMessageShown()

// The snackbar is cleared
assertThat(tasksViewModel.uiState.first().userMessage).isEqualTo(null)
}

@Test
fun completeTask_dataAndSnackbarUpdated() = runTest {
// With a repository that has an active task
Expand Down