Show current user in the settings and extract code in CurrentUserProvider.
This commit is contained in:
parent
0c29852d62
commit
002ddf4f3f
12 changed files with 226 additions and 69 deletions
|
|
@ -17,23 +17,38 @@
|
||||||
package io.element.android.features.preferences.impl.root
|
package io.element.android.features.preferences.impl.root
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
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.analytics.api.preferences.AnalyticsPreferencesPresenter
|
||||||
import io.element.android.features.logout.api.LogoutPreferencePresenter
|
import io.element.android.features.logout.api.LogoutPreferencePresenter
|
||||||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesPresenter
|
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.architecture.Presenter
|
||||||
import io.element.android.libraries.core.meta.BuildType
|
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
|
import javax.inject.Inject
|
||||||
|
|
||||||
class PreferencesRootPresenter @Inject constructor(
|
class PreferencesRootPresenter @Inject constructor(
|
||||||
private val logoutPresenter: LogoutPreferencePresenter,
|
private val logoutPresenter: LogoutPreferencePresenter,
|
||||||
private val rageshakePresenter: RageshakePreferencesPresenter,
|
private val rageshakePresenter: RageshakePreferencesPresenter,
|
||||||
private val analyticsPresenter: AnalyticsPreferencesPresenter,
|
private val analyticsPresenter: AnalyticsPreferencesPresenter,
|
||||||
|
private val currentUserProvider: CurrentUserProvider,
|
||||||
private val buildType: BuildType,
|
private val buildType: BuildType,
|
||||||
) : Presenter<PreferencesRootState> {
|
) : Presenter<PreferencesRootState> {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): PreferencesRootState {
|
override fun present(): PreferencesRootState {
|
||||||
|
val matrixUser: MutableState<MatrixUser?> = rememberSaveable {
|
||||||
|
mutableStateOf(null)
|
||||||
|
}
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
initialLoad(matrixUser)
|
||||||
|
}
|
||||||
|
|
||||||
val logoutState = logoutPresenter.present()
|
val logoutState = logoutPresenter.present()
|
||||||
val rageshakeState = rageshakePresenter.present()
|
val rageshakeState = rageshakePresenter.present()
|
||||||
val analyticsState = analyticsPresenter.present()
|
val analyticsState = analyticsPresenter.present()
|
||||||
|
|
@ -42,8 +57,12 @@ class PreferencesRootPresenter @Inject constructor(
|
||||||
logoutState = logoutState,
|
logoutState = logoutState,
|
||||||
rageshakeState = rageshakeState,
|
rageshakeState = rageshakeState,
|
||||||
analyticsState = analyticsState,
|
analyticsState = analyticsState,
|
||||||
myUser = Async.Uninitialized,
|
myUser = matrixUser.value,
|
||||||
showDeveloperSettings = showDeveloperSettings
|
showDeveloperSettings = showDeveloperSettings
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun CoroutineScope.initialLoad(matrixUser: MutableState<MatrixUser?>) = launch {
|
||||||
|
matrixUser.value = currentUserProvider.provide()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.analytics.api.preferences.AnalyticsPreferencesState
|
||||||
import io.element.android.features.logout.api.LogoutPreferenceState
|
import io.element.android.features.logout.api.LogoutPreferenceState
|
||||||
import io.element.android.features.rageshake.api.preferences.RageshakePreferencesState
|
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
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
|
||||||
data class PreferencesRootState(
|
data class PreferencesRootState(
|
||||||
val logoutState: LogoutPreferenceState,
|
val logoutState: LogoutPreferenceState,
|
||||||
val rageshakeState: RageshakePreferencesState,
|
val rageshakeState: RageshakePreferencesState,
|
||||||
val analyticsState: AnalyticsPreferencesState,
|
val analyticsState: AnalyticsPreferencesState,
|
||||||
val myUser: Async<MatrixUser>,
|
val myUser: MatrixUser?,
|
||||||
val showDeveloperSettings: Boolean
|
val showDeveloperSettings: Boolean
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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.analytics.api.preferences.aAnalyticsPreferencesState
|
||||||
import io.element.android.features.logout.api.aLogoutPreferenceState
|
import io.element.android.features.logout.api.aLogoutPreferenceState
|
||||||
import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState
|
import io.element.android.features.rageshake.api.preferences.aRageshakePreferencesState
|
||||||
import io.element.android.libraries.architecture.Async
|
|
||||||
|
|
||||||
fun aPreferencesRootState() = PreferencesRootState(
|
fun aPreferencesRootState() = PreferencesRootState(
|
||||||
logoutState = aLogoutPreferenceState(),
|
logoutState = aLogoutPreferenceState(),
|
||||||
rageshakeState = aRageshakePreferencesState(),
|
rageshakeState = aRageshakePreferencesState(),
|
||||||
analyticsState = aAnalyticsPreferencesState(),
|
analyticsState = aAnalyticsPreferencesState(),
|
||||||
myUser = Async.Uninitialized,
|
myUser = null,
|
||||||
showDeveloperSettings = true
|
showDeveloperSettings = true
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -92,5 +92,5 @@ fun PreferencesRootViewDarkPreview(@PreviewParameter(MatrixUserProvider::class)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ContentToPreview(matrixUser: MatrixUser) {
|
private fun ContentToPreview(matrixUser: MatrixUser) {
|
||||||
PreferencesRootView(aPreferencesRootState().copy(myUser = Async.Success(matrixUser)))
|
PreferencesRootView(aPreferencesRootState().copy(myUser = matrixUser))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,10 @@
|
||||||
|
|
||||||
package io.element.android.features.preferences.impl.user
|
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.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
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.ElementPreviewDark
|
||||||
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
import io.element.android.libraries.designsystem.preview.ElementPreviewLight
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
|
|
@ -32,16 +28,13 @@ import io.element.android.libraries.matrix.ui.components.MatrixUserWithNullProvi
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UserPreferences(
|
fun UserPreferences(
|
||||||
user: Async<MatrixUser>,
|
user: MatrixUser?,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
when (val userData = user.dataOrNull()) {
|
MatrixUserHeader(
|
||||||
null -> Spacer(modifier = modifier.height(1.dp))
|
modifier = modifier,
|
||||||
else -> MatrixUserHeader(
|
matrixUser = user
|
||||||
modifier = modifier,
|
)
|
||||||
matrixUser = userData
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
|
|
@ -56,9 +49,5 @@ internal fun UserPreferencesDarkPreview(@PreviewParameter(MatrixUserWithNullProv
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ContentToPreview(matrixUser: MatrixUser?) {
|
private fun ContentToPreview(matrixUser: MatrixUser?) {
|
||||||
if (matrixUser == null) {
|
UserPreferences(matrixUser)
|
||||||
UserPreferences(Async.Uninitialized)
|
|
||||||
} else {
|
|
||||||
UserPreferences(Async.Success(matrixUser))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.FakeRageShake
|
||||||
import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore
|
import io.element.android.features.rageshake.test.rageshake.FakeRageshakeDataStore
|
||||||
import io.element.android.libraries.architecture.Async
|
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 io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
@ -35,27 +39,36 @@ import org.junit.Test
|
||||||
class PreferencesRootPresenterTest {
|
class PreferencesRootPresenterTest {
|
||||||
@Test
|
@Test
|
||||||
fun `present - initial state`() = runTest {
|
fun `present - initial state`() = runTest {
|
||||||
val logoutPresenter = DefaultLogoutPreferencePresenter(FakeMatrixClient())
|
val matrixClient = FakeMatrixClient()
|
||||||
|
val logoutPresenter = DefaultLogoutPreferencePresenter(matrixClient)
|
||||||
val rageshakePresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore())
|
val rageshakePresenter = DefaultRageshakePreferencesPresenter(FakeRageShake(), FakeRageshakeDataStore())
|
||||||
val analyticsPresenter = DefaultAnalyticsPreferencesPresenter(FakeAnalyticsService(), A_BUILD_META)
|
val analyticsPresenter = DefaultAnalyticsPreferencesPresenter(FakeAnalyticsService(), A_BUILD_META)
|
||||||
val presenter = PreferencesRootPresenter(
|
val presenter = PreferencesRootPresenter(
|
||||||
logoutPresenter,
|
logoutPresenter,
|
||||||
rageshakePresenter,
|
rageshakePresenter,
|
||||||
analyticsPresenter,
|
analyticsPresenter,
|
||||||
|
CurrentUserProvider(matrixClient),
|
||||||
A_BUILD_META.buildType
|
A_BUILD_META.buildType
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionClock.Immediate) {
|
moleculeFlow(RecompositionClock.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
skipItems(1)
|
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
assertThat(initialState.logoutState.logoutAction).isEqualTo(Async.Uninitialized)
|
assertThat(initialState.myUser).isNull()
|
||||||
assertThat(initialState.analyticsState.isEnabled).isFalse()
|
val loadedState = awaitItem()
|
||||||
assertThat(initialState.rageshakeState.isEnabled).isTrue()
|
assertThat(loadedState.logoutState.logoutAction).isEqualTo(Async.Uninitialized)
|
||||||
assertThat(initialState.rageshakeState.isSupported).isTrue()
|
assertThat(loadedState.analyticsState.isEnabled).isFalse()
|
||||||
assertThat(initialState.rageshakeState.sensitivity).isEqualTo(1.0f)
|
assertThat(loadedState.rageshakeState.isEnabled).isTrue()
|
||||||
assertThat(initialState.myUser).isEqualTo(Async.Uninitialized)
|
assertThat(loadedState.rageshakeState.isSupported).isTrue()
|
||||||
assertThat(initialState.showDeveloperSettings).isEqualTo(true)
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,10 @@ import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
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.LeaveRoomEvent
|
||||||
import io.element.android.features.leaveroom.api.LeaveRoomPresenter
|
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.RoomListRoomSummary
|
||||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryPlaceholders
|
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryPlaceholders
|
||||||
import io.element.android.libraries.architecture.Presenter
|
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.eventformatter.api.RoomLastMessageFormatter
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
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.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.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.user.MatrixUser
|
||||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||||
|
|
@ -60,6 +60,7 @@ private const val extendedRangeSize = 40
|
||||||
|
|
||||||
class RoomListPresenter @Inject constructor(
|
class RoomListPresenter @Inject constructor(
|
||||||
private val client: MatrixClient,
|
private val client: MatrixClient,
|
||||||
|
private val currentUserProvider: CurrentUserProvider,
|
||||||
private val lastMessageTimestampFormatter: LastMessageTimestampFormatter,
|
private val lastMessageTimestampFormatter: LastMessageTimestampFormatter,
|
||||||
private val roomLastMessageFormatter: RoomLastMessageFormatter,
|
private val roomLastMessageFormatter: RoomLastMessageFormatter,
|
||||||
private val sessionVerificationService: SessionVerificationService,
|
private val sessionVerificationService: SessionVerificationService,
|
||||||
|
|
@ -162,13 +163,7 @@ class RoomListPresenter @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun CoroutineScope.initialLoad(matrixUser: MutableState<MatrixUser?>) = launch {
|
private fun CoroutineScope.initialLoad(matrixUser: MutableState<MatrixUser?>) = launch {
|
||||||
val userAvatarUrl = client.loadUserAvatarURLString().getOrNull()
|
matrixUser.value = currentUserProvider.provide()
|
||||||
val userDisplayName = client.loadUserDisplayName().getOrNull()
|
|
||||||
matrixUser.value = MatrixUser(
|
|
||||||
userId = UserId(client.sessionId.value),
|
|
||||||
displayName = userDisplayName,
|
|
||||||
avatarUrl = userAvatarUrl,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateVisibleRange(range: IntRange) {
|
private fun updateVisibleRange(range: IntRange) {
|
||||||
|
|
|
||||||
|
|
@ -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.components.avatar.AvatarSize
|
||||||
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
import io.element.android.libraries.designsystem.utils.SnackbarDispatcher
|
||||||
import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter
|
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.api.verification.SessionVerifiedStatus
|
||||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||||
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
import io.element.android.libraries.matrix.test.AN_EXCEPTION
|
||||||
|
|
@ -50,8 +51,10 @@ class RoomListPresenterTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - should start with no user and then load user with success`() = runTest {
|
fun `present - should start with no user and then load user with success`() = runTest {
|
||||||
|
val matrixClient = FakeMatrixClient()
|
||||||
val presenter = RoomListPresenter(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(),
|
matrixClient,
|
||||||
|
CurrentUserProvider(matrixClient),
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService(),
|
FakeSessionVerificationService(),
|
||||||
|
|
@ -75,11 +78,13 @@ class RoomListPresenterTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - should start with no user and then load user with error`() = runTest {
|
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(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(
|
matrixClient,
|
||||||
userDisplayName = Result.failure(AN_EXCEPTION),
|
CurrentUserProvider(matrixClient),
|
||||||
userAvatarURLString = Result.failure(AN_EXCEPTION),
|
|
||||||
),
|
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService(),
|
FakeSessionVerificationService(),
|
||||||
|
|
@ -100,8 +105,10 @@ class RoomListPresenterTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - should filter room with success`() = runTest {
|
fun `present - should filter room with success`() = runTest {
|
||||||
|
val matrixClient = FakeMatrixClient()
|
||||||
val presenter = RoomListPresenter(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(),
|
matrixClient,
|
||||||
|
CurrentUserProvider(matrixClient),
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService(),
|
FakeSessionVerificationService(),
|
||||||
|
|
@ -127,10 +134,12 @@ class RoomListPresenterTests {
|
||||||
@Test
|
@Test
|
||||||
fun `present - load 1 room with success`() = runTest {
|
fun `present - load 1 room with success`() = runTest {
|
||||||
val roomSummaryDataSource = FakeRoomSummaryDataSource()
|
val roomSummaryDataSource = FakeRoomSummaryDataSource()
|
||||||
|
val matrixClient = FakeMatrixClient(
|
||||||
|
roomSummaryDataSource = roomSummaryDataSource
|
||||||
|
)
|
||||||
val presenter = RoomListPresenter(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(
|
matrixClient,
|
||||||
roomSummaryDataSource = roomSummaryDataSource
|
CurrentUserProvider(matrixClient),
|
||||||
),
|
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService(),
|
FakeSessionVerificationService(),
|
||||||
|
|
@ -159,10 +168,12 @@ class RoomListPresenterTests {
|
||||||
@Test
|
@Test
|
||||||
fun `present - load 1 room with success and filter rooms`() = runTest {
|
fun `present - load 1 room with success and filter rooms`() = runTest {
|
||||||
val roomSummaryDataSource = FakeRoomSummaryDataSource()
|
val roomSummaryDataSource = FakeRoomSummaryDataSource()
|
||||||
|
val matrixClient = FakeMatrixClient(
|
||||||
|
roomSummaryDataSource = roomSummaryDataSource
|
||||||
|
)
|
||||||
val presenter = RoomListPresenter(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(
|
matrixClient,
|
||||||
roomSummaryDataSource = roomSummaryDataSource
|
CurrentUserProvider(matrixClient),
|
||||||
),
|
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService(),
|
FakeSessionVerificationService(),
|
||||||
|
|
@ -197,10 +208,12 @@ class RoomListPresenterTests {
|
||||||
@Test
|
@Test
|
||||||
fun `present - update visible range`() = runTest {
|
fun `present - update visible range`() = runTest {
|
||||||
val roomSummaryDataSource = FakeRoomSummaryDataSource()
|
val roomSummaryDataSource = FakeRoomSummaryDataSource()
|
||||||
|
val matrixClient = FakeMatrixClient(
|
||||||
|
roomSummaryDataSource = roomSummaryDataSource
|
||||||
|
)
|
||||||
val presenter = RoomListPresenter(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(
|
matrixClient,
|
||||||
roomSummaryDataSource = roomSummaryDataSource
|
CurrentUserProvider(matrixClient),
|
||||||
),
|
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService(),
|
FakeSessionVerificationService(),
|
||||||
|
|
@ -245,10 +258,12 @@ class RoomListPresenterTests {
|
||||||
@Test
|
@Test
|
||||||
fun `present - handle DismissRequestVerificationPrompt`() = runTest {
|
fun `present - handle DismissRequestVerificationPrompt`() = runTest {
|
||||||
val roomSummaryDataSource = FakeRoomSummaryDataSource()
|
val roomSummaryDataSource = FakeRoomSummaryDataSource()
|
||||||
|
val matrixClient = FakeMatrixClient(
|
||||||
|
roomSummaryDataSource = roomSummaryDataSource
|
||||||
|
)
|
||||||
val presenter = RoomListPresenter(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(
|
matrixClient,
|
||||||
roomSummaryDataSource = roomSummaryDataSource
|
CurrentUserProvider(matrixClient),
|
||||||
),
|
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService().apply {
|
FakeSessionVerificationService().apply {
|
||||||
|
|
@ -274,8 +289,10 @@ class RoomListPresenterTests {
|
||||||
@Test
|
@Test
|
||||||
fun `present - sets invite state`() = runTest {
|
fun `present - sets invite state`() = runTest {
|
||||||
val inviteStateFlow = MutableStateFlow(InvitesState.NoInvites)
|
val inviteStateFlow = MutableStateFlow(InvitesState.NoInvites)
|
||||||
|
val matrixClient = FakeMatrixClient()
|
||||||
val presenter = RoomListPresenter(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(),
|
matrixClient,
|
||||||
|
CurrentUserProvider(matrixClient),
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService(),
|
FakeSessionVerificationService(),
|
||||||
|
|
@ -304,8 +321,10 @@ class RoomListPresenterTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - show context menu`() = runTest {
|
fun `present - show context menu`() = runTest {
|
||||||
|
val matrixClient = FakeMatrixClient()
|
||||||
val presenter = RoomListPresenter(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(),
|
matrixClient,
|
||||||
|
CurrentUserProvider(matrixClient),
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService(),
|
FakeSessionVerificationService(),
|
||||||
|
|
@ -331,8 +350,10 @@ class RoomListPresenterTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - hide context menu`() = runTest {
|
fun `present - hide context menu`() = runTest {
|
||||||
|
val matrixClient = FakeMatrixClient()
|
||||||
val presenter = RoomListPresenter(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(),
|
matrixClient,
|
||||||
|
CurrentUserProvider(matrixClient),
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService(),
|
FakeSessionVerificationService(),
|
||||||
|
|
@ -363,8 +384,10 @@ class RoomListPresenterTests {
|
||||||
@Test
|
@Test
|
||||||
fun `present - leave room calls into leave room presenter`() = runTest {
|
fun `present - leave room calls into leave room presenter`() = runTest {
|
||||||
val leaveRoomPresenter = LeaveRoomPresenterFake()
|
val leaveRoomPresenter = LeaveRoomPresenterFake()
|
||||||
|
val matrixClient = FakeMatrixClient()
|
||||||
val presenter = RoomListPresenter(
|
val presenter = RoomListPresenter(
|
||||||
FakeMatrixClient(),
|
matrixClient,
|
||||||
|
CurrentUserProvider(matrixClient),
|
||||||
createDateFormatter(),
|
createDateFormatter(),
|
||||||
FakeRoomLastMessageFormatter(),
|
FakeRoomLastMessageFormatter(),
|
||||||
FakeSessionVerificationService(),
|
FakeSessionVerificationService(),
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package io.element.android.libraries.matrix.ui.components
|
package io.element.android.libraries.matrix.ui.components
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
|
@ -42,13 +41,16 @@ import io.element.android.libraries.theme.ElementTheme
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MatrixUserHeader(
|
fun MatrixUserHeader(
|
||||||
matrixUser: MatrixUser,
|
matrixUser: MatrixUser?,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onClick: () -> Unit = {},
|
// onClick: () -> Unit = {},
|
||||||
) {
|
) {
|
||||||
|
if (matrixUser == null) {
|
||||||
|
return MatrixUserHeaderPlaceholder(modifier = modifier)
|
||||||
|
}
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.clickable(onClick = onClick)
|
// .clickable(onClick = onClick)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 16.dp),
|
.padding(horizontal = 16.dp),
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
}
|
||||||
|
|
@ -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.MatrixClient
|
||||||
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.room.RoomMembershipObserver
|
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 io.element.android.services.toolbox.impl.strings.AndroidStringProvider
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
@ -60,6 +61,7 @@ class RoomListScreen(
|
||||||
private val stringProvider = AndroidStringProvider(context.resources)
|
private val stringProvider = AndroidStringProvider(context.resources)
|
||||||
private val presenter = RoomListPresenter(
|
private val presenter = RoomListPresenter(
|
||||||
client = matrixClient,
|
client = matrixClient,
|
||||||
|
currentUserProvider = CurrentUserProvider(matrixClient),
|
||||||
lastMessageTimestampFormatter = DefaultLastMessageTimestampFormatter(dateTimeProvider, dateFormatters),
|
lastMessageTimestampFormatter = DefaultLastMessageTimestampFormatter(dateTimeProvider, dateFormatters),
|
||||||
roomLastMessageFormatter = DefaultRoomLastMessageFormatter(
|
roomLastMessageFormatter = DefaultRoomLastMessageFormatter(
|
||||||
sp = stringProvider,
|
sp = stringProvider,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue