Skip to content

Commit e6139fe

Browse files
authored
Improve UX of sync status screen (#3337)
* card ui update * updated test * added loader * update ui
1 parent 0a8939e commit e6139fe

File tree

5 files changed

+48
-53
lines changed

5 files changed

+48
-53
lines changed

app/src/main/java/org/groundplatform/android/ui/syncstatus/SyncListItem.kt

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,25 +22,27 @@ import androidx.compose.foundation.layout.Spacer
2222
import androidx.compose.foundation.layout.fillMaxWidth
2323
import androidx.compose.foundation.layout.height
2424
import androidx.compose.foundation.layout.padding
25-
import androidx.compose.foundation.layout.width
25+
import androidx.compose.foundation.layout.size
26+
import androidx.compose.material3.CircularProgressIndicator
2627
import androidx.compose.material3.HorizontalDivider
2728
import androidx.compose.material3.Icon
2829
import androidx.compose.material3.MaterialTheme
2930
import androidx.compose.material3.Text
3031
import androidx.compose.runtime.Composable
3132
import androidx.compose.ui.Alignment.Companion.CenterVertically
3233
import androidx.compose.ui.Modifier
33-
import androidx.compose.ui.graphics.vector.ImageVector
34+
import androidx.compose.ui.platform.LocalConfiguration
3435
import androidx.compose.ui.platform.LocalContext
36+
import androidx.compose.ui.res.painterResource
3537
import androidx.compose.ui.res.stringResource
36-
import androidx.compose.ui.res.vectorResource
3738
import androidx.compose.ui.text.TextStyle
3839
import androidx.compose.ui.text.font.Font
3940
import androidx.compose.ui.text.font.FontFamily
4041
import androidx.compose.ui.text.font.FontWeight
4142
import androidx.compose.ui.tooling.preview.Preview
4243
import androidx.compose.ui.unit.dp
4344
import androidx.compose.ui.unit.sp
45+
import java.text.SimpleDateFormat
4446
import java.util.Date
4547
import org.groundplatform.android.R
4648
import org.groundplatform.android.model.mutation.Mutation
@@ -61,8 +63,9 @@ fun SyncListItem(modifier: Modifier, detail: SyncStatusDetail) {
6163
fontWeight = FontWeight(500),
6264
letterSpacing = 0.1.sp,
6365
)
66+
Spacer(Modifier.height(4.dp))
6467
Text(
65-
text = detail.user,
68+
text = "${detail.label}${detail.subtitle}",
6669
style =
6770
TextStyle(
6871
fontSize = 16.sp,
@@ -78,20 +81,12 @@ fun SyncListItem(modifier: Modifier, detail: SyncStatusDetail) {
7881
fontWeight = FontWeight(400),
7982
color = MaterialTheme.colorScheme.onSurfaceVariant,
8083
)
81-
Text(text = detail.label, style = textStyle)
82-
Text(text = detail.subtitle, style = textStyle)
84+
Text(text = detail.description, style = textStyle)
85+
Spacer(Modifier.height(4.dp))
86+
Text(text = stringResource(id = detail.status.toLabel()), fontSize = 11.sp)
8387
}
8488
Column(modifier = modifier.padding(start = 16.dp).align(alignment = CenterVertically)) {
85-
Row(verticalAlignment = CenterVertically) {
86-
Text(text = stringResource(id = detail.status.toLabel()), fontSize = 11.sp)
87-
Spacer(modifier = Modifier.width(10.dp))
88-
Icon(
89-
imageVector = ImageVector.vectorResource(id = detail.status.toIcon()),
90-
contentDescription = "",
91-
tint = MaterialTheme.colorScheme.onSurfaceVariant,
92-
modifier = Modifier.padding(1.dp).width(24.dp).height(24.dp),
93-
)
94-
}
89+
StatusIcon(status = detail.status, modifier = Modifier)
9590
}
9691
}
9792
HorizontalDivider(
@@ -102,9 +97,35 @@ fun SyncListItem(modifier: Modifier, detail: SyncStatusDetail) {
10297
}
10398
}
10499

100+
private fun Mutation.SyncStatus.isActiveProgress(): Boolean =
101+
this == Mutation.SyncStatus.IN_PROGRESS || this == Mutation.SyncStatus.MEDIA_UPLOAD_IN_PROGRESS
102+
103+
@Composable
104+
private fun StatusIcon(status: Mutation.SyncStatus, modifier: Modifier = Modifier) {
105+
val tint = MaterialTheme.colorScheme.onSurfaceVariant
106+
107+
if (status.isActiveProgress()) {
108+
CircularProgressIndicator(
109+
modifier = modifier.padding(1.dp).size(24.dp),
110+
strokeWidth = 2.dp,
111+
color = tint,
112+
)
113+
} else {
114+
Icon(
115+
painter = painterResource(id = status.toIcon()),
116+
contentDescription = null,
117+
tint = tint,
118+
modifier = modifier.padding(1.dp).size(24.dp),
119+
)
120+
}
121+
}
122+
105123
@Composable
106-
private fun Date.toFormattedDate(): String =
107-
DateFormat.getDateFormat(LocalContext.current).format(this)
124+
private fun Date.toFormattedDate(): String {
125+
val locale = LocalConfiguration.current.locales[0]
126+
val dateFormat = SimpleDateFormat("MMM d, yyyy", locale)
127+
return dateFormat.format(this)
128+
}
108129

109130
@Composable
110131
private fun Date.toFormattedTime(): String =
@@ -129,7 +150,7 @@ private fun Mutation.SyncStatus.toIcon(): Int =
129150
Mutation.SyncStatus.MEDIA_UPLOAD_IN_PROGRESS,
130151
Mutation.SyncStatus.IN_PROGRESS -> R.drawable.ic_sync
131152
Mutation.SyncStatus.MEDIA_UPLOAD_PENDING -> R.drawable.baseline_check_24
132-
Mutation.SyncStatus.COMPLETED -> R.drawable.outline_done_all_24
153+
Mutation.SyncStatus.COMPLETED -> R.drawable.baseline_check_24
133154
Mutation.SyncStatus.FAILED -> R.drawable.outline_error_outline_24
134155
Mutation.SyncStatus.UNKNOWN -> error("Unexpected status")
135156
}
@@ -145,6 +166,7 @@ fun PreviewSyncListItem(
145166
label = "Map the farms",
146167
subtitle = "IDX21311",
147168
status = Mutation.SyncStatus.PENDING,
169+
description = "Lacuna Fund Cocoa Mapping",
148170
)
149171
) {
150172
AppTheme { SyncListItem(Modifier, detail) }

app/src/main/java/org/groundplatform/android/ui/syncstatus/SyncStatusDetail.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,6 @@ data class SyncStatusDetail(
3434
val label: String,
3535
/** A human-readable label providing further information on the change. */
3636
val subtitle: String,
37+
/** A description of the survey. */
38+
val description: String = "",
3739
)

app/src/main/java/org/groundplatform/android/ui/syncstatus/SyncStatusViewModel.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ internal constructor(
8181
status = status,
8282
label = locationOfInterestHelper.getJobName(loi) ?: "",
8383
subtitle = locationOfInterestHelper.getDisplayLoiName(loi),
84+
description = surveyRepository.getOfflineSurvey(mutation.surveyId)?.description ?: "",
8485
)
8586
}
8687
}
@@ -92,6 +93,7 @@ internal constructor(
9293
status = status,
9394
label = mutation.job.name ?: "",
9495
subtitle = surveyRepository.getOfflineSurvey(mutation.surveyId)?.title ?: "",
96+
description = surveyRepository.getOfflineSurvey(mutation.surveyId)?.description ?: "",
9597
)
9698
}
9799
}

