Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(android.TripDetails): Trip stop list UI #703

Merged
merged 8 commits into from
Feb 4, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ fun RoutePill(
RoutePillSpec.Content.Empty -> {}
is RoutePillSpec.Content.Text ->
Text(
pillContent.text.uppercase(),
if (route?.type == RouteType.COMMUTER_RAIL) pillContent.text
else pillContent.text.uppercase(),
modifier = finalModifier,
color = if (isActive) textColor else Color.Unspecified,
fontSize = fontSize,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.mbta.tid.mbta_app.android.stopDetails

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.painterResource
import com.mbta.tid.mbta_app.android.R

@Composable
fun ColoredRouteLine(color: Color, modifier: Modifier = Modifier) {
Column(modifier) {
Canvas(modifier = Modifier.fillMaxHeight()) {
val height = size.height
drawRect(
color = color,
topLeft = Offset(x = -6f, y = 0f),
size = Size(12f, height),
)
}
}
}

@Composable
fun RouteLineTwist(color: Color, modifier: Modifier = Modifier) {
Column(modifier, horizontalAlignment = Alignment.CenterHorizontally) {
Row(Modifier.weight(1f)) { ColoredRouteLine(color) }

Box() {
Icon(
painterResource(R.drawable.stop_trip_line_twist),
contentDescription = null,
tint = color
)
Icon(painterResource(R.drawable.stop_trip_line_twist_shadow), contentDescription = null)
}

Row(Modifier.weight(1f)) { ColoredRouteLine(color) }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import androidx.compose.material3.ButtonDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.tooling.preview.Preview
Expand All @@ -29,13 +30,9 @@ import com.mbta.tid.mbta_app.model.ObjectCollectionBuilder
import com.mbta.tid.mbta_app.model.PatternsByStop
import com.mbta.tid.mbta_app.model.RealtimePatterns
import com.mbta.tid.mbta_app.model.Route
import com.mbta.tid.mbta_app.model.RouteType
import com.mbta.tid.mbta_app.model.StopDetailsFilter

@ColorRes
fun deselectedBackgroundColor(route: Route): Int =
if (route.type == RouteType.COMMUTER_RAIL || route.id == "Blue") R.color.deselected_toggle_2
else R.color.deselected_toggle_1
@ColorRes fun deselectedBackgroundColor(route: Route): Int = R.color.deselected_toggle_2

@Composable
fun DirectionPicker(
Expand All @@ -51,7 +48,10 @@ fun DirectionPicker(
if (availableDirections.size > 1) {
val deselectedBackgroundColor = colorResource(deselectedBackgroundColor(route))
Row(
Modifier.background(deselectedBackgroundColor, RoundedCornerShape(8.dp))
Modifier.background(
deselectedBackgroundColor.copy(alpha = 0.6f),
RoundedCornerShape(8.dp)
)
.padding(2.dp)
.fillMaxWidth()
.height(IntrinsicSize.Max),
Expand All @@ -67,14 +67,13 @@ fun DirectionPicker(
}

Button(
modifier = Modifier.weight(1f).fillMaxHeight(),
modifier = Modifier.weight(1f).fillMaxHeight().alpha(1f),
onClick = action,
shape = RoundedCornerShape(6.dp),
colors =
ButtonDefaults.buttonColors(
containerColor =
if (isSelected) Color.fromHex(route.color)
else deselectedBackgroundColor,
if (isSelected) Color.fromHex(route.color) else Color.Transparent,
contentColor =
if (isSelected) Color.fromHex(route.textColor)
else colorResource(R.color.deselected_toggle_text)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ fun StopDetailsFilteredHeader(
verticalAlignment = Alignment.CenterVertically
) {
if (onPin != null) {
PinButton(pinned, colorResource(R.color.key), onPin)
PinButton(pinned, colorResource(R.color.text), onPin)
}
if (onClose != null) {
ActionButton(ActionButtonKind.Close) { onClose() }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource
Expand All @@ -16,12 +17,14 @@ import com.mbta.tid.mbta_app.android.R

@Composable
fun StopDot(routeAccents: TripRouteAccents, targeted: Boolean, modifier: Modifier = Modifier) {
Box(
modifier
.background(routeAccents.color, CircleShape)
.border(1.dp, colorResource(R.color.stop_dot_halo), CircleShape)
.size(14.dp)
) {
Box(contentAlignment = Alignment.Center) {
Box(
modifier
.background(routeAccents.color, CircleShape)
.border(1.dp, colorResource(R.color.stop_dot_halo), CircleShape)
.size(14.dp)
) {}

if (targeted) {
Image(
painterResource(R.drawable.stop_pin_indicator),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@ package com.mbta.tid.mbta_app.android.stopDetails
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import com.mbta.tid.mbta_app.android.ModalRoutes
import com.mbta.tid.mbta_app.android.state.getGlobalData
import com.mbta.tid.mbta_app.android.util.IsLoadingSheetContents
import com.mbta.tid.mbta_app.android.util.modifiers.loadingShimmer
import com.mbta.tid.mbta_app.android.util.rememberSuspend
import com.mbta.tid.mbta_app.model.LoadingPlaceholders
import com.mbta.tid.mbta_app.model.ObjectCollectionBuilder
import com.mbta.tid.mbta_app.model.RouteType
import com.mbta.tid.mbta_app.model.Stop
import com.mbta.tid.mbta_app.model.TripDetailsFilter
Expand Down Expand Up @@ -73,7 +77,9 @@ fun TripDetailsView(
AlertsStreamDataResponse(mapOf()),
globalResponse
)
} else null
} else {
null
}
}
}

Expand Down Expand Up @@ -106,24 +112,76 @@ fun TripDetailsView(
null
}

Column() {
Column(Modifier.zIndex(1F)) {
TripHeaderCard(tripId, headerSpec, stopId, routeAccents, now, onTap = onHeaderTap)
}
Column(Modifier.offset(y = (-6).dp).padding(horizontal = 4.dp)) {
TripStops(
TripDetailsView(
tripId,
headerSpec,
onHeaderTap,
routeAccents,
stopId,
stops,
tripFilter,
now,
globalResponse
)
} else {
val placeholderTripInfo = LoadingPlaceholders.tripDetailsInfo()
val placeholderTripStops = LoadingPlaceholders.tripDetailsStops()
val placeholderTripId = placeholderTripInfo.vehicle.tripId ?: ""

val placeholderHeaderSpec =
TripHeaderSpec.getSpec(
placeholderTripId,
placeholderTripInfo.stops,
null,
placeholderTripInfo.vehicle,
placeholderTripInfo.vehicleStop
)
val placeholderRouteAccents = TripRouteAccents(placeholderTripInfo.route)

CompositionLocalProvider(IsLoadingSheetContents provides true) {
Column(modifier = Modifier.loadingShimmer()) {
TripDetailsView(
placeholderTripId,
placeholderHeaderSpec,
null,
placeholderRouteAccents,
stopId,
stops,
tripFilter.stopSequence,
headerSpec,
placeholderTripStops,
tripFilter,
now,
globalResponse,
routeAccents
globalResponse ?: GlobalResponse(ObjectCollectionBuilder())
)
}
}
} else {
// TODO: loading
CircularProgressIndicator()
}
}

@Composable
private fun TripDetailsView(
tripId: String,
headerSpec: TripHeaderSpec?,
onHeaderTap: (() -> Unit)?,
routeAccents: TripRouteAccents,
stopId: String,
stops: TripDetailsStopList,
tripFilter: TripDetailsFilter?,
now: Instant,
globalResponse: GlobalResponse
) {
Column() {
Column(Modifier.zIndex(1F)) {
TripHeaderCard(tripId, headerSpec, stopId, routeAccents, now, onTap = onHeaderTap)
}
Column(Modifier.offset(y = (-6).dp).padding(horizontal = 4.dp)) {
TripStops(
stopId,
stops,
tripFilter?.stopSequence,
headerSpec,
now,
globalResponse,
routeAccents
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import com.mbta.tid.mbta_app.android.component.InfoCircle
import com.mbta.tid.mbta_app.android.component.UpcomingTripView
import com.mbta.tid.mbta_app.android.component.UpcomingTripViewState
import com.mbta.tid.mbta_app.android.component.routeIcon
import com.mbta.tid.mbta_app.android.util.modifiers.placeholderIfLoading
import com.mbta.tid.mbta_app.android.util.typeText
import com.mbta.tid.mbta_app.model.ObjectCollectionBuilder
import com.mbta.tid.mbta_app.model.RouteType
Expand Down Expand Up @@ -221,7 +222,7 @@ private fun VehicleDescription(
val context = LocalContext.current
if (vehicle.tripId == tripId) {
Column(
Modifier.clearAndSetSemantics {
Modifier.placeholderIfLoading().clearAndSetSemantics {
contentDescription =
vehicleDescriptionAccessibilityText(
vehicle,
Expand All @@ -235,7 +236,11 @@ private fun VehicleDescription(
verticalArrangement = Arrangement.spacedBy(2.dp)
) {
VehicleStatusDescription(vehicle.currentStatus, stopEntry) // TODO footnote
Text(stop.name, style = MaterialTheme.typography.headlineLarge) // TODO size and bold
Text(
stop.name,
style = MaterialTheme.typography.headlineLarge,
modifier = Modifier.placeholderIfLoading()
) // TODO size and bold
}
}
}
Expand Down Expand Up @@ -414,7 +419,8 @@ private fun LiveIndicator() {
Image(painterResource(R.drawable.live_data), null, Modifier.size(16.dp))
Text(
stringResource(R.string.live),
style = MaterialTheme.typography.bodySmall
style = MaterialTheme.typography.bodySmall,
modifier = Modifier.placeholderIfLoading()
) // TODO footnote
}
}
Expand Down
Loading