diff --git a/compose/src/main/java/com/kizitonwose/calendar/compose/Calendar.kt b/compose/src/main/java/com/kizitonwose/calendar/compose/Calendar.kt index b901c97f..a9ba05b1 100644 --- a/compose/src/main/java/com/kizitonwose/calendar/compose/Calendar.kt +++ b/compose/src/main/java/com/kizitonwose/calendar/compose/Calendar.kt @@ -176,7 +176,7 @@ private fun Calendar( contentPadding = contentPadding, ) { CalendarMonths( - monthCount = state.monthIndexCount, + monthCount = state.calendarInfo.indexCount, monthData = { offset -> state.store[offset] }, contentHeightMode = contentHeightMode, dayContent = dayContent, @@ -196,7 +196,7 @@ private fun Calendar( contentPadding = contentPadding, ) { CalendarMonths( - monthCount = state.monthIndexCount, + monthCount = state.calendarInfo.indexCount, monthData = { offset -> state.store[offset] }, contentHeightMode = contentHeightMode, dayContent = dayContent, diff --git a/compose/src/main/java/com/kizitonwose/calendar/compose/CalendarInfo.kt b/compose/src/main/java/com/kizitonwose/calendar/compose/CalendarInfo.kt new file mode 100644 index 00000000..115a019e --- /dev/null +++ b/compose/src/main/java/com/kizitonwose/calendar/compose/CalendarInfo.kt @@ -0,0 +1,10 @@ +package com.kizitonwose.calendar.compose + +import com.kizitonwose.calendar.core.OutDateStyle +import java.time.DayOfWeek + +internal data class CalendarInfo( + val indexCount: Int, + private val firstDayOfWeek: DayOfWeek? = null, + private val outDateStyle: OutDateStyle? = null, +) diff --git a/compose/src/main/java/com/kizitonwose/calendar/compose/CalendarState.kt b/compose/src/main/java/com/kizitonwose/calendar/compose/CalendarState.kt index 5da25fc9..7cd45d7b 100644 --- a/compose/src/main/java/com/kizitonwose/calendar/compose/CalendarState.kt +++ b/compose/src/main/java/com/kizitonwose/calendar/compose/CalendarState.kt @@ -182,7 +182,7 @@ class CalendarState internal constructor( firstVisibleItemScrollOffset = visibleItemState?.firstVisibleItemScrollOffset ?: 0, ) - internal var monthIndexCount by mutableStateOf(0) + internal var calendarInfo by mutableStateOf(CalendarInfo(indexCount = 0)) internal val store = DataStore { offset -> getCalendarMonthData( @@ -200,7 +200,16 @@ class CalendarState internal constructor( private fun monthDataChanged() { store.clear() checkDateRange(startMonth, endMonth) - monthIndexCount = getMonthIndicesCount(startMonth, endMonth) + // Read the firstDayOfWeek and outDateStyle properties to ensure recomposition + // even though they are unused in the CalendarInfo. Alternatively, we could use + // mutableStateMapOf() as the backing store for DataStore() to ensure recomposition + // but not sure how compose handles recomposition of a lazy list that reads from + // such map when an entry unrelated to the visible indices changes. + calendarInfo = CalendarInfo( + indexCount = getMonthIndicesCount(startMonth, endMonth), + firstDayOfWeek = firstDayOfWeek, + outDateStyle = outDateStyle, + ) } /** diff --git a/compose/src/main/java/com/kizitonwose/calendar/compose/heatmapcalendar/HeatMapCalendar.kt b/compose/src/main/java/com/kizitonwose/calendar/compose/heatmapcalendar/HeatMapCalendar.kt index bfe9504e..0782b26f 100644 --- a/compose/src/main/java/com/kizitonwose/calendar/compose/heatmapcalendar/HeatMapCalendar.kt +++ b/compose/src/main/java/com/kizitonwose/calendar/compose/heatmapcalendar/HeatMapCalendar.kt @@ -45,7 +45,7 @@ internal fun HeatMapCalendarImpl( contentPadding = contentPadding, ) { items( - count = state.monthIndexCount, + count = state.calendarInfo.indexCount, key = { offset -> state.store[offset].yearMonth }, ) { offset -> val calendarMonth = state.store[offset] diff --git a/compose/src/main/java/com/kizitonwose/calendar/compose/heatmapcalendar/HeatMapCalendarState.kt b/compose/src/main/java/com/kizitonwose/calendar/compose/heatmapcalendar/HeatMapCalendarState.kt index 25fbe52d..aef39282 100644 --- a/compose/src/main/java/com/kizitonwose/calendar/compose/heatmapcalendar/HeatMapCalendarState.kt +++ b/compose/src/main/java/com/kizitonwose/calendar/compose/heatmapcalendar/HeatMapCalendarState.kt @@ -15,6 +15,7 @@ import androidx.compose.runtime.saveable.Saver import androidx.compose.runtime.saveable.listSaver import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import com.kizitonwose.calendar.compose.CalendarInfo import com.kizitonwose.calendar.compose.CalendarLayoutInfo import com.kizitonwose.calendar.compose.VisibleItemState import com.kizitonwose.calendar.core.CalendarMonth @@ -162,7 +163,7 @@ class HeatMapCalendarState internal constructor( firstVisibleItemScrollOffset = visibleItemState?.firstVisibleItemScrollOffset ?: 0, ) - internal var monthIndexCount by mutableStateOf(0) + internal var calendarInfo by mutableStateOf(CalendarInfo(indexCount = 0)) internal val store = DataStore { offset -> getHeatMapCalendarMonthData( @@ -179,7 +180,10 @@ class HeatMapCalendarState internal constructor( private fun monthDataChanged() { store.clear() checkDateRange(startMonth, endMonth) - monthIndexCount = getMonthIndicesCount(startMonth, endMonth) + calendarInfo = CalendarInfo( + indexCount = getMonthIndicesCount(startMonth, endMonth), + firstDayOfWeek = firstDayOfWeek, + ) } /** diff --git a/compose/src/main/java/com/kizitonwose/calendar/compose/weekcalendar/WeekCalendarState.kt b/compose/src/main/java/com/kizitonwose/calendar/compose/weekcalendar/WeekCalendarState.kt index 9ee80a12..80e62705 100644 --- a/compose/src/main/java/com/kizitonwose/calendar/compose/weekcalendar/WeekCalendarState.kt +++ b/compose/src/main/java/com/kizitonwose/calendar/compose/weekcalendar/WeekCalendarState.kt @@ -10,6 +10,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.Saver import androidx.compose.runtime.saveable.listSaver @@ -179,7 +180,7 @@ class WeekCalendarState internal constructor( ).week } - internal var weekIndexCount by mutableStateOf(0) + internal var weekIndexCount by mutableIntStateOf(0) internal val listState = run { // Update date range and weekIndexCount initially. diff --git a/data/src/main/java/com/kizitonwose/calendar/data/DataStore.kt b/data/src/main/java/com/kizitonwose/calendar/data/DataStore.kt index f87b4df7..7445bd89 100644 --- a/data/src/main/java/com/kizitonwose/calendar/data/DataStore.kt +++ b/data/src/main/java/com/kizitonwose/calendar/data/DataStore.kt @@ -4,9 +4,12 @@ package com.kizitonwose.calendar.data * Basically [MutableMap.getOrPut] but allows us read the map * in multiple places without calling `getOrPut` everywhere. */ -class DataStore(private val create: (offset: Int) -> V) : HashMap() { +class DataStore( + private val store: MutableMap = HashMap(), + private val create: (offset: Int) -> V, +) : MutableMap by store { override fun get(key: Int): V { - val value = super.get(key) + val value = store[key] return if (value == null) { val data = create(key) put(key, data) diff --git a/sample/src/main/java/com/kizitonwose/calendar/sample/compose/Example6Page.kt b/sample/src/main/java/com/kizitonwose/calendar/sample/compose/Example6Page.kt index df31250b..d9ff85e0 100644 --- a/sample/src/main/java/com/kizitonwose/calendar/sample/compose/Example6Page.kt +++ b/sample/src/main/java/com/kizitonwose/calendar/sample/compose/Example6Page.kt @@ -19,6 +19,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -61,7 +62,7 @@ private enum class Level(val color: Color) { } private fun generateRandomData(startDate: LocalDate, endDate: LocalDate): Map { - val levels = Level.values() + val levels = Level.entries return (0..ChronoUnit.DAYS.between(startDate, endDate)) .associateTo(hashMapOf()) { count -> startDate.plusDays(count) to levels.random() @@ -70,7 +71,7 @@ private fun generateRandomData(startDate: LocalDate, endDate: LocalDate): Map + Level.entries.forEach { level -> LevelBox(level.color) } Text(text = "More", fontSize = 10.sp)