mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-27 20:24:32 +01:00
Update message request states for 1:1 and groups chats.
This commit is contained in:
committed by
Greyson Parrelli
parent
20cecbd5cd
commit
886bebb088
@@ -5,12 +5,14 @@ import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.TextUtils;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewKt;
|
||||
@@ -92,25 +94,39 @@ public class ConversationHeaderView extends ConstraintLayout {
|
||||
return title.toString();
|
||||
}
|
||||
|
||||
public void setAbout(@NonNull Recipient recipient) {
|
||||
String about;
|
||||
if (recipient.isReleaseNotes()) {
|
||||
about = getContext().getString(R.string.ReleaseNotes__signal_release_notes_and_news);
|
||||
} else {
|
||||
about = recipient.getCombinedAboutAndEmoji();
|
||||
}
|
||||
|
||||
binding.messageRequestAbout.setText(about);
|
||||
binding.messageRequestAbout.setVisibility(TextUtils.isEmpty(about) ? GONE : VISIBLE);
|
||||
public void showReleaseNoteHeader() {
|
||||
binding.messageRequestInfo.setVisibility(View.GONE);
|
||||
binding.releaseHeaderContainer.setVisibility(View.VISIBLE);
|
||||
binding.releaseHeaderDescription1.setText(prependIcon(getContext().getString(R.string.ReleaseNotes__this_is_official_chat_period), R.drawable.symbol_official_20));
|
||||
binding.releaseHeaderDescription2.setText(prependIcon(getContext().getString(R.string.ReleaseNotes__keep_up_to_date_period), R.drawable.symbol_bell_20));
|
||||
}
|
||||
|
||||
public void setSubtitle(@NonNull CharSequence subtitle, @DrawableRes int iconRes) {
|
||||
public void setAbout(@NonNull Recipient recipient) {
|
||||
String about = recipient.getCombinedAboutAndEmoji();
|
||||
binding.messageRequestAbout.setText(about);
|
||||
binding.messageRequestAbout.setVisibility(TextUtils.isEmpty(about) || recipient.isReleaseNotes() ? GONE : VISIBLE);
|
||||
}
|
||||
|
||||
public void setSubtitle(@NonNull CharSequence subtitle, @DrawableRes int iconRes, @Nullable Runnable onClick) {
|
||||
if (TextUtils.isEmpty(subtitle)) {
|
||||
hideSubtitle();
|
||||
return;
|
||||
}
|
||||
|
||||
binding.messageRequestSubtitle.setText(prependIcon(subtitle, iconRes));
|
||||
if (onClick != null) {
|
||||
binding.messageRequestSubtitle.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
CharSequence builder = SpanUtil.clickSubstring(
|
||||
subtitle,
|
||||
subtitle,
|
||||
listener -> onClick.run(),
|
||||
ContextCompat.getColor(getContext(), R.color.signal_colorOnSurface),
|
||||
true
|
||||
);
|
||||
binding.messageRequestSubtitle.setText(prependIcon(builder, iconRes));
|
||||
} else {
|
||||
binding.messageRequestSubtitle.setText(prependIcon(subtitle, iconRes));
|
||||
}
|
||||
|
||||
binding.messageRequestSubtitle.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
@@ -134,6 +150,32 @@ public class ConversationHeaderView extends ConstraintLayout {
|
||||
binding.messageRequestButton.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public void showWarningSubtitle() {
|
||||
binding.messageRequestReviewCarefully.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public void hideWarningSubtitle() {
|
||||
binding.messageRequestReviewCarefully.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void setUnverifiedNameSubtitle(@DrawableRes int iconRes, @StringRes int clickableRes, boolean forGroup, @Nullable Runnable onClick) {
|
||||
binding.messageRequestProfileNameUnverified.setVisibility(View.VISIBLE);
|
||||
binding.messageRequestProfileNameUnverified.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
CharSequence builder = SpanUtil.clickSubstring(
|
||||
getContext(),
|
||||
R.string.ConversationFragment_profile_names_not_verified,
|
||||
clickableRes,
|
||||
listener -> onClick.run(),
|
||||
true,
|
||||
R.color.signal_colorOnSurface
|
||||
);
|
||||
binding.messageRequestProfileNameUnverified.setText(prependIcon(builder, iconRes, forGroup));
|
||||
}
|
||||
|
||||
public void hideUnverifiedNameSubtitle() {
|
||||
binding.messageRequestProfileNameUnverified.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void showBackgroundBubble(boolean enabled) {
|
||||
if (enabled) {
|
||||
setBackgroundResource(R.drawable.wallpaper_bubble_background_18);
|
||||
@@ -176,6 +218,9 @@ public class ConversationHeaderView extends ConstraintLayout {
|
||||
binding.messageRequestInfoOutline.setVisibility(View.VISIBLE);
|
||||
binding.messageRequestDivider.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
} else if (ViewKt.isVisible(binding.releaseHeaderContainer)) {
|
||||
binding.messageRequestInfoOutline.setVisibility(View.GONE);
|
||||
binding.messageRequestDivider.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
binding.messageRequestInfoOutline.setVisibility(View.GONE);
|
||||
binding.messageRequestDivider.setVisibility(View.GONE);
|
||||
@@ -183,9 +228,15 @@ public class ConversationHeaderView extends ConstraintLayout {
|
||||
}
|
||||
|
||||
private @NonNull CharSequence prependIcon(@NonNull CharSequence input, @DrawableRes int iconRes) {
|
||||
return prependIcon(input, iconRes, false);
|
||||
}
|
||||
|
||||
|
||||
private @NonNull CharSequence prependIcon(@NonNull CharSequence input, @DrawableRes int iconRes, boolean useIntrinsicWidth) {
|
||||
Drawable drawable = ContextCompat.getDrawable(getContext(), iconRes);
|
||||
Preconditions.checkNotNull(drawable);
|
||||
drawable.setBounds(0, 0, (int) DimensionUnit.SP.toPixels(20), (int) DimensionUnit.SP.toPixels(20));
|
||||
int width = useIntrinsicWidth ? drawable.getIntrinsicWidth() : (int) DimensionUnit.SP.toPixels(20);
|
||||
drawable.setBounds(0, 0, width, (int) DimensionUnit.SP.toPixels(20));
|
||||
drawable.setColorFilter(ContextCompat.getColor(getContext(), R.color.signal_colorOnSurface), PorterDuff.Mode.SRC_ATOP);
|
||||
|
||||
return new SpannableStringBuilder()
|
||||
|
||||
@@ -186,9 +186,10 @@ public class ConversationTitleView extends ConstraintLayout {
|
||||
}
|
||||
|
||||
private void setRecipientTitle(@NonNull Recipient recipient) {
|
||||
if (recipient.isGroup()) setGroupRecipientTitle(recipient);
|
||||
else if (recipient.isSelf()) setSelfTitle();
|
||||
else setIndividualRecipientTitle(recipient);
|
||||
if (recipient.isGroup()) setGroupRecipientTitle(recipient);
|
||||
else if (recipient.isSelf()) setSelfTitle();
|
||||
else if (recipient.isReleaseNotes()) setReleaseNotesTitle(recipient);
|
||||
else setIndividualRecipientTitle(recipient);
|
||||
}
|
||||
|
||||
private void setGroupRecipientTitle(@NonNull Recipient recipient) {
|
||||
@@ -200,6 +201,13 @@ public class ConversationTitleView extends ConstraintLayout {
|
||||
updateSubtitleVisibility();
|
||||
}
|
||||
|
||||
private void setReleaseNotesTitle(@NonNull Recipient recipient) {
|
||||
final String displayName = recipient.getDisplayName(getContext());
|
||||
this.title.setText(displayName);
|
||||
this.subtitle.setText(R.string.ReleaseNotes__official_only_chat);
|
||||
updateSubtitleVisibility();
|
||||
}
|
||||
|
||||
private void setIndividualRecipientTitle(@NonNull Recipient recipient) {
|
||||
final String displayName = recipient.getDisplayName(getContext());
|
||||
this.title.setText(displayName);
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
|
||||
package org.thoughtcrime.securesms.conversation.v2
|
||||
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import android.view.GestureDetector
|
||||
import android.view.GestureDetector.SimpleOnGestureListener
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.text.HtmlCompat
|
||||
import androidx.core.view.children
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
@@ -23,6 +23,7 @@ import org.signal.core.util.toOptional
|
||||
import org.thoughtcrime.securesms.BindableConversationItem
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.Unbindable
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.ConversationSettingsActivity
|
||||
import org.thoughtcrime.securesms.conversation.ConversationAdapter.ItemClickListener
|
||||
import org.thoughtcrime.securesms.conversation.ConversationAdapterBridge
|
||||
import org.thoughtcrime.securesms.conversation.ConversationHeaderView
|
||||
@@ -78,6 +79,7 @@ class ConversationAdapterV2(
|
||||
|
||||
companion object {
|
||||
private val TAG = Log.tag(ConversationAdapterV2::class.java)
|
||||
private val MIN_GROUPS_THRESHOLD = 2
|
||||
}
|
||||
|
||||
private val _selected = hashSetOf<MultiselectPart>()
|
||||
@@ -539,41 +541,66 @@ class ConversationAdapterV2(
|
||||
val title: String = conversationBanner.setTitle(recipient) {
|
||||
displayDialogFragment(AboutSheet.create(recipient))
|
||||
}
|
||||
|
||||
if (recipient.isReleaseNotes) {
|
||||
conversationBanner.showReleaseNoteHeader()
|
||||
}
|
||||
|
||||
conversationBanner.setAbout(recipient)
|
||||
|
||||
if (recipient.isGroup) {
|
||||
if (!groupInfo.hasExistingContacts) {
|
||||
conversationBanner.setUnverifiedNameSubtitle(R.drawable.symbol_group_question_20, R.string.ConversationFragment_group_names, true) {
|
||||
clickListener.onShowUnverifiedProfileSheet(true)
|
||||
}
|
||||
} else {
|
||||
conversationBanner.hideUnverifiedNameSubtitle()
|
||||
}
|
||||
|
||||
if (groupInfo.pendingMemberCount > 0) {
|
||||
val invited = context.resources.getQuantityString(R.plurals.MessageRequestProfileView_invited, groupInfo.pendingMemberCount, groupInfo.pendingMemberCount)
|
||||
conversationBanner.setSubtitle(context.resources.getQuantityString(R.plurals.MessageRequestProfileView_members_and_invited, groupInfo.fullMemberCount, groupInfo.fullMemberCount, invited), R.drawable.symbol_group_light_20)
|
||||
conversationBanner.setSubtitle(context.resources.getQuantityString(R.plurals.MessageRequestProfileView_members_and_invited, groupInfo.fullMemberCount, groupInfo.fullMemberCount, invited), R.drawable.symbol_group_light_20) { goToGroupSettings(recipient) }
|
||||
} else if (groupInfo.fullMemberCount > 0) {
|
||||
conversationBanner.setSubtitle(context.resources.getQuantityString(R.plurals.MessageRequestProfileView_members, groupInfo.fullMemberCount, groupInfo.fullMemberCount), R.drawable.symbol_group_light_20)
|
||||
conversationBanner.setSubtitle(context.resources.getQuantityString(R.plurals.MessageRequestProfileView_members, groupInfo.fullMemberCount, groupInfo.fullMemberCount), R.drawable.symbol_group_light_20) { goToGroupSettings(recipient) }
|
||||
} else {
|
||||
conversationBanner.hideSubtitle()
|
||||
}
|
||||
} else if (isSelf) {
|
||||
conversationBanner.setSubtitle(context.getString(R.string.ConversationFragment__you_can_add_notes_for_yourself_in_this_conversation), R.drawable.symbol_note_light_24)
|
||||
conversationBanner.setSubtitle(context.getString(R.string.ConversationFragment__you_can_add_notes_for_yourself_in_this_conversation), R.drawable.symbol_note_light_24, null)
|
||||
} else {
|
||||
if (recipient.nickname.isEmpty && !recipient.isSystemContact) {
|
||||
conversationBanner.setUnverifiedNameSubtitle(R.drawable.symbol_person_question_16, R.string.ConversationFragment_profile_names, false) {
|
||||
clickListener.onShowUnverifiedProfileSheet(false)
|
||||
}
|
||||
} else {
|
||||
conversationBanner.hideUnverifiedNameSubtitle()
|
||||
}
|
||||
|
||||
val subtitle: String? = recipient.takeIf { it.shouldShowE164 }?.e164?.map { e164: String? -> PhoneNumberFormatter.prettyPrint(e164!!) }?.orElse(null)
|
||||
if (subtitle == null || subtitle == title) {
|
||||
conversationBanner.hideSubtitle()
|
||||
} else {
|
||||
conversationBanner.setSubtitle(subtitle, R.drawable.symbol_phone_light_20)
|
||||
conversationBanner.setSubtitle(subtitle, R.drawable.symbol_phone_light_20, null)
|
||||
}
|
||||
}
|
||||
|
||||
conversationBanner.hideButton()
|
||||
|
||||
if (messageRequestState?.isAccepted == false && sharedGroups.isEmpty() && !isSelf && !recipient.isGroup) {
|
||||
conversationBanner.setDescription(context.getString(R.string.ConversationUpdateItem_no_groups_in_common_review_requests_carefully), R.drawable.symbol_error_circle_24)
|
||||
if (messageRequestState?.isAccepted == false && !isSelf && !recipient.isGroup) {
|
||||
if (sharedGroups.size < MIN_GROUPS_THRESHOLD) {
|
||||
conversationBanner.showWarningSubtitle()
|
||||
}
|
||||
conversationBanner.setButton(context.getString(R.string.ConversationFragment_safety_tips)) {
|
||||
clickListener.onShowSafetyTips(false)
|
||||
}
|
||||
} else if (messageRequestState?.isAccepted == false && recipient.isGroup && !groupInfo.hasExistingContacts) {
|
||||
conversationBanner.setDescription(context.getString(R.string.ConversationUpdateItem_no_contacts_in_this_group_review_requests_carefully), R.drawable.symbol_error_circle_24)
|
||||
conversationBanner.setDescription(getDescription(context, sharedGroups), R.drawable.symbol_group_light_20)
|
||||
} else if (messageRequestState?.isAccepted == false && recipient.isGroup) {
|
||||
conversationBanner.showWarningSubtitle()
|
||||
conversationBanner.setButton(context.getString(R.string.ConversationFragment_safety_tips)) {
|
||||
clickListener.onShowSafetyTips(true)
|
||||
}
|
||||
} else if (sharedGroups.isEmpty() || isSelf) {
|
||||
} else if ((recipient.isGroup && sharedGroups.isEmpty()) || isSelf) {
|
||||
conversationBanner.hideWarningSubtitle()
|
||||
if (TextUtils.isEmpty(groupInfo.description)) {
|
||||
conversationBanner.setLinkifyDescription(false)
|
||||
conversationBanner.hideDescription()
|
||||
@@ -592,23 +619,37 @@ class ConversationAdapterV2(
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val description: String = when (sharedGroups.size) {
|
||||
1 -> context.getString(R.string.MessageRequestProfileView_member_of_one_group, sharedGroups[0])
|
||||
2 -> context.getString(R.string.MessageRequestProfileView_member_of_two_groups, sharedGroups[0], sharedGroups[1])
|
||||
3 -> context.getString(R.string.MessageRequestProfileView_member_of_many_groups, sharedGroups[0], sharedGroups[1], sharedGroups[2])
|
||||
else -> {
|
||||
val others: Int = sharedGroups.size - 2
|
||||
context.getString(
|
||||
R.string.MessageRequestProfileView_member_of_many_groups,
|
||||
sharedGroups[0],
|
||||
sharedGroups[1],
|
||||
context.resources.getQuantityString(R.plurals.MessageRequestProfileView_member_of_d_additional_groups, others, others)
|
||||
)
|
||||
}
|
||||
}
|
||||
conversationBanner.setDescription(HtmlCompat.fromHtml(description, 0), R.drawable.symbol_group_light_20)
|
||||
conversationBanner.hideWarningSubtitle()
|
||||
conversationBanner.setDescription(getDescription(context, sharedGroups), R.drawable.symbol_group_light_20)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDescription(context: Context, sharedGroups: List<String>): String {
|
||||
return when (sharedGroups.size) {
|
||||
0 -> context.getString(R.string.ConversationUpdateItem_no_groups_in_common_review_requests_carefully)
|
||||
1 -> context.getString(R.string.MessageRequestProfileView_member_of_one_group, sharedGroups[0])
|
||||
2 -> context.getString(R.string.MessageRequestProfileView_member_of_two_groups, sharedGroups[0], sharedGroups[1])
|
||||
3 -> context.getString(R.string.MessageRequestProfileView_member_of_many_groups, sharedGroups[0], sharedGroups[1], sharedGroups[2])
|
||||
else -> {
|
||||
val others: Int = sharedGroups.size - 2
|
||||
context.getString(
|
||||
R.string.MessageRequestProfileView_member_of_many_groups,
|
||||
sharedGroups[0],
|
||||
sharedGroups[1],
|
||||
context.resources.getQuantityString(R.plurals.MessageRequestProfileView_member_of_d_additional_groups, others, others)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun goToGroupSettings(recipient: Recipient) {
|
||||
val intent = ConversationSettingsActivity.forGroup(getContext(), recipient.requireGroupId())
|
||||
val bundle = ConversationSettingsActivity.createTransitionBundle(
|
||||
getContext(),
|
||||
conversationBanner.getViewById(R.id.message_request_avatar)
|
||||
)
|
||||
getContext().startActivity(intent, bundle)
|
||||
}
|
||||
}
|
||||
|
||||
private inner class OnScrollStateChangedListener : RecyclerView.OnScrollListener() {
|
||||
|
||||
@@ -2952,6 +2952,10 @@ class ConversationFragment :
|
||||
ConversationDialogs.displaySafetyNumberLearnMoreDialog(this@ConversationFragment, recipient)
|
||||
}
|
||||
|
||||
override fun onShowUnverifiedProfileSheet(forGroup: Boolean) {
|
||||
UnverifiedProfileNameBottomSheet.show(parentFragmentManager, forGroup)
|
||||
}
|
||||
|
||||
override fun onJoinGroupCallClicked() {
|
||||
val activity = activity ?: return
|
||||
val recipient = viewModel.recipientSnapshot ?: return
|
||||
|
||||
@@ -15,6 +15,7 @@ import android.widget.FrameLayout
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestState
|
||||
import org.thoughtcrime.securesms.messagerequests.MessageRequestsBottomView
|
||||
@@ -82,7 +83,25 @@ class DisabledInputView @JvmOverloads constructor(
|
||||
setMessageRequestData(recipient, messageRequestState)
|
||||
setWallpaperEnabled(recipient.hasWallpaper)
|
||||
|
||||
setAcceptOnClickListener { listener?.onAcceptMessageRequestClicked() }
|
||||
setAcceptOnClickListener {
|
||||
if (messageRequestState.isFewConnectionsIndividual) {
|
||||
MaterialAlertDialogBuilder(context)
|
||||
.setTitle(R.string.MessageRequestBottomView_accept_request)
|
||||
.setMessage(R.string.MessageRequestBottomView_review_requests_carefully)
|
||||
.setPositiveButton(R.string.MessageRequestBottomView_accept) { _, _ -> listener?.onAcceptMessageRequestClicked() }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
} else if (messageRequestState.isGroupV2Add) {
|
||||
MaterialAlertDialogBuilder(context)
|
||||
.setTitle(R.string.MessageRequestBottomView_join_group)
|
||||
.setMessage(R.string.MessageRequestBottomView_review_requests_carefully_groups)
|
||||
.setPositiveButton(R.string.MessageRequestBottomView_join) { _, _ -> listener?.onAcceptMessageRequestClicked() }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show()
|
||||
} else {
|
||||
listener?.onAcceptMessageRequestClicked()
|
||||
}
|
||||
}
|
||||
setDeleteOnClickListener { listener?.onDeleteClicked() }
|
||||
setBlockOnClickListener { listener?.onBlockClicked() }
|
||||
setUnblockOnClickListener { listener?.onUnblockClicked() }
|
||||
|
||||
@@ -88,6 +88,7 @@ data class SafetyTipData(
|
||||
)
|
||||
|
||||
private val tips = listOf(
|
||||
SafetyTipData(heroImage = R.drawable.safety_tip0, titleText = R.string.SafetyTips_tip0_title, messageText = R.string.SafetyTips_tip0_message),
|
||||
SafetyTipData(heroImage = R.drawable.safety_tip1, titleText = R.string.SafetyTips_tip1_title, messageText = R.string.SafetyTips_tip1_message),
|
||||
SafetyTipData(heroImage = R.drawable.safety_tip2, titleText = R.string.SafetyTips_tip2_title, messageText = R.string.SafetyTips_tip2_message),
|
||||
SafetyTipData(heroImage = R.drawable.safety_tip3, titleText = R.string.SafetyTips_tip3_title, messageText = R.string.SafetyTips_tip3_message),
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
package org.thoughtcrime.securesms.conversation.v2
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
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.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.SpanStyle
|
||||
import androidx.compose.ui.text.buildAnnotatedString
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import org.signal.core.ui.BottomSheets
|
||||
import org.signal.core.ui.Previews
|
||||
import org.signal.core.ui.SignalPreview
|
||||
import org.signal.core.ui.horizontalGutters
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.util.BottomSheetUtil
|
||||
|
||||
/**
|
||||
* Bottom sheet shown in message request state that explains that profile names are unverified
|
||||
*/
|
||||
class UnverifiedProfileNameBottomSheet : ComposeBottomSheetDialogFragment() {
|
||||
|
||||
override val peekHeightPercentage: Float = 0.75f
|
||||
|
||||
companion object {
|
||||
private const val FOR_GROUP_ARG = "for_group"
|
||||
|
||||
@JvmStatic
|
||||
fun show(fragmentManager: FragmentManager, forGroup: Boolean) {
|
||||
UnverifiedProfileNameBottomSheet()
|
||||
.apply {
|
||||
arguments = bundleOf(
|
||||
FOR_GROUP_ARG to forGroup
|
||||
)
|
||||
}
|
||||
.show(fragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun SheetContent() {
|
||||
ProfileNameSheet(
|
||||
forGroup = requireArguments().getBoolean(FOR_GROUP_ARG, false)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ProfileNameSheet(forGroup: Boolean = true) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.horizontalGutters()
|
||||
) {
|
||||
BottomSheets.Handle()
|
||||
|
||||
val (imageVector, placeholder, text) =
|
||||
if (forGroup) {
|
||||
Triple(
|
||||
R.drawable.symbol_group_question_55,
|
||||
stringResource(R.string.ConversationFragment_group_names),
|
||||
stringResource(id = R.string.ProfileNameBottomSheet__group_names_on_signal, stringResource(R.string.ConversationFragment_group_names))
|
||||
)
|
||||
} else {
|
||||
Triple(
|
||||
R.drawable.symbol_person_question_40,
|
||||
stringResource(R.string.ConversationFragment_profile_names),
|
||||
stringResource(id = R.string.ProfileNameBottomSheet__profile_names_on_signal, stringResource(R.string.ConversationFragment_profile_names))
|
||||
)
|
||||
}
|
||||
|
||||
Icon(
|
||||
imageVector = ImageVector.vectorResource(imageVector),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(top = 38.dp, bottom = 24.dp)
|
||||
.size(height = 56.dp, width = 72.dp)
|
||||
)
|
||||
|
||||
val annotatedText = remember {
|
||||
buildAnnotatedString {
|
||||
val start = text.indexOf(placeholder)
|
||||
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
|
||||
append(text.substring(start, start + placeholder.length))
|
||||
}
|
||||
append(text.substring(start + placeholder.length))
|
||||
}
|
||||
}
|
||||
|
||||
Text(
|
||||
text = annotatedText,
|
||||
modifier = Modifier.padding(bottom = 20.dp)
|
||||
)
|
||||
|
||||
if (forGroup) {
|
||||
InfoRow(stringResource(R.string.ProfileNameBottomSheet__be_cautious_of_groups))
|
||||
InfoRow(stringResource(R.string.ProfileNameBottomSheet__profile_names_in_groups))
|
||||
} else {
|
||||
InfoRow(stringResource(R.string.ProfileNameBottomSheet__profile_names_arent_verified))
|
||||
InfoRow(stringResource(R.string.ProfileNameBottomSheet__be_cautious_of_accounts))
|
||||
}
|
||||
|
||||
InfoRow(stringResource(R.string.ProfileNameBottomSheet__dont_share_personal))
|
||||
|
||||
Spacer(Modifier.size(55.dp))
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun InfoRow(text: String) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(IntrinsicSize.Min)
|
||||
.fillMaxWidth()
|
||||
.padding(start = 16.dp, bottom = 12.dp)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.width(4.dp)
|
||||
.padding(vertical = 5.dp)
|
||||
.fillMaxHeight()
|
||||
.clip(RoundedCornerShape(10.dp))
|
||||
.background(color = MaterialTheme.colorScheme.outline.copy(.4f))
|
||||
)
|
||||
|
||||
Text(
|
||||
text = text,
|
||||
modifier = Modifier.padding(start = 12.dp),
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@SignalPreview
|
||||
@Composable
|
||||
private fun ProfileNameSheetPreview() {
|
||||
Previews.BottomSheetPreview {
|
||||
ProfileNameSheet()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user