Implement the majority of the new nicknames and notes feature.

This commit is contained in:
Alex Hart
2024-03-22 16:03:04 -03:00
committed by Nicholas Tinsley
parent 7a24554b68
commit 303929090b
20 changed files with 1504 additions and 23 deletions

View File

@@ -505,6 +505,10 @@ public class Recipient {
return contactUri;
}
public @Nullable String getNote() {
return note;
}
public @Nullable String getGroupName(@NonNull Context context) {
if (groupId != null && Util.isEmpty(this.groupName)) {
RecipientId selfId = ApplicationDependencies.getRecipientCache().getSelfId();

View File

@@ -10,6 +10,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
@@ -17,6 +18,7 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Icon
import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
@@ -27,9 +29,11 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
@@ -44,6 +48,7 @@ import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.avatar.AvatarImage
import org.thoughtcrime.securesms.components.emoji.EmojiTextView
import org.thoughtcrime.securesms.compose.ComposeBottomSheetDialogFragment
import org.thoughtcrime.securesms.nicknames.ViewNoteSheet
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter
import org.thoughtcrime.securesms.recipients.Recipient
import org.thoughtcrime.securesms.recipients.RecipientId
@@ -101,10 +106,12 @@ class AboutSheet : ComposeBottomSheetDialogFragment() {
},
groupsInCommon = groupsInCommonCount,
profileSharing = recipient.get().isProfileSharing,
systemContact = recipient.get().isSystemContact
systemContact = recipient.get().isSystemContact,
note = recipient.get().note ?: ""
),
onClickSignalConnections = this::openSignalConnectionsSheet,
onAvatarClicked = this::openProfilePhotoViewer
onAvatarClicked = this::openProfilePhotoViewer,
onNoteClicked = this::openNoteSheet
)
}
}
@@ -117,6 +124,11 @@ class AboutSheet : ComposeBottomSheetDialogFragment() {
private fun openProfilePhotoViewer() {
startActivity(AvatarPreviewActivity.intentFromRecipientId(requireContext(), recipientId))
}
private fun openNoteSheet() {
dismiss()
ViewNoteSheet.create(recipientId).show(parentFragmentManager, null)
}
}
private data class AboutModel(
@@ -130,14 +142,16 @@ private data class AboutModel(
val formattedE164: String?,
val profileSharing: Boolean,
val systemContact: Boolean,
val groupsInCommon: Int
val groupsInCommon: Int,
val note: String
)
@Composable
private fun Content(
model: AboutModel,
onClickSignalConnections: () -> Unit,
onAvatarClicked: () -> Unit
onAvatarClicked: () -> Unit,
onNoteClicked: () -> Unit
) {
Box(
contentAlignment = Alignment.Center,
@@ -180,12 +194,15 @@ private fun Content(
)
if (model.about.isNotNullOrBlank()) {
val textColor = LocalContentColor.current
AboutRow(
startIcon = painterResource(R.drawable.symbol_edit_24),
text = {
Row {
AndroidView(factory = ::EmojiTextView) {
it.text = model.about
it.setTextColor(textColor.toArgb())
TextViewCompat.setTextAppearance(it, R.style.Signal_Text_BodyLarge)
}
@@ -255,6 +272,16 @@ private fun Content(
modifier = Modifier.fillMaxWidth()
)
if (model.note.isNotBlank()) {
AboutRow(
startIcon = painterResource(id = R.drawable.symbol_note_light_24),
text = model.note,
modifier = Modifier.fillMaxWidth(),
endIcon = painterResource(id = R.drawable.symbol_chevron_right_compact_bold_16),
onClick = onNoteClicked
)
}
Spacer(modifier = Modifier.size(26.dp))
}
}
@@ -272,7 +299,10 @@ private fun AboutRow(
text = {
Text(
text = text,
style = MaterialTheme.typography.bodyLarge
style = MaterialTheme.typography.bodyLarge,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.weight(1f, false)
)
},
modifier = modifier,
@@ -284,7 +314,7 @@ private fun AboutRow(
@Composable
private fun AboutRow(
startIcon: Painter,
text: @Composable () -> Unit,
text: @Composable RowScope.() -> Unit,
modifier: Modifier = Modifier,
endIcon: Painter? = null,
onClick: (() -> Unit)? = null
@@ -346,10 +376,12 @@ private fun ContentPreviewDefault() {
formattedE164 = "(123) 456-7890",
profileSharing = true,
systemContact = true,
groupsInCommon = 0
groupsInCommon = 0,
note = "GET ME SPIDERMAN BEFORE I BLOW A DANG GASKET"
),
onClickSignalConnections = {},
onAvatarClicked = {}
onAvatarClicked = {},
onNoteClicked = {}
)
}
}
@@ -373,10 +405,12 @@ private fun ContentPreviewInContactsNotProfileSharing() {
formattedE164 = null,
profileSharing = false,
systemContact = true,
groupsInCommon = 3
groupsInCommon = 3,
note = "GET ME SPIDER MAN"
),
onClickSignalConnections = {},
onAvatarClicked = {}
onAvatarClicked = {},
onNoteClicked = {}
)
}
}
@@ -400,10 +434,12 @@ private fun ContentPreviewGroupsInCommonNoE164() {
formattedE164 = null,
profileSharing = true,
systemContact = false,
groupsInCommon = 3
groupsInCommon = 3,
note = "GET ME SPIDERMAN"
),
onClickSignalConnections = {},
onAvatarClicked = {}
onAvatarClicked = {},
onNoteClicked = {}
)
}
}
@@ -427,10 +463,12 @@ private fun ContentPreviewNotAConnection() {
formattedE164 = null,
profileSharing = false,
systemContact = false,
groupsInCommon = 3
groupsInCommon = 3,
note = "GET ME SPIDERMAN"
),
onClickSignalConnections = {},
onAvatarClicked = {}
onAvatarClicked = {},
onNoteClicked = {}
)
}
}

