diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt index 366ce13847..4211ebd4b7 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt @@ -470,6 +470,21 @@ object ChatModel { // update current chat return if (chatId.value == groupInfo.id) { val memberIndex = groupMembersIndexes[member.groupMemberId] + val updated = chatItems.value.map { + // Take into account only specific changes, not all. Other member updates are not important and can be skipped + if (it.chatDir is CIDirection.GroupRcv && it.chatDir.groupMember.groupMemberId == member.groupMemberId && + (it.chatDir.groupMember.image != member.image || + it.chatDir.groupMember.chatViewName != member.chatViewName || + it.chatDir.groupMember.blocked != member.blocked || + it.chatDir.groupMember.memberRole != member.memberRole) + ) + it.copy(chatDir = CIDirection.GroupRcv(member)) + else + it + } + if (updated != chatItems.value) { + chatItems.replaceAll(updated) + } if (memberIndex != null) { groupMembers[memberIndex] = member false diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt index 797d8e66b8..c7df983324 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatItemInfoView.kt @@ -28,6 +28,7 @@ import chat.simplex.common.views.chat.item.ItemAction import chat.simplex.common.views.chat.item.MarkdownText import chat.simplex.common.views.helpers.* import chat.simplex.common.ui.theme.* +import chat.simplex.common.views.chat.group.MemberProfileImage import chat.simplex.common.views.chatlist.* import chat.simplex.res.MR import dev.icerock.moko.resources.ImageResource @@ -334,7 +335,7 @@ fun ChatItemInfoView(chatRh: Long?, ci: ChatItem, ciInfo: ChatItemInfo, devTools SectionItemView( padding = PaddingValues(horizontal = 0.dp) ) { - ProfileImage(size = 36.dp, member.image) + MemberProfileImage(size = 36.dp, member) Spacer(Modifier.width(DEFAULT_SPACE_AFTER_ICON)) Text( member.chatViewName, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt index c65aaabc02..c0a7775040 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt @@ -1387,7 +1387,7 @@ val MEMBER_IMAGE_SIZE: Dp = 38.dp @Composable fun MemberImage(member: GroupMember) { - ProfileImage(MEMBER_IMAGE_SIZE * fontSizeSqrtMultiplier, member.memberProfile.image, backgroundColor = MaterialTheme.colors.background) + MemberProfileImage(MEMBER_IMAGE_SIZE * fontSizeSqrtMultiplier, member, backgroundColor = MaterialTheme.colors.background) } @Composable diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt index 1f63e61a02..5d69972886 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupChatInfoView.kt @@ -487,7 +487,7 @@ private fun MemberRow(member: GroupMember, user: Boolean = false, onClick: (() - verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp) ) { - ProfileImage(size = 46.dp, member.image) + MemberProfileImage(size = 46.dp, member) Spacer(Modifier.width(DEFAULT_PADDING_HALF)) Column { Row(verticalAlignment = Alignment.CenterVertically) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt index 7a087a9263..4e84b1b651 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/GroupMemberInfoView.kt @@ -25,8 +25,7 @@ import dev.icerock.moko.resources.compose.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp +import androidx.compose.ui.unit.* import chat.simplex.common.model.* import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.model.ChatModel.withChats @@ -495,7 +494,7 @@ fun GroupMemberInfoHeader(member: GroupMember) { Modifier.padding(horizontal = 16.dp), horizontalAlignment = Alignment.CenterHorizontally ) { - ProfileImage(size = 192.dp, member.image, color = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight) + MemberProfileImage(size = 192.dp, member, color = if (isInDarkTheme()) GroupDark else SettingsSecondaryLight) val text = buildAnnotatedString { if (member.verified) { appendInlineContent(id = "shieldIcon") @@ -625,6 +624,22 @@ private fun RoleSelectionRow( } } +@Composable +fun MemberProfileImage( + size: Dp, + mem: GroupMember, + color: Color = MaterialTheme.colors.secondaryVariant, + backgroundColor: Color? = null +) { + ProfileImage( + size = size, + image = mem.image, + color = color, + backgroundColor = backgroundColor, + blurred = mem.blocked + ) +} + private fun updateMemberRoleDialog( newRole: GroupMemberRole, member: GroupMember, 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 ea692a9724..1289687601 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 @@ -11,8 +11,7 @@ import androidx.compose.runtime.Composable 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.draw.* import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.* import androidx.compose.ui.layout.ContentScale @@ -55,7 +54,8 @@ fun ProfileImage( image: String? = null, icon: ImageResource = MR.images.ic_account_circle_filled, color: Color = MaterialTheme.colors.secondaryVariant, - backgroundColor: Color? = null + backgroundColor: Color? = null, + blurred: Boolean = false ) { Box(Modifier.size(size)) { if (image == null) { @@ -88,7 +88,7 @@ fun ProfileImage( imageBitmap, stringResource(MR.strings.image_descr_profile_image), contentScale = ContentScale.Crop, - modifier = ProfileIconModifier(size) + modifier = ProfileIconModifier(size, blurred = blurred) ) } } @@ -109,12 +109,12 @@ private const val squareToCircleRatio = 0.935f private const val radiusFactor = (1 - squareToCircleRatio) / 50 @Composable -fun ProfileIconModifier(size: Dp, padding: Boolean = true): Modifier { +fun ProfileIconModifier(size: Dp, padding: Boolean = true, blurred: Boolean = false): Modifier { val percent = remember { appPreferences.profileImageCornerRadius.state } val r = max(0f, percent.value) val pad = if (padding) size / 12 else 0.dp val m = Modifier.size(size) - return when { + val m1 = when { r >= 50 -> m.padding(pad).clip(CircleShape) r <= 0 -> { @@ -126,6 +126,7 @@ fun ProfileIconModifier(size: Dp, padding: Boolean = true): Modifier { m.padding((size - sz) / 2).clip(RoundedCornerShape(size = sz * r / 100)) } } + return if (blurred) m1.blur(size / 4) else m1 } /** [AccountCircleFilled] has its inner padding which leads to visible border if there is background underneath.