Merge pull request #5503 from element-hq/feature/bma/immutableCleanup
Do some cleanup on our immutable annotation usage
This commit is contained in:
33
.github/workflows/quality.yml
vendored
33
.github/workflows/quality.yml
vendored
@@ -103,6 +103,39 @@ jobs:
|
|||||||
path: |
|
path: |
|
||||||
**/build/reports/**/*.*
|
**/build/reports/**/*.*
|
||||||
|
|
||||||
|
compose:
|
||||||
|
name: Compose tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
# Allow all jobs on main and develop. Just one per PR.
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.ref == 'refs/heads/main' && format('check-compose-main-{0}', github.sha) || github.ref == 'refs/heads/develop' && format('check-compose-develop-{0}', github.sha) || format('check-compose-{0}', github.ref) }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
# Ensure we are building the branch and not the branch after being merged on develop
|
||||||
|
# https://github.com/actions/checkout/issues/881
|
||||||
|
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.ref }}
|
||||||
|
- name: Add SSH private keys for submodule repositories
|
||||||
|
uses: webfactory/ssh-agent@a6f90b1f127823b31d4d4a8d96047790581349bd # v0.9.1
|
||||||
|
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }}
|
||||||
|
with:
|
||||||
|
ssh-private-key: ${{ secrets.ELEMENT_ENTERPRISE_DEPLOY_KEY }}
|
||||||
|
- name: Clone submodules
|
||||||
|
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == 'element-hq/element-x-android' }}
|
||||||
|
run: git submodule update --init --recursive
|
||||||
|
- name: Use JDK 21
|
||||||
|
uses: actions/setup-java@v5
|
||||||
|
with:
|
||||||
|
distribution: 'temurin' # See 'Supported distributions' for available options
|
||||||
|
java-version: '21'
|
||||||
|
- name: Configure gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v5
|
||||||
|
with:
|
||||||
|
cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
|
||||||
|
- name: Run compose tests
|
||||||
|
run: ./tools/compose/check_stability.sh
|
||||||
|
|
||||||
lint:
|
lint:
|
||||||
name: Android lint check
|
name: Android lint check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -7,12 +7,10 @@
|
|||||||
|
|
||||||
package io.element.android.appnav.root
|
package io.element.android.appnav.root
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.features.rageshake.api.crash.CrashDetectionState
|
import io.element.android.features.rageshake.api.crash.CrashDetectionState
|
||||||
import io.element.android.features.rageshake.api.detection.RageshakeDetectionState
|
import io.element.android.features.rageshake.api.detection.RageshakeDetectionState
|
||||||
import io.element.android.services.apperror.api.AppErrorState
|
import io.element.android.services.apperror.api.AppErrorState
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class RootState(
|
data class RootState(
|
||||||
val rageshakeDetectionState: RageshakeDetectionState,
|
val rageshakeDetectionState: RageshakeDetectionState,
|
||||||
val crashDetectionState: CrashDetectionState,
|
val crashDetectionState: CrashDetectionState,
|
||||||
|
|||||||
@@ -8,10 +8,13 @@
|
|||||||
package io.element.android.features.createroom.impl.configureroom
|
package io.element.android.features.createroom.impl.configureroom
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
|
// Annotate with @Immutable since `Uri` is unstable
|
||||||
|
@Immutable
|
||||||
data class CreateRoomConfig(
|
data class CreateRoomConfig(
|
||||||
val roomName: String? = null,
|
val roomName: String? = null,
|
||||||
val topic: String? = null,
|
val topic: String? = null,
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
package io.element.android.features.home.impl
|
package io.element.android.features.home.impl
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.features.home.impl.roomlist.RoomListState
|
import io.element.android.features.home.impl.roomlist.RoomListState
|
||||||
import io.element.android.features.home.impl.spaces.HomeSpacesState
|
import io.element.android.features.home.impl.spaces.HomeSpacesState
|
||||||
import io.element.android.features.logout.api.direct.DirectLogoutState
|
import io.element.android.features.logout.api.direct.DirectLogoutState
|
||||||
@@ -15,7 +14,6 @@ import io.element.android.libraries.designsystem.utils.snackbar.SnackbarMessage
|
|||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class HomeState(
|
data class HomeState(
|
||||||
/**
|
/**
|
||||||
* The current user of this session, in case of multiple accounts, will contains 3 items, with the
|
* The current user of this session, in case of multiple accounts, will contains 3 items, with the
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import io.element.android.libraries.push.api.battery.BatteryOptimizationState
|
|||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.ImmutableSet
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class RoomListState(
|
data class RoomListState(
|
||||||
val contextMenu: ContextMenu,
|
val contextMenu: ContextMenu,
|
||||||
val declineInviteMenu: DeclineInviteMenu,
|
val declineInviteMenu: DeclineInviteMenu,
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ import io.element.android.features.invite.api.SeenInvitesStore
|
|||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar
|
import io.element.android.libraries.matrix.ui.safety.rememberHideInvitesAvatar
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.persistentSetOf
|
import kotlinx.collections.immutable.persistentSetOf
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableSet
|
import kotlinx.collections.immutable.toImmutableSet
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
||||||
@@ -28,7 +30,10 @@ class HomeSpacesPresenter(
|
|||||||
@Composable
|
@Composable
|
||||||
override fun present(): HomeSpacesState {
|
override fun present(): HomeSpacesState {
|
||||||
val hideInvitesAvatar by client.rememberHideInvitesAvatar()
|
val hideInvitesAvatar by client.rememberHideInvitesAvatar()
|
||||||
val spaceRooms by client.spaceService.spaceRoomsFlow.collectAsState(emptyList())
|
val spaceRooms by remember {
|
||||||
|
client.spaceService.spaceRoomsFlow.map { it.toImmutableList() }
|
||||||
|
}.collectAsState(persistentListOf())
|
||||||
|
|
||||||
val seenSpaceInvites by remember {
|
val seenSpaceInvites by remember {
|
||||||
seenInvitesStore.seenRoomIds().map { it.toImmutableSet() }
|
seenInvitesStore.seenRoomIds().map { it.toImmutableSet() }
|
||||||
}.collectAsState(persistentSetOf())
|
}.collectAsState(persistentSetOf())
|
||||||
|
|||||||
@@ -9,11 +9,12 @@ package io.element.android.features.home.impl.spaces
|
|||||||
|
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.spaces.SpaceRoom
|
import io.element.android.libraries.matrix.api.spaces.SpaceRoom
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.ImmutableSet
|
import kotlinx.collections.immutable.ImmutableSet
|
||||||
|
|
||||||
data class HomeSpacesState(
|
data class HomeSpacesState(
|
||||||
val space: CurrentSpace,
|
val space: CurrentSpace,
|
||||||
val spaceRooms: List<SpaceRoom>,
|
val spaceRooms: ImmutableList<SpaceRoom>,
|
||||||
val seenSpaceInvites: ImmutableSet<RoomId>,
|
val seenSpaceInvites: ImmutableSet<RoomId>,
|
||||||
val hideInvitesAvatar: Boolean,
|
val hideInvitesAvatar: Boolean,
|
||||||
val eventSink: (HomeSpacesEvents) -> Unit,
|
val eventSink: (HomeSpacesEvents) -> Unit,
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
|||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.spaces.SpaceRoom
|
import io.element.android.libraries.matrix.api.spaces.SpaceRoom
|
||||||
import io.element.android.libraries.previewutils.room.aSpaceRoom
|
import io.element.android.libraries.previewutils.room.aSpaceRoom
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableSet
|
import kotlinx.collections.immutable.toImmutableSet
|
||||||
|
|
||||||
open class HomeSpacesStateProvider : PreviewParameterProvider<HomeSpacesState> {
|
open class HomeSpacesStateProvider : PreviewParameterProvider<HomeSpacesState> {
|
||||||
@@ -39,7 +40,7 @@ internal fun aHomeSpacesState(
|
|||||||
eventSink: (HomeSpacesEvents) -> Unit = {},
|
eventSink: (HomeSpacesEvents) -> Unit = {},
|
||||||
) = HomeSpacesState(
|
) = HomeSpacesState(
|
||||||
space = space,
|
space = space,
|
||||||
spaceRooms = spaceRooms,
|
spaceRooms = spaceRooms.toImmutableList(),
|
||||||
seenSpaceInvites = seenSpaceInvites.toImmutableSet(),
|
seenSpaceInvites = seenSpaceInvites.toImmutableSet(),
|
||||||
hideInvitesAvatar = hideInvitesAvatar,
|
hideInvitesAvatar = hideInvitesAvatar,
|
||||||
eventSink = eventSink,
|
eventSink = eventSink,
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import kotlinx.collections.immutable.ImmutableList
|
|||||||
|
|
||||||
internal const val MAX_KNOCK_MESSAGE_LENGTH = 500
|
internal const val MAX_KNOCK_MESSAGE_LENGTH = 500
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class JoinRoomState(
|
data class JoinRoomState(
|
||||||
val roomIdOrAlias: RoomIdOrAlias,
|
val roomIdOrAlias: RoomIdOrAlias,
|
||||||
val contentState: ContentState,
|
val contentState: ContentState,
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
package io.element.android.features.leaveroom.api
|
package io.element.android.features.leaveroom.api
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
@Immutable
|
||||||
interface LeaveRoomState {
|
interface LeaveRoomState {
|
||||||
val eventSink: (LeaveRoomEvent) -> Unit
|
val eventSink: (LeaveRoomEvent) -> Unit
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import io.element.android.features.login.impl.accountprovider.AccountProvider
|
|||||||
import io.element.android.features.login.impl.changeserver.ChangeServerState
|
import io.element.android.features.login.impl.changeserver.ChangeServerState
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.core.uri.ensureProtocol
|
import io.element.android.libraries.core.uri.ensureProtocol
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
class ChangeAccountProviderPresenter(
|
class ChangeAccountProviderPresenter(
|
||||||
@@ -39,6 +40,7 @@ class ChangeAccountProviderPresenter(
|
|||||||
isValid = true,
|
isValid = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
.toImmutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val canSearchForAccountProviders = remember {
|
val canSearchForAccountProviders = remember {
|
||||||
|
|||||||
@@ -9,10 +9,11 @@ package io.element.android.features.login.impl.screens.changeaccountprovider
|
|||||||
|
|
||||||
import io.element.android.features.login.impl.accountprovider.AccountProvider
|
import io.element.android.features.login.impl.accountprovider.AccountProvider
|
||||||
import io.element.android.features.login.impl.changeserver.ChangeServerState
|
import io.element.android.features.login.impl.changeserver.ChangeServerState
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
// Do not use default value, so no member get forgotten in the presenters.
|
// Do not use default value, so no member get forgotten in the presenters.
|
||||||
data class ChangeAccountProviderState(
|
data class ChangeAccountProviderState(
|
||||||
val accountProviders: List<AccountProvider>,
|
val accountProviders: ImmutableList<AccountProvider>,
|
||||||
val canSearchForAccountProviders: Boolean,
|
val canSearchForAccountProviders: Boolean,
|
||||||
val changeServerState: ChangeServerState,
|
val changeServerState: ChangeServerState,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import io.element.android.features.login.impl.accountprovider.AccountProvider
|
|||||||
import io.element.android.features.login.impl.accountprovider.anAccountProvider
|
import io.element.android.features.login.impl.accountprovider.anAccountProvider
|
||||||
import io.element.android.features.login.impl.changeserver.ChangeServerState
|
import io.element.android.features.login.impl.changeserver.ChangeServerState
|
||||||
import io.element.android.features.login.impl.changeserver.aChangeServerState
|
import io.element.android.features.login.impl.changeserver.aChangeServerState
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
open class ChangeAccountProviderStateProvider : PreviewParameterProvider<ChangeAccountProviderState> {
|
open class ChangeAccountProviderStateProvider : PreviewParameterProvider<ChangeAccountProviderState> {
|
||||||
override val values: Sequence<ChangeAccountProviderState>
|
override val values: Sequence<ChangeAccountProviderState>
|
||||||
@@ -29,7 +30,7 @@ fun aChangeAccountProviderState(
|
|||||||
canSearchForAccountProviders: Boolean = true,
|
canSearchForAccountProviders: Boolean = true,
|
||||||
changeServerState: ChangeServerState = aChangeServerState(),
|
changeServerState: ChangeServerState = aChangeServerState(),
|
||||||
) = ChangeAccountProviderState(
|
) = ChangeAccountProviderState(
|
||||||
accountProviders = accountProviders,
|
accountProviders = accountProviders.toImmutableList(),
|
||||||
canSearchForAccountProviders = canSearchForAccountProviders,
|
canSearchForAccountProviders = canSearchForAccountProviders,
|
||||||
changeServerState = changeServerState,
|
changeServerState = changeServerState,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import io.element.android.features.login.impl.login.LoginHelper
|
|||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.core.uri.ensureProtocol
|
import io.element.android.libraries.core.uri.ensureProtocol
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
class ChooseAccountProviderPresenter(
|
class ChooseAccountProviderPresenter(
|
||||||
@@ -69,6 +70,7 @@ class ChooseAccountProviderPresenter(
|
|||||||
isValid = true,
|
isValid = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
.toImmutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
return ChooseAccountProviderState(
|
return ChooseAccountProviderState(
|
||||||
|
|||||||
@@ -10,10 +10,11 @@ package io.element.android.features.login.impl.screens.chooseaccountprovider
|
|||||||
import io.element.android.features.login.impl.accountprovider.AccountProvider
|
import io.element.android.features.login.impl.accountprovider.AccountProvider
|
||||||
import io.element.android.features.login.impl.login.LoginMode
|
import io.element.android.features.login.impl.login.LoginMode
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
// Do not use default value, so no member get forgotten in the presenters.
|
// Do not use default value, so no member get forgotten in the presenters.
|
||||||
data class ChooseAccountProviderState(
|
data class ChooseAccountProviderState(
|
||||||
val accountProviders: List<AccountProvider>,
|
val accountProviders: ImmutableList<AccountProvider>,
|
||||||
val selectedAccountProvider: AccountProvider?,
|
val selectedAccountProvider: AccountProvider?,
|
||||||
val loginMode: AsyncData<LoginMode>,
|
val loginMode: AsyncData<LoginMode>,
|
||||||
val eventSink: (ChooseAccountProviderEvents) -> Unit,
|
val eventSink: (ChooseAccountProviderEvents) -> Unit,
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import io.element.android.features.login.impl.accountprovider.AccountProvider
|
|||||||
import io.element.android.features.login.impl.accountprovider.anAccountProvider
|
import io.element.android.features.login.impl.accountprovider.anAccountProvider
|
||||||
import io.element.android.features.login.impl.login.LoginMode
|
import io.element.android.features.login.impl.login.LoginMode
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
open class ChooseAccountProviderStateProvider : PreviewParameterProvider<ChooseAccountProviderState> {
|
open class ChooseAccountProviderStateProvider : PreviewParameterProvider<ChooseAccountProviderState> {
|
||||||
private val server1 = anAccountProvider(
|
private val server1 = anAccountProvider(
|
||||||
@@ -70,7 +71,7 @@ fun aChooseAccountProviderState(
|
|||||||
loginMode: AsyncData<LoginMode> = AsyncData.Uninitialized,
|
loginMode: AsyncData<LoginMode> = AsyncData.Uninitialized,
|
||||||
eventSink: (ChooseAccountProviderEvents) -> Unit = {},
|
eventSink: (ChooseAccountProviderEvents) -> Unit = {},
|
||||||
) = ChooseAccountProviderState(
|
) = ChooseAccountProviderState(
|
||||||
accountProviders = accountProviders,
|
accountProviders = accountProviders.toImmutableList(),
|
||||||
selectedAccountProvider = selectedAccountProvider,
|
selectedAccountProvider = selectedAccountProvider,
|
||||||
loginMode = loginMode,
|
loginMode = loginMode,
|
||||||
eventSink = eventSink,
|
eventSink = eventSink,
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
package io.element.android.features.messages.impl
|
package io.element.android.features.messages.impl
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.features.messages.api.timeline.voicemessages.composer.VoiceMessageComposerState
|
import io.element.android.features.messages.api.timeline.voicemessages.composer.VoiceMessageComposerState
|
||||||
import io.element.android.features.messages.impl.actionlist.ActionListState
|
import io.element.android.features.messages.impl.actionlist.ActionListState
|
||||||
import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState
|
import io.element.android.features.messages.impl.crypto.identity.IdentityChangeState
|
||||||
@@ -29,7 +28,6 @@ import io.element.android.libraries.matrix.api.encryption.identity.IdentityState
|
|||||||
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
|
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class MessagesState(
|
data class MessagesState(
|
||||||
val roomId: RoomId,
|
val roomId: RoomId,
|
||||||
val roomName: String?,
|
val roomName: String?,
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import io.element.android.features.messages.impl.crypto.sendfailure.VerifiedUser
|
|||||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class ActionListState(
|
data class ActionListState(
|
||||||
val target: Target,
|
val target: Target,
|
||||||
val eventSink: (ActionListEvents) -> Unit,
|
val eventSink: (ActionListEvents) -> Unit,
|
||||||
|
|||||||
@@ -9,11 +9,9 @@ package io.element.android.features.messages.impl.actionlist.model
|
|||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.libraries.designsystem.icons.CompoundDrawables
|
import io.element.android.libraries.designsystem.icons.CompoundDrawables
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
@Immutable
|
|
||||||
enum class TimelineItemAction(
|
enum class TimelineItemAction(
|
||||||
@StringRes val titleRes: Int,
|
@StringRes val titleRes: Int,
|
||||||
@DrawableRes val icon: Int,
|
@DrawableRes val icon: Int,
|
||||||
|
|||||||
@@ -7,9 +7,6 @@
|
|||||||
|
|
||||||
package io.element.android.features.messages.impl.attachments.preview
|
package io.element.android.features.messages.impl.attachments.preview
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
|
|
||||||
@Immutable
|
|
||||||
sealed interface AttachmentsPreviewEvents {
|
sealed interface AttachmentsPreviewEvents {
|
||||||
data object SendAttachment : AttachmentsPreviewEvents
|
data object SendAttachment : AttachmentsPreviewEvents
|
||||||
data object CancelAndDismiss : AttachmentsPreviewEvents
|
data object CancelAndDismiss : AttachmentsPreviewEvents
|
||||||
|
|||||||
@@ -8,12 +8,10 @@
|
|||||||
package io.element.android.features.messages.impl.messagecomposer
|
package io.element.android.features.messages.impl.messagecomposer
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion
|
import io.element.android.libraries.textcomposer.mentions.ResolvedSuggestion
|
||||||
import io.element.android.libraries.textcomposer.model.MessageComposerMode
|
import io.element.android.libraries.textcomposer.model.MessageComposerMode
|
||||||
import io.element.android.libraries.textcomposer.model.Suggestion
|
import io.element.android.libraries.textcomposer.model.Suggestion
|
||||||
|
|
||||||
@Immutable
|
|
||||||
sealed interface MessageComposerEvents {
|
sealed interface MessageComposerEvents {
|
||||||
data object ToggleFullScreenState : MessageComposerEvents
|
data object ToggleFullScreenState : MessageComposerEvents
|
||||||
data object SendMessage : MessageComposerEvents
|
data object SendMessage : MessageComposerEvents
|
||||||
@@ -30,6 +28,7 @@ sealed interface MessageComposerEvents {
|
|||||||
data object Location : PickAttachmentSource
|
data object Location : PickAttachmentSource
|
||||||
data object Poll : PickAttachmentSource
|
data object Poll : PickAttachmentSource
|
||||||
}
|
}
|
||||||
|
|
||||||
data class ToggleTextFormatting(val enabled: Boolean) : MessageComposerEvents
|
data class ToggleTextFormatting(val enabled: Boolean) : MessageComposerEvents
|
||||||
data class Error(val error: Throwable) : MessageComposerEvents
|
data class Error(val error: Throwable) : MessageComposerEvents
|
||||||
data class TypingNotice(val isTyping: Boolean) : MessageComposerEvents
|
data class TypingNotice(val isTyping: Boolean) : MessageComposerEvents
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ class PinnedMessagesListPresenter(
|
|||||||
// We do not care about the call state here.
|
// We do not care about the call state here.
|
||||||
roomCallState = aStandByCallState(),
|
roomCallState = aStandByCallState(),
|
||||||
// don't compute this value or the pin icon will be shown
|
// don't compute this value or the pin icon will be shown
|
||||||
pinnedEventIds = emptyList(),
|
pinnedEventIds = persistentListOf(),
|
||||||
typingNotificationState = TypingNotificationState(
|
typingNotificationState = TypingNotificationState(
|
||||||
renderTypingNotifications = false,
|
renderTypingNotifications = false,
|
||||||
typingMembers = persistentListOf(),
|
typingMembers = persistentListOf(),
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.MessageShield
|
|||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class TimelineState(
|
data class TimelineState(
|
||||||
val timelineItems: ImmutableList<TimelineItem>,
|
val timelineItems: ImmutableList<TimelineItem>,
|
||||||
val timelineRoomInfo: TimelineRoomInfo,
|
val timelineRoomInfo: TimelineRoomInfo,
|
||||||
@@ -72,14 +71,13 @@ sealed interface FocusRequestState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class TimelineRoomInfo(
|
data class TimelineRoomInfo(
|
||||||
val isDm: Boolean,
|
val isDm: Boolean,
|
||||||
val name: String?,
|
val name: String?,
|
||||||
val userHasPermissionToSendMessage: Boolean,
|
val userHasPermissionToSendMessage: Boolean,
|
||||||
val userHasPermissionToSendReaction: Boolean,
|
val userHasPermissionToSendReaction: Boolean,
|
||||||
val roomCallState: RoomCallState,
|
val roomCallState: RoomCallState,
|
||||||
val pinnedEventIds: List<EventId>,
|
val pinnedEventIds: ImmutableList<EventId>,
|
||||||
val typingNotificationState: TypingNotificationState,
|
val typingNotificationState: TypingNotificationState,
|
||||||
val predecessorRoom: PredecessorRoom?,
|
val predecessorRoom: PredecessorRoom?,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ internal fun aTimelineRoomInfo(
|
|||||||
userHasPermissionToSendMessage = userHasPermissionToSendMessage,
|
userHasPermissionToSendMessage = userHasPermissionToSendMessage,
|
||||||
userHasPermissionToSendReaction = true,
|
userHasPermissionToSendReaction = true,
|
||||||
roomCallState = aStandByCallState(),
|
roomCallState = aStandByCallState(),
|
||||||
pinnedEventIds = pinnedEventIds,
|
pinnedEventIds = pinnedEventIds.toImmutableList(),
|
||||||
typingNotificationState = typingNotificationState,
|
typingNotificationState = typingNotificationState,
|
||||||
predecessorRoom = predecessorRoom,
|
predecessorRoom = predecessorRoom,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,11 +8,14 @@
|
|||||||
package io.element.android.features.messages.impl.timeline.components.customreaction.picker
|
package io.element.android.features.messages.impl.timeline.components.customreaction.picker
|
||||||
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import io.element.android.emojibasebindings.Emoji
|
import io.element.android.emojibasebindings.Emoji
|
||||||
import io.element.android.libraries.designsystem.theme.components.IconSource
|
import io.element.android.libraries.designsystem.theme.components.IconSource
|
||||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
|
// Emoji is unstable (because from an external library?), so we annotate with @Immutable
|
||||||
|
@Immutable
|
||||||
data class EmojiPickerState(
|
data class EmojiPickerState(
|
||||||
val categories: ImmutableList<EmojiCategory>,
|
val categories: ImmutableList<EmojiCategory>,
|
||||||
val allEmojis: ImmutableList<Emoji>,
|
val allEmojis: ImmutableList<Emoji>,
|
||||||
|
|||||||
@@ -7,10 +7,8 @@
|
|||||||
|
|
||||||
package io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet
|
package io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
import io.element.android.features.messages.impl.timeline.model.TimelineItem
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class ReadReceiptBottomSheetState(
|
data class ReadReceiptBottomSheetState(
|
||||||
val selectedEvent: TimelineItem.Event?,
|
val selectedEvent: TimelineItem.Event?,
|
||||||
val eventSink: (ReadReceiptBottomSheetEvents) -> Unit,
|
val eventSink: (ReadReceiptBottomSheetEvents) -> Unit,
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import io.element.android.features.messages.impl.timeline.model.TimelineItemReac
|
|||||||
import io.element.android.features.messages.impl.timeline.model.TimelineItemReadReceipts
|
import io.element.android.features.messages.impl.timeline.model.TimelineItemReadReceipts
|
||||||
import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo
|
import io.element.android.features.messages.impl.timeline.model.TimelineItemThreadInfo
|
||||||
import io.element.android.features.messages.impl.utils.messagesummary.MessageSummaryFormatter
|
import io.element.android.features.messages.impl.utils.messagesummary.MessageSummaryFormatter
|
||||||
import io.element.android.libraries.architecture.map
|
|
||||||
import io.element.android.libraries.core.bool.orTrue
|
import io.element.android.libraries.core.bool.orTrue
|
||||||
import io.element.android.libraries.dateformatter.api.DateFormatter
|
import io.element.android.libraries.dateformatter.api.DateFormatter
|
||||||
import io.element.android.libraries.dateformatter.api.DateFormatterMode
|
import io.element.android.libraries.dateformatter.api.DateFormatterMode
|
||||||
@@ -37,7 +36,6 @@ import io.element.android.libraries.matrix.api.timeline.item.event.getDisambigua
|
|||||||
import io.element.android.libraries.matrix.ui.messages.reply.map
|
import io.element.android.libraries.matrix.ui.messages.reply.map
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
@AssistedInject
|
@AssistedInject
|
||||||
class TimelineItemEventFactory(
|
class TimelineItemEventFactory(
|
||||||
@@ -146,10 +144,9 @@ class TimelineItemEventFactory(
|
|||||||
senders = reaction.senders
|
senders = reaction.senders
|
||||||
.sortedByDescending { it.timestamp }
|
.sortedByDescending { it.timestamp }
|
||||||
.map {
|
.map {
|
||||||
val date = Date(it.timestamp)
|
|
||||||
AggregatedReactionSender(
|
AggregatedReactionSender(
|
||||||
senderId = it.senderId,
|
senderId = it.senderId,
|
||||||
timestamp = date,
|
timestamp = it.timestamp,
|
||||||
sentTime = dateFormatter.format(
|
sentTime = dateFormatter.format(
|
||||||
it.timestamp,
|
it.timestamp,
|
||||||
DateFormatterMode.TimeOrDate,
|
DateFormatterMode.TimeOrDate,
|
||||||
|
|||||||
@@ -33,13 +33,14 @@ fun anAggregatedReaction(
|
|||||||
val timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, java.util.Locale.US).apply {
|
val timeFormatter = DateFormat.getTimeInstance(DateFormat.SHORT, java.util.Locale.US).apply {
|
||||||
timeZone = TimeZone.getTimeZone("UTC")
|
timeZone = TimeZone.getTimeZone("UTC")
|
||||||
}
|
}
|
||||||
val date = Date(1_689_061_264L)
|
val timestamp = 1_689_061_264L
|
||||||
|
val date = Date(timestamp)
|
||||||
val senders = buildList {
|
val senders = buildList {
|
||||||
repeat(count) { index ->
|
repeat(count) { index ->
|
||||||
add(
|
add(
|
||||||
AggregatedReactionSender(
|
AggregatedReactionSender(
|
||||||
senderId = if (isHighlighted && index == 0) userId else UserId("@user$index:server.org"),
|
senderId = if (isHighlighted && index == 0) userId else UserId("@user$index:server.org"),
|
||||||
timestamp = date,
|
timestamp = timestamp,
|
||||||
sentTime = timeFormatter.format(date),
|
sentTime = timeFormatter.format(date),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,15 +7,12 @@
|
|||||||
|
|
||||||
package io.element.android.features.messages.impl.timeline.model
|
package io.element.android.features.messages.impl.timeline.model
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class AggregatedReactionSender(
|
data class AggregatedReactionSender(
|
||||||
val senderId: UserId,
|
val senderId: UserId,
|
||||||
val timestamp: Date,
|
val timestamp: Long,
|
||||||
val sentTime: String,
|
val sentTime: String,
|
||||||
val user: MatrixUser? = null
|
val user: MatrixUser? = null
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -57,13 +57,11 @@ sealed interface TimelineItem {
|
|||||||
is GroupedEvents -> "groupedEvent"
|
is GroupedEvents -> "groupedEvent"
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class Virtual(
|
data class Virtual(
|
||||||
val id: UniqueId,
|
val id: UniqueId,
|
||||||
val model: TimelineItemVirtualModel
|
val model: TimelineItemVirtualModel
|
||||||
) : TimelineItem
|
) : TimelineItem
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class Event(
|
data class Event(
|
||||||
val id: UniqueId,
|
val id: UniqueId,
|
||||||
// Note: eventId can be null when the event is a local echo
|
// Note: eventId can be null when the event is a local echo
|
||||||
@@ -124,7 +122,6 @@ sealed interface TimelineItem {
|
|||||||
val sendhandle: SendHandle? get() = sendHandleProvider()
|
val sendhandle: SendHandle? get() = sendHandleProvider()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class GroupedEvents(
|
data class GroupedEvents(
|
||||||
val id: UniqueId,
|
val id: UniqueId,
|
||||||
val events: ImmutableList<Event>,
|
val events: ImmutableList<Event>,
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
package io.element.android.features.preferences.impl.about
|
package io.element.android.features.preferences.impl.about
|
||||||
|
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
data class AboutState(
|
data class AboutState(
|
||||||
val elementLegals: List<ElementLegal>,
|
val elementLegals: ImmutableList<ElementLegal>,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
package io.element.android.features.preferences.impl.about
|
package io.element.android.features.preferences.impl.about
|
||||||
|
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
open class AboutStateProvider : PreviewParameterProvider<AboutState> {
|
open class AboutStateProvider : PreviewParameterProvider<AboutState> {
|
||||||
override val values: Sequence<AboutState>
|
override val values: Sequence<AboutState>
|
||||||
@@ -19,5 +20,5 @@ open class AboutStateProvider : PreviewParameterProvider<AboutState> {
|
|||||||
fun anAboutState(
|
fun anAboutState(
|
||||||
elementLegals: List<ElementLegal> = getAllLegals(),
|
elementLegals: List<ElementLegal> = getAllLegals(),
|
||||||
) = AboutState(
|
) = AboutState(
|
||||||
elementLegals = elementLegals,
|
elementLegals = elementLegals.toImmutableList(),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ package io.element.android.features.preferences.impl.about
|
|||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import io.element.android.features.preferences.impl.BuildConfig
|
import io.element.android.features.preferences.impl.BuildConfig
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
private const val COPYRIGHT_URL = BuildConfig.URL_COPYRIGHT
|
private const val COPYRIGHT_URL = BuildConfig.URL_COPYRIGHT
|
||||||
private const val USE_POLICY_URL = BuildConfig.URL_ACCEPTABLE_USE
|
private const val USE_POLICY_URL = BuildConfig.URL_ACCEPTABLE_USE
|
||||||
@@ -24,8 +26,8 @@ sealed class ElementLegal(
|
|||||||
data object PrivacyPolicy : ElementLegal(CommonStrings.common_privacy_policy, PRIVACY_URL)
|
data object PrivacyPolicy : ElementLegal(CommonStrings.common_privacy_policy, PRIVACY_URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getAllLegals(): List<ElementLegal> {
|
fun getAllLegals(): ImmutableList<ElementLegal> {
|
||||||
return listOf(
|
return persistentListOf(
|
||||||
ElementLegal.Copyright,
|
ElementLegal.Copyright,
|
||||||
ElementLegal.AcceptableUsePolicy,
|
ElementLegal.AcceptableUsePolicy,
|
||||||
ElementLegal.PrivacyPolicy,
|
ElementLegal.PrivacyPolicy,
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
package io.element.android.features.preferences.impl.notifications
|
package io.element.android.features.preferences.impl.notifications
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
import io.element.android.libraries.fullscreenintent.api.FullScreenIntentPermissionsState
|
||||||
@@ -15,7 +14,6 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
|||||||
import io.element.android.libraries.pushproviders.api.Distributor
|
import io.element.android.libraries.pushproviders.api.Distributor
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class NotificationSettingsState(
|
data class NotificationSettingsState(
|
||||||
val matrixSettings: MatrixSettings,
|
val matrixSettings: MatrixSettings,
|
||||||
val appSettings: AppSettings,
|
val appSettings: AppSettings,
|
||||||
|
|||||||
@@ -8,12 +8,15 @@
|
|||||||
package io.element.android.features.preferences.impl.user.editprofile
|
package io.element.android.features.preferences.impl.user.editprofile
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
||||||
import io.element.android.libraries.permissions.api.PermissionsState
|
import io.element.android.libraries.permissions.api.PermissionsState
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
|
// Annotate with @Immutable since `Uri` is unstable
|
||||||
|
@Immutable
|
||||||
data class EditUserProfileState(
|
data class EditUserProfileState(
|
||||||
val userId: UserId,
|
val userId: UserId,
|
||||||
val displayName: String,
|
val displayName: String,
|
||||||
|
|||||||
@@ -7,9 +7,6 @@
|
|||||||
|
|
||||||
package io.element.android.features.rageshake.api.crash
|
package io.element.android.features.rageshake.api.crash
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class CrashDetectionState(
|
data class CrashDetectionState(
|
||||||
val appName: String,
|
val appName: String,
|
||||||
val crashDetected: Boolean,
|
val crashDetected: Boolean,
|
||||||
|
|||||||
@@ -7,10 +7,8 @@
|
|||||||
|
|
||||||
package io.element.android.features.rageshake.api.detection
|
package io.element.android.features.rageshake.api.detection
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState
|
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class RageshakeDetectionState(
|
data class RageshakeDetectionState(
|
||||||
val takeScreenshot: Boolean,
|
val takeScreenshot: Boolean,
|
||||||
val showDialog: Boolean,
|
val showDialog: Boolean,
|
||||||
|
|||||||
@@ -7,12 +7,10 @@
|
|||||||
|
|
||||||
package io.element.android.features.roomaliasresolver.impl
|
package io.element.android.features.roomaliasresolver.impl
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
import io.element.android.libraries.matrix.api.core.RoomAlias
|
import io.element.android.libraries.matrix.api.core.RoomAlias
|
||||||
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class RoomAliasResolverState(
|
data class RoomAliasResolverState(
|
||||||
val roomAlias: RoomAlias,
|
val roomAlias: RoomAlias,
|
||||||
val resolveState: AsyncData<ResolvedRoomAlias>,
|
val resolveState: AsyncData<ResolvedRoomAlias>,
|
||||||
|
|||||||
@@ -8,12 +8,15 @@
|
|||||||
package io.element.android.features.roomdetails.impl.edit
|
package io.element.android.features.roomdetails.impl.edit
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
import io.element.android.libraries.matrix.ui.media.AvatarAction
|
||||||
import io.element.android.libraries.permissions.api.PermissionsState
|
import io.element.android.libraries.permissions.api.PermissionsState
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
|
// Annotate with @Immutable since `Uri` is unstable
|
||||||
|
@Immutable
|
||||||
data class RoomDetailsEditState(
|
data class RoomDetailsEditState(
|
||||||
val roomId: RoomId,
|
val roomId: RoomId,
|
||||||
/** The raw room name (i.e. the room name from the state event `m.room.name`), not the display name. */
|
/** The raw room name (i.e. the room name from the state event `m.room.name`), not the display name. */
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-library")
|
id("io.element.android-compose-library")
|
||||||
id("kotlin-parcelize")
|
id("kotlin-parcelize")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
package io.element.android.features.roomdirectory.api
|
package io.element.android.features.roomdirectory.api
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||||
import io.element.android.libraries.matrix.api.core.RoomAlias
|
import io.element.android.libraries.matrix.api.core.RoomAlias
|
||||||
@@ -17,7 +16,6 @@ import kotlinx.parcelize.IgnoredOnParcel
|
|||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@Immutable
|
|
||||||
data class RoomDescription(
|
data class RoomDescription(
|
||||||
val roomId: RoomId,
|
val roomId: RoomId,
|
||||||
val name: String?,
|
val name: String?,
|
||||||
|
|||||||
@@ -42,14 +42,14 @@ class RoomDirectoryPresenterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - room directory list emits empty state`() = runTest {
|
fun `present - room directory list emits empty state`() = runTest {
|
||||||
val directoryListStateFlow = MutableSharedFlow<RoomDirectoryList.State>(replay = 1)
|
val directoryListStateFlow = MutableSharedFlow<RoomDirectoryList.SearchResult>(replay = 1)
|
||||||
val roomDirectoryList = FakeRoomDirectoryList(directoryListStateFlow)
|
val roomDirectoryList = FakeRoomDirectoryList(directoryListStateFlow)
|
||||||
val roomDirectoryService = FakeRoomDirectoryService { roomDirectoryList }
|
val roomDirectoryService = FakeRoomDirectoryService { roomDirectoryList }
|
||||||
val presenter = createRoomDirectoryPresenter(roomDirectoryService = roomDirectoryService)
|
val presenter = createRoomDirectoryPresenter(roomDirectoryService = roomDirectoryService)
|
||||||
presenter.test {
|
presenter.test {
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
directoryListStateFlow.emit(
|
directoryListStateFlow.emit(
|
||||||
RoomDirectoryList.State(false, emptyList())
|
RoomDirectoryList.SearchResult(false, emptyList())
|
||||||
)
|
)
|
||||||
awaitItem().also { state ->
|
awaitItem().also { state ->
|
||||||
assertThat(state.displayEmptyState).isTrue()
|
assertThat(state.displayEmptyState).isTrue()
|
||||||
@@ -60,14 +60,14 @@ class RoomDirectoryPresenterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - room directory list emits non-empty state`() = runTest {
|
fun `present - room directory list emits non-empty state`() = runTest {
|
||||||
val directoryListStateFlow = MutableSharedFlow<RoomDirectoryList.State>(replay = 1)
|
val directoryListStateFlow = MutableSharedFlow<RoomDirectoryList.SearchResult>(replay = 1)
|
||||||
val roomDirectoryList = FakeRoomDirectoryList(directoryListStateFlow)
|
val roomDirectoryList = FakeRoomDirectoryList(directoryListStateFlow)
|
||||||
val roomDirectoryService = FakeRoomDirectoryService { roomDirectoryList }
|
val roomDirectoryService = FakeRoomDirectoryService { roomDirectoryList }
|
||||||
val presenter = createRoomDirectoryPresenter(roomDirectoryService = roomDirectoryService)
|
val presenter = createRoomDirectoryPresenter(roomDirectoryService = roomDirectoryService)
|
||||||
presenter.test {
|
presenter.test {
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
directoryListStateFlow.emit(
|
directoryListStateFlow.emit(
|
||||||
RoomDirectoryList.State(
|
RoomDirectoryList.SearchResult(
|
||||||
hasMoreToLoad = true,
|
hasMoreToLoad = true,
|
||||||
items = listOf(aRoomDescription())
|
items = listOf(aRoomDescription())
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
package io.element.android.features.roommembermoderation.api
|
package io.element.android.features.roommembermoderation.api
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
@Immutable
|
||||||
interface RoomMemberModerationState {
|
interface RoomMemberModerationState {
|
||||||
val canKick: Boolean
|
val canKick: Boolean
|
||||||
val canBan: Boolean
|
val canBan: Boolean
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ package io.element.android.features.space.impl.leave
|
|||||||
import io.element.android.libraries.architecture.AsyncAction
|
import io.element.android.libraries.architecture.AsyncAction
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
data class LeaveSpaceState(
|
data class LeaveSpaceState(
|
||||||
val spaceName: String?,
|
val spaceName: String?,
|
||||||
@@ -18,10 +19,15 @@ data class LeaveSpaceState(
|
|||||||
val leaveSpaceAction: AsyncAction<Unit>,
|
val leaveSpaceAction: AsyncAction<Unit>,
|
||||||
val eventSink: (LeaveSpaceEvents) -> Unit,
|
val eventSink: (LeaveSpaceEvents) -> Unit,
|
||||||
) {
|
) {
|
||||||
private val rooms = selectableSpaceRooms.dataOrNull().orEmpty()
|
private val rooms = selectableSpaceRooms.dataOrNull().orEmpty().toImmutableList()
|
||||||
private val partition = rooms.partition { it.isLastAdmin }
|
private val lastAdminRooms: ImmutableList<SelectableSpaceRoom>
|
||||||
private val lastAdminRooms = partition.first
|
private val selectableRooms: ImmutableList<SelectableSpaceRoom>
|
||||||
private val selectableRooms = partition.second
|
|
||||||
|
init {
|
||||||
|
val partition = rooms.partition { it.isLastAdmin }
|
||||||
|
lastAdminRooms = partition.first.toImmutableList()
|
||||||
|
selectableRooms = partition.second.toImmutableList()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if we should show the quick action to select/deselect all rooms.
|
* True if we should show the quick action to select/deselect all rooms.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-library")
|
id("io.element.android-compose-library")
|
||||||
id("kotlin-parcelize")
|
id("kotlin-parcelize")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,13 +7,11 @@
|
|||||||
|
|
||||||
package io.element.android.features.verifysession.impl.incoming
|
package io.element.android.features.verifysession.impl.incoming
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import io.element.android.libraries.matrix.api.core.DeviceId
|
import io.element.android.libraries.matrix.api.core.DeviceId
|
||||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationData
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationData
|
||||||
import io.element.android.libraries.matrix.api.verification.VerificationRequest
|
import io.element.android.libraries.matrix.api.verification.VerificationRequest
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class IncomingVerificationState(
|
data class IncomingVerificationState(
|
||||||
val step: Step,
|
val step: Step,
|
||||||
val request: VerificationRequest.Incoming,
|
val request: VerificationRequest.Incoming,
|
||||||
|
|||||||
@@ -7,13 +7,11 @@
|
|||||||
|
|
||||||
package io.element.android.features.verifysession.impl.outgoing
|
package io.element.android.features.verifysession.impl.outgoing
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import io.element.android.libraries.architecture.AsyncData
|
import io.element.android.libraries.architecture.AsyncData
|
||||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationData
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationData
|
||||||
import io.element.android.libraries.matrix.api.verification.VerificationRequest
|
import io.element.android.libraries.matrix.api.verification.VerificationRequest
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class OutgoingVerificationState(
|
data class OutgoingVerificationState(
|
||||||
val step: Step,
|
val step: Step,
|
||||||
val request: VerificationRequest.Outgoing,
|
val request: VerificationRequest.Outgoing,
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import androidx.compose.ui.graphics.Color
|
|||||||
/**
|
/**
|
||||||
* This class holds all the semantic tokens of the Compound theme.
|
* This class holds all the semantic tokens of the Compound theme.
|
||||||
*/
|
*/
|
||||||
@Immutable
|
|
||||||
data class SemanticColors(
|
data class SemanticColors(
|
||||||
/** Background colour for accent or brand actions. State: Hover */
|
/** Background colour for accent or brand actions. State: Hover */
|
||||||
val bgAccentHovered: Color,
|
val bgAccentHovered: Color,
|
||||||
|
|||||||
@@ -7,11 +7,9 @@
|
|||||||
|
|
||||||
package io.element.android.libraries.designsystem.components.avatar
|
package io.element.android.libraries.designsystem.components.avatar
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.libraries.core.data.tryOrNull
|
import io.element.android.libraries.core.data.tryOrNull
|
||||||
import java.text.BreakIterator
|
import java.text.BreakIterator
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class AvatarData(
|
data class AvatarData(
|
||||||
val id: String,
|
val id: String,
|
||||||
val name: String?,
|
val name: String?,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-library")
|
id("io.element.android-compose-library")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|||||||
@@ -156,8 +156,8 @@ public class CameraPositionState(
|
|||||||
/**
|
/**
|
||||||
* The default saver implementation for [CameraPositionState].
|
* The default saver implementation for [CameraPositionState].
|
||||||
*/
|
*/
|
||||||
public val Saver: Saver<CameraPositionState, SaveableCameraPositionState> = Saver(
|
public val Saver: Saver<CameraPositionState, SaveableCameraPositionData> = Saver(
|
||||||
save = { SaveableCameraPositionState(it.position, it.cameraMode.toInternal()) },
|
save = { SaveableCameraPositionData(it.position, it.cameraMode.toInternal()) },
|
||||||
restore = { CameraPositionState(it.position, CameraMode.fromInternal(it.cameraMode)) }
|
restore = { CameraPositionState(it.position, CameraMode.fromInternal(it.cameraMode)) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ public val currentCameraPositionState: CameraPositionState
|
|||||||
get() = LocalCameraPositionState.current
|
get() = LocalCameraPositionState.current
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
public data class SaveableCameraPositionState(
|
public data class SaveableCameraPositionData(
|
||||||
val position: CameraPosition,
|
val position: CameraPosition,
|
||||||
val cameraMode: Int
|
val cameraMode: Int
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
package io.element.android.libraries.matrix.api.room
|
package io.element.android.libraries.matrix.api.room
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
import io.element.android.libraries.matrix.api.core.RoomAlias
|
import io.element.android.libraries.matrix.api.core.RoomAlias
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
@@ -19,7 +18,6 @@ import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
|
|||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class RoomInfo(
|
data class RoomInfo(
|
||||||
val id: RoomId,
|
val id: RoomId,
|
||||||
/** The room's name from the room state event if received from sync, or one that's been computed otherwise. */
|
/** The room's name from the room state event if received from sync, or one that's been computed otherwise. */
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
package io.element.android.libraries.matrix.api.room
|
package io.element.android.libraries.matrix.api.room
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
|
||||||
@@ -24,6 +25,7 @@ data class RoomMember(
|
|||||||
/**
|
/**
|
||||||
* Role of the RoomMember, based on its [powerLevel].
|
* Role of the RoomMember, based on its [powerLevel].
|
||||||
*/
|
*/
|
||||||
|
@Immutable
|
||||||
sealed interface Role {
|
sealed interface Role {
|
||||||
data class Owner(val isCreator: Boolean) : Role
|
data class Owner(val isCreator: Boolean) : Role
|
||||||
data object Admin : Role
|
data object Admin : Role
|
||||||
|
|||||||
@@ -26,9 +26,9 @@ interface RoomDirectoryList {
|
|||||||
/**
|
/**
|
||||||
* The current search results as a state flow.
|
* The current search results as a state flow.
|
||||||
*/
|
*/
|
||||||
val state: Flow<State>
|
val state: Flow<SearchResult>
|
||||||
|
|
||||||
data class State(
|
data class SearchResult(
|
||||||
val hasMoreToLoad: Boolean,
|
val hasMoreToLoad: Boolean,
|
||||||
val items: List<RoomDescription>,
|
val items: List<RoomDescription>,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
package io.element.android.libraries.matrix.api.timeline
|
package io.element.android.libraries.matrix.api.timeline
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||||
@@ -42,6 +43,7 @@ interface Timeline : AutoCloseable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
|
@Immutable
|
||||||
sealed interface Mode : Parcelable {
|
sealed interface Mode : Parcelable {
|
||||||
data object Live : Mode
|
data object Live : Mode
|
||||||
data class FocusedOnEvent(val eventId: EventId) : Mode
|
data class FocusedOnEvent(val eventId: EventId) : Mode
|
||||||
|
|||||||
@@ -7,10 +7,8 @@
|
|||||||
|
|
||||||
package io.element.android.libraries.matrix.api.timeline.item.event
|
package io.element.android.libraries.matrix.api.timeline.item.event
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class EventReaction(
|
data class EventReaction(
|
||||||
val key: String,
|
val key: String,
|
||||||
val senders: ImmutableList<ReactionSender>
|
val senders: ImmutableList<ReactionSender>
|
||||||
|
|||||||
@@ -8,10 +8,13 @@
|
|||||||
package io.element.android.libraries.matrix.api.verification
|
package io.element.android.libraries.matrix.api.verification
|
||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
||||||
|
@Immutable
|
||||||
sealed interface VerificationRequest : Parcelable {
|
sealed interface VerificationRequest : Parcelable {
|
||||||
|
@Immutable
|
||||||
sealed interface Outgoing : VerificationRequest {
|
sealed interface Outgoing : VerificationRequest {
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object CurrentSession : Outgoing
|
data object CurrentSession : Outgoing
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
package io.element.android.libraries.matrix.impl.room
|
package io.element.android.libraries.matrix.impl.room
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
import io.element.android.libraries.core.extensions.runCatchingExceptions
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
import io.element.android.libraries.matrix.api.room.NotJoinedRoom
|
import io.element.android.libraries.matrix.api.room.NotJoinedRoom
|
||||||
@@ -15,7 +14,6 @@ import io.element.android.libraries.matrix.api.room.RoomMembershipDetails
|
|||||||
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
|
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
|
||||||
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
|
import io.element.android.libraries.matrix.impl.room.member.RoomMemberMapper
|
||||||
|
|
||||||
@Immutable
|
|
||||||
class NotJoinedRustRoom(
|
class NotJoinedRustRoom(
|
||||||
private val sessionId: SessionId,
|
private val sessionId: SessionId,
|
||||||
override val localRoom: RustBaseRoom?,
|
override val localRoom: RustBaseRoom?,
|
||||||
|
|||||||
@@ -73,9 +73,9 @@ class RustRoomDirectoryList(
|
|||||||
return !inner.isAtLastPage()
|
return !inner.isAtLastPage()
|
||||||
}
|
}
|
||||||
|
|
||||||
override val state: Flow<RoomDirectoryList.State> =
|
override val state: Flow<RoomDirectoryList.SearchResult> =
|
||||||
combine(hasMoreToLoad, processor.roomDescriptionsFlow) { hasMoreToLoad, items ->
|
combine(hasMoreToLoad, processor.roomDescriptionsFlow) { hasMoreToLoad, items ->
|
||||||
RoomDirectoryList.State(
|
RoomDirectoryList.SearchResult(
|
||||||
hasMoreToLoad = hasMoreToLoad,
|
hasMoreToLoad = hasMoreToLoad,
|
||||||
items = items
|
items = items
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class RustBaseRoomDirectoryListTest {
|
|||||||
)
|
)
|
||||||
val initialItem = awaitItem()
|
val initialItem = awaitItem()
|
||||||
assertThat(initialItem).isEqualTo(
|
assertThat(initialItem).isEqualTo(
|
||||||
RoomDirectoryList.State(
|
RoomDirectoryList.SearchResult(
|
||||||
hasMoreToLoad = true,
|
hasMoreToLoad = true,
|
||||||
items = listOf(mapper.map(aRustRoomDescription()))
|
items = listOf(mapper.map(aRustRoomDescription()))
|
||||||
)
|
)
|
||||||
@@ -57,7 +57,7 @@ class RustBaseRoomDirectoryListTest {
|
|||||||
)
|
)
|
||||||
val nextItem = awaitItem()
|
val nextItem = awaitItem()
|
||||||
assertThat(nextItem).isEqualTo(
|
assertThat(nextItem).isEqualTo(
|
||||||
RoomDirectoryList.State(
|
RoomDirectoryList.SearchResult(
|
||||||
hasMoreToLoad = false,
|
hasMoreToLoad = false,
|
||||||
items = listOf(
|
items = listOf(
|
||||||
mapper.map(aRustRoomDescription()),
|
mapper.map(aRustRoomDescription()),
|
||||||
@@ -66,7 +66,7 @@ class RustBaseRoomDirectoryListTest {
|
|||||||
)
|
)
|
||||||
val finalItem = awaitItem()
|
val finalItem = awaitItem()
|
||||||
assertThat(finalItem).isEqualTo(
|
assertThat(finalItem).isEqualTo(
|
||||||
RoomDirectoryList.State(
|
RoomDirectoryList.SearchResult(
|
||||||
hasMoreToLoad = false,
|
hasMoreToLoad = false,
|
||||||
items = listOf(
|
items = listOf(
|
||||||
mapper.map(aRustRoomDescription()),
|
mapper.map(aRustRoomDescription()),
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
package io.element.android.libraries.matrix.test.room
|
package io.element.android.libraries.matrix.test.room
|
||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import io.element.android.libraries.matrix.api.room.BaseRoom
|
import io.element.android.libraries.matrix.api.room.BaseRoom
|
||||||
import io.element.android.libraries.matrix.api.room.NotJoinedRoom
|
import io.element.android.libraries.matrix.api.room.NotJoinedRoom
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipDetails
|
import io.element.android.libraries.matrix.api.room.RoomMembershipDetails
|
||||||
@@ -15,7 +14,6 @@ import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
|
|||||||
import io.element.android.tests.testutils.lambda.lambdaError
|
import io.element.android.tests.testutils.lambda.lambdaError
|
||||||
import io.element.android.tests.testutils.simulateLongTask
|
import io.element.android.tests.testutils.simulateLongTask
|
||||||
|
|
||||||
@Immutable
|
|
||||||
class FakeNotJoinedRoom(
|
class FakeNotJoinedRoom(
|
||||||
override val localRoom: BaseRoom? = null,
|
override val localRoom: BaseRoom? = null,
|
||||||
override val previewInfo: RoomPreviewInfo = aRoomPreviewInfo(),
|
override val previewInfo: RoomPreviewInfo = aRoomPreviewInfo(),
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import kotlinx.coroutines.flow.Flow
|
|||||||
import kotlinx.coroutines.flow.emptyFlow
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
|
|
||||||
class FakeRoomDirectoryList(
|
class FakeRoomDirectoryList(
|
||||||
override val state: Flow<RoomDirectoryList.State> = emptyFlow(),
|
override val state: Flow<RoomDirectoryList.SearchResult> = emptyFlow(),
|
||||||
val filterLambda: (String?, Int, String?) -> Result<Unit> = { _, _, _ -> Result.success(Unit) },
|
val filterLambda: (String?, Int, String?) -> Result<Unit> = { _, _, _ -> Result.success(Unit) },
|
||||||
val loadMoreLambda: () -> Result<Unit> = { Result.success(Unit) }
|
val loadMoreLambda: () -> Result<Unit> = { Result.success(Unit) }
|
||||||
) : RoomDirectoryList {
|
) : RoomDirectoryList {
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
package io.element.android.libraries.matrix.ui.model
|
package io.element.android.libraries.matrix.ui.model
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Immutable
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
@@ -21,7 +20,6 @@ import io.element.android.libraries.matrix.api.core.UserId
|
|||||||
import io.element.android.libraries.matrix.api.room.RoomMember
|
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||||
import io.element.android.libraries.matrix.ui.R
|
import io.element.android.libraries.matrix.ui.R
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class InviteSender(
|
data class InviteSender(
|
||||||
val userId: UserId,
|
val userId: UserId,
|
||||||
val displayName: String,
|
val displayName: String,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-library")
|
id("io.element.android-compose-library")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-library")
|
id("io.element.android-compose-library")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-library")
|
id("io.element.android-compose-library")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
|
|
||||||
package io.element.android.libraries.sessionstorage.api
|
package io.element.android.libraries.sessionstorage.api
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
|
@Immutable
|
||||||
sealed interface LoggedInState {
|
sealed interface LoggedInState {
|
||||||
data object NotLoggedIn : LoggedInState
|
data object NotLoggedIn : LoggedInState
|
||||||
data class LoggedIn(
|
data class LoggedIn(
|
||||||
|
|||||||
@@ -128,15 +128,15 @@ class MarkdownTextEditorState(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class SavedState(
|
data class SavedValue(
|
||||||
val text: CharSequence,
|
val text: CharSequence,
|
||||||
val selectionStart: Int,
|
val selectionStart: Int,
|
||||||
val selectionEnd: Int,
|
val selectionEnd: Int,
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
}
|
}
|
||||||
|
|
||||||
object MarkdownTextEditorStateSaver : Saver<MarkdownTextEditorState, MarkdownTextEditorState.SavedState> {
|
object MarkdownTextEditorStateSaver : Saver<MarkdownTextEditorState, MarkdownTextEditorState.SavedValue> {
|
||||||
override fun restore(value: MarkdownTextEditorState.SavedState): MarkdownTextEditorState {
|
override fun restore(value: MarkdownTextEditorState.SavedValue): MarkdownTextEditorState {
|
||||||
return MarkdownTextEditorState(
|
return MarkdownTextEditorState(
|
||||||
initialText = "",
|
initialText = "",
|
||||||
initialFocus = false,
|
initialFocus = false,
|
||||||
@@ -146,8 +146,8 @@ object MarkdownTextEditorStateSaver : Saver<MarkdownTextEditorState, MarkdownTex
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun SaverScope.save(value: MarkdownTextEditorState): MarkdownTextEditorState.SavedState {
|
override fun SaverScope.save(value: MarkdownTextEditorState): MarkdownTextEditorState.SavedValue {
|
||||||
return MarkdownTextEditorState.SavedState(
|
return MarkdownTextEditorState.SavedValue(
|
||||||
text = value.text.value(),
|
text = value.text.value(),
|
||||||
selectionStart = value.selection.first,
|
selectionStart = value.selection.first,
|
||||||
selectionEnd = value.selection.last,
|
selectionEnd = value.selection.last,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* Please see LICENSE files in the repository root for full details.
|
* Please see LICENSE files in the repository root for full details.
|
||||||
*/
|
*/
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-library")
|
id("io.element.android-compose-library")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|||||||
@@ -7,11 +7,14 @@
|
|||||||
|
|
||||||
package io.element.android.libraries.troubleshoot.api.test
|
package io.element.android.libraries.troubleshoot.api.test
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
|
||||||
data class NotificationTroubleshootTestState(
|
data class NotificationTroubleshootTestState(
|
||||||
val name: String,
|
val name: String,
|
||||||
val description: String,
|
val description: String,
|
||||||
val status: Status,
|
val status: Status,
|
||||||
) {
|
) {
|
||||||
|
@Immutable
|
||||||
sealed interface Status {
|
sealed interface Status {
|
||||||
data class Idle(val visible: Boolean) : Status
|
data class Idle(val visible: Boolean) : Status
|
||||||
data object InProgress : Status
|
data object InProgress : Status
|
||||||
|
|||||||
@@ -158,7 +158,6 @@ fun Project.setupKover() {
|
|||||||
"io.element.android.libraries.designsystem.swipe.SwipeableActionsState",
|
"io.element.android.libraries.designsystem.swipe.SwipeableActionsState",
|
||||||
"io.element.android.libraries.designsystem.theme.components.bottomsheet.CustomSheetState",
|
"io.element.android.libraries.designsystem.theme.components.bottomsheet.CustomSheetState",
|
||||||
"io.element.android.libraries.maplibre.compose.CameraPositionState",
|
"io.element.android.libraries.maplibre.compose.CameraPositionState",
|
||||||
"io.element.android.libraries.maplibre.compose.SaveableCameraPositionState",
|
|
||||||
"io.element.android.libraries.maplibre.compose.SymbolState",
|
"io.element.android.libraries.maplibre.compose.SymbolState",
|
||||||
"io.element.android.libraries.matrix.api.room.RoomMembershipState",
|
"io.element.android.libraries.matrix.api.room.RoomMembershipState",
|
||||||
"io.element.android.libraries.matrix.api.room.RoomMembersState",
|
"io.element.android.libraries.matrix.api.room.RoomMembersState",
|
||||||
|
|||||||
@@ -7,8 +7,12 @@
|
|||||||
|
|
||||||
package io.element.android.tests.konsist
|
package io.element.android.tests.konsist
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
import com.lemonappdev.konsist.api.Konsist
|
import com.lemonappdev.konsist.api.Konsist
|
||||||
|
import com.lemonappdev.konsist.api.ext.list.withAnnotationOf
|
||||||
|
import com.lemonappdev.konsist.api.ext.list.withNameEndingWith
|
||||||
import com.lemonappdev.konsist.api.ext.list.withoutName
|
import com.lemonappdev.konsist.api.ext.list.withoutName
|
||||||
|
import com.lemonappdev.konsist.api.verify.assertEmpty
|
||||||
import com.lemonappdev.konsist.api.verify.assertFalse
|
import com.lemonappdev.konsist.api.verify.assertFalse
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
@@ -60,4 +64,14 @@ class KonsistImmutableTest {
|
|||||||
it.text.contains(".toPersistentMap()")
|
it.text.contains(".toPersistentMap()")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Immutable annotation is not used on sealed interface for Presenter Events`() {
|
||||||
|
Konsist
|
||||||
|
.scopeFromProduction()
|
||||||
|
.interfaces()
|
||||||
|
.withNameEndingWith("Events")
|
||||||
|
.withAnnotationOf(Immutable::class)
|
||||||
|
.assertEmpty()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
23
tools/compose/check_stability.sh
Executable file
23
tools/compose/check_stability.sh
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Build the project with compose report
|
||||||
|
echo "Building the project with compose report..."
|
||||||
|
./gradlew assembleGplayDebug -PcomposeCompilerReports=true -PcomposeCompilerMetrics=true --stacktrace
|
||||||
|
|
||||||
|
echo "Checking stability of State classes..."
|
||||||
|
# Using the find command, list all the files ending with -classes.txt
|
||||||
|
find . -type f -name "*-classes.txt" | while read -r file; do
|
||||||
|
# echo "Processing $file"
|
||||||
|
# Check that there is no line containing "unstable class .*State {"
|
||||||
|
if grep -E 'unstable class .*State \{' "$file"; then
|
||||||
|
echo "❌ ERROR: Found unstable State class in $file"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
Reference in New Issue
Block a user