Skip to content

Commit

Permalink
Taco sample fast follows (slackhq#523)
Browse files Browse the repository at this point in the history
Addressing a couple minor comments that weren't fixed in the initial
[PR](slackhq#496). Also reworked how
colours were applied to address a couple issues in dark mode.


https://user-images.githubusercontent.com/56161/228905793-b88cfb6d-5359-4a81-a649-7e42b476eb5b.mp4
  • Loading branch information
kierse authored Apr 3, 2023
1 parent a371eff commit 00370e7
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ package com.slack.circuit.tacos

import androidx.activity.compose.BackHandler
import androidx.annotation.StringRes
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
Expand All @@ -16,6 +15,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.ArrowForward
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
Expand All @@ -30,7 +30,6 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.graphics.vector.rememberVectorPainter
import androidx.compose.ui.res.stringResource
Expand Down Expand Up @@ -108,14 +107,11 @@ internal class OrderTacosPresenter(
private val toppingsProducer: OrderStep.StateProducer<ToppingsOrderStep.State>,
private val confirmationProducer: OrderStep.StateProducer<ConfirmationOrderStep.OrderState>,
private val summaryProducer: OrderStep.StateProducer<SummaryOrderStep.SummaryState>,
private val initialStep: OrderStep = FillingsOrderStep,
private val initialOrderDetails: OrderDetails = OrderDetails()
) : Presenter<OrderTacosScreen.State> {
@Composable override fun present(): OrderTacosScreen.State = presentInternal()

@Composable
internal fun presentInternal(
initialStep: OrderStep = FillingsOrderStep,
initialOrderDetails: OrderDetails = OrderDetails(),
): OrderTacosScreen.State {
override fun present(): OrderTacosScreen.State {
var currentStep by remember { mutableStateOf(initialStep) }
var orderDetails by remember { mutableStateOf(initialOrderDetails) }
var isNextEnabled by remember { mutableStateOf(false) }
Expand Down Expand Up @@ -168,7 +164,7 @@ private fun processNavigation(
onNavEvent: (OrderStep) -> Unit
) {
val newIndex = currentStep.index + navEvent.indexModifier
onNavEvent(orderSteps.getOrElse(newIndex) { currentStep })
onNavEvent(orderSteps[newIndex])
}

private fun updateOrder(
Expand Down Expand Up @@ -267,17 +263,9 @@ private fun NavigationButton(
) {
if (!visible) return

val tintColour =
when (enabled) {
true -> MaterialTheme.colorScheme.onSurface
false -> MaterialTheme.colorScheme.outline
}

IconButton(modifier = modifier, enabled = enabled, onClick = onClick) {
Image(
modifier = Modifier,
Icon(
painter = rememberVectorPainter(image = direction.icon),
colorFilter = ColorFilter.tint(tintColour),
contentDescription = stringResource(direction.descriptionResId),
)
}
Expand All @@ -293,18 +281,24 @@ private fun OrderTotal(
) {
if (!isVisible) return

val color =
val bdColor =
when {
onConfirmationStep -> MaterialTheme.colorScheme.onTertiaryContainer
else -> MaterialTheme.colorScheme.tertiaryContainer
onConfirmationStep -> MaterialTheme.colorScheme.secondaryContainer
else -> MaterialTheme.colorScheme.primaryContainer
}
val textColor =
when {
onConfirmationStep -> MaterialTheme.colorScheme.onSecondaryContainer
else -> MaterialTheme.colorScheme.onPrimaryContainer
}

var boxModifier =
modifier
.fillMaxWidth()
.defaultMinSize(minHeight = 28.dp)
.defaultMinSize(minHeight = 32.dp)
.padding(horizontal = 4.dp)
.clip(RoundedCornerShape(4.dp))
.background(color)
.background(bdColor)
if (onConfirmationStep) boxModifier = boxModifier.clickable(onClick = onClick)

val label =
Expand All @@ -316,13 +310,13 @@ private fun OrderTotal(
Text(
text = label,
modifier = Modifier.align(Alignment.CenterStart).padding(start = 4.dp),
color = MaterialTheme.colorScheme.onPrimary,
color = textColor,
fontWeight = FontWeight.Bold,
)
Text(
text = "$$orderCost",
modifier = Modifier.align(Alignment.CenterEnd).padding(end = 4.dp),
color = MaterialTheme.colorScheme.onPrimary,
color = textColor,
fontWeight = FontWeight.Bold,
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
Expand Down Expand Up @@ -85,7 +85,7 @@ internal fun FillingsUi(state: FillingsOrderStep.State, modifier: Modifier = Mod
@Composable
private fun Loading(modifier: Modifier = Modifier) {
Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
CircularProgressIndicator(color = MaterialTheme.colorScheme.onSurface)
CircularProgressIndicator()
}
}

Expand All @@ -96,7 +96,7 @@ private fun FillingsList(
) {
val sink = state.eventSink
val scrollState = rememberScrollState()
Column(modifier = modifier.verticalScroll(scrollState)) {
Column(modifier = modifier.verticalScroll(scrollState).fillMaxWidth()) {
Instructions(resId = R.string.fillings_step_instructions)
state.list.forEach { ingredient ->
Filling(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Checkbox
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.produceState
Expand Down Expand Up @@ -112,7 +112,7 @@ internal fun ToppingsUi(state: ToppingsOrderStep.State, modifier: Modifier = Mod
@Composable
private fun Loading(modifier: Modifier = Modifier) {
Box(modifier = modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
CircularProgressIndicator(color = MaterialTheme.colorScheme.onSurface)
CircularProgressIndicator()
}
}

Expand All @@ -123,7 +123,7 @@ private fun ToppingsList(
) {
val sink = state.eventSink
val scrollState = rememberScrollState()
Column(modifier = modifier.verticalScroll(scrollState)) {
Column(modifier = modifier.verticalScroll(scrollState).fillMaxWidth()) {
Instructions(resId = R.string.toppings_step_instructions)
state.list.forEach { ingredient ->
Topping(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ import androidx.compose.ui.graphics.Color

val md_theme_light_primary = Color(0xFF6750A4)
val md_theme_light_onPrimary = Color(0xFFFFFFFF)
val md_theme_light_primaryContainer = Color(0xFFE9DDFF)
val md_theme_light_onPrimaryContainer = Color(0xFF22005D)
val md_theme_light_primaryContainer = Color(0xFF7E5260)
val md_theme_light_onPrimaryContainer = Color(0xFFFFFFFF)
val md_theme_light_secondary = Color(0xFF625B71)
val md_theme_light_onSecondary = Color(0xFFFFFFFF)
val md_theme_light_secondaryContainer = Color(0xFFE8DEF8)
val md_theme_light_onSecondaryContainer = Color(0xFF1E192B)
val md_theme_light_secondaryContainer = Color(0xFFBA1A1A)
val md_theme_light_onSecondaryContainer = Color(0xFFFFFFFF)
val md_theme_light_tertiary = Color(0xFF7E5260)
val md_theme_light_onTertiary = Color(0xFFFFFFFF)
val md_theme_light_tertiaryContainer = Color(0xFF7E5260)
val md_theme_light_onTertiaryContainer = Color(0xFFBA1A1A)
val md_theme_light_tertiaryContainer = Color(0xFFFFD9E3)
val md_theme_light_onTertiaryContainer = Color(0xFF31101D)
val md_theme_light_error = Color(0xFFBA1A1A)
val md_theme_light_errorContainer = Color(0xFFFFDAD6)
val md_theme_light_onError = Color(0xFFFFFFFF)
Expand All @@ -39,12 +39,12 @@ val md_theme_light_scrim = Color(0xFF000000)

val md_theme_dark_primary = Color(0xFFCFBCFF)
val md_theme_dark_onPrimary = Color(0xFF381E72)
val md_theme_dark_primaryContainer = Color(0xFF4F378A)
val md_theme_dark_onPrimaryContainer = Color(0xFFE9DDFF)
val md_theme_dark_primaryContainer = Color(0xFF7A294B)
val md_theme_dark_onPrimaryContainer = Color(0xFFFFFFFF)
val md_theme_dark_secondary = Color(0xFFCBC2DB)
val md_theme_dark_onSecondary = Color(0xFF332D41)
val md_theme_dark_secondaryContainer = Color(0xFF4A4458)
val md_theme_dark_onSecondaryContainer = Color(0xFFE8DEF8)
val md_theme_dark_secondaryContainer = Color(0xFF930009)
val md_theme_dark_onSecondaryContainer = Color(0xFFFFFFFF)
val md_theme_dark_tertiary = Color(0xFFEFB8C8)
val md_theme_dark_onTertiary = Color(0xFF4A2532)
val md_theme_dark_tertiaryContainer = Color(0xFF633B48)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable

private val LightColors =
private val LightMaterialColors =
lightColorScheme(
primary = md_theme_light_primary,
onPrimary = md_theme_light_onPrimary,
Expand Down Expand Up @@ -41,7 +41,7 @@ private val LightColors =
scrim = md_theme_light_scrim,
)

private val DarkColors =
private val DarkMaterialColors =
darkColorScheme(
primary = md_theme_dark_primary,
onPrimary = md_theme_dark_onPrimary,
Expand Down Expand Up @@ -76,11 +76,11 @@ private val DarkColors =

@Composable
fun TacoTheme(useDarkTheme: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) {
val colors =
val materialColors =
when {
useDarkTheme -> DarkColors
else -> LightColors
useDarkTheme -> DarkMaterialColors
else -> LightMaterialColors
}

MaterialTheme(colorScheme = colors, content = content)
MaterialTheme(colorScheme = materialColors, content = content)
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,33 +68,16 @@ class OrderTacosPresenterTest {
toppingsProducer = { _, _ -> ToppingsOrderStep.State.Loading },
confirmationProducer = { _, _ -> error("wrong step") },
summaryProducer = { _, _ -> error("wrong step") },
initialStep = ToppingsOrderStep
)

moleculeFlow(RecompositionClock.Immediate) { presenter.presentInternal(ToppingsOrderStep) }
moleculeFlow(RecompositionClock.Immediate) { presenter.present() }
.test {
awaitItem().run { eventSink(OrderTacosScreen.Event.Previous) }
assertThat(awaitItem().stepState).isEqualTo(FillingsOrderStep.State.Loading)
}
}

@Test
fun `present - do nothing if navigation event does not make sense`() = runTest {
val presenter =
OrderTacosPresenter(
fillingsProducer = { _, _ -> FillingsOrderStep.State.Loading },
toppingsProducer = { _, _ -> ToppingsOrderStep.State.Loading },
confirmationProducer = { _, _ -> error("wrong step") },
summaryProducer = { _, _ -> error("wrong step") },
)

presenter.test {
awaitItem().run { eventSink(OrderTacosScreen.Event.Previous) }

// navigation invalid; should not recompose
expectNoEvents()
}
}

@Test
fun `present - toggles next button based on OrderStep validation event`() = runTest {
lateinit var sink: (OrderStep.Event) -> Unit
Expand Down Expand Up @@ -162,9 +145,10 @@ class OrderTacosPresenterTest {
},
confirmationProducer = { _, _ -> error("wrong step") },
summaryProducer = { _, _ -> error("wrong step") },
initialStep = ToppingsOrderStep,
)

moleculeFlow(RecompositionClock.Immediate) { presenter.presentInternal(ToppingsOrderStep) }
moleculeFlow(RecompositionClock.Immediate) { presenter.present() }
.test {
awaitItem()
assertThat(details).isEqualTo(OrderDetails())
Expand Down Expand Up @@ -194,9 +178,10 @@ class OrderTacosPresenterTest {
sink = eventSink
SummaryOrderStep.SummaryState {}
},
initialStep = SummaryOrderStep,
)

moleculeFlow(RecompositionClock.Immediate) { presenter.presentInternal(SummaryOrderStep) }
moleculeFlow(RecompositionClock.Immediate) { presenter.present() }
.test {
assertThat(awaitItem().stepState).isInstanceOf(SummaryOrderStep.SummaryState::class.java)

Expand All @@ -222,11 +207,10 @@ class OrderTacosPresenterTest {
toppingsProducer = { _, _ -> error("wrong step") },
confirmationProducer = { _, _ -> error("wrong step") },
summaryProducer = { _, _ -> error("wrong step") },
initialOrderDetails = initialData,
)

moleculeFlow(RecompositionClock.Immediate) {
presenter.presentInternal(initialOrderDetails = initialData)
}
moleculeFlow(RecompositionClock.Immediate) { presenter.present() }
.test { awaitItem().run { assertThat(orderCost).isEqualTo(expectedCost.toCurrencyString()) } }
}
}

0 comments on commit 00370e7

Please sign in to comment.