refactor(ui/info): split up info panel state

This commit is contained in:
Cilly Leang 2026-03-31 20:53:21 +11:00
parent f0ce780bba
commit aad5ae4024
Signed by: cilly
GPG key ID: 6500251E087653C9
7 changed files with 73 additions and 64 deletions

View file

@ -30,15 +30,23 @@ import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.coerceAtMost import androidx.compose.ui.unit.coerceAtMost
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import moe.lava.banksia.ui.screens.map.MapScreenEvent
import moe.lava.banksia.ui.state.InfoPanelState
import kotlin.time.Duration.Companion.milliseconds import kotlin.time.Duration.Companion.milliseconds
sealed class InfoPanelEvent
sealed class InfoPanelState {
abstract val loading: Boolean
data object None : InfoPanelState() {
override val loading = false
}
}
@OptIn(ExperimentalMaterial3ExpressiveApi::class) @OptIn(ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
fun InfoPanel( fun InfoPanel(
state: InfoPanelState, state: InfoPanelState,
onEvent: (MapScreenEvent) -> Unit, onEvent: (InfoPanelEvent) -> Unit,
onPeekHeightChange: (Dp) -> Unit, onPeekHeightChange: (Dp) -> Unit,
) { ) {
if (state is InfoPanelState.None) if (state is InfoPanelState.None)
@ -66,9 +74,9 @@ fun InfoPanel(
) { ) {
Box { Box {
when (state) { when (state) {
is InfoPanelState.Route -> RouteInfoPanel(state, onEvent) is RouteInfoPanelState -> RouteInfoPanel(state, onEvent)
is InfoPanelState.Stop -> StopInfoPanel(state, onEvent) is StopInfoPanelState -> StopInfoPanel(state, onEvent)
is InfoPanelState.Trip -> TripInfoPanel(state, onEvent) is TripInfoPanelState -> TripInfoPanel(state, onEvent)
is InfoPanelState.None -> throw UnsupportedOperationException() is InfoPanelState.None -> throw UnsupportedOperationException()
} }

View file

@ -9,14 +9,22 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import moe.lava.banksia.model.RouteType
import moe.lava.banksia.ui.components.RouteIcon import moe.lava.banksia.ui.components.RouteIcon
import moe.lava.banksia.ui.screens.map.MapScreenEvent
import moe.lava.banksia.ui.state.InfoPanelState sealed class RouteInfoPanelEvent : InfoPanelEvent()
data class RouteInfoPanelState(
val name: String,
val type: RouteType,
) : InfoPanelState() {
override val loading = false
}
@Composable @Composable
internal fun RouteInfoPanel( internal fun RouteInfoPanel(
state: InfoPanelState.Route, state: RouteInfoPanelState,
onEvent: (MapScreenEvent) -> Unit, onEvent: (RouteInfoPanelEvent) -> Unit,
) { ) {
Column(Modifier.fillMaxWidth()) { Column(Modifier.fillMaxWidth()) {
Row { Row {

View file

@ -16,13 +16,25 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import moe.lava.banksia.ui.screens.map.MapScreenEvent
import moe.lava.banksia.ui.state.InfoPanelState sealed class StopInfoPanelEvent : InfoPanelEvent()
data class StopInfoPanelState(
val id: String,
val name: String,
val subname: String? = null,
val departures: List<Departure>? = null,
) : InfoPanelState() {
override val loading: Boolean
get() = departures == null
data class Departure(val directionName: String, val formattedTimes: String)
}
@Composable @Composable
internal fun StopInfoPanel( internal fun StopInfoPanel(
state: InfoPanelState.Stop, state: StopInfoPanelState,
onEvent: (MapScreenEvent) -> Unit, onEvent: (StopInfoPanelEvent) -> Unit,
) { ) {
Column(Modifier.fillMaxWidth()) { Column(Modifier.fillMaxWidth()) {
Text( Text(

View file

@ -9,14 +9,23 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import moe.lava.banksia.model.RouteType
import moe.lava.banksia.ui.components.RouteIcon import moe.lava.banksia.ui.components.RouteIcon
import moe.lava.banksia.ui.screens.map.MapScreenEvent
import moe.lava.banksia.ui.state.InfoPanelState sealed class TripInfoPanelEvent : InfoPanelEvent()
data class TripInfoPanelState(
val direction: String,
val type: RouteType,
val routeName: String? = null,
) : InfoPanelState() {
override val loading = routeName == null
}
@Composable @Composable
internal fun TripInfoPanel( internal fun TripInfoPanel(
state: InfoPanelState.Trip, state: TripInfoPanelState,
onEvent: (MapScreenEvent) -> Unit, onEvent: (TripInfoPanelEvent) -> Unit,
) { ) {
Column(Modifier.fillMaxWidth()) { Column(Modifier.fillMaxWidth()) {
Row { Row {

View file

@ -38,9 +38,9 @@ import moe.lava.banksia.ui.layout.AppBottomSheet
import moe.lava.banksia.ui.layout.Searcher import moe.lava.banksia.ui.layout.Searcher
import moe.lava.banksia.ui.layout.SheetStateWrapper import moe.lava.banksia.ui.layout.SheetStateWrapper
import moe.lava.banksia.ui.layout.info.InfoPanel import moe.lava.banksia.ui.layout.info.InfoPanel
import moe.lava.banksia.ui.layout.info.InfoPanelState
import moe.lava.banksia.ui.map.Maps import moe.lava.banksia.ui.map.Maps
import moe.lava.banksia.ui.platform.BanksiaTheme import moe.lava.banksia.ui.platform.BanksiaTheme
import moe.lava.banksia.ui.state.InfoPanelState
import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.painterResource
import org.koin.compose.viewmodel.koinViewModel import org.koin.compose.viewmodel.koinViewModel

View file

@ -21,10 +21,14 @@ import moe.lava.banksia.client.repository.StopTimeRepository
import moe.lava.banksia.data.ptv.PtvService import moe.lava.banksia.data.ptv.PtvService
import moe.lava.banksia.model.Route import moe.lava.banksia.model.Route
import moe.lava.banksia.model.RouteType import moe.lava.banksia.model.RouteType
import moe.lava.banksia.ui.layout.info.InfoPanelEvent
import moe.lava.banksia.ui.layout.info.InfoPanelState
import moe.lava.banksia.ui.layout.info.RouteInfoPanelState
import moe.lava.banksia.ui.layout.info.StopInfoPanelState
import moe.lava.banksia.ui.layout.info.TripInfoPanelState
import moe.lava.banksia.ui.map.util.CameraPosition import moe.lava.banksia.ui.map.util.CameraPosition
import moe.lava.banksia.ui.map.util.CameraPositionBounds import moe.lava.banksia.ui.map.util.CameraPositionBounds
import moe.lava.banksia.ui.map.util.Marker import moe.lava.banksia.ui.map.util.Marker
import moe.lava.banksia.ui.state.InfoPanelState
import moe.lava.banksia.ui.state.MapState import moe.lava.banksia.ui.state.MapState
import moe.lava.banksia.ui.state.SearchState import moe.lava.banksia.ui.state.SearchState
import moe.lava.banksia.util.BoxedValue import moe.lava.banksia.util.BoxedValue
@ -99,6 +103,12 @@ class MapScreenViewModel(
} }
} }
fun handleEvent(event: InfoPanelEvent) {
viewModelScope.launch {
// when (event) { }
}
}
fun bindTracker(locationTracker: LocationTracker) { fun bindTracker(locationTracker: LocationTracker) {
locationTrackerJob = locationTracker.getLocationsFlow() locationTrackerJob = locationTracker.getLocationsFlow()
.onEach { lastKnownLocation = Point(it.latitude, it.longitude) } .onEach { lastKnownLocation = Point(it.latitude, it.longitude) }
@ -162,7 +172,7 @@ class MapScreenViewModel(
val route = routeRepository.get(routeId) val route = routeRepository.get(routeId)
// val gtfsRoute = ptvService.route(routeId) // val gtfsRoute = ptvService.route(routeId)
iInfoState.update { iInfoState.update {
InfoPanelState.Route( RouteInfoPanelState(
name = route.name, name = route.name,
type = route.type, type = route.type,
) )
@ -187,7 +197,7 @@ class MapScreenViewModel(
.onEach { run -> .onEach { run ->
if (routeName == null) { if (routeName == null) {
iInfoState.update { iInfoState.update {
InfoPanelState.Trip( TripInfoPanelState(
direction = run.destinationName, direction = run.destinationName,
type = RouteType.MetroTrain, // XXX HACK TODO FIXME type = RouteType.MetroTrain, // XXX HACK TODO FIXME
) )
@ -196,7 +206,7 @@ class MapScreenViewModel(
} }
iInfoState.update { iInfoState.update {
InfoPanelState.Trip( TripInfoPanelState(
direction = run.destinationName, direction = run.destinationName,
type = RouteType.MetroTrain, // FIXME HACK XXX TODO type = RouteType.MetroTrain, // FIXME HACK XXX TODO
routeName = routeName, routeName = routeName,
@ -219,7 +229,7 @@ class MapScreenViewModel(
val name = split[0] val name = split[0]
val subname = split.getOrNull(1) val subname = split.getOrNull(1)
iInfoState.update { iInfoState.update {
InfoPanelState.Stop( StopInfoPanelState(
id = stop.id, id = stop.id,
name = name, name = name,
subname = subname, subname = subname,
@ -242,10 +252,10 @@ class MapScreenViewModel(
"${diff}mn" "${diff}mn"
} }
} }
InfoPanelState.Stop.Departure(headsign, times) StopInfoPanelState.Departure(headsign, times)
} }
iInfoState.update { iInfoState.update {
if (it !is InfoPanelState.Stop) if (it !is StopInfoPanelState)
it it
else else
it.copy(departures = departures) it.copy(departures = departures)

View file

@ -1,38 +0,0 @@
package moe.lava.banksia.ui.state
import moe.lava.banksia.model.RouteType
sealed class InfoPanelState {
abstract val loading: Boolean
data object None : InfoPanelState() {
override val loading = false
}
data class Route(
val name: String,
val type: RouteType,
) : InfoPanelState() {
override val loading = false
}
data class Stop(
val id: String,
val name: String,
val subname: String? = null,
val departures: List<Departure>? = null,
) : InfoPanelState() {
override val loading: Boolean
get() = departures == null
data class Departure(val directionName: String, val formattedTimes: String)
}
data class Trip(
val direction: String,
val type: RouteType,
val routeName: String? = null,
) : InfoPanelState() {
override val loading = routeName == null
}
}