Skip to content

Commit

Permalink
Hide close button after data is collected (#3059)
Browse files Browse the repository at this point in the history
* Simplify compose ui for confirmation dialog

* Hide close button after submission in DataCollectionFragment

* Removes the navigation icon from the toolbar after submission.

* Handle back button after submission in DataCollectionFragment

*   Navigate back to the home screen after a task is submitted when the back button is pressed.
*   Extract navigation logic to a separate private method.

* Move confirmation dialog logic into `DataSubmissionConfirmationDialog`

* Remove logic for removing the compose view on close button click as the fragment itself gets dismissed

* Fix import order

* Fix class name

* Fix import order

* Add unit tests
  • Loading branch information
shobhitagarwal1612 authored Feb 24, 2025
1 parent daed8d3 commit 7515b7e
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ProgressBar
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.constraintlayout.widget.Guideline
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.doOnLayout
Expand Down Expand Up @@ -161,16 +159,13 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
}

private fun onTaskSubmitted() {
// Hide close button
binding.dataCollectionToolbar.navigationIcon = null

// Display a confirmation dialog and move to home screen after that.
renderComposableDialog {
val openAlertDialog = remember { mutableStateOf(true) }
when {
openAlertDialog.value -> {
DataSubmissionConfirmationDialog {
openAlertDialog.value = false
findNavController().navigate(HomeScreenFragmentDirections.showHomeScreen())
}
}
DataSubmissionConfirmationScreen {
findNavController().navigate(HomeScreenFragmentDirections.showHomeScreen())
}
}
}
Expand All @@ -193,7 +188,10 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
}

