diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt index 2f441bcfa2..bb8b656ee6 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenter.kt @@ -17,23 +17,38 @@ package io.element.android.features.preferences.impl.root import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesPresenter import io.element.android.features.logout.api.LogoutPreferencePresenter import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter -import io.element.android.libraries.architecture.Async import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.core.meta.BuildType +import io.element.android.libraries.matrix.api.user.CurrentUserProvider +import io.element.android.libraries.matrix.api.user.MatrixUser +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.launch import javax.inject.Inject class PreferencesRootPresenter @Inject constructor( private val logoutPresenter: LogoutPreferencePresenter, private val rageshakePresenter: RageshakePreferencesPresenter, private val analyticsPresenter: AnalyticsPreferencesPresenter, + private val currentUserProvider: CurrentUserProvider, private val buildType: BuildType, ) : Presenter { @Composable override fun present(): PreferencesRootState { + val matrixUser: MutableState = rememberSaveable { + mutableStateOf(null) + } + LaunchedEffect(Unit) { + initialLoad(matrixUser) + } + val logoutState = logoutPresenter.present() val rageshakeState = rageshakePresenter.present() val analyticsState = analyticsPresenter.present() @@ -42,8 +57,12 @@ class PreferencesRootPresenter @Inject constructor( logoutState = logoutState, rageshakeState = rageshakeState, analyticsState = analyticsState, - myUser = Async.Uninitialized, + myUser = matrixUser.value, showDeveloperSettings = showDeveloperSettings ) } + + private fun CoroutineScope.initialLoad(matrixUser: MutableState) = launch { + matrixUser.value = currentUserProvider.provide() + } } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt index 78435e7ad5..d427d01ab9 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootState.kt @@ -19,13 +19,12 @@ package io.element.android.features.preferences.impl.root import io.element.android.features.analytics.api.preferences.AnalyticsPreferencesState import io.element.android.features.logout.api.LogoutPreferenceState import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState -import io.element.android.libraries.architecture.Async import io.element.android.libraries.matrix.api.user.MatrixUser data class PreferencesRootState( val logoutState: LogoutPreferenceState, val rageshakeState: RageshakePreferencesState, val analyticsState: AnalyticsPreferencesState, - val myUser: Async, + val myUser: MatrixUser?, val showDeveloperSettings: Boolean ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt index 2c78c1f431..db8e7e1f8a 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootStateProvider.kt @@ -19,12 +19,11 @@ package io.element.android.features.preferences.impl.root import io.element.android.features.analytics.api.preferences.aAnalyticsPreferencesState import io.element.android.features.logout.api.aLogoutPreferenceState import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState -import io.element.android.libraries.architecture.Async fun aPreferencesRootState() = PreferencesRootState( logoutState = aLogoutPreferenceState(), rageshakeState = aRageshakePreferencesState(), analyticsState = aAnalyticsPreferencesState(), - myUser = Async.Uninitialized, + myUser = null, showDeveloperSettings = true ) diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt index 6d6545d838..8ea02883ac 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootView.kt @@ -92,5 +92,5 @@ fun PreferencesRootViewDarkPreview(@PreviewParameter(MatrixUserProvider::class) @Composable private fun ContentToPreview(matrixUser: MatrixUser) { - PreferencesRootView(aPreferencesRootState().copy(myUser = Async.Success(matrixUser))) + PreferencesRootView(aPreferencesRootState().copy(myUser = matrixUser)) } diff --git a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt index ed367007aa..3e00a588e0 100644 --- a/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt +++ b/features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/user/UserPreferences.kt @@ -16,14 +16,10 @@ package io.element.android.features.preferences.impl.user -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.unit.dp -import io.element.android.libraries.architecture.Async import io.element.android.libraries.designsystem.preview.ElementPreviewDark import io.element.android.libraries.designsystem.preview.ElementPreviewLight import io.element.android.libraries.matrix.api.user.MatrixUser @@ -32,16 +28,13 @@ import io.element.android.libraries.matrix.ui.components.MatrixUserWithNullProvi @Composable fun UserPreferences( - user: Async, + user: MatrixUser?, modifier: Modifier = Modifier, ) { - when (val userData = user.dataOrNull()) { - null -> Spacer(modifier = modifier.height(1.dp)) - else -> MatrixUserHeader( - modifier = modifier, - matrixUser = userData - ) - } + MatrixUserHeader( + modifier = modifier, + matrixUser = user + ) } @Preview @@ -56,9 +49,5 @@ internal fun UserPreferencesDarkPreview(@PreviewParameter(MatrixUserWithNullProv @Composable private fun ContentToPreview(matrixUser: MatrixUser?) { - if (matrixUser == null) { - UserPreferences(Async.Uninitialized) - } else { - UserPreferences(Async.Success(matrixUser)) - } + UserPreferences(matrixUser) } diff --git a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt index 2ecd3276ee..6600656803 100644 --- a/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt +++ b/features/preferences/impl/src/test/kotlin/io/element/android/features/preferences/impl/root/PreferencesRootPresenterTest.kt @@ -28,6 +28,10 @@ import io.element.android.features.rageshake.impl.preferences.DefaultRageshakePr import io.element.android.features.rageshake.test.rageshake.FakeRageShake import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore import io.element.android.libraries.architecture.Async +import io.element.android.libraries.matrix.api.user.CurrentUserProvider +import io.element.android.libraries.matrix.api.user.MatrixUser +import io.element.android.libraries.matrix.test.AN_AVATAR_URL +import io.element.android.libraries.matrix.test.A_USER_NAME import io.element.android.libraries.matrix.test.FakeMatrixClient import kotlinx.coroutines.test.runTest import org.junit.Test @@ -35,27 +39,36 @@ import org.junit.Test class PreferencesRootPresenterTest { @Test fun `present - initial state`() = runTest { - val logoutPresenter = DefaultLogoutPreferencePresenter(FakeMatrixClient()) + val matrixClient = FakeMatrixClient() + val logoutPresenter = DefaultLogoutPreferencePresenter(matrixClient) val rageshakePresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore()) val analyticsPresenter = DefaultAnalyticsPreferencesPresenter(FakeAnalyticsService(), A_BUILD_META) val presenter = PreferencesRootPresenter( logoutPresenter, rageshakePresenter, analyticsPresenter, + CurrentUserProvider(matrixClient), A_BUILD_META.buildType ) moleculeFlow(RecompositionClock.Immediate) { presenter.present() }.test { - skipItems(1) val initialState = awaitItem() - assertThat(initialState.logoutState.logoutAction).isEqualTo(Async.Uninitialized) - assertThat(initialState.analyticsState.isEnabled).isFalse() - assertThat(initialState.rageshakeState.isEnabled).isTrue() - assertThat(initialState.rageshakeState.isSupported).isTrue() - assertThat(initialState.rageshakeState.sensitivity).isEqualTo(1.0f) - assertThat(initialState.myUser).isEqualTo(Async.Uninitialized) - assertThat(initialState.showDeveloperSettings).isEqualTo(true) + assertThat(initialState.myUser).isNull() + val loadedState = awaitItem() + assertThat(loadedState.logoutState.logoutAction).isEqualTo(Async.Uninitialized) + assertThat(loadedState.analyticsState.isEnabled).isFalse() + assertThat(loadedState.rageshakeState.isEnabled).isTrue() + assertThat(loadedState.rageshakeState.isSupported).isTrue() + assertThat(loadedState.rageshakeState.sensitivity).isEqualTo(1.0f) + assertThat(loadedState.myUser).isEqualTo( + MatrixUser( + userId = matrixClient.sessionId, + displayName = A_USER_NAME, + avatarUrl = AN_AVATAR_URL + ) + ) + assertThat(loadedState.showDeveloperSettings).isEqualTo(true) } } } diff --git a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt index 8bfe839eed..a929f068ee 100644 --- a/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt +++ b/features/roomlist/impl/src/main/kotlin/io/element/android/features/roomlist/impl/RoomListPresenter.kt @@ -26,10 +26,10 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue -import io.element.android.features.networkmonitor.api.NetworkMonitor -import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.features.leaveroom.api.LeaveRoomEvent import io.element.android.features.leaveroom.api.LeaveRoomPresenter +import io.element.android.features.networkmonitor.api.NetworkMonitor +import io.element.android.features.networkmonitor.api.NetworkStatus import io.element.android.features.roomlist.impl.model.RoomListRoomSummary import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryPlaceholders import io.element.android.libraries.architecture.Presenter @@ -43,8 +43,8 @@ import io.element.android.libraries.designsystem.utils.collectSnackbarMessageAsS import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId -import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.RoomSummary +import io.element.android.libraries.matrix.api.user.CurrentUserProvider import io.element.android.libraries.matrix.api.user.MatrixUser import io.element.android.libraries.matrix.api.verification.SessionVerificationService import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus @@ -60,6 +60,7 @@ private const val extendedRangeSize = 40 class RoomListPresenter @Inject constructor( private val client: MatrixClient, + private val currentUserProvider: CurrentUserProvider, private val lastMessageTimestampFormatter: LastMessageTimestampFormatter, private val roomLastMessageFormatter: RoomLastMessageFormatter, private val sessionVerificationService: SessionVerificationService, @@ -162,13 +163,7 @@ class RoomListPresenter @Inject constructor( } private fun CoroutineScope.initialLoad(matrixUser: MutableState) = launch { - val userAvatarUrl = client.loadUserAvatarURLString().getOrNull() - val userDisplayName = client.loadUserDisplayName().getOrNull() - matrixUser.value = MatrixUser( - userId = UserId(client.sessionId.value), - displayName = userDisplayName, - avatarUrl = userAvatarUrl, - ) + matrixUser.value = currentUserProvider.provide() } private fun updateVisibleRange(range: IntRange) { diff --git a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt index c9a2913dde..d512f7a9b1 100644 --- a/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt +++ b/features/roomlist/impl/src/test/kotlin/io/element/android/features/roomlist/impl/RoomListPresenterTests.kt @@ -31,6 +31,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.utils.SnackbarDispatcher import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter +import io.element.android.libraries.matrix.api.user.CurrentUserProvider import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus import io.element.android.libraries.matrix.test.AN_AVATAR_URL import io.element.android.libraries.matrix.test.AN_EXCEPTION @@ -50,8 +51,10 @@ class RoomListPresenterTests { @Test fun `present - should start with no user and then load user with success`() = runTest { + val matrixClient = FakeMatrixClient() val presenter = RoomListPresenter( - FakeMatrixClient(), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService(), @@ -75,11 +78,13 @@ class RoomListPresenterTests { @Test fun `present - should start with no user and then load user with error`() = runTest { + val matrixClient = FakeMatrixClient( + userDisplayName = Result.failure(AN_EXCEPTION), + userAvatarURLString = Result.failure(AN_EXCEPTION), + ) val presenter = RoomListPresenter( - FakeMatrixClient( - userDisplayName = Result.failure(AN_EXCEPTION), - userAvatarURLString = Result.failure(AN_EXCEPTION), - ), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService(), @@ -100,8 +105,10 @@ class RoomListPresenterTests { @Test fun `present - should filter room with success`() = runTest { + val matrixClient = FakeMatrixClient() val presenter = RoomListPresenter( - FakeMatrixClient(), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService(), @@ -127,10 +134,12 @@ class RoomListPresenterTests { @Test fun `present - load 1 room with success`() = runTest { val roomSummaryDataSource = FakeRoomSummaryDataSource() + val matrixClient = FakeMatrixClient( + roomSummaryDataSource = roomSummaryDataSource + ) val presenter = RoomListPresenter( - FakeMatrixClient( - roomSummaryDataSource = roomSummaryDataSource - ), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService(), @@ -159,10 +168,12 @@ class RoomListPresenterTests { @Test fun `present - load 1 room with success and filter rooms`() = runTest { val roomSummaryDataSource = FakeRoomSummaryDataSource() + val matrixClient = FakeMatrixClient( + roomSummaryDataSource = roomSummaryDataSource + ) val presenter = RoomListPresenter( - FakeMatrixClient( - roomSummaryDataSource = roomSummaryDataSource - ), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService(), @@ -197,10 +208,12 @@ class RoomListPresenterTests { @Test fun `present - update visible range`() = runTest { val roomSummaryDataSource = FakeRoomSummaryDataSource() + val matrixClient = FakeMatrixClient( + roomSummaryDataSource = roomSummaryDataSource + ) val presenter = RoomListPresenter( - FakeMatrixClient( - roomSummaryDataSource = roomSummaryDataSource - ), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService(), @@ -245,10 +258,12 @@ class RoomListPresenterTests { @Test fun `present - handle DismissRequestVerificationPrompt`() = runTest { val roomSummaryDataSource = FakeRoomSummaryDataSource() + val matrixClient = FakeMatrixClient( + roomSummaryDataSource = roomSummaryDataSource + ) val presenter = RoomListPresenter( - FakeMatrixClient( - roomSummaryDataSource = roomSummaryDataSource - ), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService().apply { @@ -274,8 +289,10 @@ class RoomListPresenterTests { @Test fun `present - sets invite state`() = runTest { val inviteStateFlow = MutableStateFlow(InvitesState.NoInvites) + val matrixClient = FakeMatrixClient() val presenter = RoomListPresenter( - FakeMatrixClient(), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService(), @@ -304,8 +321,10 @@ class RoomListPresenterTests { @Test fun `present - show context menu`() = runTest { + val matrixClient = FakeMatrixClient() val presenter = RoomListPresenter( - FakeMatrixClient(), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService(), @@ -331,8 +350,10 @@ class RoomListPresenterTests { @Test fun `present - hide context menu`() = runTest { + val matrixClient = FakeMatrixClient() val presenter = RoomListPresenter( - FakeMatrixClient(), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService(), @@ -363,8 +384,10 @@ class RoomListPresenterTests { @Test fun `present - leave room calls into leave room presenter`() = runTest { val leaveRoomPresenter = LeaveRoomPresenterFake() + val matrixClient = FakeMatrixClient() val presenter = RoomListPresenter( - FakeMatrixClient(), + matrixClient, + CurrentUserProvider(matrixClient), createDateFormatter(), FakeRoomLastMessageFormatter(), FakeSessionVerificationService(), diff --git a/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/CurrentUserProvider.kt b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/CurrentUserProvider.kt new file mode 100644 index 0000000000..2e752578a7 --- /dev/null +++ b/libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/user/CurrentUserProvider.kt @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.api.user + +import io.element.android.libraries.matrix.api.MatrixClient +import javax.inject.Inject + +class CurrentUserProvider @Inject constructor( + private val matrixClient: MatrixClient, +) { + suspend fun provide(): MatrixUser { + val userAvatarUrl = matrixClient.loadUserAvatarURLString().getOrNull() + val userDisplayName = matrixClient.loadUserDisplayName().getOrNull() + return MatrixUser( + userId = matrixClient.sessionId, + displayName = userDisplayName, + avatarUrl = userAvatarUrl, + ) + } +} diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt index c4ec772456..164d91ebff 100644 --- a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeader.kt @@ -16,7 +16,6 @@ package io.element.android.libraries.matrix.ui.components -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -42,13 +41,16 @@ import io.element.android.libraries.theme.ElementTheme @Composable fun MatrixUserHeader( - matrixUser: MatrixUser, + matrixUser: MatrixUser?, modifier: Modifier = Modifier, - onClick: () -> Unit = {}, + // onClick: () -> Unit = {}, ) { + if (matrixUser == null) { + return MatrixUserHeaderPlaceholder(modifier = modifier) + } Row( modifier = modifier - .clickable(onClick = onClick) + // .clickable(onClick = onClick) .fillMaxWidth() .padding(horizontal = 16.dp), verticalAlignment = Alignment.CenterVertically diff --git a/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt new file mode 100644 index 0000000000..b43fc36fa6 --- /dev/null +++ b/libraries/matrixui/src/main/kotlin/io/element/android/libraries/matrix/ui/components/MatrixUserHeaderPlaceholder.kt @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2023 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package io.element.android.libraries.matrix.ui.components + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import io.element.android.libraries.designsystem.atomic.atoms.PlaceholderAtom +import io.element.android.libraries.designsystem.components.avatar.AvatarSize +import io.element.android.libraries.designsystem.preview.ElementPreviewDark +import io.element.android.libraries.designsystem.preview.ElementPreviewLight +import io.element.android.libraries.designsystem.theme.roomListPlaceholder +import io.element.android.libraries.theme.ElementTheme + +@Composable +fun MatrixUserHeaderPlaceholder( + modifier: Modifier = Modifier, +) { + Row( + modifier = modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Box( + modifier = Modifier + .padding(vertical = 12.dp) + .size(AvatarSize.UserPreference.dp) + .background(color = ElementTheme.colors.roomListPlaceholder, shape = CircleShape) + ) + Spacer(modifier = Modifier.width(16.dp)) + Column( + modifier = Modifier.weight(1f) + ) { + PlaceholderAtom(width = 80.dp, height = 7.dp) + Spacer(modifier = Modifier.height(16.dp)) + PlaceholderAtom(width = 180.dp, height = 6.dp) + } + } +} + +@Preview +@Composable +fun MatrixUserHeaderPlaceholderLightPreview() = + ElementPreviewLight { ContentToPreview() } + +@Preview +@Composable +fun MatrixUserHeaderPlaceholderDarkPreview() = + ElementPreviewDark { ContentToPreview() } + +@Composable +private fun ContentToPreview() { + MatrixUserHeaderPlaceholder() +} diff --git a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt index f9cdf0f3fd..d41a565069 100644 --- a/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt +++ b/samples/minimal/src/main/kotlin/io/element/android/samples/minimal/RoomListScreen.kt @@ -38,6 +38,7 @@ import io.element.android.libraries.eventformatter.impl.StateContentFormatter import io.element.android.libraries.matrix.api.MatrixClient import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.room.RoomMembershipObserver +import io.element.android.libraries.matrix.api.user.CurrentUserProvider import io.element.android.services.toolbox.impl.strings.AndroidStringProvider import kotlinx.coroutines.launch import kotlinx.coroutines.withContext @@ -60,6 +61,7 @@ class RoomListScreen( private val stringProvider = AndroidStringProvider(context.resources) private val presenter = RoomListPresenter( client = matrixClient, + currentUserProvider = CurrentUserProvider(matrixClient), lastMessageTimestampFormatter = DefaultLastMessageTimestampFormatter(dateTimeProvider, dateFormatters), roomLastMessageFormatter = DefaultRoomLastMessageFormatter( sp = stringProvider,