Conversation
Declare the Paging 3 version and the paging-common / paging-compose libraries in the version catalog, and wire them into the app and the CalendarComponents Planning module, which will consume LazyPagingItems.
Introduce PlanningRow, a flat paged row type (WeekHeader / Event) with a planningRows(week, days) builder that flattens a week into rows. The Planning composable now renders a LazyColumn driven by LazyPagingItems<PlanningRow> (one lazy item per event) instead of a week/day map, keeping per-event virtualization and the sticky day indicator. Each event row carries its day's section keys so the sticky indicator keeps working. Preview data now provides List<PlanningRow>.
Replace PlanningViewModel.planningUiState (which eagerly observed a fixed +/-250 day range and grouped it into a full EventsByWeekAndDay map) with a Pager exposing Flow<PagingData<PlanningRow>>, rebuilt from a dynamic initialDay flow so a jump recenters the window. PlanningPagingSource pages one ISO week per key and loads a 3-week window (target week plus its neighbours) on refresh, so a jump can top-align in one shot and the previous/next weeks are preloaded. It self-invalidates on DB changes to stay live. groupWeekDays fills every day of a week (empty-day placeholders kept). Removes the now-unused PlanningUiState and EventsByWeekAndDayPreviewParameter.
…entering PlanningScreen collects the pager as LazyPagingItems<PlanningRow>, shows a loader until the first page and stays mounted afterwards, so a far jump's refresh doesn't tear down the scroll handling. - CenterOnVisibleDate positions the planning on the visible date once per screen lifetime. - ProcessJumpRequests turns a jump request into a recenter of the pager on the target date (jumpTo now returns whether the center actually changed), waits for the rebuilt refresh, then scrolls to the target row. - ReportVisibleDate reports the first visible day back as the user scrolls, to keep the calendar header in sync.
Update the top-level AGENTS.md (Planning component now driven by LazyPagingItems<PlanningRow>, PlanningRow / planningRows, the paging-compose dependency) and app/AGENTS.md (PlanningPagingSource in the planning package).
…r data management
The initial today-centering and jumps used a one-shot scrollToItem that didn't survive Paging's follow-up loads: prefetch prepends and, above all, the initial events sync refreshed the pager (replacing placeholder rows whose keys vanish), so the list slipped onto a date of the previous week. Replace the "center once" (CenterOnVisibleDate) + "process jumps" (ProcessJumpRequests) pair with a single AlignPlanningToDate coordinator that pins the list to a desired target date and re-scrolls on every content shift until the user drags (which releases the pin); an explicit jump re-pins on its date. The pager window stays centered so re-scrolling converges (no runaway scroll to the start of time).
# Conflicts: # AGENTS.md # CalendarComponents/Calendar/src/main/kotlin/com/infomaniak/calendar/components/calendar/component/ExpandableCalendar.kt # app/AGENTS.md # app/src/main/java/com/infomaniak/calendar/ui/previewparameter/EventsByWeekAndDayPreviewParameter.kt # app/src/main/java/com/infomaniak/calendar/ui/screen/planning/PlanningScreen.kt # app/src/main/java/com/infomaniak/calendar/ui/screen/planning/PlanningViewModel.kt # app/src/main/java/com/infomaniak/calendar/ui/screen/planning/ProcessJumpRequests.kt # gradle/libs.versions.toml
# Conflicts: # AGENTS.md # app/src/main/java/com/infomaniak/calendar/ui/previewparameter/EventsByWeekAndDayPreviewParameter.kt # gradle/libs.versions.toml
There was a problem hiding this comment.
Pull request overview
Migrates the planning timeline to Paging 3 for bounded, bidirectional week loading.
Changes:
- Adds flat paged planning rows and week-based data loading.
- Reworks jump alignment, grouping, previews, and loading state.
- Adds Paging dependencies and updates architecture documentation.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
gradle/libs.versions.toml |
Adds Paging artifacts. |
CalendarComponents/Planning/.../preview/PreviewData.kt |
Provides paged-row preview data. |
CalendarComponents/Planning/.../PlanningRow.kt |
Defines flat planning rows. |
CalendarComponents/Planning/.../Planning.kt |
Renders LazyPagingItems. |
CalendarComponents/Planning/build.gradle.kts |
Adds Paging Compose. |
app/.../planning/ProcessJumpRequests.kt |
Removes legacy jump handling. |
app/.../planning/PlanningViewModel.kt |
Creates and caches the pager. |
app/.../planning/PlanningUiState.kt |
Removes legacy UI state. |
app/.../planning/PlanningScreen.kt |
Integrates paged rows. |
app/.../planning/PlanningPagingSource.kt |
Loads and observes weekly pages. |
app/.../planning/PlanningEventGroupingExt.kt |
Groups one week at a time. |
app/.../planning/AlignPlanningToDate.kt |
Implements paged jump alignment. |
app/.../previewparameter/EventsByWeekAndDayPreviewParameter.kt |
Removes obsolete preview data. |
app/build.gradle.kts |
Adds app Paging dependencies. |
app/AGENTS.md |
Documents the paging source. |
AGENTS.md |
Updates component architecture documentation. |
Suppressed comments (2)
app/src/main/java/com/infomaniak/calendar/ui/screen/planning/AlignPlanningToDate.kt:135
- todo (non-blocking): Remove the consecutive trailing blank lines.
app/AGENTS.md:126 permits at most one consecutive blank line.
AGENTS.md:109
- issue (non-blocking): Do not document implementation dependencies as
apiexports.
CalendarComponents/Planning/build.gradle.kts:57-58 declares Event and Resources with implementation; only Foundation is currently exposed with api. Update this row and the dependency graph to match the build, or change the dependency declarations if re-exporting is intentional.
| `:CalendarComponents:Planning` | `com.infomaniak.calendar.components.planning` | `Planning` Composable — a `LazyColumn` driven by `LazyPagingItems<PlanningRow>` (Paging 3), with ISO week headers and one lazy item per event. `PlanningRow` is the flat paged row type (`WeekHeader` / `Event`); `planningRows(week, days)` flattens a week into rows. Also provides the `stickyDayIndicator` `Modifier` extension. Re-exports Event, Foundation, and Resources via `api`. Week header design is a **placeholder**. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| fun jumpTo(date: LocalDate): Boolean { | ||
| val changed = initialDay.value != date | ||
| initialDay.value = date |
| // Survives config changes: the initial centering must run only once per process, so a recomposition | ||
| // or rotation never re-centers over the user's (or restored) scroll. | ||
| var hasCentered by rememberSaveable { mutableStateOf(false) } |
| itemKey = row.key, | ||
| sectionItemKeys = row.daySectionKeys, | ||
| goToEventCreation = goToEventCreation, | ||
| modifier = Modifier | ||
| .ensureSectionMinHeight(sectionSizing, sectionItemKeys, itemKey) | ||
| .padding(bottom = bottomPadding), | ||
| .ensureSectionMinHeight(sectionSizing, row.daySectionKeys, row.key) |
| implementation(libs.compose.material3) | ||
| debugImplementation(core.compose.ui.tooling) | ||
|
|
||
| implementation(libs.paging.compose) |
| implementation(libs.paging) | ||
| implementation(libs.paging.compose) |
| | `:CalendarComponents:Resources` | `com.infomaniak.calendar.components.resources` | String-only module: `res/values/strings.xml` (+ translations). No Kotlin code, no Compose. Centralises all CalendarComponents string resources. | | ||
| | `:CalendarComponents:Event` | `com.infomaniak.calendar.components.event` | `EventItem` Composable — renders a single event row. Re-exports Foundation via `api`. | | ||
| | `:CalendarComponents:Planning` | `com.infomaniak.calendar.components.planning` | `Planning` Composable — a `LazyColumn` with ISO week headers and per-day event lists. Also provides the `stickyWithinItem` `Modifier` extension. Re-exports Event, Foundation, and Resources via `api`. Week header design is a **placeholder**. | | ||
| | `:CalendarComponents:Event` | `com.infomaniak.calendar.components.event` | `EventItem` Composable — renders a single event row. Re-exports Foundation via `api`. **Placeholder UI** — visual design is not final. | |
| } else { | ||
| LoadingPlanning(modifier = Modifier.padding(contentPadding)) |
| coroutineScope.launch { | ||
| runCatching { | ||
| slices.collectIndexed { index, value -> | ||
| if (index == 0) firstSlices.complete(value) else invalidate() | ||
| } |
|



No description provided.