override fun onBack(): Boolean {
if (viewPager.currentItem == 0) {
if (viewModel.uiState.value == UiState.TaskSubmitted) {
// Pressing back button after submitting task should navigate back to home screen.
navigateBack()
} else if (viewPager.currentItem == 0) {
showExitWarningDialog()
} else {
viewModel.moveToPreviousTask()
Expand All @@ -207,15 +205,17 @@ class DataCollectionFragment : AbstractFragment(), BackPressListener {
title = R.string.data_collection_cancellation_title,
description = R.string.data_collection_cancellation_description,
confirmButtonText = R.string.data_collection_cancellation_confirm_button,
onConfirmClicked = {
isNavigatingUp = true
viewModel.clearDraft()
findNavController().navigateUp()
},
onConfirmClicked = { navigateBack() },
)
}
}

private fun navigateBack() {
isNavigatingUp = true
viewModel.clearDraft()
findNavController().navigateUp()
}

private companion object {
private const val PROGRESS_SCALE = 100
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,15 @@
package com.google.android.ground.ui.datacollection

import android.content.res.Configuration
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
Expand All @@ -50,58 +47,42 @@ import com.google.android.ground.R
import com.google.android.ground.ui.theme.AppTheme

@Composable
fun DataSubmissionConfirmationDialog(onDismiss: () -> Unit) {
val configuration = LocalConfiguration.current
if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
fun DataSubmissionConfirmationScreen(onDismissed: () -> Unit) {
if (LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE) {
Row(
modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
Column(
modifier = Modifier.weight(1f).wrapContentWidth(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
) {
DataCollectionThumbnail(modifier = Modifier.weight(0.8f))
}
Column(
modifier = Modifier.fillMaxSize().weight(1f),
verticalArrangement = Arrangement.Center,
) {
DetailColumn()
Spacer(modifier = Modifier.height(24.dp))
CloseButton(modifier = Modifier.align(Alignment.CenterHorizontally), onDismiss = onDismiss)
}
DataSubmittedImage()
BodyContent { onDismissed() }
}
} else {
Column(modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background)) {
Spacer(modifier = Modifier.height(150.dp))
DataCollectionThumbnail(modifier = Modifier.padding(horizontal = 8.dp))
Spacer(modifier = Modifier.height(100.dp))
DetailColumn()
Spacer(modifier = Modifier.height(32.dp))
CloseButton(modifier = Modifier.align(Alignment.CenterHorizontally), onDismiss = onDismiss)
Column(
modifier = Modifier.fillMaxSize().background(MaterialTheme.colorScheme.background),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
) {
DataSubmittedImage()
BodyContent { onDismissed() }
}
}
}

@Composable
private fun DataCollectionThumbnail(modifier: Modifier = Modifier) {
private fun DataSubmittedImage() {
Image(
modifier = modifier,
painter = painterResource(id = R.drawable.data_submitted),
contentDescription = stringResource(R.string.data_submitted_image),
contentScale = ContentScale.Fit,
)
}

@Composable
private fun DetailColumn() {
Column(modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
private fun BodyContent(onDismiss: () -> Unit) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = stringResource(R.string.data_collection_complete),
color = MaterialTheme.colorScheme.onSurface,
fontFamily = FontFamily(Font(R.font.text_500)),
lineHeight = 28.sp,
fontSize = 22.sp,
Expand All @@ -114,34 +95,26 @@ private fun DetailColumn() {
fontSize = 14.sp,
lineHeight = 20.sp,
fontWeight = FontWeight(400),
color = MaterialTheme.colorScheme.onSurface,
fontFamily = FontFamily(Font(R.font.text_500)),
textAlign = TextAlign.Center,
)
}
}

@Composable
private fun CloseButton(modifier: Modifier = Modifier, onDismiss: () -> Unit) {
OutlinedButton(
modifier = modifier,
border = BorderStroke(width = 1.dp, color = MaterialTheme.colorScheme.outline),
onClick = { onDismiss() },
) {
Text(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp),
text = stringResource(id = R.string.close),
fontSize = 14.sp,
lineHeight = 20.sp,
fontFamily = FontFamily(Font(R.font.text_500)),
)
Spacer(modifier = Modifier.height(30.dp))
OutlinedButton(onClick = { onDismiss() }) {
Text(
modifier = Modifier.padding(horizontal = 24.dp, vertical = 10.dp),
text = stringResource(id = R.string.close),
fontSize = 14.sp,
lineHeight = 20.sp,
fontFamily = FontFamily(Font(R.font.text_500)),
)
}
}
}

@Composable
@Preview(heightDp = 320, widthDp = 800)
@Preview
@ExcludeFromJacocoGeneratedReport
fun DataSubmissionConfirmationDialogPreview() {
AppTheme { DataSubmissionConfirmationDialog {} }
fun DataSubmissionConfirmationScreenPreview() {
AppTheme { DataSubmissionConfirmationScreen {} }
}
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,28 @@ class DataCollectionFragmentTest : BaseHiltTest() {
assertSubmissionSaved(listOf(TASK_1_VALUE_DELTA, TASK_2_VALUE_DELTA))
}

@Test
fun `Displays close button on first task`() = runWithTestDispatcher {
setupFragment()

assertThat(getToolbar()?.navigationIcon).isNotNull()
}

@Test
fun `Clicking done on final task hides the navigation close button`() = runWithTestDispatcher {
setupFragment()

runner()
.inputText(TASK_1_RESPONSE)
.clickNextButton()
.validateTextIsNotDisplayed(TASK_1_NAME)
.validateTextIsDisplayed(TASK_2_NAME)
.selectOption(TASK_2_OPTION_LABEL)
.clickDoneButton() // Click "done" on final task

assertThat(getToolbar()?.navigationIcon).isNull()
}

@Test
fun `Clicking done on final task saves the submission and LOI when LOI is not provided`() =
runWithTestDispatcher {
Expand Down Expand Up @@ -487,6 +509,11 @@ class DataCollectionFragmentTest : BaseHiltTest() {

private fun runner() = TaskFragmentRunner(this, fragment)

private fun getToolbar() =
fragment.view?.findViewById<com.google.android.material.appbar.MaterialToolbar>(
R.id.data_collection_toolbar
)

companion object {
private const val TASK_ID_0 = "0"
const val TASK_0_NAME = "task 0"
Expand Down

0 comments on commit 7515b7e

Please sign in to comment.