Compare commits
1 commit
feat/depar
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 8b3016004b |
2 changed files with 207 additions and 183 deletions
|
|
@ -1,11 +1,11 @@
|
||||||
[versions]
|
[versions]
|
||||||
agp = "9.1.0"
|
agp = "9.1.0"
|
||||||
android-compileSdk = "36"
|
android-compileSdk = "37"
|
||||||
android-minSdk = "24"
|
android-minSdk = "24"
|
||||||
android-targetSdk = "36"
|
android-targetSdk = "37"
|
||||||
androidx-activity= "1.13.0"
|
androidx-activity= "1.13.0"
|
||||||
androidx-lifecycle = "2.10.0"
|
androidx-lifecycle = "2.10.0"
|
||||||
compose-multiplatform = "1.11.0-alpha04"
|
compose-multiplatform = "1.12.0-alpha02"
|
||||||
composeunstyled = "1.49.6"
|
composeunstyled = "1.49.6"
|
||||||
coroutines = "1.10.2"
|
coroutines = "1.10.2"
|
||||||
geo = "0.8.0"
|
geo = "0.8.0"
|
||||||
|
|
@ -19,7 +19,7 @@ ktor = "3.4.1"
|
||||||
logback = "1.5.32"
|
logback = "1.5.32"
|
||||||
maplibre = "0.12.1"
|
maplibre = "0.12.1"
|
||||||
material = "1.7.3"
|
material = "1.7.3"
|
||||||
material3 = "1.11.0-alpha04"
|
material3 = "1.11.0-alpha07"
|
||||||
okio = "3.17.0"
|
okio = "3.17.0"
|
||||||
playServicesLocation = "21.3.0"
|
playServicesLocation = "21.3.0"
|
||||||
secretsGradlePlugin = "2.0.1"
|
secretsGradlePlugin = "2.0.1"
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,9 @@
|
||||||
package moe.lava.banksia.ui.layout.info
|
package moe.lava.banksia.ui.layout.info
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.animation.expandVertically
|
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.animation.shrinkVertically
|
|
||||||
import androidx.compose.animation.togetherWith
|
import androidx.compose.animation.togetherWith
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
|
@ -15,12 +12,12 @@ import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
|
|
@ -34,10 +31,8 @@ import androidx.compose.material3.SegmentedListItem
|
||||||
import androidx.compose.material3.ShapeDefaults
|
import androidx.compose.material3.ShapeDefaults
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
|
@ -85,25 +80,213 @@ data class StopInfoPanelState(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun listColors() = ListItemDefaults.colors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
||||||
|
selectedContainerColor = MaterialTheme.colorScheme.primary,
|
||||||
|
selectedContentColor = MaterialTheme.colorScheme.onPrimary,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
|
private fun MonoPlatform(
|
||||||
|
state: StopInfoPanelState.DeparturePlatforms
|
||||||
|
) {
|
||||||
|
val departures = state.departures
|
||||||
|
val lazyState = LazyListState(firstVisibleItemIndex =
|
||||||
|
departures.indexOfFirst {
|
||||||
|
it.time > Clock.System.now()
|
||||||
|
}.coerceAtLeast(0)
|
||||||
|
)
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(ListItemDefaults.SegmentedGap),
|
||||||
|
state = lazyState,
|
||||||
|
) {
|
||||||
|
itemsIndexed(departures) { idx, dep ->
|
||||||
|
SegmentedListItem(
|
||||||
|
onClick = {},
|
||||||
|
colors = listColors(),
|
||||||
|
shapes = ListItemDefaults.segmentedShapes(
|
||||||
|
idx,
|
||||||
|
departures.size,
|
||||||
|
),
|
||||||
|
supportingContent = {
|
||||||
|
dep.description?.let { Text(dep.description) }
|
||||||
|
},
|
||||||
|
trailingContent = {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.spacedBy((-4).dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = (dep.time - Clock.System.now()).inWholeMinutes.toString(),
|
||||||
|
style = MaterialTheme.typography.headlineSmallEmphasized,
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "mn",
|
||||||
|
style = MaterialTheme.typography.labelSmallEmphasized,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(6.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.clip(ShapeDefaults.ExtraSmall)
|
||||||
|
.background(dep.routeColour ?: MaterialTheme.colorScheme.surface)
|
||||||
|
.padding(vertical = 2.dp, horizontal = 4.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = dep.routeName,
|
||||||
|
style = MaterialTheme.typography.labelSmallEmphasized,
|
||||||
|
color = MaterialTheme.colorScheme.surface,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = dep.headsign,
|
||||||
|
style = MaterialTheme.typography.labelLargeEmphasized,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
|
private fun ManyPlatforms(
|
||||||
|
state: List<StopInfoPanelState.DeparturePlatforms>,
|
||||||
|
) {
|
||||||
|
val expandedList = remember { mutableStateListOf(*Array(state.size) { true }) }
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
) {
|
||||||
|
state.forEachIndexed { idx, depInfo ->
|
||||||
|
val (platform, departures) = depInfo
|
||||||
|
val expanded = expandedList[idx]
|
||||||
|
stickyHeader(key = "header_${depInfo.hashCode()}") {
|
||||||
|
val base = ListItemDefaults.segmentedShapes(0, 2)
|
||||||
|
val large = MaterialTheme.shapes.large
|
||||||
|
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.animateItem()
|
||||||
|
.background(MaterialTheme.colorScheme.surfaceContainerLow)
|
||||||
|
.padding(bottom = ListItemDefaults.SegmentedGap)
|
||||||
|
) {
|
||||||
|
SegmentedListItem(
|
||||||
|
onClick = { expandedList[idx] = !expandedList[idx] },
|
||||||
|
colors = listColors(),
|
||||||
|
shapes = if (expanded) base else base.copy(shape = large),
|
||||||
|
trailingContent = {
|
||||||
|
Icon(
|
||||||
|
painterResource(if (expanded) Res.drawable.arrow_drop_up else Res.drawable.arrow_drop_down),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.background(
|
||||||
|
if (expanded) MaterialTheme.colorScheme.surface else Color.Transparent,
|
||||||
|
shape = RoundedCornerShape(100)
|
||||||
|
)
|
||||||
|
.padding(6.dp),
|
||||||
|
tint = MaterialTheme.colorScheme.onSurface,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = platform,
|
||||||
|
style = MaterialTheme.typography.labelLarge,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expanded) {
|
||||||
|
item(key = "items_${depInfo.hashCode()}") {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.animateItem(),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(ListItemDefaults.SegmentedGap),
|
||||||
|
) {
|
||||||
|
departures.filter { it.time > Clock.System.now() }.take(5)
|
||||||
|
.forEachIndexed { idx, dep ->
|
||||||
|
SegmentedListItem(
|
||||||
|
onClick = {},
|
||||||
|
colors = listColors(),
|
||||||
|
shapes = ListItemDefaults.segmentedShapes(
|
||||||
|
idx + 1,
|
||||||
|
(departures.size + 1).coerceAtMost(6),
|
||||||
|
),
|
||||||
|
supportingContent = {
|
||||||
|
dep.description?.let { Text(dep.description) }
|
||||||
|
},
|
||||||
|
trailingContent = {
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
|
verticalArrangement = Arrangement.spacedBy((-4).dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = (dep.time - Clock.System.now()).inWholeMinutes.toString(),
|
||||||
|
style = MaterialTheme.typography.headlineSmallEmphasized,
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "mn",
|
||||||
|
style = MaterialTheme.typography.labelSmallEmphasized,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(6.dp)
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
Modifier
|
||||||
|
.clip(ShapeDefaults.ExtraSmall)
|
||||||
|
.background(
|
||||||
|
dep.routeColour
|
||||||
|
?: MaterialTheme.colorScheme.surface
|
||||||
|
)
|
||||||
|
.padding(vertical = 2.dp, horizontal = 4.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = dep.routeName,
|
||||||
|
style = MaterialTheme.typography.labelSmallEmphasized,
|
||||||
|
color = MaterialTheme.colorScheme.surface,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
text = dep.headsign,
|
||||||
|
style = MaterialTheme.typography.labelLargeEmphasized,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item(key = "spacer_${depInfo.hashCode()}") {
|
||||||
|
Spacer(
|
||||||
|
modifier = Modifier.animateItem().height(10.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
@OptIn(ExperimentalMaterial3ExpressiveApi::class)
|
||||||
@Composable
|
@Composable
|
||||||
internal fun StopInfoPanel(
|
internal fun StopInfoPanel(
|
||||||
state: StopInfoPanelState,
|
state: StopInfoPanelState,
|
||||||
onEvent: (StopInfoPanelEvent) -> Unit,
|
onEvent: (StopInfoPanelEvent) -> Unit,
|
||||||
) {
|
) {
|
||||||
val colors = ListItemDefaults.colors(
|
|
||||||
containerColor = MaterialTheme.colorScheme.surfaceContainer,
|
|
||||||
selectedContainerColor = MaterialTheme.colorScheme.primary,
|
|
||||||
selectedContentColor = MaterialTheme.colorScheme.onPrimary,
|
|
||||||
)
|
|
||||||
// val spec = fadeIn(MaterialTheme.motionScheme.defaultEffectsSpec())
|
|
||||||
// .togetherWith(fadeOut(MaterialTheme.motionScheme.defaultEffectsSpec()))
|
|
||||||
val spec = fadeIn(tween(300, 300)) togetherWith fadeOut(tween(300))
|
val spec = fadeIn(tween(300, 300)) togetherWith fadeOut(tween(300))
|
||||||
|
|
||||||
AnimatedContent(
|
AnimatedContent(
|
||||||
targetState = state,
|
targetState = state,
|
||||||
contentKey = { it.id },
|
contentKey = { it.id },
|
||||||
// transitionSpec = { spec },
|
|
||||||
transitionSpec = { spec },
|
transitionSpec = { spec },
|
||||||
) { state ->
|
) { state ->
|
||||||
Column(Modifier.fillMaxWidth().fillMaxHeight()) {
|
Column(Modifier.fillMaxWidth().fillMaxHeight()) {
|
||||||
|
|
@ -136,169 +319,10 @@ internal fun StopInfoPanel(
|
||||||
transitionSpec = { spec },
|
transitionSpec = { spec },
|
||||||
) { departures ->
|
) { departures ->
|
||||||
departures?.let { departurePlatforms ->
|
departures?.let { departurePlatforms ->
|
||||||
val lazyState = if (departurePlatforms.size == 1) {
|
if (departurePlatforms.size > 1) {
|
||||||
LazyListState(firstVisibleItemIndex =
|
ManyPlatforms(departurePlatforms)
|
||||||
departurePlatforms[0].departures.indexOfFirst {
|
} else if (departurePlatforms.size == 1) {
|
||||||
it.time > Clock.System.now()
|
MonoPlatform(departurePlatforms[0])
|
||||||
}.coerceAtLeast(0)
|
|
||||||
)
|
|
||||||
} else LazyListState()
|
|
||||||
LazyColumn(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(ListItemDefaults.SegmentedGap),
|
|
||||||
state = lazyState,
|
|
||||||
) {
|
|
||||||
if (departurePlatforms.size > 1) {
|
|
||||||
items(departurePlatforms) { (platform, departures) ->
|
|
||||||
// departurePlatforms.forEach { (platform, departures) ->
|
|
||||||
var expanded by rememberSaveable { mutableStateOf(true) }
|
|
||||||
val base = ListItemDefaults.segmentedShapes(0, 2)
|
|
||||||
val large = MaterialTheme.shapes.large
|
|
||||||
|
|
||||||
if (departurePlatforms.size > 1) {
|
|
||||||
SegmentedListItem(
|
|
||||||
onClick = { expanded = !expanded },
|
|
||||||
colors = colors,
|
|
||||||
shapes = if (expanded) base else base.copy(shape = large),
|
|
||||||
trailingContent = {
|
|
||||||
Icon(
|
|
||||||
painterResource(if (expanded) Res.drawable.arrow_drop_up else Res.drawable.arrow_drop_down),
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier
|
|
||||||
.background(
|
|
||||||
if (expanded) MaterialTheme.colorScheme.surface else Color.Transparent,
|
|
||||||
shape = RoundedCornerShape(100)
|
|
||||||
)
|
|
||||||
.padding(6.dp),
|
|
||||||
tint = MaterialTheme.colorScheme.onSurface,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = platform,
|
|
||||||
style = MaterialTheme.typography.labelLarge,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AnimatedVisibility(
|
|
||||||
visible = expanded,
|
|
||||||
enter = expandVertically(MaterialTheme.motionScheme.fastSpatialSpec()),
|
|
||||||
exit = shrinkVertically(MaterialTheme.motionScheme.fastSpatialSpec()),
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.height(200.dp),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(ListItemDefaults.SegmentedGap)
|
|
||||||
) {
|
|
||||||
departures
|
|
||||||
.filter { it.time > Clock.System.now() }
|
|
||||||
.take(5)
|
|
||||||
.forEachIndexed { idx, dep ->
|
|
||||||
SegmentedListItem(
|
|
||||||
onClick = {},
|
|
||||||
colors = colors,
|
|
||||||
shapes = ListItemDefaults.segmentedShapes(
|
|
||||||
idx + if (departurePlatforms.size > 1) 1 else 0,
|
|
||||||
departures.size + 1
|
|
||||||
),
|
|
||||||
supportingContent = {
|
|
||||||
dep.description?.let { Text(dep.description) }
|
|
||||||
},
|
|
||||||
trailingContent = {
|
|
||||||
Column(
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
verticalArrangement = Arrangement.spacedBy((-4).dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = (dep.time - Clock.System.now()).inWholeMinutes.toString(),
|
|
||||||
style = MaterialTheme.typography.headlineSmallEmphasized,
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = "mn",
|
|
||||||
style = MaterialTheme.typography.labelSmallEmphasized,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(6.dp)
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
Modifier
|
|
||||||
.clip(ShapeDefaults.ExtraSmall)
|
|
||||||
.background(dep.routeColour ?: MaterialTheme.colorScheme.surface)
|
|
||||||
.padding(vertical = 2.dp, horizontal = 4.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = dep.routeName,
|
|
||||||
style = MaterialTheme.typography.labelSmallEmphasized,
|
|
||||||
color = MaterialTheme.colorScheme.surface,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Text(
|
|
||||||
text = dep.headsign,
|
|
||||||
style = MaterialTheme.typography.labelLargeEmphasized,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
|
||||||
}
|
|
||||||
} else if (departurePlatforms.size == 1) {
|
|
||||||
itemsIndexed(departurePlatforms[0].departures) { idx, dep ->
|
|
||||||
// departurePlatforms[0].departures.forEachIndexed { idx, dep ->
|
|
||||||
SegmentedListItem(
|
|
||||||
onClick = {},
|
|
||||||
colors = colors,
|
|
||||||
shapes = ListItemDefaults.segmentedShapes(
|
|
||||||
idx,
|
|
||||||
departurePlatforms[0].departures.size,
|
|
||||||
),
|
|
||||||
supportingContent = {
|
|
||||||
dep.description?.let { Text(dep.description) }
|
|
||||||
},
|
|
||||||
trailingContent = {
|
|
||||||
Column(
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
verticalArrangement = Arrangement.spacedBy((-4).dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = (dep.time - Clock.System.now()).inWholeMinutes.toString(),
|
|
||||||
style = MaterialTheme.typography.headlineSmallEmphasized,
|
|
||||||
)
|
|
||||||
Text(
|
|
||||||
text = "mn",
|
|
||||||
style = MaterialTheme.typography.labelSmallEmphasized,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(6.dp)
|
|
||||||
) {
|
|
||||||
Box(
|
|
||||||
Modifier
|
|
||||||
.clip(ShapeDefaults.ExtraSmall)
|
|
||||||
.background(dep.routeColour ?: MaterialTheme.colorScheme.surface)
|
|
||||||
.padding(vertical = 2.dp, horizontal = 4.dp)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = dep.routeName,
|
|
||||||
style = MaterialTheme.typography.labelSmallEmphasized,
|
|
||||||
color = MaterialTheme.colorScheme.surface,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Text(
|
|
||||||
text = dep.headsign,
|
|
||||||
style = MaterialTheme.typography.labelLargeEmphasized,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue