Skip to content

Commit 7f27820

Browse files
authored
Merge pull request #350 from ryanw-mobile/feature/344-agile-screen-cheapest-timeslots
(#344) agile screen: blink cheapest timeslots
2 parents 7fd188c + bc62638 commit 7f27820

File tree

7 files changed

+51
-15
lines changed

7 files changed

+51
-15
lines changed

composeApp/src/commonMain/kotlin/com/rwmobi/kunigami/ui/components/IndicatorTextValueGridItem.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
package com.rwmobi.kunigami.ui.components
1717

18+
import androidx.compose.animation.core.animateFloatAsState
1819
import androidx.compose.desktop.ui.tooling.preview.Preview
1920
import androidx.compose.foundation.layout.Arrangement
2021
import androidx.compose.foundation.layout.Box
@@ -29,8 +30,14 @@ import androidx.compose.foundation.layout.wrapContentWidth
2930
import androidx.compose.material3.MaterialTheme
3031
import androidx.compose.material3.Text
3132
import androidx.compose.runtime.Composable
33+
import androidx.compose.runtime.LaunchedEffect
34+
import androidx.compose.runtime.getValue
35+
import androidx.compose.runtime.mutableStateOf
36+
import androidx.compose.runtime.remember
37+
import androidx.compose.runtime.setValue
3238
import androidx.compose.ui.Alignment
3339
import androidx.compose.ui.Modifier
40+
import androidx.compose.ui.draw.alpha
3441
import androidx.compose.ui.draw.drawBehind
3542
import androidx.compose.ui.geometry.Offset
3643
import androidx.compose.ui.geometry.Size
@@ -40,17 +47,34 @@ import androidx.compose.ui.text.font.FontWeight
4047
import androidx.compose.ui.unit.dp
4148
import com.rwmobi.kunigami.ui.composehelper.getScreenSizeInfo
4249
import com.rwmobi.kunigami.ui.theme.getDimension
50+
import kotlinx.coroutines.delay
4351

4452
@Composable
4553
fun IndicatorTextValueGridItem(
4654
modifier: Modifier = Modifier,
4755
indicatorColor: Color,
4856
label: String,
4957
value: String,
58+
shouldBlinkValue: Boolean = false,
5059
) {
5160
val dimension = getScreenSizeInfo().getDimension()
61+
var isBlinkingTextVisible by remember { mutableStateOf(true) }
62+
val blinkingAlpha by animateFloatAsState(if (isBlinkingTextVisible) 1f else 0f)
63+
LaunchedEffect(shouldBlinkValue) {
64+
if (shouldBlinkValue) {
65+
while (true) {
66+
isBlinkingTextVisible = !isBlinkingTextVisible
67+
delay(if (isBlinkingTextVisible) 1000 else 500)
68+
}
69+
} else {
70+
// Clean up
71+
isBlinkingTextVisible = true
72+
}
73+
}
74+
5275
Row(
5376
modifier = modifier.fillMaxWidth()
77+
.alpha(blinkingAlpha)
5478
.drawBehind {
5579
val width = dimension.grid_1.toPx()
5680
drawRect(

composeApp/src/commonMain/kotlin/com/rwmobi/kunigami/ui/destinations/agile/AgileScreen.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ fun AgileScreen(
228228
partitionedItems = rateGroupsWithPartitions.partitionedItems,
229229
shouldHideLastColumn = shouldHideLastRateGroupColumn,
230230
rateRange = uiState.rateRange,
231+
minimumVatInclusivePrice = uiState.minimumVatInclusivePrice,
231232
rowIndex = rowIndex,
232233
)
233234
}

composeApp/src/commonMain/kotlin/com/rwmobi/kunigami/ui/destinations/agile/AgileUIState.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ data class AgileUIState(
5151
val latestFixedTariff: Tariff? = null,
5252
val latestFlexibleTariff: Tariff? = null,
5353
val rateGroupedCells: List<RateGroup> = emptyList(),
54+
val minimumVatInclusivePrice: Double = 0.0,
5455
val rateRange: ClosedFloatingPointRange<Double> = 0.0..0.0,
5556
val barChartData: BarChartData? = null,
5657
val requestScrollToTop: Boolean = false,

composeApp/src/commonMain/kotlin/com/rwmobi/kunigami/ui/destinations/agile/components/AgileTariffCardAdaptive.kt

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,10 @@ internal fun AgileTariffCardAdaptive(
106106
null
107107
}
108108

109-
val isCurrentRateOverpriced: Boolean = vatInclusivePrice?.let {
110-
it >= minOf(
111-
latestFixedTariff?.vatInclusiveStandardUnitRate ?: Double.MAX_VALUE,
112-
latestFlexibleTariff?.vatInclusiveStandardUnitRate ?: Double.MAX_VALUE,
113-
)
114-
} ?: false
109+
val isCurrentRateOverpriced: Boolean = vatInclusivePrice >= minOf(
110+
latestFixedTariff?.vatInclusiveStandardUnitRate ?: Double.MAX_VALUE,
111+
latestFlexibleTariff?.vatInclusiveStandardUnitRate ?: Double.MAX_VALUE,
112+
)
115113

116114
when (requestedAdaptiveLayout) {
117115
WindowWidthSizeClass.Compact,

composeApp/src/commonMain/kotlin/com/rwmobi/kunigami/ui/destinations/agile/components/CurrentRateTile.kt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,16 @@ internal fun CurrentRateTile(
123123
}
124124
}
125125

126-
// Launch a coroutine to toggle visibility
127-
var isVisible by remember { mutableStateOf(isCurrentRateOverpriced) }
128-
LaunchedEffect(Unit) {
126+
var isOverpricedTagVisible by remember { mutableStateOf(isCurrentRateOverpriced) }
127+
LaunchedEffect(isCurrentRateOverpriced) {
129128
if (isCurrentRateOverpriced) {
130129
while (true) {
131-
isVisible = !isVisible // Toggle visibility
132-
delay(500) // Blink duration
130+
isOverpricedTagVisible = !isOverpricedTagVisible
131+
delay(500)
133132
}
134133
} else {
135134
// Clean up if we move on to a cheaper slot
136-
isVisible = false
135+
isOverpricedTagVisible = false
137136
}
138137
}
139138
Row(
@@ -148,7 +147,7 @@ internal fun CurrentRateTile(
148147
)
149148

150149
AnimatedVisibility(
151-
visible = isVisible,
150+
visible = isOverpricedTagVisible,
152151
enter = fadeIn(),
153152
exit = fadeOut(),
154153
) {

composeApp/src/commonMain/kotlin/com/rwmobi/kunigami/ui/destinations/agile/components/RateGroupCells.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ internal fun RateGroupCells(
3737
rowIndex: Int,
3838
shouldHideLastColumn: Boolean,
3939
rateRange: ClosedFloatingPointRange<Double>,
40+
minimumVatInclusivePrice: Double,
4041
) {
4142
val dimension = getScreenSizeInfo().getDimension()
4243
Row(
@@ -52,6 +53,9 @@ internal fun RateGroupCells(
5253
for (columnIndex in columnRangeToRender) {
5354
val item = partitionedItems.getOrNull(columnIndex)?.getOrNull(rowIndex)
5455
if (item != null) {
56+
val value = item.vatInclusivePrice.roundToTwoDecimalPlaces().toString(precision = 2)
57+
val shouldBlinkValue = item.vatInclusivePrice == minimumVatInclusivePrice
58+
5559
IndicatorTextValueGridItem(
5660
modifier = Modifier.weight(1f),
5761
indicatorColor = RatePalette.lookupColorFromRange(
@@ -60,8 +64,8 @@ internal fun RateGroupCells(
6064
shouldUseDarkTheme = shouldUseDarkTheme(),
6165
),
6266
label = item.validity.start.getLocalHHMMString(),
63-
value = item.vatInclusivePrice.roundToTwoDecimalPlaces()
64-
.toString(precision = 2),
67+
value = value,
68+
shouldBlinkValue = shouldBlinkValue,
6569
)
6670
} else {
6771
Spacer(modifier = Modifier.weight(1f))

composeApp/src/commonMain/kotlin/com/rwmobi/kunigami/ui/viewmodels/AgileViewModel.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,12 @@ class AgileViewModel(
174174
}
175175

176176
val rateGroupedCells = groupChartCells(rates = rates)
177+
val minimumVatInclusivePrice = getMinimumVatInclusivePrice(rateGroupedCells)
177178
_uiState.update { currentUiState ->
178179
currentUiState.copy(
179180
requestedScreenType = AgileScreenType.Chart,
180181
rateGroupedCells = rateGroupedCells,
182+
minimumVatInclusivePrice = minimumVatInclusivePrice,
181183
rateRange = rateRange,
182184
barChartData = BarChartData.fromRates(
183185
rates = rates,
@@ -300,6 +302,13 @@ class AgileViewModel(
300302
)
301303
}
302304

305+
private fun getMinimumVatInclusivePrice(rateGroupedCells: List<RateGroup>): Double {
306+
return rateGroupedCells
307+
.flatMap { it.rates }
308+
.map { it.vatInclusivePrice }
309+
.minOrNull() ?: 0.0
310+
}
311+
303312
override fun onCleared() {
304313
super.onCleared()
305314
Logger.v("AgileViewModel", message = { "onCleared" })

0 commit comments

Comments
 (0)