Show member labels in conversation settings.

This commit is contained in:
jeffrey-signal
2026-02-09 13:09:46 -05:00
committed by Greyson Parrelli
parent 0199cd24ef
commit d7b7727aa6
13 changed files with 252 additions and 92 deletions

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2026 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.groups.memberlabel
import androidx.annotation.ColorInt
/**
* A member's custom label within a group.
*/
data class MemberLabel(
val emoji: String?,
val text: String
)
data class StyledMemberLabel(
val label: MemberLabel,
@param:ColorInt val tintColor: Int
)

View File

@@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import org.signal.core.ui.compose.DayNightPreviews
import org.signal.core.ui.compose.Previews
@@ -66,7 +67,8 @@ fun MemberLabelPill(
text = text,
color = textColor,
style = textStyle,
maxLines = 1
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}

View File

@@ -8,12 +8,18 @@ package org.thoughtcrime.securesms.groups.memberlabel
import android.content.Context
import android.util.AttributeSet
import androidx.annotation.ColorInt
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.AbstractComposeView
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
/**
* @see MemberLabelPill
@@ -26,6 +32,8 @@ class MemberLabelPillView : AbstractComposeView {
private var memberLabel: MemberLabel? by mutableStateOf(null)
private var tintColor: Color by mutableStateOf(Color.Unspecified)
var style: Style by mutableStateOf(Style())
fun setLabel(label: MemberLabel, tintColor: Color) {
this.memberLabel = label
this.tintColor = tintColor
@@ -42,8 +50,16 @@ class MemberLabelPillView : AbstractComposeView {
MemberLabelPill(
emoji = label.emoji,
text = label.text,
tintColor = tintColor
tintColor = tintColor,
modifier = Modifier.padding(horizontal = style.horizontalPadding, vertical = style.verticalPadding),
textStyle = style.textStyle()
)
}
}
data class Style(
val horizontalPadding: Dp = 12.dp,
val verticalPadding: Dp = 2.dp,
val textStyle: @Composable () -> TextStyle = { MaterialTheme.typography.bodyLarge }
)
}

View File

@@ -59,6 +59,27 @@ class MemberLabelRepository private constructor(
return@withContext groupRecord.requireV2GroupProperties().memberLabel(aci)
}
/**
* Gets member labels for a list of recipients in a group.
*
* Returns a map of [RecipientId] to [MemberLabel] for members that have labels.
*/
suspend fun getLabels(groupId: GroupId.V2, recipients: List<Recipient>): Map<RecipientId, MemberLabel> = withContext(Dispatchers.IO) {
if (!RemoteConfig.receiveMemberLabels) {
return@withContext emptyMap()
}
val groupRecord = groupsTable.getGroup(groupId).orNull() ?: return@withContext emptyMap()
val labelsByAci = groupRecord.requireV2GroupProperties().memberLabelsByAci()
buildMap {
recipients.forEach { recipient ->
val aci = recipient.serviceId.orNull() as? ServiceId.ACI
labelsByAci[aci]?.let { label -> put(recipient.id, label) }
}
}
}
/**
* Sets the group member label for the current user.
*/
@@ -70,11 +91,3 @@ class MemberLabelRepository private constructor(
GroupManager.updateMemberLabel(context, groupId, label.text, label.emoji.orEmpty())
}
}
/**
* A member's custom label within a group.
*/
data class MemberLabel(
val emoji: String?,
val text: String
)