diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt index 5483b3f041..bf3e7774c7 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow import androidx.compose.ui.focus.* import androidx.compose.ui.graphics.* import androidx.compose.ui.text.font.FontStyle @@ -95,7 +96,9 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf if (newChatSheetState.value.isVisible()) hideNewChatSheet(true) else showNewChatSheet() } }, - Modifier.padding(end = DEFAULT_PADDING - 16.dp + endPadding, bottom = DEFAULT_PADDING - 16.dp).size(AppBarHeight * fontSizeSqrtMultiplier), + Modifier + .padding(end = DEFAULT_PADDING - 16.dp + endPadding, bottom = DEFAULT_PADDING - 16.dp) + .size(AppBarHeight * fontSizeSqrtMultiplier), elevation = FloatingActionButtonDefaults.elevation( defaultElevation = 0.dp, pressedElevation = 0.dp, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatPreviewView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatPreviewView.kt index 0e215724f7..c42b7e3ec3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatPreviewView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatPreviewView.kt @@ -25,6 +25,7 @@ import chat.simplex.common.views.chat.item.MarkdownText import chat.simplex.common.views.helpers.* import chat.simplex.common.model.* import chat.simplex.common.model.GroupInfo +import chat.simplex.common.platform.appPlatform import chat.simplex.common.platform.chatModel import chat.simplex.common.views.chat.item.markedDeletedText import chat.simplex.res.MR @@ -47,11 +48,10 @@ fun ChatPreviewView( @Composable fun inactiveIcon() { - val sp18 = with(LocalDensity.current) { 18.sp.toDp() } Icon( painterResource(MR.images.ic_cancel_filled), stringResource(MR.strings.icon_descr_group_inactive), - Modifier.size(sp18).background(MaterialTheme.colors.background, CircleShape), + Modifier.size(18.sp.toDp()).background(MaterialTheme.colors.background, CircleShape), tint = MaterialTheme.colors.secondary ) } @@ -88,8 +88,7 @@ fun ChatPreviewView( @Composable fun VerifiedIcon() { - val sp19 = with(LocalDensity.current) { 19.sp.toDp() } - Icon(painterResource(MR.images.ic_verified_user), null, Modifier.size(sp19).padding(end = 3.dp, top = 1.dp), tint = MaterialTheme.colors.secondary) + Icon(painterResource(MR.images.ic_verified_user), null, Modifier.size(19.sp.toDp()).padding(end = 3.sp.toDp(), top = 1.sp.toDp()), tint = MaterialTheme.colors.secondary) } fun messageDraft(draft: ComposeState, sp20: Dp): Pair Unit, Map> { @@ -193,7 +192,12 @@ fun ChatPreviewView( senderBold = true, maxLines = 2, overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.body1.copy(color = if (isInDarkTheme()) MessagePreviewDark else MessagePreviewLight, lineHeight = 22.sp), + style = TextStyle( + fontFamily = Inter, + fontSize = 15.sp, + color = if (isInDarkTheme()) MessagePreviewDark else MessagePreviewLight, + lineHeight = 21.sp + ), inlineContent = inlineTextContent, modifier = Modifier.fillMaxWidth(), ) @@ -223,11 +227,10 @@ fun ChatPreviewView( @Composable fun progressView() { - val sp15 = with(LocalDensity.current) { 15.sp.toDp() } CircularProgressIndicator( Modifier - .padding(horizontal = 2.dp) - .size(sp15), + .size(15.sp.toDp()) + .offset(y = 2.sp.toDp()), color = MaterialTheme.colors.secondary, strokeWidth = 1.5.dp ) @@ -235,7 +238,6 @@ fun ChatPreviewView( @Composable fun chatStatusImage() { - val sp19 = with(LocalDensity.current) { 19.sp.toDp() } if (cInfo is ChatInfo.Direct) { if (cInfo.contact.active && cInfo.contact.activeConn != null) { val descr = contactNetworkStatus?.statusString @@ -249,7 +251,8 @@ fun ChatPreviewView( contentDescription = descr, tint = MaterialTheme.colors.secondary, modifier = Modifier - .size(sp19) + .size(19.sp.toDp()) + .offset(x = 2.sp.toDp()) ) else -> @@ -272,18 +275,17 @@ fun ChatPreviewView( Row { Box(contentAlignment = Alignment.BottomEnd) { ChatInfoImage(cInfo, size = 72.dp * fontSizeSqrtMultiplier) - Box(Modifier.padding(end = 6.dp, bottom = 6.dp)) { + Box(Modifier.padding(end = 6.sp.toDp(), bottom = 6.sp.toDp())) { chatPreviewImageOverlayIcon() } } Column( modifier = Modifier - .padding(horizontal = 8.dp) + .padding(start = 8.dp, end = 8.sp.toDp()) .weight(1F) ) { chatPreviewTitle() - val height = with(LocalDensity.current) { 46.sp.toDp() } - Row(Modifier.heightIn(min = height)) { + Row(Modifier.heightIn(min = 46.sp.toDp()).padding(top = 3.sp.toDp())) { chatPreviewText() } } @@ -292,67 +294,50 @@ fun ChatPreviewView( contentAlignment = Alignment.TopEnd ) { val ts = chat.chatItems.lastOrNull()?.timestampText ?: getTimestampText(chat.chatInfo.chatTs) - Text( - ts, - color = MaterialTheme.colors.secondary, - style = MaterialTheme.typography.body2, - modifier = Modifier.padding(bottom = 5.dp) - ) + ChatListTimestampView(ts) val n = chat.chatStats.unreadCount val showNtfsIcon = !chat.chatInfo.ntfsEnabled && (chat.chatInfo is ChatInfo.Direct || chat.chatInfo is ChatInfo.Group) - val sp17 = with(LocalDensity.current) { 17.sp.toDp() } - val sp21 = with(LocalDensity.current) { 21.sp.toDp() } - val sp23 = with(LocalDensity.current) { 23.sp.toDp() } - val sp46 = with(LocalDensity.current) { 46.sp.toDp() } if (n > 0 || chat.chatStats.unreadChat) { Box( - Modifier.padding(top = sp23, end = with(LocalDensity.current) { 3.sp.toDp() }), - contentAlignment = Alignment.Center - ) { + Modifier.padding(top = 24.5.sp.toDp())) { Text( if (n > 0) unreadCountStr(n) else "", color = Color.White, - fontSize = 11.sp, + fontSize = 10.sp, modifier = Modifier .background(if (disabled || showNtfsIcon) MaterialTheme.colors.secondary else MaterialTheme.colors.primaryVariant, shape = CircleShape) .badgeLayout() - .padding(horizontal = 3.dp) - .padding(vertical = 1.dp) + .padding(horizontal = 3.sp.toDp()) + .padding(vertical = 1.sp.toDp()) ) } } else if (showNtfsIcon) { Box( - Modifier.padding(top = sp21), - contentAlignment = Alignment.Center - ) { + Modifier.padding(top = 22.sp.toDp())) { Icon( painterResource(MR.images.ic_notifications_off_filled), contentDescription = generalGetString(MR.strings.notifications), tint = MaterialTheme.colors.secondary, modifier = Modifier - .padding(horizontal = 3.dp) - .padding(vertical = 1.dp) - .size(sp17) + .size(17.sp.toDp()) + .offset(x = 2.5.sp.toDp()) ) } } else if (chat.chatInfo.chatSettings?.favorite == true) { Box( - Modifier.padding(top = sp21), - contentAlignment = Alignment.Center - ) { + Modifier.padding(top = 20.sp.toDp())) { Icon( painterResource(MR.images.ic_star_filled), contentDescription = generalGetString(MR.strings.favorite_chat), tint = MaterialTheme.colors.secondary, modifier = Modifier - .padding(horizontal = 3.dp) - .padding(vertical = 1.dp) - .size(sp17) + .size(20.sp.toDp()) + .offset(x = 2.5.sp.toDp()) ) } } Box( - Modifier.padding(top = sp46), + Modifier.padding(top = 46.sp.toDp()), contentAlignment = Alignment.Center ) { chatStatusImage() @@ -364,13 +349,13 @@ fun ChatPreviewView( @Composable fun IncognitoIcon(incognito: Boolean) { if (incognito) { - val sp21 = with(LocalDensity.current) { 21.sp.toDp() } Icon( painterResource(MR.images.ic_theater_comedy), contentDescription = null, tint = MaterialTheme.colors.secondary, modifier = Modifier - .size(sp21) + .size(21.sp.toDp()) + .offset(x = 1.sp.toDp()) ) } } @@ -388,6 +373,23 @@ fun unreadCountStr(n: Int): String { return if (n < 1000) "$n" else "${n / 1000}" + stringResource(MR.strings.thousand_abbreviation) } +@Composable fun ChatListTimestampView(ts: String) { + Box(contentAlignment = Alignment.BottomStart) { + // This should be the same font style as in title to make date located on the same line as title + Text( + " ", + style = MaterialTheme.typography.h3, + fontWeight = FontWeight.Bold, + ) + Text( + ts, + Modifier.padding(bottom = 5.sp.toDp()).offset(x = if (appPlatform.isDesktop) 1.5.sp.toDp() else 0.dp), + color = MaterialTheme.colors.secondary, + style = MaterialTheme.typography.body2.copy(fontSize = 13.sp), + ) + } +} + @Preview/*( uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ContactConnectionView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ContactConnectionView.kt index 99d6c5db15..349f1f12d4 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ContactConnectionView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ContactConnectionView.kt @@ -1,5 +1,6 @@ package chat.simplex.common.views.chatlist +import androidx.compose.foundation.background import androidx.compose.foundation.layout.* import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -7,25 +8,26 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.common.ui.theme.* -import chat.simplex.common.views.helpers.ProfileImage import chat.simplex.common.model.PendingContactConnection import chat.simplex.common.model.getTimestampText +import chat.simplex.common.views.helpers.* import chat.simplex.res.MR @Composable fun ContactConnectionView(contactConnection: PendingContactConnection) { Row { - Box(Modifier.size(72.dp), contentAlignment = Alignment.Center) { - ProfileImage(size = 54.dp, null, if (contactConnection.initiated) MR.images.ic_add_link else MR.images.ic_link) + Box(Modifier.size(72.dp * fontSizeSqrtMultiplier), contentAlignment = Alignment.Center) { + ProfileImage(size = 54.dp * fontSizeSqrtMultiplier, null, if (contactConnection.initiated) MR.images.ic_add_link else MR.images.ic_link) } Column( modifier = Modifier - .padding(horizontal = 8.dp) + .padding(start = 8.dp / fontSizeSqrtMultiplier, end = 8.sp.toDp()) .weight(1F) ) { Text( @@ -36,21 +38,25 @@ fun ContactConnectionView(contactConnection: PendingContactConnection) { fontWeight = FontWeight.Bold, color = MaterialTheme.colors.secondary ) - val height = with(LocalDensity.current) { 46.sp.toDp() } - Text(contactConnection.description, Modifier.heightIn(min = height), maxLines = 2, color = if (isInDarkTheme()) MessagePreviewDark else MessagePreviewLight) + Text( + contactConnection.description, + Modifier.heightIn(min = 46.sp.toDp()).padding(top = 3.sp.toDp()), + maxLines = 2, + style = TextStyle( + fontFamily = Inter, + fontSize = 15.sp, + color = if (isInDarkTheme()) MessagePreviewDark else MessagePreviewLight, + lineHeight = 21.sp + ) + ) } Box( contentAlignment = Alignment.TopEnd ) { val ts = getTimestampText(contactConnection.updatedAt) - Text( - ts, - color = MaterialTheme.colors.secondary, - style = MaterialTheme.typography.body2, - modifier = Modifier.padding(bottom = 5.dp) - ) + ChatListTimestampView(ts) Box( - Modifier.padding(top = 50.dp), + Modifier.padding(top = 50.sp.toDp()), contentAlignment = Alignment.Center ) { IncognitoIcon(contactConnection.incognito) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ContactRequestView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ContactRequestView.kt index 8debcce98c..901761f65c 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ContactRequestView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ContactRequestView.kt @@ -6,24 +6,25 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.TextStyle import dev.icerock.moko.resources.compose.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import chat.simplex.common.ui.theme.* -import chat.simplex.common.views.helpers.ChatInfoImage import chat.simplex.common.model.ChatInfo import chat.simplex.common.model.getTimestampText +import chat.simplex.common.views.helpers.* import chat.simplex.res.MR @Composable fun ContactRequestView(contactRequest: ChatInfo.ContactRequest) { Row { - ChatInfoImage(contactRequest, size = 72.dp) + ChatInfoImage(contactRequest, size = 72.dp * fontSizeSqrtMultiplier) Column( modifier = Modifier - .padding(horizontal = 8.dp) + .padding(start = 8.dp, end = 8.sp.toDp()) .weight(1F) ) { Text( @@ -32,21 +33,21 @@ fun ContactRequestView(contactRequest: ChatInfo.ContactRequest) { overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.h3, fontWeight = FontWeight.Bold, - color = MaterialTheme.colors.primary + color = MaterialTheme.colors.primary, + ) + Text( + stringResource(MR.strings.contact_wants_to_connect_with_you), + Modifier.heightIn(min = 46.sp.toDp()).padding(top = 3.sp.toDp()), + maxLines = 2, + style = TextStyle( + fontFamily = Inter, + fontSize = 15.sp, + color = if (isInDarkTheme()) MessagePreviewDark else MessagePreviewLight, + lineHeight = 21.sp + ) ) - val height = with(LocalDensity.current) { 46.sp.toDp() } - Text(stringResource(MR.strings.contact_wants_to_connect_with_you), Modifier.heightIn(min = height), maxLines = 2, color = if (isInDarkTheme()) MessagePreviewDark else MessagePreviewLight) } val ts = getTimestampText(contactRequest.contactRequest.updatedAt) - Column( - Modifier.fillMaxHeight(), - ) { - Text( - ts, - color = MaterialTheme.colors.secondary, - style = MaterialTheme.typography.body2, - modifier = Modifier.padding(bottom = 5.dp) - ) - } + ChatListTimestampView(ts) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt index 8199a3f2d6..f79ff441d3 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt @@ -284,7 +284,7 @@ fun UserProfilePickerItem( Text( unreadCountStr(unreadCount), color = Color.White, - fontSize = 11.sp, + fontSize = 10.sp, modifier = Modifier .background(MaterialTheme.colors.primaryVariant, shape = CircleShape) .padding(2.dp) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt index 3d57f0f8b7..ea692a9724 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/ChatInfoImage.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.* import androidx.compose.ui.layout.ContentScale @@ -27,7 +28,7 @@ import dev.icerock.moko.resources.ImageResource import kotlin.math.max @Composable -fun ChatInfoImage(chatInfo: ChatInfo, size: Dp, iconColor: Color = MaterialTheme.colors.secondaryVariant) { +fun ChatInfoImage(chatInfo: ChatInfo, size: Dp, iconColor: Color = MaterialTheme.colors.secondaryVariant, shadow: Boolean = false) { val icon = when (chatInfo) { is ChatInfo.Group -> MR.images.ic_supervised_user_circle_filled diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt index ccef86c343..cc4194d0c8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt @@ -529,6 +529,12 @@ val fontSizeSqrtMultiplier: Float val desktopDensityScaleMultiplier: Float @Composable get() = if (appPlatform.isDesktop) remember { appPrefs.densityScale.state }.value else 1f +@Composable +fun TextUnit.toDp(): Dp { + check(type == TextUnitType.Sp) { "Only Sp can convert to Px" } + return Dp(value * LocalDensity.current.fontScale) +} + @Composable fun DisposableEffectOnGone(always: () -> Unit = {}, whenDispose: () -> Unit = {}, whenGone: () -> Unit) { DisposableEffect(Unit) {