mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-05-04 07:25:25 +01:00
Update group terminated banner.
This commit is contained in:
@@ -73,7 +73,6 @@ import org.thoughtcrime.securesms.components.settings.conversation.preferences.L
|
|||||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.LegacyGroupPreference
|
import org.thoughtcrime.securesms.components.settings.conversation.preferences.LegacyGroupPreference
|
||||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.RecipientPreference
|
import org.thoughtcrime.securesms.components.settings.conversation.preferences.RecipientPreference
|
||||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.SharedMediaPreference
|
import org.thoughtcrime.securesms.components.settings.conversation.preferences.SharedMediaPreference
|
||||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.TerminatedBannerPreference
|
|
||||||
import org.thoughtcrime.securesms.components.settings.conversation.preferences.Utils.formatMutedUntil
|
import org.thoughtcrime.securesms.components.settings.conversation.preferences.Utils.formatMutedUntil
|
||||||
import org.thoughtcrime.securesms.conversation.ConversationIntents
|
import org.thoughtcrime.securesms.conversation.ConversationIntents
|
||||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerV2
|
import org.thoughtcrime.securesms.conversation.colors.ColorizerV2
|
||||||
@@ -306,7 +305,6 @@ class ConversationSettingsFragment :
|
|||||||
InternalPreference.register(adapter)
|
InternalPreference.register(adapter)
|
||||||
GroupDescriptionPreference.register(adapter)
|
GroupDescriptionPreference.register(adapter)
|
||||||
LegacyGroupPreference.register(adapter)
|
LegacyGroupPreference.register(adapter)
|
||||||
TerminatedBannerPreference.register(adapter)
|
|
||||||
CallPreference.register(adapter)
|
CallPreference.register(adapter)
|
||||||
|
|
||||||
val recipientId = args.recipientId
|
val recipientId = args.recipientId
|
||||||
@@ -369,17 +367,10 @@ class ConversationSettingsFragment :
|
|||||||
return@configure
|
return@configure
|
||||||
}
|
}
|
||||||
|
|
||||||
state.withGroupSettingsState {
|
|
||||||
if (it.isTerminated) {
|
|
||||||
customPref(TerminatedBannerPreference.Model())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
customPref(
|
customPref(
|
||||||
AvatarPreference.Model(
|
AvatarPreference.Model(
|
||||||
recipient = state.recipient,
|
recipient = state.recipient,
|
||||||
storyViewState = state.storyViewState,
|
storyViewState = state.storyViewState,
|
||||||
reduceTopMargin = state.isTerminatedGroup,
|
|
||||||
onAvatarClick = { avatar ->
|
onAvatarClick = { avatar ->
|
||||||
val viewAvatarIntent = AvatarPreviewActivity.intentFromRecipientId(requireContext(), state.recipient.id)
|
val viewAvatarIntent = AvatarPreviewActivity.intentFromRecipientId(requireContext(), state.recipient.id)
|
||||||
val viewAvatarTransitionBundle = AvatarPreviewActivity.createTransitionBundle(requireActivity(), avatar)
|
val viewAvatarTransitionBundle = AvatarPreviewActivity.createTransitionBundle(requireActivity(), avatar)
|
||||||
@@ -434,7 +425,8 @@ class ConversationSettingsFragment :
|
|||||||
customPref(
|
customPref(
|
||||||
BioTextPreference.GroupModel(
|
BioTextPreference.GroupModel(
|
||||||
groupTitle = groupState.groupTitle,
|
groupTitle = groupState.groupTitle,
|
||||||
groupMembershipDescription = groupMembershipDescription
|
groupMembershipDescription = groupMembershipDescription,
|
||||||
|
isTerminated = groupState.isTerminated
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package org.thoughtcrime.securesms.components.settings.conversation.preferences
|
package org.thoughtcrime.securesms.components.settings.conversation.preferences
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
import org.signal.core.util.dp
|
|
||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
import org.thoughtcrime.securesms.avatar.view.AvatarView
|
import org.thoughtcrime.securesms.avatar.view.AvatarView
|
||||||
import org.thoughtcrime.securesms.badges.BadgeImageView
|
import org.thoughtcrime.securesms.badges.BadgeImageView
|
||||||
@@ -27,7 +25,6 @@ object AvatarPreference {
|
|||||||
class Model(
|
class Model(
|
||||||
val recipient: Recipient,
|
val recipient: Recipient,
|
||||||
val storyViewState: StoryViewState,
|
val storyViewState: StoryViewState,
|
||||||
val reduceTopMargin: Boolean = false,
|
|
||||||
val onAvatarClick: (AvatarView) -> Unit,
|
val onAvatarClick: (AvatarView) -> Unit,
|
||||||
val onBadgeClick: (Badge) -> Unit
|
val onBadgeClick: (Badge) -> Unit
|
||||||
) : PreferenceModel<Model>() {
|
) : PreferenceModel<Model>() {
|
||||||
@@ -38,8 +35,7 @@ object AvatarPreference {
|
|||||||
override fun areContentsTheSame(newItem: Model): Boolean {
|
override fun areContentsTheSame(newItem: Model): Boolean {
|
||||||
return super.areContentsTheSame(newItem) &&
|
return super.areContentsTheSame(newItem) &&
|
||||||
recipient.hasSameContent(newItem.recipient) &&
|
recipient.hasSameContent(newItem.recipient) &&
|
||||||
storyViewState == newItem.storyViewState &&
|
storyViewState == newItem.storyViewState
|
||||||
reduceTopMargin == newItem.reduceTopMargin
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,10 +49,6 @@ object AvatarPreference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun bind(model: Model) {
|
override fun bind(model: Model) {
|
||||||
(itemView.layoutParams as? ViewGroup.MarginLayoutParams)?.let {
|
|
||||||
it.topMargin = if (model.reduceTopMargin) 0.dp else 40.dp
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model.recipient.isSelf) {
|
if (model.recipient.isSelf) {
|
||||||
badge.setBadge(null)
|
badge.setBadge(null)
|
||||||
badge.setOnClickListener(null)
|
badge.setOnClickListener(null)
|
||||||
|
|||||||
@@ -2,11 +2,13 @@ package org.thoughtcrime.securesms.components.settings.conversation.preferences
|
|||||||
|
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.text.SpannableStringBuilder
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import org.thoughtcrime.securesms.R
|
import org.thoughtcrime.securesms.R
|
||||||
import org.thoughtcrime.securesms.components.settings.PreferenceModel
|
import org.thoughtcrime.securesms.components.settings.PreferenceModel
|
||||||
|
import org.thoughtcrime.securesms.fonts.SignalSymbols
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil
|
import org.thoughtcrime.securesms.util.ServiceUtil
|
||||||
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
|
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
|
||||||
@@ -61,7 +63,8 @@ object BioTextPreference {
|
|||||||
|
|
||||||
class GroupModel(
|
class GroupModel(
|
||||||
val groupTitle: String,
|
val groupTitle: String,
|
||||||
val groupMembershipDescription: String?
|
val groupMembershipDescription: String?,
|
||||||
|
val isTerminated: Boolean = false
|
||||||
) : BioTextPreferenceModel<GroupModel>() {
|
) : BioTextPreferenceModel<GroupModel>() {
|
||||||
override fun getHeadlineText(context: Context): CharSequence = groupTitle
|
override fun getHeadlineText(context: Context): CharSequence = groupTitle
|
||||||
|
|
||||||
@@ -72,7 +75,8 @@ object BioTextPreference {
|
|||||||
override fun areContentsTheSame(newItem: GroupModel): Boolean {
|
override fun areContentsTheSame(newItem: GroupModel): Boolean {
|
||||||
return super.areContentsTheSame(newItem) &&
|
return super.areContentsTheSame(newItem) &&
|
||||||
groupTitle == newItem.groupTitle &&
|
groupTitle == newItem.groupTitle &&
|
||||||
groupMembershipDescription == newItem.groupMembershipDescription
|
groupMembershipDescription == newItem.groupMembershipDescription &&
|
||||||
|
isTerminated == newItem.isTerminated
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun areItemsTheSame(newItem: GroupModel): Boolean {
|
override fun areItemsTheSame(newItem: GroupModel): Boolean {
|
||||||
@@ -85,6 +89,7 @@ object BioTextPreference {
|
|||||||
private val headline: TextView = itemView.findViewById(R.id.bio_preference_headline)
|
private val headline: TextView = itemView.findViewById(R.id.bio_preference_headline)
|
||||||
private val subhead1: TextView = itemView.findViewById(R.id.bio_preference_subhead_1)
|
private val subhead1: TextView = itemView.findViewById(R.id.bio_preference_subhead_1)
|
||||||
protected val subhead2: TextView = itemView.findViewById(R.id.bio_preference_subhead_2)
|
protected val subhead2: TextView = itemView.findViewById(R.id.bio_preference_subhead_2)
|
||||||
|
private val terminatedPill: TextView = itemView.findViewById(R.id.bio_preference_terminated_pill)
|
||||||
|
|
||||||
override fun bind(model: T) {
|
override fun bind(model: T) {
|
||||||
headline.text = model.getHeadlineText(context)
|
headline.text = model.getHeadlineText(context)
|
||||||
@@ -94,6 +99,17 @@ object BioTextPreference {
|
|||||||
headline.setOnClickListener { clickListener() }
|
headline.setOnClickListener { clickListener() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (model is GroupModel && model.isTerminated) {
|
||||||
|
val glyphSpan = SignalSymbols.getSpannedString(context, SignalSymbols.Weight.REGULAR, SignalSymbols.Glyph.GROUP_X)
|
||||||
|
terminatedPill.text = SpannableStringBuilder()
|
||||||
|
.append(glyphSpan)
|
||||||
|
.append(" ")
|
||||||
|
.append(context.getString(R.string.ConversationSettingsFragment__this_group_was_ended))
|
||||||
|
terminatedPill.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
terminatedPill.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
model.getSubhead1Text(context).let {
|
model.getSubhead1Text(context).let {
|
||||||
subhead1.text = it
|
subhead1.text = it
|
||||||
subhead1.visibility = if (it == null) View.GONE else View.VISIBLE
|
subhead1.visibility = if (it == null) View.GONE else View.VISIBLE
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2025 Signal Messenger, LLC
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.thoughtcrime.securesms.components.settings.conversation.preferences
|
|
||||||
|
|
||||||
import android.view.View
|
|
||||||
import org.thoughtcrime.securesms.R
|
|
||||||
import org.thoughtcrime.securesms.components.settings.PreferenceModel
|
|
||||||
import org.thoughtcrime.securesms.util.adapter.mapping.LayoutFactory
|
|
||||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingAdapter
|
|
||||||
import org.thoughtcrime.securesms.util.adapter.mapping.MappingViewHolder
|
|
||||||
|
|
||||||
object TerminatedBannerPreference {
|
|
||||||
|
|
||||||
fun register(adapter: MappingAdapter) {
|
|
||||||
adapter.registerFactory(Model::class.java, LayoutFactory(::ViewHolder, R.layout.conversation_settings_terminated_banner))
|
|
||||||
}
|
|
||||||
|
|
||||||
class Model : PreferenceModel<Model>() {
|
|
||||||
override fun areItemsTheSame(newItem: Model): Boolean = true
|
|
||||||
override fun areContentsTheSame(newItem: Model): Boolean = true
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ViewHolder(itemView: View) : MappingViewHolder<Model>(itemView) {
|
|
||||||
override fun bind(model: Model) = Unit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3675,12 +3675,19 @@ class ConversationFragment :
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onBlockJoinRequest(recipient: Recipient) {
|
override fun onBlockJoinRequest(recipient: Recipient) {
|
||||||
|
if (conversationGroupViewModel.groupRecordSnapshot?.isTerminated == true) {
|
||||||
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
|
.setMessage(R.string.conversation_activity__group_action_not_allowed_group_ended)
|
||||||
|
.setPositiveButton(android.R.string.ok) { d, _ -> d.dismiss() }
|
||||||
|
.show()
|
||||||
|
} else {
|
||||||
MaterialAlertDialogBuilder(requireContext()).setTitle(R.string.ConversationFragment__block_request)
|
MaterialAlertDialogBuilder(requireContext()).setTitle(R.string.ConversationFragment__block_request)
|
||||||
.setMessage(getString(R.string.ConversationFragment__s_will_not_be_able_to_join_or_request_to_join_this_group_via_the_group_link, recipient.getDisplayName(requireContext())))
|
.setMessage(getString(R.string.ConversationFragment__s_will_not_be_able_to_join_or_request_to_join_this_group_via_the_group_link, recipient.getDisplayName(requireContext())))
|
||||||
.setNegativeButton(R.string.ConversationFragment__cancel, null)
|
.setNegativeButton(R.string.ConversationFragment__cancel, null)
|
||||||
.setPositiveButton(R.string.ConversationFragment__block_request_button) { _, _ -> handleBlockJoinRequest(recipient) }
|
.setPositiveButton(R.string.ConversationFragment__block_request_button) { _, _ -> handleBlockJoinRequest(recipient) }
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onRecipientNameClicked(target: RecipientId) {
|
override fun onRecipientNameClicked(target: RecipientId) {
|
||||||
context ?: return
|
context ?: return
|
||||||
|
|||||||
@@ -236,12 +236,12 @@ final class GroupsV2UpdateMessageProducer {
|
|||||||
|
|
||||||
private void describeGroupTerminateUpdate(@NonNull GroupTerminateChangeUpdate update, @NonNull List<UpdateDescription> updates) {
|
private void describeGroupTerminateUpdate(@NonNull GroupTerminateChangeUpdate update, @NonNull List<UpdateDescription> updates) {
|
||||||
if (update.updaterAci == null) {
|
if (update.updaterAci == null) {
|
||||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_was_terminated), Glyph.X_CIRCLE));
|
updates.add(updateDescription(context.getString(R.string.MessageRecord_the_group_was_terminated), Glyph.GROUP_X));
|
||||||
} else {
|
} else {
|
||||||
if (selfIds.matches(update.updaterAci)) {
|
if (selfIds.matches(update.updaterAci)) {
|
||||||
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_terminated_the_group), Glyph.X_CIRCLE));
|
updates.add(updateDescription(context.getString(R.string.MessageRecord_you_terminated_the_group), Glyph.GROUP_X));
|
||||||
} else {
|
} else {
|
||||||
updates.add(updateDescription(R.string.MessageRecord_s_terminated_the_group, update.updaterAci, Glyph.X_CIRCLE));
|
updates.add(updateDescription(R.string.MessageRecord_s_terminated_the_group, update.updaterAci, Glyph.GROUP_X));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ object SignalSymbols {
|
|||||||
GIF('\uE037'),
|
GIF('\uE037'),
|
||||||
GIF_RECTANGLE('\uE097'),
|
GIF_RECTANGLE('\uE097'),
|
||||||
GROUP('\uE038'),
|
GROUP('\uE038'),
|
||||||
|
GROUP_X('\uE0AE'),
|
||||||
HEART('\uE039'),
|
HEART('\uE039'),
|
||||||
INCOMING('\uE03A'),
|
INCOMING('\uE03A'),
|
||||||
INFO('\uE03B'),
|
INFO('\uE03B'),
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
<corners android:radius="12dp" />
|
<corners android:radius="8dp" />
|
||||||
<stroke
|
<solid android:color="@color/signal_colorSurfaceVariant" />
|
||||||
android:width="1dp"
|
|
||||||
android:color="@color/signal_colorOutline_38" />
|
|
||||||
</shape>
|
</shape>
|
||||||
@@ -20,6 +20,26 @@
|
|||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
tools:text="Miles Morales" />
|
tools:text="Miles Morales" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/bio_preference_terminated_pill"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:background="@drawable/terminated_pill_background"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingTop="6dp"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:paddingBottom="6dp"
|
||||||
|
android:textAppearance="@style/Signal.Text.BodyMedium"
|
||||||
|
android:textColor="@color/signal_colorOnSurface"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/bio_preference_headline"
|
||||||
|
tools:text="This group was ended."
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||||
android:id="@+id/bio_preference_subhead_1"
|
android:id="@+id/bio_preference_subhead_1"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@@ -33,7 +53,7 @@
|
|||||||
android:textColor="@color/signal_text_secondary"
|
android:textColor="@color/signal_text_secondary"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/bio_preference_headline"
|
app:layout_constraintTop_toBottomOf="@id/bio_preference_terminated_pill"
|
||||||
tools:text=":-) Just hanging around." />
|
tools:text=":-) Just hanging around." />
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginTop="48dp"
|
|
||||||
android:paddingStart="12dp"
|
|
||||||
android:paddingEnd="12dp"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:paddingBottom="8dp">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/terminated_banner_text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:background="@drawable/terminated_banner_background"
|
|
||||||
android:paddingStart="16dp"
|
|
||||||
android:paddingEnd="16dp"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:paddingBottom="16dp"
|
|
||||||
android:text="@string/ConversationSettingsFragment__this_group_was_ended"
|
|
||||||
android:textAppearance="@style/Signal.Text.BodyMedium"
|
|
||||||
android:textColor="@color/signal_colorOnSurface" />
|
|
||||||
|
|
||||||
</FrameLayout>
|
|
||||||
@@ -3640,7 +3640,7 @@
|
|||||||
<!-- Dialog body shown when tapping a failed message in a terminated group -->
|
<!-- Dialog body shown when tapping a failed message in a terminated group -->
|
||||||
<string name="conversation_activity__send_failed_group_ended">Send failed because the group was ended. You can no longer send and receive messages in this group.</string>
|
<string name="conversation_activity__send_failed_group_ended">Send failed because the group was ended. You can no longer send and receive messages in this group.</string>
|
||||||
<!-- Dialog body shown when tapping a group action button (e.g. invite friends) in a terminated group -->
|
<!-- Dialog body shown when tapping a group action button (e.g. invite friends) in a terminated group -->
|
||||||
<string name="conversation_activity__group_action_not_allowed_group_ended">You can no longer invite friends or add members to this group.</string>
|
<string name="conversation_activity__group_action_not_allowed_group_ended">This action is unavailable because the group has ended.</string>
|
||||||
<!-- Dialog body when a message failed to delete and retry is possible. -->
|
<!-- Dialog body when a message failed to delete and retry is possible. -->
|
||||||
<string name="conversation_activity__message_failed_to_delete_retry">Message failed to delete. Check your connection and try again.</string>
|
<string name="conversation_activity__message_failed_to_delete_retry">Message failed to delete. Check your connection and try again.</string>
|
||||||
<!-- Dialog body when a message failed to delete. -->
|
<!-- Dialog body when a message failed to delete. -->
|
||||||
|
|||||||
Reference in New Issue
Block a user