View File

@@ -17,6 +17,7 @@ import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
@@ -39,6 +40,7 @@ import org.thoughtcrime.securesms.contacts.avatars.FallbackPhoto80dp;
import org.thoughtcrime.securesms.fonts.SignalSymbols;
import org.thoughtcrime.securesms.groups.GroupId;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.nicknames.NicknameActivity;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientExporter;
import org.thoughtcrime.securesms.recipients.RecipientId;
@@ -46,6 +48,7 @@ import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.recipients.ui.about.AboutSheet;
import org.thoughtcrime.securesms.util.BottomSheetUtil;
import org.thoughtcrime.securesms.util.ContextUtil;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.SpanUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
@@ -74,6 +77,7 @@ public final class RecipientBottomSheetDialogFragment extends BottomSheetDialogF
private AvatarView avatar;
private TextView fullName;
private TextView about;
private TextView nickname;
private TextView blockButton;
private TextView unblockButton;
private TextView addContactButton;
@@ -92,6 +96,8 @@ public final class RecipientBottomSheetDialogFragment extends BottomSheetDialogF
private ButtonStripPreference.ViewHolder buttonStripViewHolder;
private ActivityResultLauncher<NicknameActivity.Args> nicknameLauncher;
public static void show(FragmentManager fragmentManager, @NonNull RecipientId recipientId, @Nullable GroupId groupId) {
Recipient recipient = Recipient.resolved(recipientId);
if (recipient.isSelf()) {
@@ -127,6 +133,7 @@ public final class RecipientBottomSheetDialogFragment extends BottomSheetDialogF
avatar = view.findViewById(R.id.rbs_recipient_avatar);
fullName = view.findViewById(R.id.rbs_full_name);
about = view.findViewById(R.id.rbs_about);
nickname = view.findViewById(R.id.rbs_nickname_button);
blockButton = view.findViewById(R.id.rbs_block_button);
unblockButton = view.findViewById(R.id.rbs_unblock_button);
addContactButton = view.findViewById(R.id.rbs_add_contact_button);
@@ -150,6 +157,8 @@ public final class RecipientBottomSheetDialogFragment extends BottomSheetDialogF
public void onViewCreated(@NonNull View fragmentView, @Nullable Bundle savedInstanceState) {
super.onViewCreated(fragmentView, savedInstanceState);
nicknameLauncher = registerForActivityResult(new NicknameActivity.Contract(), (b) -> {});
Bundle arguments = requireArguments();
RecipientId recipientId = RecipientId.from(Objects.requireNonNull(arguments.getString(ARGS_RECIPIENT_ID)));
GroupId groupId = GroupId.parseNullableOrThrow(arguments.getString(ARGS_GROUP_ID));
@@ -214,6 +223,16 @@ public final class RecipientBottomSheetDialogFragment extends BottomSheetDialogF
dismiss();
AboutSheet.create(recipient).show(getParentFragmentManager(), null);
});
if (FeatureFlags.nicknames() && groupId != null) {
nickname.setVisibility(View.VISIBLE);
nickname.setOnClickListener(v -> {
nicknameLauncher.launch(new NicknameActivity.Args(
recipientId,
false
));
});
}
}
String aboutText = recipient.getCombinedAboutAndEmoji();