From 3820d08af887f4085b835245a5330ce6366cea40 Mon Sep 17 00:00:00 2001 From: IanRDavies Date: Fri, 18 Feb 2022 16:55:50 +0000 Subject: [PATCH] chat list styling round 2 (#334) * initial restyling: * polish styling a little * lint * more linting * add dependency * add time to messages when they exist * if no chat items show time from time chat created * playing with colours * rename shared colour * flip title text colour in dark mode --- apps/android/app/build.gradle | 2 +- .../java/chat/simplex/app/model/ChatModel.kt | 10 ++- .../java/chat/simplex/app/ui/theme/Color.kt | 5 ++ .../java/chat/simplex/app/ui/theme/Theme.kt | 26 ++++--- .../app/views/chatlist/ChatListView.kt | 17 ++++- .../app/views/chatlist/ChatPreviewView.kt | 71 ++++++++++++++----- 6 files changed, 100 insertions(+), 31 deletions(-) diff --git a/apps/android/app/build.gradle b/apps/android/app/build.gradle index f4c0a8434c..34c6c464b6 100644 --- a/apps/android/app/build.gradle +++ b/apps/android/app/build.gradle @@ -9,7 +9,7 @@ android { defaultConfig { applicationId "chat.simplex.app" - minSdk 24 + minSdk 26 targetSdk 32 versionCode 1 versionName "1.0" diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt index 0cd97da752..b53b62e839 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt @@ -209,6 +209,7 @@ interface SomeChat { val id: ChatId val apiId: Long val ready: Boolean + val createdAt: Instant } @Serializable @@ -250,6 +251,7 @@ sealed class ChatInfo: SomeChat, NamedChat { override val id get() = contact.id override val apiId get() = contact.apiId override val ready get() = contact.ready + override val createdAt get() = contact.createdAt override val displayName get() = contact.displayName override val fullName get() = contact.displayName @@ -265,6 +267,7 @@ sealed class ChatInfo: SomeChat, NamedChat { override val id get() = groupInfo.id override val apiId get() = groupInfo.apiId override val ready get() = groupInfo.ready + override val createdAt get() = groupInfo.createdAt override val displayName get() = groupInfo.displayName override val fullName get() = groupInfo.displayName @@ -280,6 +283,7 @@ sealed class ChatInfo: SomeChat, NamedChat { override val id get() = contactRequest.id override val apiId get() = contactRequest.apiId override val ready get() = contactRequest.ready + override val createdAt get() = contactRequest.createdAt override val displayName get() = contactRequest.displayName override val fullName get() = contactRequest.displayName @@ -296,7 +300,7 @@ class Contact( val profile: Profile, val activeConn: Connection, val viaGroup: Long? = null, - val createdAt: Instant + override val createdAt: Instant ): SomeChat, NamedChat { override val chatType get() = ChatType.Direct override val id get() = "@$contactId" @@ -341,7 +345,7 @@ class GroupInfo ( val groupId: Long, override val localDisplayName: String, val groupProfile: GroupProfile, - val createdAt: Instant + override val createdAt: Instant ): SomeChat, NamedChat { override val chatType get() = ChatType.Group override val id get() = "#$groupId" @@ -402,7 +406,7 @@ class UserContactRequest ( val contactRequestId: Long, override val localDisplayName: String, val profile: Profile, - val createdAt: Instant + override val createdAt: Instant ): SomeChat, NamedChat { override val chatType get() = ChatType.ContactRequest override val id get() = "<@$contactRequestId" diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt index 59390dc153..ec2f0b1f12 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Color.kt @@ -7,3 +7,8 @@ val Purple500 = Color(0xFF6200EE) val Purple700 = Color(0xFF3700B3) val Teal200 = Color(0xFF03DAC5) val Gray = Color(0x22222222) +val AppleBlue = Color(0, 136, 255, 255) +val AppleGreen = Color(98, 196, 103, 255) +val LightGray = Color(241, 242, 246, 255) +val DarkGray = Color(43, 44, 46, 255) +val HighOrLowlight = Color(134, 135, 139, 255) diff --git a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt index 49a849e800..d486720301 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/ui/theme/Theme.kt @@ -5,21 +5,29 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.darkColors import androidx.compose.material.lightColors import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color private val DarkColorPalette = darkColors( - primary = Purple200, - primaryVariant = Purple700, - secondary = Teal200, - secondaryVariant = Gray + primary = AppleBlue, + primaryVariant = AppleGreen, + secondary = DarkGray, + /* + background: Color = Color(0xFF121212), + surface: Color = Color(0xFF121212), + error: Color = Color(0xFFCF6679), + onPrimary: Color = Color.Black, + onSecondary: Color = Color.Black, + onBackground: Color = Color.White, + onSurface: Color = Color.White, + onError: Color = Color.Black + */ ) private val LightColorPalette = lightColors( - primary = Purple500, - primaryVariant = Purple700, - secondary = Teal200, - secondaryVariant = Gray + primary = AppleBlue, + primaryVariant = AppleGreen, + secondary = LightGray, /* Other default colors to override - background = Color.White, surface = Color.White, onPrimary = Color.White, onSecondary = Color.Black, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt index 11f346ebed..8a08347af0 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListView.kt @@ -1,5 +1,6 @@ package chat.simplex.app.views.chatlist +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -19,6 +20,7 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import androidx.compose.material.Icon +import androidx.compose.material.MaterialTheme import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.* import androidx.compose.ui.Alignment @@ -26,7 +28,11 @@ import androidx.compose.ui.text.font.FontWeight @Composable fun ChatListView(chatModel: ChatModel, navController: NavController) { - Column(modifier = Modifier.padding(vertical = 8.dp).fillMaxWidth()) { + Column(modifier = Modifier + .padding(vertical = 8.dp) + .fillMaxSize() + .background(MaterialTheme.colors.background) + ) { ChatListToolbar() ChatList(chatModel, navController) Button( @@ -49,12 +55,19 @@ fun ChatListToolbar() { Icon( Icons.Outlined.Settings, "Settings Cog", + tint = MaterialTheme.colors.primary, modifier = Modifier.padding(horizontal = 10.dp) ) - Text("Your chats", fontWeight = FontWeight.Bold, modifier = Modifier.padding(5.dp)) + Text( + "Your chats", + color=MaterialTheme.colors.onBackground, + fontWeight = FontWeight.Bold, + modifier = Modifier.padding(5.dp) + ) Icon( Icons.Outlined.PersonAdd, "Add Contact", + tint = MaterialTheme.colors.primary, modifier = Modifier.padding(horizontal = 10.dp) ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt index 9b19cd2c87..a96155665e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatPreviewView.kt @@ -1,6 +1,8 @@ package chat.simplex.app.views.chatlist +import android.icu.text.SimpleDateFormat import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -16,39 +18,76 @@ import chat.simplex.app.model.* import androidx.compose.material.Icon import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Person -import androidx.compose.ui.Alignment import androidx.compose.ui.draw.clip import androidx.compose.ui.text.font.* +import androidx.compose.ui.text.style.TextOverflow +import chat.simplex.app.ui.theme.HighOrLowlight import chat.simplex.app.ui.theme.SimpleXTheme +import kotlinx.datetime.Instant +import kotlinx.datetime.toJavaInstant +import java.time.LocalDateTime +import java.time.Instant as JavaInstant +import java.util.* + + + +fun getDisplayTime(t: Instant) : String { + val timeFormatter = SimpleDateFormat("HH:mm", Locale.getDefault()) + val dateFormatter = SimpleDateFormat("dd/MM/y", Locale.getDefault()) + val timeProvided: JavaInstant = t.toJavaInstant() + val tz = TimeZone.getDefault() + val dateProvided = LocalDateTime.ofInstant(timeProvided, tz.toZoneId()).toLocalDate() + val today = LocalDateTime.now().atZone(tz.toZoneId()).toLocalDate() + val yesterday = today.minusDays(1) + + return when (dateProvided) { + today -> timeFormatter.format(Date.from(timeProvided)) + yesterday -> "yesterday" + else -> dateFormatter.format(Date.from(timeProvided)) + } +} @Composable fun ChatPreviewView(chat: Chat, goToChat: () -> Unit) { Surface( - border=BorderStroke(0.5.dp, MaterialTheme.colors.secondaryVariant), + border=BorderStroke(0.5.dp, MaterialTheme.colors.secondary), modifier= Modifier .fillMaxWidth() .clickable(onClick = goToChat) - + .height(80.dp) ) { Row( modifier = Modifier.fillMaxWidth().padding(horizontal = 14.dp), - verticalAlignment = Alignment.CenterVertically ) { - - Icon( - Icons.Filled.Person, - contentDescription = "Avatar Placeholder", - modifier = Modifier - .size(30.dp) - .clip(CircleShape) - .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape) - ) - + Column(verticalArrangement=Arrangement.Center, modifier=Modifier.fillMaxHeight()) { + Icon( + Icons.Filled.Person, + contentDescription = "Avatar Placeholder", + tint = MaterialTheme.colors.background, + modifier = Modifier + .size(55.dp) + .clip(CircleShape) + .border(1.5.dp, MaterialTheme.colors.secondary, CircleShape) + .background(MaterialTheme.colors.secondary) + ) + } Spacer(modifier = Modifier.width(6.dp)) Column(modifier = Modifier.padding(all = 8.dp)) { - Text(chat.chatInfo.chatViewName, fontWeight = FontWeight.Bold) + Row(horizontalArrangement=Arrangement.SpaceBetween, modifier=Modifier.fillMaxWidth()) { + Text(chat.chatInfo.chatViewName, fontWeight = FontWeight.Bold) + ( + if (chat.chatItems.count() > 0) { + Text(getDisplayTime(chat.chatItems.last().meta.itemTs), color = HighOrLowlight) + } + else Text(getDisplayTime(chat.chatInfo.createdAt), color = HighOrLowlight) + ) + } if (chat.chatItems.count() > 0) { - Text(chat.chatItems.last().content.text) + Text( + chat.chatItems.last().content.text, + maxLines = 2, + overflow = TextOverflow.Ellipsis, + ) } } }