mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-20 08:39:22 +01:00
Separate v1 and v2 colorizer implementations.
This commit is contained in:
committed by
Cody Henthorne
parent
a8a6fec19d
commit
0b8e8a7b2f
@@ -46,7 +46,7 @@ import org.signal.paging.PagingController;
|
||||
import org.thoughtcrime.securesms.BindableConversationItem;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizable;
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer;
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerV1;
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart;
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
@@ -113,7 +113,7 @@ public class ConversationAdapter
|
||||
private boolean hasWallpaper;
|
||||
private boolean isMessageRequestAccepted;
|
||||
private ConversationMessage inlineContent;
|
||||
private Colorizer colorizer;
|
||||
private ColorizerV1 colorizer;
|
||||
private boolean isTypingViewEnabled;
|
||||
private ConversationItemDisplayMode displayMode;
|
||||
private PulseRequest pulseRequest;
|
||||
@@ -124,7 +124,7 @@ public class ConversationAdapter
|
||||
@NonNull Locale locale,
|
||||
@Nullable ItemClickListener clickListener,
|
||||
boolean hasWallpaper,
|
||||
@NonNull Colorizer colorizer)
|
||||
@NonNull ColorizerV1 colorizer)
|
||||
{
|
||||
super(new DiffUtil.ItemCallback<ConversationMessage>() {
|
||||
@Override
|
||||
|
||||
@@ -19,7 +19,7 @@ import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.recyclerview.SmoothScrollingLinearLayoutManager
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerV1
|
||||
import org.thoughtcrime.securesms.conversation.colors.RecyclerViewColorizer
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
@@ -74,7 +74,8 @@ class PinnedMessagesBottomSheet : FixedRoundedCornerBottomSheetDialogFragment()
|
||||
val conversationRecipientId = RecipientId.from(arguments?.getString(KEY_CONVERSATION_RECIPIENT_ID, null) ?: throw IllegalArgumentException())
|
||||
val conversationRecipient = Recipient.resolved(conversationRecipientId)
|
||||
|
||||
val colorizer = Colorizer()
|
||||
@Suppress("DEPRECATION")
|
||||
val colorizer = ColorizerV1()
|
||||
|
||||
messageAdapter = ConversationAdapter(requireContext(), viewLifecycleOwner, Glide.with(this), Locale.getDefault(), ConversationAdapterListener(), conversationRecipient.hasWallpaper, colorizer).apply {
|
||||
setCondensedMode(ConversationItemDisplayMode.Condensed(ConversationItemDisplayMode.MessageMode.PINNED))
|
||||
|
||||
@@ -29,7 +29,7 @@ import org.thoughtcrime.securesms.components.SignalProgressDialog
|
||||
import org.thoughtcrime.securesms.components.menu.ActionItem
|
||||
import org.thoughtcrime.securesms.components.menu.SignalContextMenu
|
||||
import org.thoughtcrime.securesms.components.recyclerview.SmoothScrollingLinearLayoutManager
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerV1
|
||||
import org.thoughtcrime.securesms.conversation.colors.RecyclerViewColorizer
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart.Attachments
|
||||
@@ -93,7 +93,8 @@ class ScheduledMessagesBottomSheet : FixedRoundedCornerBottomSheetDialogFragment
|
||||
return
|
||||
}
|
||||
|
||||
val colorizer = Colorizer()
|
||||
@Suppress("DEPRECATION")
|
||||
val colorizer = ColorizerV1()
|
||||
|
||||
messageAdapter = ConversationAdapter(requireContext(), viewLifecycleOwner, Glide.with(this), Locale.getDefault(), ConversationAdapterListener(), conversationRecipient.hasWallpaper, colorizer).apply {
|
||||
setCondensedMode(ConversationItemDisplayMode.Condensed(ConversationItemDisplayMode.MessageMode.SCHEDULED))
|
||||
|
||||
@@ -11,25 +11,11 @@ import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.signal.core.ui.R as CoreUiR
|
||||
|
||||
/**
|
||||
* Helper class for all things ChatColors.
|
||||
* Provides conversation bubble and sender name colors.
|
||||
*
|
||||
* - Maintains a mapping for group recipient colors
|
||||
* - Gives easy access to different bubble colors
|
||||
* - Watches and responds to RecyclerView scroll and layout changes to update a ColorizerView
|
||||
* Use [ColorizerV2] for new CFv2 code, and [ColorizerV1] for legacy CFv1 code.
|
||||
*/
|
||||
class Colorizer @JvmOverloads constructor(groupMemberIds: List<ServiceId> = emptyList()) {
|
||||
|
||||
private var colorsHaveBeenSet = false
|
||||
|
||||
@Deprecated("Not needed for CFv2")
|
||||
private val groupSenderColors: MutableMap<RecipientId, NameColor> = mutableMapOf()
|
||||
|
||||
private val groupMembers: LinkedHashSet<ServiceId> = linkedSetOf()
|
||||
|
||||
init {
|
||||
onGroupMembershipChanged(groupMemberIds)
|
||||
}
|
||||
|
||||
interface Colorizer {
|
||||
@ColorInt
|
||||
fun getOutgoingBodyTextColor(context: Context): Int {
|
||||
return ContextCompat.getColor(context, R.color.conversation_outgoing_body_color)
|
||||
@@ -77,42 +63,90 @@ class Colorizer @JvmOverloads constructor(groupMemberIds: List<ServiceId> = empt
|
||||
return getNameColor(context, recipient).getColor(context)
|
||||
}
|
||||
|
||||
fun onGroupMembershipChanged(serviceIds: List<ServiceId>) {
|
||||
groupMembers.addAll(serviceIds.sortedBy { it.toString() })
|
||||
}
|
||||
fun getNameColor(context: Context, recipient: Recipient): NameColor
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
fun getNameColor(context: Context, recipient: Recipient): NameColor {
|
||||
if (groupMembers.isEmpty()) {
|
||||
return groupSenderColors[recipient.id] ?: getDefaultColor(context, recipient)
|
||||
}
|
||||
/**
|
||||
* [Colorizer] implementation for CFv1 (legacy ConversationFragment).
|
||||
*
|
||||
* Colors are pre-assigned via [onNameColorsChanged] using a static [RecipientId] → [NameColor] map.
|
||||
*
|
||||
* See [ColorizerV2] for the CFv2 position-based approach.
|
||||
*/
|
||||
@Deprecated("Use ColorizerV2 instead. This class only exists to support the legacy CFv1.")
|
||||
class ColorizerV1 : Colorizer {
|
||||
private var colorsHaveBeenSet = false
|
||||
private val groupSenderColors: MutableMap<RecipientId, NameColor> = mutableMapOf()
|
||||
|
||||
val serviceId = recipient.serviceId.orNull()
|
||||
if (serviceId != null) {
|
||||
val position = groupMembers.indexOf(serviceId)
|
||||
if (position >= 0) {
|
||||
return ChatColorsPalette.Names.all[position % ChatColorsPalette.Names.all.size]
|
||||
}
|
||||
}
|
||||
return getDefaultColor(context, recipient)
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated("Not needed for CFv2", ReplaceWith("onGroupMembershipChanged"))
|
||||
/**
|
||||
* Replaces the entire mapping of group member IDs to name colors.
|
||||
*
|
||||
* Must be called before [getNameColor] to ensure colors are assigned correctly.
|
||||
*/
|
||||
fun onNameColorsChanged(nameColorMap: Map<RecipientId, NameColor>) {
|
||||
groupSenderColors.clear()
|
||||
groupSenderColors.putAll(nameColorMap)
|
||||
colorsHaveBeenSet = true
|
||||
}
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
private fun getDefaultColor(context: Context, recipient: Recipient): NameColor {
|
||||
return if (colorsHaveBeenSet) {
|
||||
ChatColorsPalette.Names.all[groupSenderColors.size % ChatColorsPalette.Names.all.size]
|
||||
/**
|
||||
* Returns the name color for the given recipient based on their position in the group member list.
|
||||
*/
|
||||
override fun getNameColor(context: Context, recipient: Recipient): NameColor {
|
||||
val assignedColor = groupSenderColors[recipient.id]
|
||||
if (assignedColor != null) return assignedColor
|
||||
|
||||
if (colorsHaveBeenSet) {
|
||||
return nameColorForPosition(groupSenderColors.size)
|
||||
.also { groupSenderColors[recipient.id] = it }
|
||||
} else {
|
||||
val colorInt = getIncomingBodyTextColor(context, recipient.hasWallpaper)
|
||||
NameColor(lightColor = colorInt, darkColor = colorInt)
|
||||
}
|
||||
|
||||
val colorInt = getIncomingBodyTextColor(context, recipient.hasWallpaper)
|
||||
return NameColor(lightColor = colorInt, darkColor = colorInt)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [Colorizer] implementation for CFv2 (ConversationFragment v2).
|
||||
*
|
||||
* Colors are derived from each member's sorted position in the group, populated via
|
||||
* [onGroupMembershipChanged]. For the legacy CFv1 approach, see [ColorizerV1].
|
||||
*/
|
||||
class ColorizerV2 @JvmOverloads constructor(groupMemberIds: List<ServiceId> = emptyList()) : Colorizer {
|
||||
private val groupMembers: LinkedHashSet<ServiceId> = linkedSetOf()
|
||||
|
||||
init {
|
||||
onGroupMembershipChanged(groupMemberIds)
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the entire set of group members used for position-based name color assignment.
|
||||
*
|
||||
* Must be called before [getNameColor] to ensure colors are assigned correctly.
|
||||
*/
|
||||
fun onGroupMembershipChanged(serviceIds: List<ServiceId>) {
|
||||
groupMembers.addAll(serviceIds.sortedBy { it.toString() })
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the [NameColor] for the given [recipient] based on their sorted position among the
|
||||
* other group members supplied via [onGroupMembershipChanged].
|
||||
*
|
||||
* Falls back to a default text color if the recipient has no service ID or is not
|
||||
* found in the current membership set.
|
||||
*/
|
||||
override fun getNameColor(context: Context, recipient: Recipient): NameColor {
|
||||
val serviceId = recipient.serviceId.orNull()
|
||||
if (serviceId != null) {
|
||||
val position = groupMembers.indexOf(serviceId)
|
||||
if (position >= 0) return nameColorForPosition(position)
|
||||
}
|
||||
|
||||
val colorInt = getIncomingBodyTextColor(context, recipient.hasWallpaper)
|
||||
return NameColor(lightColor = colorInt, darkColor = colorInt)
|
||||
}
|
||||
}
|
||||
|
||||
private fun nameColorForPosition(position: Int): NameColor {
|
||||
return ChatColorsPalette.Names.all[position % ChatColorsPalette.Names.all.size]
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.components.DeliveryStatusView
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerV2
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerView
|
||||
import org.thoughtcrime.securesms.util.DateUtils
|
||||
import org.thoughtcrime.securesms.util.Projection
|
||||
@@ -101,7 +102,7 @@ class ChatColorPreviewView @JvmOverloads constructor(
|
||||
wallpaper = findViewById(R.id.wallpaper)
|
||||
wallpaperDim = findViewById(R.id.wallpaper_dim)
|
||||
colorizerView = findViewById(R.id.colorizer)
|
||||
colorizer = Colorizer()
|
||||
colorizer = ColorizerV2()
|
||||
} finally {
|
||||
typedArray?.recycle()
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import org.thoughtcrime.securesms.conversation.ConversationAdapterBridge
|
||||
import org.thoughtcrime.securesms.conversation.ConversationBottomSheetCallback
|
||||
import org.thoughtcrime.securesms.conversation.ConversationItemDisplayMode
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerV1
|
||||
import org.thoughtcrime.securesms.conversation.colors.RecyclerViewColorizer
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
@@ -74,7 +74,8 @@ class MessageQuotesBottomSheet : FixedRoundedCornerBottomSheetDialogFragment() {
|
||||
val conversationRecipientId = RecipientId.from(arguments?.getString(KEY_CONVERSATION_RECIPIENT_ID, null) ?: throw IllegalArgumentException())
|
||||
val conversationRecipient = Recipient.resolved(conversationRecipientId)
|
||||
|
||||
val colorizer = Colorizer()
|
||||
@Suppress("DEPRECATION")
|
||||
val colorizer = ColorizerV1()
|
||||
|
||||
messageAdapter = ConversationAdapter(requireContext(), viewLifecycleOwner, Glide.with(this), Locale.getDefault(), ConversationAdapterListener(), conversationRecipient.hasWallpaper, colorizer).apply {
|
||||
setCondensedMode(ConversationItemDisplayMode.Condensed(ConversationItemDisplayMode.MessageMode.STANDARD))
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.thoughtcrime.securesms.conversation.ConversationAdapterBridge
|
||||
import org.thoughtcrime.securesms.conversation.ConversationBottomSheetCallback
|
||||
import org.thoughtcrime.securesms.conversation.ConversationItemDisplayMode
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerV1
|
||||
import org.thoughtcrime.securesms.conversation.colors.RecyclerViewColorizer
|
||||
import org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart
|
||||
import org.thoughtcrime.securesms.conversation.quotes.OriginalMessageSeparatorDecoration
|
||||
@@ -83,7 +83,8 @@ class EditMessageHistoryDialog : FixedRoundedCornerBottomSheetDialogFragment() {
|
||||
|
||||
disposables.bindTo(viewLifecycleOwner)
|
||||
|
||||
val colorizer = Colorizer()
|
||||
@Suppress("DEPRECATION")
|
||||
val colorizer = ColorizerV1()
|
||||
|
||||
val messageAdapter = ConversationAdapter(
|
||||
requireContext(),
|
||||
|
||||
@@ -210,7 +210,7 @@ import org.thoughtcrime.securesms.conversation.SelectedConversationModel
|
||||
import org.thoughtcrime.securesms.conversation.ShowAdminsBottomSheetDialog
|
||||
import org.thoughtcrime.securesms.conversation.clicklisteners.PollVotesFragment
|
||||
import org.thoughtcrime.securesms.conversation.colors.ChatColors
|
||||
import org.thoughtcrime.securesms.conversation.colors.Colorizer
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerV2
|
||||
import org.thoughtcrime.securesms.conversation.colors.RecyclerViewColorizer
|
||||
import org.thoughtcrime.securesms.conversation.drafts.DraftRepository
|
||||
import org.thoughtcrime.securesms.conversation.drafts.DraftRepository.ShareOrDraftData
|
||||
@@ -535,7 +535,7 @@ class ConversationFragment :
|
||||
}
|
||||
|
||||
private val conversationTooltips = ConversationTooltips(this)
|
||||
private val colorizer = Colorizer()
|
||||
private val colorizer = ColorizerV2()
|
||||
private val textDraftSaveDebouncer = Debouncer(500)
|
||||
private val doubleTapToEditDebouncer = DoubleClickDebouncer(200)
|
||||
private val recentEmojis: RecentEmojiPageModel by lazy { RecentEmojiPageModel(AppDependencies.application, TextSecurePreferences.RECENT_STORAGE_KEY) }
|
||||
|
||||
Reference in New Issue
Block a user