From 5984ffc96024a222a4d0eb9d0fc84f00f9ff839c Mon Sep 17 00:00:00 2001 From: ganfra Date: Thu, 3 Nov 2022 12:57:49 +0100 Subject: [PATCH] Refine UI --- .../x/features/roomlist/RoomListScreen.kt | 56 ++++++++++++------- .../x/features/roomlist/RoomListViewModel.kt | 3 +- .../roomlist/model/RoomListViewState.kt | 4 +- gradle/libs.versions.toml | 1 + libraries/designsystem/build.gradle.kts | 1 + .../element/android/x/designsystem/Theme.kt | 13 ++--- .../io/element/android/x/designsystem/Type.kt | 9 +++ .../designsystem/components/avatar/Avatar.kt | 36 ++++++++---- 8 files changed, 82 insertions(+), 41 deletions(-) diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt index 2169a266ad..c54c5e8bb2 100644 --- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt +++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListScreen.kt @@ -1,3 +1,5 @@ +@file:OptIn(ExperimentalMaterial3Api::class) + package io.element.android.x.features.roomlist import Avatar @@ -19,6 +21,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview @@ -63,40 +66,48 @@ fun RoomListContent( onRoomClicked: (RoomId) -> Unit, onLogoutClicked: () -> Unit, ) { + val appBarState = rememberTopAppBarState() + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(appBarState) LogCompositions(tag = "RoomListScreen", msg = "Content") - Surface(color = MaterialTheme.colorScheme.background) { - Column( - modifier = Modifier.fillMaxSize() - ) { - RoomListTopBar( - matrixUser = matrixUser, - onLogoutClicked = onLogoutClicked - ) - LazyColumn { - items(roomSummaries, key = { it.id }) { room -> + Scaffold( + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + topBar = { + RoomListTopBar(matrixUser, onLogoutClicked, scrollBehavior) + }, + content = { padding -> + LazyColumn(modifier = Modifier.padding(padding)) { + items(roomSummaries) { room -> RoomItem(room = room) { onRoomClicked(it) } } } } - } + ) } + @OptIn(ExperimentalMaterial3Api::class) @Composable -fun RoomListTopBar(matrixUser: MatrixUser?, onLogoutClicked: () -> Unit) { +fun RoomListTopBar( + matrixUser: MatrixUser?, + onLogoutClicked: () -> Unit, + scrollBehavior: TopAppBarScrollBehavior +) { LogCompositions(tag = "RoomListScreen", msg = "TopBar") if (matrixUser == null) return - TopAppBar( + MediumTopAppBar( + modifier = Modifier + .nestedScroll(scrollBehavior.nestedScrollConnection), title = { - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { + Text( + fontWeight = FontWeight.Bold, + text = "All Chats" + ) + }, + navigationIcon = { + IconButton(onClick = {}) { Avatar(matrixUser.avatarData) - Spacer(modifier = Modifier.width(8.dp)) - Text("${matrixUser.username}") } }, actions = { @@ -105,7 +116,8 @@ fun RoomListTopBar(matrixUser: MatrixUser?, onLogoutClicked: () -> Unit) { ) { Icon(Icons.Default.ExitToApp, contentDescription = "logout") } - } + }, + scrollBehavior = scrollBehavior, ) } @@ -121,6 +133,7 @@ private fun RoomItem( Column( modifier = modifier .fillMaxWidth() + .height(72.dp) .clickable( onClick = { onClick(room.roomId) }, indication = rememberRipple(), @@ -141,7 +154,7 @@ private fun RoomItem( ) { Text( fontSize = 16.sp, - fontWeight = FontWeight.Bold, + fontWeight = FontWeight.SemiBold, text = room.name, maxLines = 1, overflow = TextOverflow.Ellipsis @@ -149,6 +162,7 @@ private fun RoomItem( Text( text = room.lastMessage?.toString().orEmpty(), color = MaterialTheme.colorScheme.secondary, + fontSize = 15.sp, maxLines = 1, overflow = TextOverflow.Ellipsis ) diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt index 7c8a31a1c2..3798150ac0 100644 --- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt +++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/RoomListViewModel.kt @@ -1,5 +1,6 @@ package io.element.android.x.features.roomlist +import androidx.compose.ui.unit.dp import com.airbnb.mvrx.Fail import com.airbnb.mvrx.Loading import com.airbnb.mvrx.MavericksViewModel @@ -46,7 +47,7 @@ class RoomListViewModel(initialState: RoomListViewState) : val userAvatarUrl = client.loadUserAvatarURLString().getOrNull() val userDisplayName = client.loadUserDisplayName().getOrNull() val avatarData = - loadAvatarData(client, userDisplayName ?: client.userId().value, userAvatarUrl) + loadAvatarData(client, userDisplayName ?: client.userId().value, userAvatarUrl, 32) MatrixUser( username = userDisplayName ?: client.userId().value, avatarUrl = userAvatarUrl, diff --git a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListViewState.kt b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListViewState.kt index 52f8cfdfcf..4bc97316bd 100644 --- a/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListViewState.kt +++ b/features/roomlist/src/main/java/io/element/android/x/features/roomlist/model/RoomListViewState.kt @@ -3,12 +3,12 @@ package io.element.android.x.features.roomlist.model import com.airbnb.mvrx.Async import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.Uninitialized -import io.element.android.x.features.roomlist.model.MatrixUser -import io.element.android.x.matrix.room.RoomSummary +import io.element.android.x.matrix.core.RoomId data class RoomListViewState( val user: Async = Uninitialized, val rooms: Async> = Uninitialized, val canLoadMore: Boolean = false, val logoutAction: Async = Uninitialized, + val roomsById: Map = emptyMap() ) : MavericksState diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ea2510df11..6ca1660ecf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -56,6 +56,7 @@ coroutines_test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", ve accompanist_animation = { module = "com.google.accompanist:accompanist-navigation-animation", version.ref = "accompanist" } accompanist_permission = { module = "com.google.accompanist:accompanist-permissions", version.ref = "accompanist" } accompanist_material = { module = "com.google.accompanist:accompanist-navigation-material", version.ref = "accompanist" } +accompanist_systemui = { module = "com.google.accompanist:accompanist-systemuicontroller", version.ref = "accompanist" } # Test test_junit = { module = "junit:junit", version.ref = "test_junit" } diff --git a/libraries/designsystem/build.gradle.kts b/libraries/designsystem/build.gradle.kts index ad560836e4..3d7bfff108 100644 --- a/libraries/designsystem/build.gradle.kts +++ b/libraries/designsystem/build.gradle.kts @@ -8,5 +8,6 @@ android { dependencies { // Should not be there, but this is a POC implementation("io.coil-kt:coil-compose:2.2.1") + implementation(libs.accompanist.systemui) } } \ No newline at end of file diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt index b3d6f48d77..d41f75b7e1 100644 --- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt +++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Theme.kt @@ -11,6 +11,7 @@ import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat +import com.google.accompanist.systemuicontroller.rememberSystemUiController private val DarkColorScheme = darkColorScheme( primary = Color.White, @@ -58,13 +59,11 @@ fun ElementXTheme( darkTheme -> DarkColorScheme else -> LightColorScheme } - val view = LocalView.current - if (!view.isInEditMode) { - SideEffect { - val window = (view.context as Activity).window - window.statusBarColor = colorScheme.primary.toArgb() - WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme - } + val systemUiController = rememberSystemUiController() + SideEffect { + systemUiController.setStatusBarColor( + color = colorScheme.background + ) } MaterialTheme( diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt index 61abc8f135..37f0303aff 100644 --- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt +++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/Type.kt @@ -8,13 +8,22 @@ import androidx.compose.ui.unit.sp // Set of Material typography styles to start with val Typography = Typography( + bodyLarge = TextStyle( fontFamily = FontFamily.Default, fontWeight = FontWeight.Normal, fontSize = 16.sp, lineHeight = 24.sp, letterSpacing = 0.5.sp + ), + headlineSmall = TextStyle( + fontFamily = FontFamily.Default, + fontWeight = FontWeight.Bold, + fontSize = 32.sp, + lineHeight = 24.sp, + letterSpacing = 0.5.sp ) + /* Other default text styles to override titleLarge = TextStyle( fontFamily = FontFamily.Default, diff --git a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt index 33c93c1e8e..bbbe50a035 100644 --- a/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt +++ b/libraries/designsystem/src/main/java/io/element/android/x/designsystem/components/avatar/Avatar.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import coil.compose.AsyncImage @@ -18,28 +19,43 @@ import io.element.android.x.designsystem.AvatarGradientStart import io.element.android.x.designsystem.components.avatar.AvatarData @Composable -fun Avatar(avatarData: AvatarData) { +fun Avatar(avatarData: AvatarData, modifier: Modifier = Modifier) { if (avatarData.model == null) { InitialsAvatar( - modifier = Modifier + modifier = modifier .size(avatarData.size.dp) .clip(CircleShape), initials = avatarData.initials ) } else { - AsyncImage( - model = avatarData.model, - onError = { - Log.e("TAG", "Error $it\n${it.result}", it.result.throwable) - }, - contentDescription = null, - modifier = Modifier + ImageAvatar( + modifier = modifier .size(avatarData.size.dp) - .clip(CircleShape) + .clip(CircleShape), + avatarData = avatarData ) } } +@Composable +private fun ImageAvatar( + avatarData: AvatarData, + modifier: Modifier = Modifier, +) { + AsyncImage( + model = avatarData.model, + onError = { + Log.e("TAG", "Error $it\n${it.result}", it.result.throwable) + }, + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = modifier + .size(avatarData.size.dp) + .clip(CircleShape) + ) +} + + @Composable private fun InitialsAvatar( initials: String,