Refresh room summaries when date or time changes in the device (#3683)

* Add `DateTimeObserver` to rebuild the room summary data when the date/time changes.

* Add time changed action too, to trigger when the user manually changes date/time

* Fix timezone issue by adding `TimezoneProvider`, fix tests

* Create test for `DateTimeObserver` usage in `RoomListDataSource`

* Create aRoomListRoomSummaryFactory function.

* Improve test by faking the lastMessageTimestampFormatter

---------

Co-authored-by: Benoit Marty <benoit@matrix.org>
This commit is contained in:
Jorge Martin Espinosa 2024-10-16 11:10:58 +02:00 committed by GitHub
parent 0562b2ffdb
commit 2e9dce391b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 262 additions and 26 deletions

View file

@ -11,7 +11,6 @@ import android.text.format.DateFormat
import android.text.format.DateUtils
import kotlinx.datetime.Clock
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toJavaLocalDate
import kotlinx.datetime.toJavaLocalDateTime
@ -25,7 +24,7 @@ import kotlin.math.absoluteValue
class DateFormatters @Inject constructor(
private val locale: Locale,
private val clock: Clock,
private val timeZone: TimeZone,
private val timeZoneProvider: TimezoneProvider,
) {
private val onlyTimeFormatter: DateTimeFormatter by lazy {
DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT).withLocale(locale)
@ -70,7 +69,7 @@ class DateFormatters @Inject constructor(
return if (period.years.absoluteValue >= 1) {
formatDateWithYear(dateToFormat)
} else if (useRelative && period.days.absoluteValue < 2 && period.months.absoluteValue < 1) {
getRelativeDay(dateToFormat.toInstant(timeZone).toEpochMilliseconds())
getRelativeDay(dateToFormat.toInstant(timeZoneProvider.provide()).toEpochMilliseconds())
} else {
formatDateWithMonth(dateToFormat)
}

View file

@ -10,21 +10,20 @@ package io.element.android.libraries.dateformatter.impl
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toLocalDateTime
import javax.inject.Inject
class LocalDateTimeProvider @Inject constructor(
private val clock: Clock,
private val timezone: TimeZone,
private val timezoneProvider: TimezoneProvider,
) {
fun providesNow(): LocalDateTime {
val now: Instant = clock.now()
return now.toLocalDateTime(timezone)
return now.toLocalDateTime(timezoneProvider.provide())
}
fun providesFromTimestamp(timestamp: Long): LocalDateTime {
val tsInstant = Instant.fromEpochMilliseconds(timestamp)
return tsInstant.toLocalDateTime(timezone)
return tsInstant.toLocalDateTime(timezoneProvider.provide())
}
}

View file

@ -0,0 +1,14 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.libraries.dateformatter.impl
import kotlinx.datetime.TimeZone
fun interface TimezoneProvider {
fun provide(): TimeZone
}

View file

@ -10,6 +10,7 @@ package io.element.android.libraries.dateformatter.impl.di
import com.squareup.anvil.annotations.ContributesTo
import dagger.Module
import dagger.Provides
import io.element.android.libraries.dateformatter.impl.TimezoneProvider
import io.element.android.libraries.di.AppScope
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
@ -25,5 +26,5 @@ object DateFormatterModule {
fun providesLocale(): Locale = Locale.getDefault()
@Provides
fun providesTimezone(): TimeZone = TimeZone.currentSystemDefault()
fun providesTimezone(): TimezoneProvider = TimezoneProvider { TimeZone.currentSystemDefault() }
}

View file

@ -93,7 +93,7 @@ class DefaultLastMessageTimestampFormatterTest {
val now = "1980-04-06T18:35:24.00Z"
val dat = "1979-04-06T18:35:24.00Z"
val clock = FakeClock().apply { givenInstant(Instant.parse(now)) }
val dateFormatters = DateFormatters(Locale.US, clock, TimeZone.UTC)
val dateFormatters = DateFormatters(Locale.US, clock) { TimeZone.UTC }
assertThat(dateFormatters.formatDateWithFullFormat(Instant.parse(dat).toLocalDateTime(TimeZone.UTC))).isEqualTo("Friday, April 6, 1979")
}
@ -102,8 +102,8 @@ class DefaultLastMessageTimestampFormatterTest {
*/
private fun createFormatter(@Suppress("SameParameterValue") currentDate: String): LastMessageTimestampFormatter {
val clock = FakeClock().apply { givenInstant(Instant.parse(currentDate)) }
val localDateTimeProvider = LocalDateTimeProvider(clock, TimeZone.UTC)
val dateFormatters = DateFormatters(Locale.US, clock, TimeZone.UTC)
val localDateTimeProvider = LocalDateTimeProvider(clock) { TimeZone.UTC }
val dateFormatters = DateFormatters(Locale.US, clock) { TimeZone.UTC }
return DefaultLastMessageTimestampFormatter(localDateTimeProvider, dateFormatters)
}
}