android, desktop: blur images of blocked group members (#4579)

* android, desktop: blur images of blocked group members

* simplify

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
Stanislav Dmitrenko
2024-08-05 23:01:50 +09:00
committed by GitHub
parent 55331289d3
commit b04f159970
6 changed files with 44 additions and 12 deletions

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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) {

View File

@@ -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,

View File

@@ -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.