From 3d7f50453fdf8de605874b1139cce0718803681f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 2 Jul 2025 08:31:52 +0000 Subject: [PATCH 01/13] Update kotlin --- gradle/libs.versions.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3668aa2938..ee087f202e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,9 +4,9 @@ [versions] # Project android_gradle_plugin = "8.11.0" -kotlin = "2.1.21" +kotlin = "2.2.0" kotlinpoet = "2.2.0" -ksp = "2.1.21-2.0.2" +ksp = "2.2.0-2.0.2" firebaseAppDistribution = "5.1.1" # AndroidX @@ -33,8 +33,8 @@ accompanist = "0.37.3" test_core = "1.6.1" # Jetbrain -datetime = "0.6.2" -serialization_json = "1.8.1" +datetime = "0.7.0-0.6.x-compat" +serialization_json = "1.9.0" #other detekt = "1.23.8" From 7a79b47bc8542776e5f1064179a53edac364f4e3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 12:01:20 +0200 Subject: [PATCH 02/13] Fix warning about freeCompilerArgs deprecation. --- libraries/maplibre-compose/build.gradle.kts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/maplibre-compose/build.gradle.kts b/libraries/maplibre-compose/build.gradle.kts index a2c1b5de1c..756a09c32c 100644 --- a/libraries/maplibre-compose/build.gradle.kts +++ b/libraries/maplibre-compose/build.gradle.kts @@ -13,8 +13,10 @@ plugins { android { namespace = "io.element.android.libraries.maplibre.compose" - kotlinOptions { - freeCompilerArgs += "-Xexplicit-api=strict" + kotlin { + compilerOptions { + explicitApi() + } } } From a001fa2296565d0c20a7f8a528a6be925461418d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 12:18:40 +0200 Subject: [PATCH 03/13] Fix compilation warning for annotations --- build.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build.gradle.kts b/build.gradle.kts index 317a6ab5bd..0e585a3d6b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -98,6 +98,10 @@ allprojects { // Uncomment to suppress Compose Kotlin compiler compatibility warning // freeCompilerArgs.addAll(listOf("-P", "plugin:androidx.compose.compiler.plugins.kotlin:suppressKotlinVersionCompatibilityCheck=true")) + + // Fix compilation warning for annotations + // See https://youtrack.jetbrains.com/issue/KT-73255/Change-defaulting-rule-for-annotations for more details + freeCompilerArgs.add("-Xannotation-default-target=first-only") } } } From 58101feb609951634a003187d97de642614dd085 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 12:21:15 +0200 Subject: [PATCH 04/13] Fix compilation error. toEpochDays() now returns a Long. --- .../android/libraries/dateformatter/impl/DateFormatterDay.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatterDay.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatterDay.kt index ecf5399302..bc8d8aedc0 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatterDay.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatterDay.kt @@ -33,8 +33,8 @@ class DefaultDateFormatterDay @Inject constructor( return if (useRelative) { val dayDiff = today.date.toEpochDays() - dateToFormat.date.toEpochDays() when (dayDiff) { - 0 -> dateFormatters.getRelativeDay(timestamp, "Today") - 1 -> dateFormatters.getRelativeDay(timestamp, "Yesterday") + 0L -> dateFormatters.getRelativeDay(timestamp, "Today") + 1L -> dateFormatters.getRelativeDay(timestamp, "Yesterday") else -> if (dayDiff < 7) { dateFormatters.formatDateWithDay(dateToFormat) } else { From 067e5972223f15b92dc9ed08e8e4bdfbb201014d Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 12:22:31 +0200 Subject: [PATCH 05/13] Kotlin compiler 2.2.0 --- .idea/kotlinc.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml index 1e16934f61..03fcfb7bea 100644 --- a/.idea/kotlinc.xml +++ b/.idea/kotlinc.xml @@ -1,6 +1,6 @@ - \ No newline at end of file From d478077487b36c7e396f1f295738b6b4c2ba6cc8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 12:23:06 +0200 Subject: [PATCH 06/13] ExperimentalTime OptIn is now needed. --- .../android/libraries/dateformatter/impl/DateFormatters.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt index d44c6d5c35..3728749317 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt @@ -20,6 +20,7 @@ import java.time.Period import java.util.Locale import javax.inject.Inject import kotlin.math.absoluteValue +import kotlin.time.ExperimentalTime @SingleIn(AppScope::class) class DateFormatters @Inject constructor( @@ -67,6 +68,7 @@ class DateFormatters @Inject constructor( return dateTimeFormatters.dateWithFullFormatNoYearFormatter.format(localDateTime.toJavaLocalDateTime()) } + @OptIn(ExperimentalTime::class) internal fun formatDate( dateToFormat: LocalDateTime, currentDate: LocalDateTime, From ec182bf8a05506ff0b1f4037c179fd9f0c40dbe8 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 12:29:17 +0200 Subject: [PATCH 07/13] Fix deprecation and add OptIn on Clock and Instant --- .../android/libraries/dateformatter/impl/DateFormatters.kt | 3 ++- .../libraries/dateformatter/impl/LocalDateTimeProvider.kt | 6 ++++-- .../libraries/dateformatter/impl/di/DateFormatterModule.kt | 4 +++- .../impl/previews/DateFormatterModeViewPreview.kt | 5 ++++- .../libraries/dateformatter/impl/previews/Factory.kt | 4 +++- .../libraries/dateformatter/impl/previews/PreviewClock.kt | 6 ++++-- .../dateformatter/impl/DefaultDateFormatterFrTest.kt | 4 +++- .../dateformatter/impl/DefaultDateFormatterTest.kt | 4 +++- .../element/android/libraries/dateformatter/impl/Factory.kt | 4 +++- .../android/libraries/dateformatter/impl/FakeClock.kt | 6 ++++-- 10 files changed, 33 insertions(+), 13 deletions(-) diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt index 3728749317..91ce539cee 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt @@ -10,7 +10,6 @@ package io.element.android.libraries.dateformatter.impl import android.text.format.DateUtils import io.element.android.libraries.di.AppScope import io.element.android.libraries.di.SingleIn -import kotlinx.datetime.Clock import kotlinx.datetime.LocalDateTime import kotlinx.datetime.toInstant import kotlinx.datetime.toJavaLocalDate @@ -20,8 +19,10 @@ import java.time.Period import java.util.Locale import javax.inject.Inject import kotlin.math.absoluteValue +import kotlin.time.Clock import kotlin.time.ExperimentalTime +@OptIn(ExperimentalTime::class) @SingleIn(AppScope::class) class DateFormatters @Inject constructor( localeChangeObserver: LocaleChangeObserver, diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/LocalDateTimeProvider.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/LocalDateTimeProvider.kt index c2cd062082..175da2ef9c 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/LocalDateTimeProvider.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/LocalDateTimeProvider.kt @@ -7,12 +7,14 @@ package io.element.android.libraries.dateformatter.impl -import kotlinx.datetime.Clock -import kotlinx.datetime.Instant import kotlinx.datetime.LocalDateTime import kotlinx.datetime.toLocalDateTime import javax.inject.Inject +import kotlin.time.Clock +import kotlin.time.ExperimentalTime +import kotlin.time.Instant +@OptIn(ExperimentalTime::class) class LocalDateTimeProvider @Inject constructor( private val clock: Clock, private val timezoneProvider: TimezoneProvider, diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/di/DateFormatterModule.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/di/DateFormatterModule.kt index 1fe22483a4..8decb527e2 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/di/DateFormatterModule.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/di/DateFormatterModule.kt @@ -12,10 +12,12 @@ 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 import java.util.Locale +import kotlin.time.Clock +import kotlin.time.ExperimentalTime +@OptIn(ExperimentalTime::class) @Module @ContributesTo(AppScope::class) object DateFormatterModule { diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/DateFormatterModeViewPreview.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/DateFormatterModeViewPreview.kt index b88badcc98..8b34e51e3f 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/DateFormatterModeViewPreview.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/DateFormatterModeViewPreview.kt @@ -5,6 +5,8 @@ * Please see LICENSE files in the repository root for full details. */ +@file:OptIn(ExperimentalTime::class) + package io.element.android.libraries.dateformatter.impl.previews import androidx.compose.foundation.layout.Column @@ -28,7 +30,8 @@ import io.element.android.libraries.dateformatter.impl.DefaultDateFormatter import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.allBooleans -import kotlinx.datetime.Instant +import kotlin.time.ExperimentalTime +import kotlin.time.Instant @Preview @Composable diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/Factory.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/Factory.kt index 88afcb554f..23f3d8733a 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/Factory.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/Factory.kt @@ -16,13 +16,15 @@ import io.element.android.libraries.dateformatter.impl.DateFormatters import io.element.android.libraries.dateformatter.impl.DefaultDateFormatter import io.element.android.libraries.dateformatter.impl.DefaultDateFormatterDay import io.element.android.libraries.dateformatter.impl.LocalDateTimeProvider -import kotlinx.datetime.Instant import kotlinx.datetime.TimeZone import java.util.Locale +import kotlin.time.ExperimentalTime +import kotlin.time.Instant /** * Create DefaultDateFormatter and set current time to the provided date. */ +@OptIn(ExperimentalTime::class) fun createFormatter( context: Context, currentDate: String, diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewClock.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewClock.kt index a86fb04455..5b9c26287e 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewClock.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewClock.kt @@ -7,9 +7,11 @@ package io.element.android.libraries.dateformatter.impl.previews -import kotlinx.datetime.Clock -import kotlinx.datetime.Instant +import kotlin.time.Clock +import kotlin.time.ExperimentalTime +import kotlin.time.Instant +@OptIn(ExperimentalTime::class) class PreviewClock : Clock { private var instant: Instant = Instant.fromEpochMilliseconds(0) diff --git a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterFrTest.kt b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterFrTest.kt index 7300b0d4ef..4955dadcaf 100644 --- a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterFrTest.kt +++ b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterFrTest.kt @@ -11,11 +11,13 @@ import android.os.Build import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import io.element.android.libraries.dateformatter.api.DateFormatterMode -import kotlinx.datetime.Instant import org.junit.Test import org.junit.runner.RunWith import org.robolectric.annotation.Config +import kotlin.time.ExperimentalTime +import kotlin.time.Instant +@OptIn(ExperimentalTime::class) @RunWith(AndroidJUnit4::class) @Config(qualifiers = "fr", sdk = [Build.VERSION_CODES.TIRAMISU]) class DefaultDateFormatterFrTest { diff --git a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterTest.kt b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterTest.kt index 25cda55654..c059675907 100644 --- a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterTest.kt +++ b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterTest.kt @@ -11,11 +11,13 @@ import android.os.Build import androidx.test.ext.junit.runners.AndroidJUnit4 import com.google.common.truth.Truth.assertThat import io.element.android.libraries.dateformatter.api.DateFormatterMode -import kotlinx.datetime.Instant import org.junit.Test import org.junit.runner.RunWith import org.robolectric.annotation.Config +import kotlin.time.ExperimentalTime +import kotlin.time.Instant +@OptIn(ExperimentalTime::class) @RunWith(AndroidJUnit4::class) @Config(qualifiers = "en", sdk = [Build.VERSION_CODES.TIRAMISU]) class DefaultDateFormatterTest { diff --git a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/Factory.kt b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/Factory.kt index 6ab588022d..d3fd71a4b4 100644 --- a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/Factory.kt +++ b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/Factory.kt @@ -8,13 +8,15 @@ package io.element.android.libraries.dateformatter.impl import io.element.android.tests.testutils.InstrumentationStringProvider -import kotlinx.datetime.Instant import kotlinx.datetime.TimeZone import java.util.Locale +import kotlin.time.ExperimentalTime +import kotlin.time.Instant /** * Create DefaultDateFormatter and set current time to the provided date. */ +@OptIn(ExperimentalTime::class) fun createFormatter(currentDate: String): DefaultDateFormatter { val clock = FakeClock().apply { givenInstant(Instant.parse(currentDate)) } val localDateTimeProvider = LocalDateTimeProvider(clock) { TimeZone.UTC } diff --git a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/FakeClock.kt b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/FakeClock.kt index 047e87e62a..fb26bda5bb 100644 --- a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/FakeClock.kt +++ b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/FakeClock.kt @@ -7,9 +7,11 @@ package io.element.android.libraries.dateformatter.impl -import kotlinx.datetime.Clock -import kotlinx.datetime.Instant +import kotlin.time.Clock +import kotlin.time.ExperimentalTime +import kotlin.time.Instant +@OptIn(ExperimentalTime::class) class FakeClock : Clock { private var instant: Instant = Instant.fromEpochMilliseconds(0) From 42dccf9b86ee67f14dc9d80e6f1a26a4c561ea75 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 12:32:08 +0200 Subject: [PATCH 08/13] Upgrade lint version to 8.12.0-alpha07 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index eafefba3e6..513fcac955 100644 --- a/gradle.properties +++ b/gradle.properties @@ -40,7 +40,7 @@ signing.element.nightly.keyPassword=Secret # Customise the Lint version to use a more recent version than the one bundled with AGP # https://googlesamples.github.io/android-custom-lint-rules/usage/newer-lint.md.html -android.experimental.lint.version=8.11.0 +android.experimental.lint.version=8.12.0-alpha07 # Enable test fixture for all modules by default android.experimental.enableTestFixtures=true From 2d0c039c68cb4ba8ab57d458bdf1760423a0504c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 13:23:17 +0200 Subject: [PATCH 09/13] Improve test coverage of SendActionState --- .../impl/attachments/SendActionStateTest.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/SendActionStateTest.kt diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/SendActionStateTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/SendActionStateTest.kt new file mode 100644 index 0000000000..10290610dc --- /dev/null +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/attachments/SendActionStateTest.kt @@ -0,0 +1,26 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.features.messages.impl.attachments + +import com.google.common.truth.Truth.assertThat +import io.element.android.features.messages.impl.attachments.preview.SendActionState +import io.element.android.features.messages.impl.attachments.preview.aMediaUploadInfo +import io.element.android.libraries.mediaupload.api.MediaUploadInfo +import org.junit.Test + +class SendActionStateTest { + @Test + fun `mediaUploadInfo() should return the value from Uploading class`() { + val mediaUploadInfo: MediaUploadInfo = aMediaUploadInfo() + val state: SendActionState = SendActionState.Sending.Uploading( + progress = 0.5f, + mediaUploadInfo = aMediaUploadInfo() + ) + assertThat(state.mediaUploadInfo()).isEqualTo(mediaUploadInfo) + } +} From fa6c8044478906ae7551ef8e36a96977ef6c3262 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 13:29:22 +0200 Subject: [PATCH 10/13] Improve test coverage of PinnedMessagesBannerState --- .../features/messages/impl/MessagesView.kt | 2 +- .../banner/PinnedMessagesBannerState.kt | 39 +++++++++---------- .../pinned/banner/PinnedMessagesBannerView.kt | 2 +- .../PinnedMessagesBannerPresenterTest.kt | 5 ++- 4 files changed, 23 insertions(+), 25 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index debea82cf0..dff12448bf 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -391,7 +391,7 @@ private fun MessagesViewContent( Box { val scrollBehavior = PinnedMessagesBannerViewDefaults.rememberScrollBehavior( - pinnedMessagesCount = state.pinnedMessagesBannerState.pinnedMessagesCount(), + pinnedMessagesCount = (state.pinnedMessagesBannerState as? PinnedMessagesBannerState.Visible)?.pinnedMessagesCount() ?: 0, ) TimelineView( state = state.timelineState, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt index ff36ba8999..244ade3a5a 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt @@ -10,14 +10,30 @@ package io.element.android.features.messages.impl.pinned.banner import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.AnnotatedString import io.element.android.libraries.designsystem.text.toAnnotatedString import io.element.android.libraries.ui.strings.CommonStrings @Immutable sealed interface PinnedMessagesBannerState { data object Hidden : PinnedMessagesBannerState - sealed interface Visible : PinnedMessagesBannerState + sealed interface Visible : PinnedMessagesBannerState { + fun pinnedMessagesCount() = when (this) { + is Loading -> expectedPinnedMessagesCount + is Loaded -> loadedPinnedMessagesCount + } + + fun currentPinnedMessageIndex() = when (this) { + is Loading -> expectedPinnedMessagesCount - 1 + is Loaded -> currentPinnedMessageIndex + } + + @Composable + fun formattedMessage() = when (this) { + is Loading -> stringResource(id = CommonStrings.screen_room_pinned_banner_loading_description).toAnnotatedString() + is Loaded -> currentPinnedMessage.formatted + } + } + data class Loading(val expectedPinnedMessagesCount: Int) : Visible data class Loaded( val currentPinnedMessage: PinnedMessagesBannerItem, @@ -25,23 +41,4 @@ sealed interface PinnedMessagesBannerState { val loadedPinnedMessagesCount: Int, val eventSink: (PinnedMessagesBannerEvents) -> Unit ) : Visible - - fun pinnedMessagesCount() = when (this) { - is Hidden -> 0 - is Loading -> expectedPinnedMessagesCount - is Loaded -> loadedPinnedMessagesCount - } - - fun currentPinnedMessageIndex() = when (this) { - is Hidden -> 0 - is Loading -> expectedPinnedMessagesCount - 1 - is Loaded -> currentPinnedMessageIndex - } - - @Composable - fun formattedMessage() = when (this) { - is Hidden -> AnnotatedString("") - is Loading -> stringResource(id = CommonStrings.screen_room_pinned_banner_loading_description).toAnnotatedString() - is Loaded -> currentPinnedMessage.formatted - } } diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt index aef0848b1e..194cc433f4 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt @@ -78,7 +78,7 @@ fun PinnedMessagesBannerView( @Composable private fun PinnedMessagesBannerRow( - state: PinnedMessagesBannerState, + state: PinnedMessagesBannerState.Visible, onClick: (EventId) -> Unit, onViewAllClick: () -> Unit, modifier: Modifier = Modifier, diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt index ecd069585f..f1fcd7e787 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerPresenterTest.kt @@ -62,7 +62,7 @@ class PinnedMessagesBannerPresenterTest { val presenter = createPinnedMessagesBannerPresenter(room = room) presenter.test { skipItems(2) - val loadingState = awaitItem() + val loadingState = awaitItem() as PinnedMessagesBannerState.Loading assertThat(loadingState).isEqualTo(PinnedMessagesBannerState.Loading(1)) assertThat(loadingState.pinnedMessagesCount()).isEqualTo(1) assertThat(loadingState.currentPinnedMessageIndex()).isEqualTo(0) @@ -167,7 +167,8 @@ class PinnedMessagesBannerPresenterTest { val presenter = createPinnedMessagesBannerPresenter(room = room) presenter.test { skipItems(2) - awaitItem().also { loadingState -> + awaitItem().also { state -> + val loadingState = state as PinnedMessagesBannerState.Loading assertThat(loadingState).isEqualTo(PinnedMessagesBannerState.Loading(1)) assertThat(loadingState.pinnedMessagesCount()).isEqualTo(1) assertThat(loadingState.currentPinnedMessageIndex()).isEqualTo(0) From b36fa123e8f0b52d52c2205c22be5887d78d4cfd Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 13:45:03 +0200 Subject: [PATCH 11/13] It seems that we can use datetime 0.7.0 Doc is at https://github.com/Kotlin/kotlinx-datetime?tab=readme-ov-file#deprecation-of-instant --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ee087f202e..74ae0a6d53 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -33,7 +33,7 @@ accompanist = "0.37.3" test_core = "1.6.1" # Jetbrain -datetime = "0.7.0-0.6.x-compat" +datetime = "0.7.0" serialization_json = "1.9.0" #other From 00504097b98c010d7703f2f02129d31eb5013573 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 14:28:13 +0200 Subject: [PATCH 12/13] `Visible` must be annotated with `Immutable` --- .../messages/impl/pinned/banner/PinnedMessagesBannerState.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt index 244ade3a5a..785de15954 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerState.kt @@ -16,6 +16,7 @@ import io.element.android.libraries.ui.strings.CommonStrings @Immutable sealed interface PinnedMessagesBannerState { data object Hidden : PinnedMessagesBannerState + @Immutable sealed interface Visible : PinnedMessagesBannerState { fun pinnedMessagesCount() = when (this) { is Loading -> expectedPinnedMessagesCount From 949d11415f6404b718c1c326d469604b3c67a8a2 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 2 Jul 2025 18:00:25 +0200 Subject: [PATCH 13/13] OptIn to ExperimentalTime for the whole module. --- libraries/dateformatter/impl/build.gradle.kts | 8 ++++++++ .../libraries/dateformatter/impl/DateFormatters.kt | 3 --- .../libraries/dateformatter/impl/LocalDateTimeProvider.kt | 2 -- .../dateformatter/impl/di/DateFormatterModule.kt | 2 -- .../impl/previews/DateFormatterModeViewPreview.kt | 3 --- .../libraries/dateformatter/impl/previews/Factory.kt | 2 -- .../libraries/dateformatter/impl/previews/PreviewClock.kt | 2 -- .../dateformatter/impl/DefaultDateFormatterFrTest.kt | 2 -- .../dateformatter/impl/DefaultDateFormatterTest.kt | 2 -- .../android/libraries/dateformatter/impl/Factory.kt | 2 -- .../android/libraries/dateformatter/impl/FakeClock.kt | 2 -- 11 files changed, 8 insertions(+), 22 deletions(-) diff --git a/libraries/dateformatter/impl/build.gradle.kts b/libraries/dateformatter/impl/build.gradle.kts index 4a619af5b7..ed8c7731bd 100644 --- a/libraries/dateformatter/impl/build.gradle.kts +++ b/libraries/dateformatter/impl/build.gradle.kts @@ -22,6 +22,14 @@ android { } } + kotlin { + compilerOptions { + optIn = listOf( + "kotlin.time.ExperimentalTime" + ) + } + } + dependencies { implementation(libs.dagger) implementation(projects.libraries.core) diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt index 91ce539cee..9e5ffd6afe 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/DateFormatters.kt @@ -20,9 +20,7 @@ import java.util.Locale import javax.inject.Inject import kotlin.math.absoluteValue import kotlin.time.Clock -import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) @SingleIn(AppScope::class) class DateFormatters @Inject constructor( localeChangeObserver: LocaleChangeObserver, @@ -69,7 +67,6 @@ class DateFormatters @Inject constructor( return dateTimeFormatters.dateWithFullFormatNoYearFormatter.format(localDateTime.toJavaLocalDateTime()) } - @OptIn(ExperimentalTime::class) internal fun formatDate( dateToFormat: LocalDateTime, currentDate: LocalDateTime, diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/LocalDateTimeProvider.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/LocalDateTimeProvider.kt index 175da2ef9c..20862fd68a 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/LocalDateTimeProvider.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/LocalDateTimeProvider.kt @@ -11,10 +11,8 @@ import kotlinx.datetime.LocalDateTime import kotlinx.datetime.toLocalDateTime import javax.inject.Inject import kotlin.time.Clock -import kotlin.time.ExperimentalTime import kotlin.time.Instant -@OptIn(ExperimentalTime::class) class LocalDateTimeProvider @Inject constructor( private val clock: Clock, private val timezoneProvider: TimezoneProvider, diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/di/DateFormatterModule.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/di/DateFormatterModule.kt index 8decb527e2..a7da8ea6ce 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/di/DateFormatterModule.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/di/DateFormatterModule.kt @@ -15,9 +15,7 @@ import io.element.android.libraries.di.AppScope import kotlinx.datetime.TimeZone import java.util.Locale import kotlin.time.Clock -import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) @Module @ContributesTo(AppScope::class) object DateFormatterModule { diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/DateFormatterModeViewPreview.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/DateFormatterModeViewPreview.kt index 8b34e51e3f..79b1022c14 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/DateFormatterModeViewPreview.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/DateFormatterModeViewPreview.kt @@ -5,8 +5,6 @@ * Please see LICENSE files in the repository root for full details. */ -@file:OptIn(ExperimentalTime::class) - package io.element.android.libraries.dateformatter.impl.previews import androidx.compose.foundation.layout.Column @@ -30,7 +28,6 @@ import io.element.android.libraries.dateformatter.impl.DefaultDateFormatter import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.theme.components.Text import io.element.android.libraries.designsystem.utils.allBooleans -import kotlin.time.ExperimentalTime import kotlin.time.Instant @Preview diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/Factory.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/Factory.kt index 23f3d8733a..d0c25f8b60 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/Factory.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/Factory.kt @@ -18,13 +18,11 @@ import io.element.android.libraries.dateformatter.impl.DefaultDateFormatterDay import io.element.android.libraries.dateformatter.impl.LocalDateTimeProvider import kotlinx.datetime.TimeZone import java.util.Locale -import kotlin.time.ExperimentalTime import kotlin.time.Instant /** * Create DefaultDateFormatter and set current time to the provided date. */ -@OptIn(ExperimentalTime::class) fun createFormatter( context: Context, currentDate: String, diff --git a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewClock.kt b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewClock.kt index 5b9c26287e..8151e07262 100644 --- a/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewClock.kt +++ b/libraries/dateformatter/impl/src/main/kotlin/io/element/android/libraries/dateformatter/impl/previews/PreviewClock.kt @@ -8,10 +8,8 @@ package io.element.android.libraries.dateformatter.impl.previews import kotlin.time.Clock -import kotlin.time.ExperimentalTime import kotlin.time.Instant -@OptIn(ExperimentalTime::class) class PreviewClock : Clock { private var instant: Instant = Instant.fromEpochMilliseconds(0) diff --git a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterFrTest.kt b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterFrTest.kt index 4955dadcaf..0e52e1de37 100644 --- a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterFrTest.kt +++ b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterFrTest.kt @@ -14,10 +14,8 @@ import io.element.android.libraries.dateformatter.api.DateFormatterMode import org.junit.Test import org.junit.runner.RunWith import org.robolectric.annotation.Config -import kotlin.time.ExperimentalTime import kotlin.time.Instant -@OptIn(ExperimentalTime::class) @RunWith(AndroidJUnit4::class) @Config(qualifiers = "fr", sdk = [Build.VERSION_CODES.TIRAMISU]) class DefaultDateFormatterFrTest { diff --git a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterTest.kt b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterTest.kt index c059675907..136bbc1293 100644 --- a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterTest.kt +++ b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/DefaultDateFormatterTest.kt @@ -14,10 +14,8 @@ import io.element.android.libraries.dateformatter.api.DateFormatterMode import org.junit.Test import org.junit.runner.RunWith import org.robolectric.annotation.Config -import kotlin.time.ExperimentalTime import kotlin.time.Instant -@OptIn(ExperimentalTime::class) @RunWith(AndroidJUnit4::class) @Config(qualifiers = "en", sdk = [Build.VERSION_CODES.TIRAMISU]) class DefaultDateFormatterTest { diff --git a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/Factory.kt b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/Factory.kt index d3fd71a4b4..20f36a0dd6 100644 --- a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/Factory.kt +++ b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/Factory.kt @@ -10,13 +10,11 @@ package io.element.android.libraries.dateformatter.impl import io.element.android.tests.testutils.InstrumentationStringProvider import kotlinx.datetime.TimeZone import java.util.Locale -import kotlin.time.ExperimentalTime import kotlin.time.Instant /** * Create DefaultDateFormatter and set current time to the provided date. */ -@OptIn(ExperimentalTime::class) fun createFormatter(currentDate: String): DefaultDateFormatter { val clock = FakeClock().apply { givenInstant(Instant.parse(currentDate)) } val localDateTimeProvider = LocalDateTimeProvider(clock) { TimeZone.UTC } diff --git a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/FakeClock.kt b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/FakeClock.kt index fb26bda5bb..c3d1f01d4f 100644 --- a/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/FakeClock.kt +++ b/libraries/dateformatter/impl/src/test/kotlin/io/element/android/libraries/dateformatter/impl/FakeClock.kt @@ -8,10 +8,8 @@ package io.element.android.libraries.dateformatter.impl import kotlin.time.Clock -import kotlin.time.ExperimentalTime import kotlin.time.Instant -@OptIn(ExperimentalTime::class) class FakeClock : Clock { private var instant: Instant = Instant.fromEpochMilliseconds(0)