diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaColumn.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaColumn.kt index d9011b21..e4d9f65a 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaColumn.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaColumn.kt @@ -27,11 +27,12 @@ import com.androidmakers.ui.model.UISession @Composable fun AgendaColumn( sessionsPerStartTime: Map>, + initialFirstVisibleItemIndex: Int = 0, onSessionClick: (UISession) -> Unit, onSessionBookmark: (UISession, Boolean) -> Unit, onApplyForAppClinicClick: () -> Unit, ) { - val listState = rememberLazyListState() + val listState = rememberLazyListState(initialFirstVisibleItemIndex = initialFirstVisibleItemIndex) LazyColumn( state = listState, diff --git a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaPager.kt b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaPager.kt index 868f45f9..2b602c77 100644 --- a/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaPager.kt +++ b/shared/ui/src/commonMain/kotlin/com/androidmakers/ui/agenda/AgendaPager.kt @@ -18,8 +18,11 @@ import androidx.compose.ui.Modifier import com.androidmakers.ui.common.EmptyLayout import com.androidmakers.ui.common.SessionFilter import com.androidmakers.ui.model.UISession +import fr.androidmakers.domain.utils.eventTimeZone import fr.androidmakers.domain.utils.formatShortTime +import kotlin.time.Clock import kotlinx.coroutines.launch +import kotlinx.datetime.todayIn @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -81,11 +84,18 @@ fun AgendaPager( onRefresh = onRefresh, state = pullRefreshState ) { + val isToday = remember(page) { + days[page].date == Clock.System.todayIn(eventTimeZone) + } + val initialScrollIndex = remember(sessionsPerStartTime, isToday) { + if (isToday) sessionsPerStartTime.currentTimeScrollIndex() else 0 + } if (sessionsPerStartTime.isEmpty()) { EmptyLayout() } else { AgendaColumn( sessionsPerStartTime = sessionsPerStartTime, + initialFirstVisibleItemIndex = initialScrollIndex, onSessionClick = onSessionClick, onApplyForAppClinicClick = onApplyForAppClinicClick, onSessionBookmark = onSessionBookmark @@ -117,3 +127,28 @@ private fun List.filter( } } } + +/** + * Computes the lazy list item index of the sticky header for the last time slot + * that has already started (i.e., whose start time <= now). Returns 0 if all + * slots are in the future. The lazy list structure is: + * index 0 : sticky header for slot 0 + * index 1..n : sessions of slot 0 + * index n+1 : sticky header for slot 1 + * ... + */ +private fun Map>.currentTimeScrollIndex(): Int { + val now = Clock.System.now() + var itemIndex = 0 + var targetIndex = 0 + + for ((_, sessions) in this) { + val slotStart = sessions.firstOrNull()?.startDate + if (slotStart != null && slotStart <= now) { + targetIndex = itemIndex + } + itemIndex += 1 + sessions.size // 1 for sticky header + N for sessions + } + + return targetIndex +}