Skip to content

Commit

Permalink
UI: Refactor DateTime selection to use serialized model (#401)
Browse files Browse the repository at this point in the history
### TL;DR
Updated the date/time selector to pass structured data instead of formatted strings between screens.

### What changed?
- Modified `DateTimeSelectorScreen` to pass `DateTimeSelectionItem` objects instead of formatted strings
- Added JSON serialization/deserialization support for `DateTimeSelectionItem`
- Updated `TimeTableScreen` and `TimeTableDestination` to handle the new structured data format
- Added a TODO for handling initial date/time data in the selector screen

### How to test?
1. Navigate to the time table screen
2. Click on the date/time selector
3. Select different dates and times
4. Verify the selected date/time appears correctly on the time table screen
5. Verify the selection persists after configuration changes

### Why make this change?
Using structured data instead of formatted strings provides better type safety and flexibility in handling date/time selections. This change also makes it easier to modify the date/time display format without changing the underlying data structure.
  • Loading branch information
ksharma-xyz authored Nov 30, 2024
1 parent 45e1e6b commit 0f4a628
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ internal fun NavGraphBuilder.dateTimeSelectorDestination(navController: NavHostC
composable<DateTimeSelectorRoute> { backStackEntry ->
val viewModel: DateTimeSelectorViewModel = koinViewModel<DateTimeSelectorViewModel>()

// TODO - If arguments have data, then display that data in the Screen else display current date time.

DateTimeSelectorScreen(
onBackClick = {
navController.popBackStack()
},
onDateTimeSelected = { dateTimeSelection ->
navController.previousBackStackEntry?.savedStateHandle?.set(
key = DateTimeSelectorRoute.DATE_TIME_TEXT_KEY,
value = dateTimeSelection,
value = dateTimeSelection?.toJsonString(),
)
navController.popBackStack()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import kotlinx.datetime.TimeZone
import kotlinx.datetime.plus
import kotlinx.datetime.toLocalDateTime
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import xyz.ksharma.krail.core.datetime.decrementDateByOneDay
import xyz.ksharma.krail.core.datetime.formatDate
import xyz.ksharma.krail.core.datetime.formatTime
Expand All @@ -54,14 +55,16 @@ import xyz.ksharma.krail.trip.planner.ui.components.themeBackgroundColor
import xyz.ksharma.krail.trip.planner.ui.components.themeContentColor
import xyz.ksharma.krail.trip.planner.ui.datetimeselector.JourneyTimeOptions.ARRIVE
import xyz.ksharma.krail.trip.planner.ui.datetimeselector.JourneyTimeOptions.LEAVE
import xyz.ksharma.krail.trip.planner.ui.state.searchstop.model.StopItem
import xyz.ksharma.krail.trip.planner.ui.state.searchstop.model.StopItem.Companion
import xyz.ksharma.krail.trip.planner.ui.timetable.ActionButton

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DateTimeSelectorScreen(
modifier: Modifier = Modifier,
onBackClick: () -> Unit = {},
onDateTimeSelected: (String?) -> Unit = {},
onDateTimeSelected: (DateTimeSelectionItem?) -> Unit = {},
) {
// Colors
val themeColorHex by LocalThemeColor.current
Expand Down Expand Up @@ -201,7 +204,7 @@ fun DateTimeSelectorScreen(
hour = timePickerState.hour,
minute = timePickerState.minute,
date = selectedDate,
).toDateTimeText()
)
}
)
},
Expand Down Expand Up @@ -229,8 +232,13 @@ data class DateTimeSelectionItem(
}
}

fun toJsonString() = Json.encodeToString(serializer(), this)

@Suppress("ConstPropertyName")
companion object {
private const val serialVersionUID: Long = 1L

fun fromJsonString(json: String) =
kotlin.runCatching { Json.decodeFromString(serializer(), json) }.getOrNull()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@ package xyz.ksharma.krail.trip.planner.ui.timetable

import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavHostController
import androidx.navigation.NavOptions
import androidx.navigation.compose.composable
import androidx.navigation.toRoute
import org.koin.compose.viewmodel.koinViewModel
import xyz.ksharma.krail.trip.planner.ui.datetimeselector.DateTimeSelectionItem
import xyz.ksharma.krail.trip.planner.ui.datetimeselector.DateTimeSelectionItem.Companion.fromJsonString
import xyz.ksharma.krail.trip.planner.ui.navigation.DateTimeSelectorRoute
import xyz.ksharma.krail.trip.planner.ui.navigation.ServiceAlertRoute
import xyz.ksharma.krail.trip.planner.ui.navigation.TimeTableRoute
Expand All @@ -32,13 +37,16 @@ internal fun NavGraphBuilder.timeTableDestination(navController: NavHostControll
// Cannot use 'rememberSaveable' here because DateTimeSelectionItem is not Parcelable.
// But it's saved in backStackEntry.savedStateHandle as json, so it's able to
// handle config changes properly.
val dateTimeSelectionText: String =
backStackEntry.savedStateHandle.get<String>(key = DateTimeSelectorRoute.DATE_TIME_TEXT_KEY)
?: "Leave: Now"
val dateTimeSelectionJson: String? =
backStackEntry.savedStateHandle.get(key = DateTimeSelectorRoute.DATE_TIME_TEXT_KEY)
var dateTimeSelectionItem: DateTimeSelectionItem? by remember {
mutableStateOf(dateTimeSelectionJson?.let { fromJsonString(it) })
}

// Lookout for new updates
LaunchedEffect(dateTimeSelectionText) {
println("Changed dateTimeSelectionItem: $dateTimeSelectionText")
LaunchedEffect(dateTimeSelectionJson) {
println("Changed dateTimeSelectionItem: $dateTimeSelectionItem")
dateTimeSelectionItem = dateTimeSelectionJson?.let { fromJsonString(it) }
}

TimeTableScreen(
Expand All @@ -58,7 +66,7 @@ internal fun NavGraphBuilder.timeTableDestination(navController: NavHostControll
}
}
},
dateTimeSelectionText = dateTimeSelectionText,
dateTimeSelectionItem = dateTimeSelectionItem,
dateTimeSelectorClicked = {
navController.navigate(
route = DateTimeSelectorRoute(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@ import xyz.ksharma.krail.trip.planner.ui.components.JourneyCardState
import xyz.ksharma.krail.trip.planner.ui.components.OriginDestination
import xyz.ksharma.krail.trip.planner.ui.components.hexToComposeColor
import xyz.ksharma.krail.trip.planner.ui.components.loading.LoadingEmojiAnim
import xyz.ksharma.krail.trip.planner.ui.components.themeBackgroundColor
import xyz.ksharma.krail.trip.planner.ui.components.themeContentColor
import xyz.ksharma.krail.trip.planner.ui.datetimeselector.DateTimeSelectionItem
import xyz.ksharma.krail.trip.planner.ui.state.TransportMode
import xyz.ksharma.krail.trip.planner.ui.state.TransportModeLine
import xyz.ksharma.krail.trip.planner.ui.state.timetable.TimeTableState
Expand All @@ -65,7 +65,7 @@ import xyz.ksharma.krail.trip.planner.ui.state.timetable.Trip
fun TimeTableScreen(
timeTableState: TimeTableState,
expandedJourneyId: String?,
dateTimeSelectionText: String,
dateTimeSelectionItem: DateTimeSelectionItem?,
onEvent: (TimeTableUiEvent) -> Unit,
onAlertClick: (String) -> Unit,
onBackClick: () -> Unit,
Expand Down Expand Up @@ -157,7 +157,7 @@ fun TimeTableScreen(

item {
Text(
text = dateTimeSelectionText,
text = dateTimeSelectionItem?.toDateTimeText() ?: "Leave: Now",
style = KrailTheme.typography.titleMedium,
color = themeContentColor(),
modifier = Modifier
Expand Down Expand Up @@ -367,7 +367,7 @@ private fun PreviewTimeTableScreen() {
onEvent = {},
onAlertClick = {},
onBackClick = {},
dateTimeSelectionText = "Leaving now",
dateTimeSelectionItem = null,
)
}
}
Expand All @@ -393,7 +393,7 @@ private fun PreviewTimeTableScreenError() {
onEvent = {},
onAlertClick = {},
onBackClick = {},
dateTimeSelectionText = "Leaving now",
dateTimeSelectionItem = null,
)
}
}
Expand All @@ -415,7 +415,7 @@ private fun PreviewTimeTableScreenNoResults() {
isError = false,
isLoading = false,
),
dateTimeSelectionText = "Leaving now",
dateTimeSelectionItem = null,
expandedJourneyId = null,
onEvent = {},
onAlertClick = {},
Expand Down

0 comments on commit 0f4a628

Please sign in to comment.