Skip to content

Commit

Permalink
Use icons to make build status indicator color-blind friendly
Browse files Browse the repository at this point in the history
Fix #4
  • Loading branch information
vincent-paing committed Sep 24, 2022
1 parent 5a2b3f0 commit 83e50c9
Show file tree
Hide file tree
Showing 2 changed files with 156 additions and 110 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package dev.aungkyawpaing.ccdroidx.feature.projectlist
package dev.aungkyawpaing.ccdroidx.feature.projectlist.component

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.filled.Schedule
import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.OpenInBrowser
import androidx.compose.material.icons.outlined.VolumeOff
Expand All @@ -15,6 +14,8 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.clearAndSetSemantics
Expand All @@ -39,100 +40,122 @@ private val prettyTime = PrettyTime()

@Composable
fun ProjectNameText(
projectName: String,
modifier: Modifier
projectName: String, modifier: Modifier
) {
Text(
modifier = modifier,
text = projectName,
style = MaterialTheme.typography.titleMedium
modifier = modifier, text = projectName, style = MaterialTheme.typography.titleMedium
)
}

fun getBuildStatusColor(buildStatus: BuildStatus, buildState: BuildState): Int {
val buildStatusColor = when (buildState) {

enum class BuildStatusIndicatorStyle {
IN_PROGRESS, FAILED, SUCCESS
}

fun getBuildStatusIndicatorStyle(
buildStatus: BuildStatus, buildState: BuildState
): BuildStatusIndicatorStyle {
return when (buildState) {
BuildState.SLEEPING -> {
when (buildStatus) {
BuildStatus.SUCCESS -> R.color.build_success
BuildStatus.FAILURE -> R.color.build_fail
BuildStatus.EXCEPTION -> R.color.build_fail
BuildStatus.UNKNOWN -> R.color.build_fail
BuildStatus.SUCCESS -> BuildStatusIndicatorStyle.SUCCESS
BuildStatus.FAILURE -> BuildStatusIndicatorStyle.FAILED
BuildStatus.EXCEPTION -> BuildStatusIndicatorStyle.FAILED
BuildStatus.UNKNOWN -> BuildStatusIndicatorStyle.FAILED
}
}
BuildState.BUILDING, BuildState.CHECKING_MODIFICATIONS -> {
R.color.build_in_progress
BuildStatusIndicatorStyle.IN_PROGRESS
}
}
return buildStatusColor
}


fun getBuildStatusColor(buildStatusIndicatorStyle: BuildStatusIndicatorStyle): Int {
return when (buildStatusIndicatorStyle) {
BuildStatusIndicatorStyle.IN_PROGRESS -> R.color.build_in_progress
BuildStatusIndicatorStyle.FAILED -> R.color.build_fail
BuildStatusIndicatorStyle.SUCCESS -> R.color.build_success
}
}

fun getBuildStatusIndicator(buildStatusIndicatorStyle: BuildStatusIndicatorStyle): ImageVector {
return when (buildStatusIndicatorStyle) {
BuildStatusIndicatorStyle.IN_PROGRESS -> Icons.Filled.Autorenew
BuildStatusIndicatorStyle.FAILED -> Icons.Filled.Close
BuildStatusIndicatorStyle.SUCCESS -> Icons.Filled.Done
}
}


@Composable
fun ProjectBuildStatusIcon(
project: Project,
modifier: Modifier
project: Project, modifier: Modifier
) {
Box(
modifier = modifier
.size(36.dp)
.clip(CircleShape)
.border(width = 1.dp, color = MaterialTheme.colorScheme.onSurface, CircleShape)
.background(
colorResource(
id = getBuildStatusColor(
project.lastBuildStatus,
project.activity
)
)
)
.semantics {
contentDescription = "Status: ${project.lastBuildStatus}"
}

val buildStatusIndicatorStyle = getBuildStatusIndicatorStyle(
project.lastBuildStatus, project.activity
)

Box(modifier = modifier
.size(36.dp)
.clip(CircleShape)
.border(width = 1.dp, color = MaterialTheme.colorScheme.onSurface, CircleShape)
.background(
colorResource(
id = getBuildStatusColor(buildStatusIndicatorStyle)
)
)
.semantics {
contentDescription = "Status: ${project.lastBuildStatus}"
}) {
Icon(
getBuildStatusIndicator(buildStatusIndicatorStyle),
tint = Color.Black,
contentDescription = null,
modifier = Modifier
.size(24.dp)
.align(Alignment.Center)
)
}
}

@Composable
fun ProjectLastBuildText(
project: Project,
modifier: Modifier
project: Project, modifier: Modifier
) {
Text(
text = project.lastBuildLabel ?: "",
Text(text = project.lastBuildLabel ?: "",
style = MaterialTheme.typography.bodyMedium,
modifier = modifier
.padding(horizontal = 8.dp, vertical = 8.dp)
.semantics {
contentDescription = "Build Label : ${project.lastBuildLabel}."
}
)
})
}

@Composable
fun ProjectLastBuildAgoText(
project: Project,
modifier: Modifier
project: Project, modifier: Modifier
) {
Row(
modifier = modifier
.padding(horizontal = 8.dp, vertical = 8.dp)
modifier = modifier.padding(horizontal = 8.dp, vertical = 8.dp)
) {
Icon(
Icons.Default.Schedule, contentDescription = null,
Icons.Default.Schedule,
contentDescription = null,
modifier = Modifier
.size(16.dp)
.align(Alignment.CenterVertically)
)
val lastBuildAgo = prettyTime.format(project.lastBuildTime)
Text(
style = MaterialTheme.typography.bodyMedium,
Text(style = MaterialTheme.typography.bodyMedium,
text = lastBuildAgo,
modifier = Modifier
.padding(start = 4.dp)
.align(Alignment.CenterVertically)
.semantics {
contentDescription = "Last built: $lastBuildAgo}"
}
)
})
}
}

Expand Down Expand Up @@ -169,51 +192,40 @@ fun ProjectCard(
val (buildStatusIndicator, name, lastSyncTime, menu, buildLabel) = createRefs()

//More action
Box(
modifier = Modifier
.size(24.dp)
.constrainAs(menu) {
top.linkTo(parent.top)
end.linkTo(parent.end)
}
) {
Box(modifier = Modifier
.size(24.dp)
.constrainAs(menu) {
top.linkTo(parent.top)
end.linkTo(parent.end)
}) {
IconButton(onClick = onExpandMenu, modifier = Modifier.clearAndSetSemantics { }) {
Icon(Icons.Default.MoreVert, contentDescription = null)
}
DropdownMenu(
expanded = menuExpanded,
onDismissRequest = { menuExpanded = false }
) {
DropdownMenu(expanded = menuExpanded, onDismissRequest = { menuExpanded = false }) {
val muteMenuText = if (project.isMuted) {
stringResource(R.string.action_item_project_unmute)
} else {
stringResource(R.string.action_item_project_mute)
}
DropdownMenuItem(
text = { Text(text = muteMenuText) },
DropdownMenuItem(text = { Text(text = muteMenuText) },
onClick = { onToggleMute(project) },
leadingIcon = {
Icon(
Icons.Outlined.VolumeOff,
contentDescription = null
Icons.Outlined.VolumeOff, contentDescription = null
)
})
DropdownMenuItem(
text = { Text(text = stringResource(R.string.action_item_project_open_repo)) },
DropdownMenuItem(text = { Text(text = stringResource(R.string.action_item_project_open_repo)) },
onClick = { onOpenRepoClick(project) },
leadingIcon = {
Icon(
Icons.Outlined.OpenInBrowser,
contentDescription = null
Icons.Outlined.OpenInBrowser, contentDescription = null
)
})
DropdownMenuItem(
text = { Text(text = stringResource(R.string.action_item_project_delete_project)) },
DropdownMenuItem(text = { Text(text = stringResource(R.string.action_item_project_delete_project)) },
onClick = { onDeleteClick(project) },
leadingIcon = {
Icon(
Icons.Outlined.Delete,
contentDescription = null
Icons.Outlined.Delete, contentDescription = null
)
})
}
Expand All @@ -223,8 +235,7 @@ fun ProjectCard(
projectName = project.name,
modifier = Modifier
.padding(horizontal = 8.dp)
.constrainAs(name)
{
.constrainAs(name) {
linkTo(start = buildStatusIndicator.end, end = menu.start)
top.linkTo(
parent.top
Expand All @@ -239,23 +250,17 @@ fun ProjectCard(
modifier = Modifier.constrainAs(buildStatusIndicator) {
linkTo(top = name.top, bottom = parent.bottom)
start.linkTo(parent.start)
}
)
})

//Last build label
ProjectLastBuildText(
project = project,
modifier = Modifier.constrainAs(buildLabel)
{
end.linkTo(parent.end)
linkTo(top = menu.bottom, bottom = lastSyncTime.bottom, bias = 1.0f)
}
)
ProjectLastBuildText(project = project, modifier = Modifier.constrainAs(buildLabel) {
end.linkTo(parent.end)
linkTo(top = menu.bottom, bottom = lastSyncTime.bottom, bias = 1.0f)
})

ProjectLastBuildAgoText(
project = project,
modifier = Modifier.constrainAs(lastSyncTime)
{
modifier = Modifier.constrainAs(lastSyncTime) {
linkTo(start = buildStatusIndicator.end, end = buildLabel.start)
linkTo(top = name.bottom, bottom = parent.bottom)
width = Dimension.fillToConstraints
Expand All @@ -268,29 +273,69 @@ fun ProjectCard(

@Preview
@Composable
fun ProjectCardPreview() {
fun ProjectCardPreviewSuccess() {
Mdc3Theme {
ProjectCard(
Project(
id = 0L,
name = "vincent-paing/ccdroidx with very long name here!",
activity = BuildState.SLEEPING,
lastBuildStatus = BuildStatus.SUCCESS,
lastBuildLabel = "1234",
lastBuildTime = ZonedDateTime.now(),
nextBuildTime = null,
webUrl = "https://www.example.com",
feedUrl = "https://www.example.com/cc.xml",
isMuted = false,
mutedUntil = null,
authentication = Authentication(
username = "username",
password = "password"
)
),
{},
{},
{}
)
ProjectCard(Project(
id = 0L,
name = "vincent-paing/ccdroidx with very long name here!",
activity = BuildState.SLEEPING,
lastBuildStatus = BuildStatus.SUCCESS,
lastBuildLabel = "1234",
lastBuildTime = ZonedDateTime.now(),
nextBuildTime = null,
webUrl = "https://www.example.com",
feedUrl = "https://www.example.com/cc.xml",
isMuted = false,
mutedUntil = null,
authentication = Authentication(
username = "username", password = "password"
)
), {}, {}, {})
}
}

@Preview
@Composable
fun ProjectCardPreviewFailed() {
Mdc3Theme {
ProjectCard(Project(
id = 0L,
name = "vincent-paing/ccdroidx with very long name here!",
activity = BuildState.SLEEPING,
lastBuildStatus = BuildStatus.FAILURE,
lastBuildLabel = "1234",
lastBuildTime = ZonedDateTime.now(),
nextBuildTime = null,
webUrl = "https://www.example.com",
feedUrl = "https://www.example.com/cc.xml",
isMuted = false,
mutedUntil = null,
authentication = Authentication(
username = "username", password = "password"
)
), {}, {}, {})
}
}

@Preview
@Composable
fun ProjectCardPreviewInProgress() {
Mdc3Theme {
ProjectCard(Project(
id = 0L,
name = "vincent-paing/ccdroidx with very long name here!",
activity = BuildState.BUILDING,
lastBuildStatus = BuildStatus.SUCCESS,
lastBuildLabel = "1234",
lastBuildTime = ZonedDateTime.now(),
nextBuildTime = null,
webUrl = "https://www.example.com",
feedUrl = "https://www.example.com/cc.xml",
isMuted = false,
mutedUntil = null,
authentication = Authentication(
username = "username", password = "password"
)
), {}, {}, {})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import dev.aungkyawpaing.ccdroidx.data.Project
import dev.aungkyawpaing.ccdroidx.feature.projectlist.component.ProjectCard

@Composable
fun ProjectList(
Expand Down

0 comments on commit 83e50c9

Please sign in to comment.