mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-19 08:09:12 +01:00
Add member labels education sheet.
This commit is contained in:
committed by
Cody Henthorne
parent
955bcde062
commit
0b2d3edcce
@@ -35,6 +35,7 @@ import org.signal.core.util.concurrent.LifecycleDisposable
|
||||
import org.signal.core.util.concurrent.addTo
|
||||
import org.signal.core.util.getParcelableArrayListExtraCompat
|
||||
import org.signal.core.util.orNull
|
||||
import org.signal.core.util.requireParcelableCompat
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.thoughtcrime.securesms.AvatarPreviewActivity
|
||||
import org.thoughtcrime.securesms.BlockUnblockDialog
|
||||
@@ -71,6 +72,7 @@ import org.thoughtcrime.securesms.conversation.ConversationIntents
|
||||
import org.thoughtcrime.securesms.conversation.colors.ColorizerV2
|
||||
import org.thoughtcrime.securesms.database.AttachmentTable
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.memberlabel.MemberLabelEducationSheet
|
||||
import org.thoughtcrime.securesms.groups.memberlabel.StyledMemberLabel
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupErrors
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupLimitDialog
|
||||
@@ -189,6 +191,16 @@ class ConversationSettingsFragment :
|
||||
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
parentFragmentManager.setFragmentResultListener(MemberLabelEducationSheet.RESULT_EDIT_MEMBER_LABEL, viewLifecycleOwner) { _, bundle ->
|
||||
val groupId = bundle.requireParcelableCompat(MemberLabelEducationSheet.KEY_GROUP_ID, GroupId.V2::class.java)
|
||||
navController.safeNavigate(ConversationSettingsFragmentDirections.actionConversationSettingsFragmentToMemberLabelFragment(groupId))
|
||||
}
|
||||
|
||||
parentFragmentManager.setFragmentResultListener(AboutSheet.RESULT_EDIT_MEMBER_LABEL, viewLifecycleOwner) { _, bundle ->
|
||||
val groupId = bundle.requireParcelableCompat(AboutSheet.RESULT_GROUP_ID, GroupId.V2::class.java)
|
||||
navController.safeNavigate(ConversationSettingsFragmentDirections.actionConversationSettingsFragmentToMemberLabelFragment(groupId))
|
||||
}
|
||||
|
||||
recyclerView?.addOnScrollListener(ConversationSettingsOnUserScrolledAnimationHelper(toolbarAvatarContainer, toolbarTitle, toolbarBackground))
|
||||
}
|
||||
|
||||
|
||||
@@ -120,6 +120,7 @@ import org.signal.core.util.concurrent.addTo
|
||||
import org.signal.core.util.dp
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.orNull
|
||||
import org.signal.core.util.requireParcelableCompat
|
||||
import org.signal.core.util.setActionItemTint
|
||||
import org.signal.donations.InAppPaymentType
|
||||
import org.signal.ringrtc.CallLinkRootKey
|
||||
@@ -158,7 +159,6 @@ import org.thoughtcrime.securesms.components.mention.MentionAnnotation
|
||||
import org.thoughtcrime.securesms.components.menu.ActionItem
|
||||
import org.thoughtcrime.securesms.components.menu.SignalBottomActionBar
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity.Companion.remoteBackups
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.CheckoutFlowActivity
|
||||
import org.thoughtcrime.securesms.components.settings.app.subscription.donate.DonateToSignalFragment
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.ConversationSettingsActivity
|
||||
@@ -257,6 +257,8 @@ import org.thoughtcrime.securesms.giph.mp4.GiphyMp4ProjectionPlayerHolder
|
||||
import org.thoughtcrime.securesms.giph.mp4.GiphyMp4ProjectionRecycler
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange
|
||||
import org.thoughtcrime.securesms.groups.memberlabel.MemberLabelActivity
|
||||
import org.thoughtcrime.securesms.groups.memberlabel.MemberLabelEducationSheet
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupChangeFailureReason
|
||||
import org.thoughtcrime.securesms.groups.ui.GroupErrors
|
||||
import org.thoughtcrime.securesms.groups.ui.LeaveGroupDialog
|
||||
@@ -319,6 +321,7 @@ import org.thoughtcrime.securesms.reactions.any.ReactWithAnyEmojiBottomSheetDial
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientExporter
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.recipients.ui.about.AboutSheet
|
||||
import org.thoughtcrime.securesms.recipients.ui.bottomsheet.RecipientBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.recipients.ui.disappearingmessages.RecipientDisappearingMessagesActivity
|
||||
import org.thoughtcrime.securesms.registration.ui.RegistrationActivity
|
||||
@@ -686,6 +689,16 @@ class ConversationFragment :
|
||||
|
||||
container.fragmentManager = childFragmentManager
|
||||
|
||||
childFragmentManager.setFragmentResultListener(MemberLabelEducationSheet.RESULT_EDIT_MEMBER_LABEL, viewLifecycleOwner) { _, bundle ->
|
||||
val groupId = bundle.requireParcelableCompat(MemberLabelEducationSheet.KEY_GROUP_ID, GroupId.V2::class.java)
|
||||
startActivity(MemberLabelActivity.createIntent(requireContext(), groupId))
|
||||
}
|
||||
|
||||
childFragmentManager.setFragmentResultListener(AboutSheet.RESULT_EDIT_MEMBER_LABEL, viewLifecycleOwner) { _, bundle ->
|
||||
val groupId = bundle.requireParcelableCompat(AboutSheet.RESULT_GROUP_ID, GroupId.V2::class.java)
|
||||
startActivity(MemberLabelActivity.createIntent(requireContext(), groupId))
|
||||
}
|
||||
|
||||
ToolbarDependentMarginListener(binding.toolbar)
|
||||
initializeMediaKeyboard()
|
||||
|
||||
@@ -1004,9 +1017,13 @@ class ConversationFragment :
|
||||
|
||||
when {
|
||||
state.isReactionDelegateShowing -> reactionDelegate.hide()
|
||||
|
||||
state.isSearchRequested -> searchMenuItem?.collapseActionView()
|
||||
|
||||
state.isInActionMode -> finishActionMode()
|
||||
|
||||
state.isMediaKeyboardShowing -> container.hideInput()
|
||||
|
||||
else -> {
|
||||
// State has changed since the back handler was enabled. Let the back press proceed
|
||||
// to the next handler by triggering onBackPressed again after setting a skip flag
|
||||
@@ -1886,13 +1903,16 @@ class ConversationFragment :
|
||||
|
||||
when (data) {
|
||||
is ShareOrDraftData.SendKeyboardImage -> sendMessageWithoutComposeInput(slide = data.slide, clearCompose = false)
|
||||
|
||||
is ShareOrDraftData.SendSticker -> sendMessageWithoutComposeInput(slide = data.slide, clearCompose = true)
|
||||
|
||||
is ShareOrDraftData.SetText -> {
|
||||
composeText.setDraftText(data.text)
|
||||
inputPanel.clickOnComposeInput()
|
||||
}
|
||||
|
||||
is ShareOrDraftData.SetLocation -> attachmentManager.setLocation(data.location, MediaConstraints.getPushMediaConstraints())
|
||||
|
||||
is ShareOrDraftData.SetEditMessage -> {
|
||||
composeText.setDraftText(data.draftText)
|
||||
inputPanel.enterEditMessageMode(Glide.with(this), data.messageEdit, true, data.clearQuote)
|
||||
@@ -2689,6 +2709,7 @@ class ConversationFragment :
|
||||
.subscribeBy { result ->
|
||||
when (result) {
|
||||
is Result.Success -> Log.d(TAG, "$logMessage complete")
|
||||
|
||||
is Result.Failure -> {
|
||||
Log.d(TAG, "$logMessage failed ${result.failure}")
|
||||
toast(GroupErrors.getUserDisplayMessage(result.failure))
|
||||
@@ -4156,8 +4177,11 @@ class ConversationFragment :
|
||||
val slides: List<Slide> = result.nonUploadedMedia.mapNotNull {
|
||||
when {
|
||||
MediaUtil.isVideoType(it.contentType) -> VideoSlide(requireContext(), it.uri, it.size, it.isVideoGif, it.width, it.height, it.caption, it.transformProperties)
|
||||
|
||||
MediaUtil.isGif(it.contentType) -> GifSlide(requireContext(), it.uri, it.size, it.width, it.height, it.isBorderless, it.caption)
|
||||
|
||||
MediaUtil.isImageType(it.contentType) -> ImageSlide(requireContext(), it.uri, it.contentType, it.size, it.width, it.height, it.isBorderless, it.caption, null, it.transformProperties)
|
||||
|
||||
MediaUtil.isDocumentType(it.contentType) -> {
|
||||
DocumentSlide(requireContext(), it.uri, it.contentType!!, it.size, it.fileName)
|
||||
}
|
||||
@@ -4359,6 +4383,7 @@ class ConversationFragment :
|
||||
.subscribeBy { result ->
|
||||
when (result) {
|
||||
is Result.Success -> Log.d(TAG, "Cancel request complete")
|
||||
|
||||
is Result.Failure -> {
|
||||
Log.d(TAG, "Cancel join request failed ${result.failure}")
|
||||
toast(GroupErrors.getUserDisplayMessage(result.failure))
|
||||
@@ -4737,9 +4762,13 @@ class ConversationFragment :
|
||||
if (button != null) {
|
||||
when (button) {
|
||||
AttachmentKeyboardButton.GALLERY -> conversationActivityResultContracts.launchGallery(recipient.id, composeText.textTrimmed, inputPanel.quote.isPresent)
|
||||
|
||||
AttachmentKeyboardButton.CONTACT -> conversationActivityResultContracts.launchSelectContact()
|
||||
|
||||
AttachmentKeyboardButton.LOCATION -> conversationActivityResultContracts.launchSelectLocation(recipient.chatColors)
|
||||
|
||||
AttachmentKeyboardButton.PAYMENT -> AttachmentManager.selectPayment(this@ConversationFragment, recipient)
|
||||
|
||||
AttachmentKeyboardButton.FILE -> {
|
||||
if (!conversationActivityResultContracts.launchSelectFile()) {
|
||||
toast(R.string.AttachmentManager_cant_open_media_selection, Toast.LENGTH_LONG)
|
||||
|
||||
@@ -244,6 +244,10 @@ sealed class GroupId(private val encodedId: String) : DatabaseId, Parcelable {
|
||||
return this as V2
|
||||
}
|
||||
|
||||
fun v2OrNull(): V2? {
|
||||
return if (isV2) (this as V2) else null
|
||||
}
|
||||
|
||||
fun requirePush(): Push {
|
||||
assert(this is Push)
|
||||
return this as Push
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.groups.memberlabel
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import org.signal.core.util.getParcelableExtraCompat
|
||||
import org.thoughtcrime.securesms.PassphraseRequiredActivity
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
|
||||
/**
|
||||
* Hosts [MemberLabelFragment], allowing navigation to the member label editor from any context.
|
||||
*/
|
||||
class MemberLabelActivity : PassphraseRequiredActivity() {
|
||||
companion object {
|
||||
private const val EXTRA_GROUP_ID = "group_id"
|
||||
|
||||
fun createIntent(context: Context, groupId: GroupId.V2): Intent {
|
||||
return Intent(context, MemberLabelActivity::class.java).apply {
|
||||
putExtra(EXTRA_GROUP_ID, groupId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
|
||||
super.onCreate(savedInstanceState, ready)
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
val groupId = intent.getParcelableExtraCompat(EXTRA_GROUP_ID, GroupId.V2::class.java)!!
|
||||
val fragment = MemberLabelFragment.newInstance(groupId)
|
||||
supportFragmentManager.beginTransaction()
|
||||
.replace(android.R.id.content, fragment)
|
||||
.commit()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.groups.memberlabel
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.defaultMinSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.BottomSheets
|
||||
import org.signal.core.ui.compose.Buttons
|
||||
import org.signal.core.ui.compose.ComposeBottomSheetDialogFragment
|
||||
import org.signal.core.ui.compose.DayNightPreviews
|
||||
import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.util.requireParcelableCompat
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.util.viewModel
|
||||
|
||||
/**
|
||||
* Explains what member labels are and provides options to edit the current user's label.
|
||||
*/
|
||||
class MemberLabelEducationSheet : ComposeBottomSheetDialogFragment() {
|
||||
companion object {
|
||||
const val RESULT_EDIT_MEMBER_LABEL = "edit_member_label"
|
||||
const val KEY_GROUP_ID = "group_id"
|
||||
|
||||
private const val FRAGMENT_TAG = "MemberLabelEducationSheet"
|
||||
private const val ARGS_GROUP_ID = "group_id"
|
||||
|
||||
fun show(fragmentManager: FragmentManager, groupId: GroupId.V2) {
|
||||
val fragment = MemberLabelEducationSheet().apply {
|
||||
arguments = bundleOf(ARGS_GROUP_ID to groupId)
|
||||
}
|
||||
fragment.show(fragmentManager, FRAGMENT_TAG)
|
||||
}
|
||||
}
|
||||
|
||||
private val groupId: GroupId.V2 by lazy {
|
||||
requireArguments().requireParcelableCompat(ARGS_GROUP_ID, GroupId.V2::class.java)
|
||||
}
|
||||
|
||||
private val viewModel: MemberLabelEducationViewModel by viewModel {
|
||||
MemberLabelEducationViewModel(groupId)
|
||||
}
|
||||
|
||||
override val peekHeightPercentage: Float = 1f
|
||||
|
||||
@Composable
|
||||
override fun SheetContent() {
|
||||
val state by viewModel.uiState.collectAsStateWithLifecycle()
|
||||
|
||||
val callbacks = remember {
|
||||
object : MemberLabelEducationUiCallbacks {
|
||||
override fun onSetLabelClicked() {
|
||||
setFragmentResult(RESULT_EDIT_MEMBER_LABEL, bundleOf(KEY_GROUP_ID to groupId))
|
||||
dismiss()
|
||||
}
|
||||
|
||||
override fun onDismiss() = dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
MemberLabelEducationSheetContent(
|
||||
state = state,
|
||||
callbacks = callbacks
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun MemberLabelEducationSheetContent(
|
||||
state: MemberLabelEducationViewModel.UiState,
|
||||
callbacks: MemberLabelEducationUiCallbacks = MemberLabelEducationUiCallbacks.Empty
|
||||
) {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
modifier = Modifier
|
||||
.padding(top = 4.dp, bottom = 28.dp, start = 28.dp, end = 28.dp)
|
||||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
BottomSheets.Handle()
|
||||
|
||||
Image(
|
||||
painter = painterResource(R.drawable.symbol_tag_filled_64),
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(top = 24.dp)
|
||||
.size(64.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.MemberLabelsEducation__title),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = stringResource(R.string.MemberLabelsEducation__body),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
textAlign = TextAlign.Center,
|
||||
modifier = Modifier.padding(top = 12.dp)
|
||||
)
|
||||
|
||||
if (state.selfCanSetLabel) {
|
||||
TextButton(
|
||||
onClick = callbacks::onSetLabelClicked,
|
||||
modifier = Modifier.padding(top = 56.dp)
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(
|
||||
if (state.selfHasLabel) R.string.MemberLabelsEducation__edit_label
|
||||
else R.string.MemberLabelsEducation__set_label
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
Spacer(modifier = Modifier.height(56.dp))
|
||||
}
|
||||
|
||||
Buttons.LargeTonal(
|
||||
onClick = callbacks::onDismiss,
|
||||
modifier = Modifier
|
||||
.padding(top = 16.dp)
|
||||
.defaultMinSize(minWidth = 220.dp)
|
||||
) {
|
||||
Text(text = stringResource(android.R.string.ok))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private interface MemberLabelEducationUiCallbacks {
|
||||
fun onSetLabelClicked()
|
||||
fun onDismiss()
|
||||
|
||||
object Empty : MemberLabelEducationUiCallbacks {
|
||||
override fun onSetLabelClicked() = Unit
|
||||
override fun onDismiss() = Unit
|
||||
}
|
||||
}
|
||||
|
||||
@AllDevicePreviews
|
||||
@Composable
|
||||
private fun MemberLabelEducationSheetPreviewCanSetNoLabel() = Previews.Preview {
|
||||
MemberLabelEducationSheetContent(
|
||||
state = MemberLabelEducationViewModel.UiState(
|
||||
selfHasLabel = false,
|
||||
selfCanSetLabel = true
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun MemberLabelEducationSheetPreviewCanSetHasLabel() = Previews.Preview {
|
||||
MemberLabelEducationSheetContent(
|
||||
state = MemberLabelEducationViewModel.UiState(
|
||||
selfHasLabel = true,
|
||||
selfCanSetLabel = true
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@DayNightPreviews
|
||||
@Composable
|
||||
private fun MemberLabelEducationSheetPreviewCannotSet() = Previews.Preview {
|
||||
MemberLabelEducationSheetContent(
|
||||
state = MemberLabelEducationViewModel.UiState(
|
||||
selfHasLabel = false,
|
||||
selfCanSetLabel = false
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2026 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.groups.memberlabel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import org.signal.core.util.concurrent.SignalDispatchers
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
class MemberLabelEducationViewModel(
|
||||
private val groupId: GroupId.V2,
|
||||
private val repository: MemberLabelRepository = MemberLabelRepository.instance
|
||||
) : ViewModel() {
|
||||
|
||||
data class UiState(
|
||||
val selfHasLabel: Boolean = false,
|
||||
val selfCanSetLabel: Boolean = false
|
||||
)
|
||||
|
||||
private val _uiState = MutableStateFlow(UiState())
|
||||
val uiState: StateFlow<UiState> = _uiState.asStateFlow()
|
||||
|
||||
init {
|
||||
viewModelScope.launch(SignalDispatchers.IO) {
|
||||
val self = Recipient.self()
|
||||
val selfMemberLabel = repository.getLabel(groupId, self.id)
|
||||
val selfCanSetLabel = repository.canSetLabel(groupId, self)
|
||||
_uiState.update {
|
||||
it.copy(
|
||||
selfHasLabel = selfMemberLabel != null,
|
||||
selfCanSetLabel = selfCanSetLabel
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,8 +38,8 @@ import androidx.compose.ui.res.vectorResource
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardCapitalization
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.fragment.navArgs
|
||||
import org.signal.core.ui.compose.AllDevicePreviews
|
||||
import org.signal.core.ui.compose.Buttons
|
||||
import org.signal.core.ui.compose.ClearableTextField
|
||||
@@ -48,6 +48,7 @@ import org.signal.core.ui.compose.Previews
|
||||
import org.signal.core.ui.compose.Scaffolds
|
||||
import org.signal.core.ui.compose.SignalIcons
|
||||
import org.signal.core.util.isNotNullOrBlank
|
||||
import org.signal.core.util.requireParcelableCompat
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.memberlabel.MemberLabelUiState.SaveState
|
||||
@@ -62,12 +63,22 @@ import org.thoughtcrime.securesms.util.viewModel
|
||||
class MemberLabelFragment : ComposeFragment(), ReactWithAnyEmojiBottomSheetDialogFragment.Callback {
|
||||
companion object {
|
||||
private const val EMOJI_PICKER_DIALOG_TAG = "emoji_picker_dialog"
|
||||
private const val ARG_GROUP_ID = "group_id"
|
||||
|
||||
fun newInstance(groupId: GroupId.V2): MemberLabelFragment {
|
||||
return MemberLabelFragment().apply {
|
||||
arguments = bundleOf(ARG_GROUP_ID to groupId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val groupId: GroupId.V2 by lazy {
|
||||
requireArguments().requireParcelableCompat(ARG_GROUP_ID, GroupId.V2::class.java)
|
||||
}
|
||||
|
||||
private val args: MemberLabelFragmentArgs by navArgs()
|
||||
private val viewModel: MemberLabelViewModel by viewModel {
|
||||
MemberLabelViewModel(
|
||||
groupId = (args.groupId as GroupId).requireV2(),
|
||||
groupId = groupId,
|
||||
recipientId = Recipient.self().id
|
||||
)
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.widget.TextViewCompat
|
||||
import androidx.fragment.app.setFragmentResult
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import androidx.navigation.Navigation
|
||||
import org.signal.core.ui.compose.BottomSheets
|
||||
import org.signal.core.ui.compose.ComposeBottomSheetDialogFragment
|
||||
import org.signal.core.ui.compose.DayNightPreviews
|
||||
@@ -53,7 +53,6 @@ import org.thoughtcrime.securesms.AvatarPreviewActivity
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.avatar.AvatarImage
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
import org.thoughtcrime.securesms.components.settings.conversation.ConversationSettingsFragmentDirections
|
||||
import org.thoughtcrime.securesms.conversation.v2.UnverifiedProfileNameBottomSheet
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.memberlabel.MemberLabel
|
||||
@@ -72,6 +71,9 @@ import org.signal.core.ui.R as CoreUiR
|
||||
class AboutSheet : ComposeBottomSheetDialogFragment() {
|
||||
|
||||
companion object {
|
||||
const val RESULT_EDIT_MEMBER_LABEL = "edit_member_label"
|
||||
const val RESULT_GROUP_ID = "group_id"
|
||||
|
||||
private const val RECIPIENT_ID = "recipient_id"
|
||||
private const val VIEWING_FROM_GROUP_ID = "viewing_from_group_id"
|
||||
|
||||
@@ -157,8 +159,7 @@ class AboutSheet : ComposeBottomSheetDialogFragment() {
|
||||
|
||||
private fun openMemberLabelScreen() {
|
||||
viewingFromGroupId?.let { groupId ->
|
||||
val navController = Navigation.findNavController(requireActivity(), R.id.nav_host_fragment)
|
||||
navController.navigate(ConversationSettingsFragmentDirections.actionConversationSettingsFragmentToMemberLabelFragment(groupId))
|
||||
setFragmentResult(RESULT_EDIT_MEMBER_LABEL, bundleOf(RESULT_GROUP_ID to groupId))
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.thoughtcrime.securesms.components.settings.conversation.preferences.B
|
||||
import org.thoughtcrime.securesms.conversation.v2.data.AvatarDownloadStateCache
|
||||
import org.thoughtcrime.securesms.fonts.SignalSymbols
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.groups.memberlabel.MemberLabelEducationSheet
|
||||
import org.thoughtcrime.securesms.groups.memberlabel.MemberLabelPillView
|
||||
import org.thoughtcrime.securesms.nicknames.NicknameActivity
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
@@ -334,7 +335,7 @@ class RecipientBottomSheetDialogFragment : FixedRoundedCornerBottomSheetDialogFr
|
||||
}
|
||||
|
||||
viewModel.recipientDetails.observe(viewLifecycleOwner) { state ->
|
||||
updateRecipientDetails(state, memberLabelView, aboutView)
|
||||
updateRecipientDetails(state, memberLabelView, aboutView, groupId?.v2OrNull())
|
||||
}
|
||||
|
||||
viewModel.canAddToAGroup.observe(getViewLifecycleOwner()) { canAdd: Boolean ->
|
||||
@@ -450,13 +451,23 @@ class RecipientBottomSheetDialogFragment : FixedRoundedCornerBottomSheetDialogFr
|
||||
private fun updateRecipientDetails(
|
||||
state: RecipientDetailsState,
|
||||
memberLabelView: MemberLabelPillView,
|
||||
aboutView: TextView
|
||||
aboutView: TextView,
|
||||
groupId: GroupId.V2?
|
||||
) {
|
||||
when {
|
||||
state.memberLabel != null -> {
|
||||
memberLabelView.setLabel(state.memberLabel.label, state.memberLabel.tintColor)
|
||||
memberLabelView.visible = true
|
||||
aboutView.visible = false
|
||||
|
||||
if (groupId != null) {
|
||||
memberLabelView.setOnClickListener {
|
||||
dismiss()
|
||||
MemberLabelEducationSheet.show(parentFragmentManager, groupId)
|
||||
}
|
||||
} else {
|
||||
memberLabelView.setOnClickListener(null)
|
||||
}
|
||||
}
|
||||
|
||||
!state.aboutText.isNullOrBlank() -> {
|
||||
|
||||
Reference in New Issue
Block a user