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 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") } } } 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..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 @@ -10,14 +10,31 @@ 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 + @Immutable + 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 +42,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/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) + } +} 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) 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 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index eb98e3c2f8..842c033c83 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" +serialization_json = "1.9.0" #other detekt = "1.23.8" 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/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 { 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..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 @@ -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,6 +19,7 @@ import java.time.Period import java.util.Locale import javax.inject.Inject import kotlin.math.absoluteValue +import kotlin.time.Clock @SingleIn(AppScope::class) class DateFormatters @Inject constructor( 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..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 @@ -7,11 +7,11 @@ 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.Instant class LocalDateTimeProvider @Inject constructor( private val clock: Clock, 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..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 @@ -12,9 +12,9 @@ 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 @Module @ContributesTo(AppScope::class) 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..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 @@ -28,7 +28,7 @@ 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.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..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 @@ -16,9 +16,9 @@ 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.Instant /** * Create DefaultDateFormatter and set current time to the provided date. 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..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 @@ -7,8 +7,8 @@ package io.element.android.libraries.dateformatter.impl.previews -import kotlinx.datetime.Clock -import kotlinx.datetime.Instant +import kotlin.time.Clock +import kotlin.time.Instant 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..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 @@ -11,10 +11,10 @@ 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.Instant @RunWith(AndroidJUnit4::class) @Config(qualifiers = "fr", sdk = [Build.VERSION_CODES.TIRAMISU]) 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..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 @@ -11,10 +11,10 @@ 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.Instant @RunWith(AndroidJUnit4::class) @Config(qualifiers = "en", sdk = [Build.VERSION_CODES.TIRAMISU]) 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..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 @@ -8,9 +8,9 @@ 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.Instant /** * Create DefaultDateFormatter and set current time to the provided date. 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..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 @@ -7,8 +7,8 @@ package io.element.android.libraries.dateformatter.impl -import kotlinx.datetime.Clock -import kotlinx.datetime.Instant +import kotlin.time.Clock +import kotlin.time.Instant class FakeClock : Clock { private var instant: Instant = Instant.fromEpochMilliseconds(0) 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() + } } }