app/src/main/res/drawable/outline_done_all_24.xml

Lines changed: 0 additions & 28 deletions
This file was deleted.

app/src/test/java/org/groundplatform/android/ui/syncstatus/SyncStatusFragmentTest.kt

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,9 @@ class SyncStatusFragmentTest : BaseHiltTest() {
8484
setupFragment()
8585

8686
composeTestRule.onNodeWithTag("sync list").assertIsDisplayed()
87-
composeTestRule.onNodeWithText("User").assertIsDisplayed() // User's display name
87+
composeTestRule.onNodeWithText("Job • Test LOI Name").assertIsDisplayed()
8888
composeTestRule.onNodeWithText("Pending").assertIsDisplayed() // Status
89-
composeTestRule.onNodeWithText("Job").assertIsDisplayed() // Label
90-
composeTestRule.onNodeWithText("Test LOI Name").assertIsDisplayed() // Subtitle
89+
composeTestRule.onNodeWithText("Test survey description").assertIsDisplayed() // Description
9190
}
9291

9392
@Test
@@ -103,10 +102,8 @@ class SyncStatusFragmentTest : BaseHiltTest() {
103102
setupFragment()
104103

105104
composeTestRule.onNodeWithTag("sync list").assertIsDisplayed()
106-
composeTestRule.onNodeWithText("User").assertIsDisplayed() // User's display name
105+
composeTestRule.onNodeWithText("Job • Survey title").assertIsDisplayed()
107106
composeTestRule.onNodeWithText("Pending").assertIsDisplayed() // Status
108-
composeTestRule.onNodeWithText("Job").assertIsDisplayed() // Label
109-
composeTestRule.onNodeWithText("Survey title").assertIsDisplayed() // Subtitle
110107
}
111108

112109
private fun setupSurvey() = runWithTestDispatcher {

0 commit comments

Comments
 (0)