Implement new about sheet.
This commit is contained in:
parent
490d3549e2
commit
9924e293c9
11 changed files with 477 additions and 8 deletions
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.avatar
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
@Composable
|
||||
fun AvatarImage(
|
||||
recipient: Recipient,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
if (LocalInspectionMode.current) {
|
||||
Spacer(
|
||||
modifier = modifier
|
||||
.background(color = Color.Red, shape = CircleShape)
|
||||
)
|
||||
} else {
|
||||
AndroidView(
|
||||
factory = ::AvatarImageView,
|
||||
modifier = modifier
|
||||
) {
|
||||
it.setAvatarUsingProfile(recipient)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -78,6 +78,7 @@ import org.thoughtcrime.securesms.profiles.edit.CreateProfileActivity
|
|||
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.stories.Stories
|
||||
import org.thoughtcrime.securesms.stories.StoryViewerArgs
|
||||
|
@ -321,7 +322,11 @@ class ConversationSettingsFragment : DSLSettingsFragment(
|
|||
)
|
||||
|
||||
state.withRecipientSettingsState {
|
||||
customPref(BioTextPreference.RecipientModel(recipient = state.recipient))
|
||||
customPref(
|
||||
BioTextPreference.RecipientModel(recipient = state.recipient, onHeadlineClickListener = {
|
||||
AboutSheet.create(state.recipient).show(parentFragmentManager, null)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
state.withGroupSettingsState { groupState ->
|
||||
|
|
|
@ -31,10 +31,13 @@ object BioTextPreference {
|
|||
abstract fun getHeadlineText(context: Context): CharSequence
|
||||
abstract fun getSubhead1Text(context: Context): String?
|
||||
abstract fun getSubhead2Text(): String?
|
||||
|
||||
open val onHeadlineClickListener: () -> Unit = {}
|
||||
}
|
||||
|
||||
class RecipientModel(
|
||||
private val recipient: Recipient
|
||||
private val recipient: Recipient,
|
||||
override val onHeadlineClickListener: () -> Unit
|
||||
) : BioTextPreferenceModel<RecipientModel>() {
|
||||
|
||||
override fun getHeadlineText(context: Context): CharSequence {
|
||||
|
@ -44,12 +47,18 @@ object BioTextPreference {
|
|||
recipient.getDisplayNameOrUsername(context)
|
||||
}
|
||||
|
||||
return if (recipient.showVerified()) {
|
||||
SpannableStringBuilder(name).apply {
|
||||
if (!recipient.showVerified() && !recipient.isIndividual) {
|
||||
return name
|
||||
}
|
||||
|
||||
return SpannableStringBuilder(name).apply {
|
||||
if (recipient.showVerified()) {
|
||||
SpanUtil.appendCenteredImageSpan(this, ContextUtil.requireDrawable(context, R.drawable.ic_official_28), 28, 28)
|
||||
}
|
||||
} else {
|
||||
name
|
||||
|
||||
if (recipient.isIndividual) {
|
||||
SpanUtil.appendCenteredImageSpan(this, ContextUtil.requireDrawable(context, R.drawable.symbol_chevron_right_24_color_on_secondary_container), 24, 24)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,6 +110,7 @@ object BioTextPreference {
|
|||
|
||||
override fun bind(model: T) {
|
||||
headline.text = model.getHeadlineText(context)
|
||||
headline.setOnClickListener { model.onHeadlineClickListener() }
|
||||
|
||||
model.getSubhead1Text(context).let {
|
||||
subhead1.text = it
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.recipients.ui.about
|
||||
|
||||
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.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
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.graphics.painter.Painter
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.core.widget.TextViewCompat
|
||||
import org.signal.core.ui.BottomSheets
|
||||
import org.signal.core.ui.theme.SignalTheme
|
||||
import org.signal.core.util.getParcelableCompat
|
||||
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.compose.ComposeBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.stories.settings.my.SignalConnectionsBottomSheetDialogFragment
|
||||
import org.thoughtcrime.securesms.util.viewModel
|
||||
|
||||
/**
|
||||
* Displays all relevant context you know for a given user on the sheet.
|
||||
*/
|
||||
class AboutSheet : ComposeBottomSheetDialogFragment() {
|
||||
|
||||
companion object {
|
||||
|
||||
private const val RECIPIENT_ID = "recipient_id"
|
||||
|
||||
@JvmStatic
|
||||
fun create(recipient: Recipient): AboutSheet {
|
||||
return AboutSheet().apply {
|
||||
arguments = bundleOf(
|
||||
RECIPIENT_ID to recipient.id
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val peekHeightPercentage: Float = 1f
|
||||
|
||||
private val recipientId: RecipientId
|
||||
get() = requireArguments().getParcelableCompat(RECIPIENT_ID, RecipientId::class.java)!!
|
||||
|
||||
private val viewModel by viewModel {
|
||||
AboutSheetViewModel(recipientId)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun SheetContent() {
|
||||
val recipient by viewModel.recipient
|
||||
val groupsInCommonCount by viewModel.groupsInCommonCount
|
||||
|
||||
if (recipient.isPresent) {
|
||||
AboutSheetContent(
|
||||
recipient = recipient.get(),
|
||||
groupsInCommonCount = groupsInCommonCount,
|
||||
onClickSignalConnections = this::openSignalConnectionsSheet,
|
||||
onAvatarClicked = this::openProfilePhotoViewer
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun openSignalConnectionsSheet() {
|
||||
dismiss()
|
||||
SignalConnectionsBottomSheetDialogFragment().show(parentFragmentManager, null)
|
||||
}
|
||||
|
||||
private fun openProfilePhotoViewer() {
|
||||
startActivity(AvatarPreviewActivity.intentFromRecipientId(requireContext(), recipientId))
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun AboutSheetContentPreview() {
|
||||
SignalTheme {
|
||||
Surface {
|
||||
AboutSheetContent(
|
||||
recipient = Recipient.UNKNOWN,
|
||||
groupsInCommonCount = 0,
|
||||
onClickSignalConnections = {},
|
||||
onAvatarClicked = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AboutSheetContent(
|
||||
recipient: Recipient,
|
||||
groupsInCommonCount: Int,
|
||||
onClickSignalConnections: () -> Unit,
|
||||
onAvatarClicked: () -> Unit
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
BottomSheets.Handle(modifier = Modifier.padding(top = 6.dp))
|
||||
}
|
||||
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
AvatarImage(
|
||||
recipient = recipient,
|
||||
modifier = Modifier
|
||||
.padding(top = 56.dp)
|
||||
.size(240.dp)
|
||||
.clickable(onClick = onAvatarClicked)
|
||||
)
|
||||
|
||||
Text(
|
||||
text = "About",
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 32.dp)
|
||||
.padding(top = 20.dp, bottom = 8.dp)
|
||||
)
|
||||
|
||||
val context = LocalContext.current
|
||||
val displayName = remember(recipient) { recipient.getDisplayName(context) }
|
||||
|
||||
AboutRow(
|
||||
startIcon = painterResource(R.drawable.symbol_person_24),
|
||||
text = displayName,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
|
||||
if (recipient.about != null) {
|
||||
AboutRow(
|
||||
startIcon = painterResource(R.drawable.symbol_edit_24),
|
||||
text = {
|
||||
Row {
|
||||
AndroidView(factory = ::EmojiTextView) {
|
||||
it.text = recipient.combinedAboutAndEmoji
|
||||
|
||||
TextViewCompat.setTextAppearance(it, R.style.Signal_Text_BodyLarge)
|
||||
}
|
||||
}
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
if (recipient.isProfileSharing) {
|
||||
AboutRow(
|
||||
startIcon = painterResource(id = R.drawable.symbol_connections_24),
|
||||
text = stringResource(id = R.string.AboutSheet__signal_connection),
|
||||
endIcon = painterResource(id = R.drawable.symbol_chevron_right_compact_bold_16),
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onClickSignalConnections)
|
||||
)
|
||||
}
|
||||
|
||||
val shortName = remember(recipient) { recipient.getShortDisplayName(context) }
|
||||
if (recipient.isSystemContact) {
|
||||
AboutRow(
|
||||
startIcon = painterResource(id = R.drawable.symbol_person_circle_24),
|
||||
text = stringResource(id = R.string.AboutSheet__s_is_in_your_system_contacts, shortName),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
if (recipient.e164.isPresent) {
|
||||
val e164 = remember(recipient.e164.get()) {
|
||||
PhoneNumberFormatter.get(context).prettyPrintFormat(recipient.e164.get())
|
||||
}
|
||||
|
||||
AboutRow(
|
||||
startIcon = painterResource(R.drawable.symbol_phone_24),
|
||||
text = e164,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
val groupsInCommonText = if (recipient.hasGroupsInCommon()) {
|
||||
stringResource(id = R.string.AboutSheet__d_groups_in_common, groupsInCommonCount)
|
||||
} else {
|
||||
stringResource(id = R.string.AboutSheet__you_have_no_groups_in_common)
|
||||
}
|
||||
|
||||
AboutRow(
|
||||
startIcon = painterResource(R.drawable.symbol_group_24),
|
||||
text = groupsInCommonText,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
|
||||
if (!recipient.isProfileSharing) {
|
||||
AboutRow(
|
||||
startIcon = painterResource(R.drawable.symbol_error_circle_24),
|
||||
text = stringResource(id = R.string.AboutSheet__review_requests_carefully),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.size(32.dp))
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun AboutRowPreview() {
|
||||
SignalTheme {
|
||||
Surface {
|
||||
AboutRow(
|
||||
startIcon = painterResource(R.drawable.symbol_person_24),
|
||||
text = "Maya Johnson",
|
||||
endIcon = painterResource(id = R.drawable.symbol_chevron_right_compact_bold_16)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AboutRow(
|
||||
startIcon: Painter,
|
||||
text: String,
|
||||
modifier: Modifier = Modifier,
|
||||
endIcon: Painter? = null
|
||||
) {
|
||||
AboutRow(
|
||||
startIcon = startIcon,
|
||||
text = {
|
||||
Text(
|
||||
text = text,
|
||||
style = MaterialTheme.typography.bodyLarge
|
||||
)
|
||||
},
|
||||
modifier = modifier,
|
||||
endIcon = endIcon
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AboutRow(
|
||||
startIcon: Painter,
|
||||
text: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
endIcon: Painter? = null
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = modifier
|
||||
.padding(horizontal = 32.dp)
|
||||
.padding(top = 12.dp)
|
||||
) {
|
||||
Icon(
|
||||
painter = startIcon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(end = 16.dp)
|
||||
.size(20.dp)
|
||||
)
|
||||
|
||||
text()
|
||||
|
||||
if (endIcon != null) {
|
||||
Icon(
|
||||
painter = endIcon,
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colorScheme.outline
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.recipients.ui.about
|
||||
|
||||
import io.reactivex.rxjava3.core.Single
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
|
||||
class AboutSheetRepository {
|
||||
fun getGroupsInCommonCount(recipientId: RecipientId): Single<Int> {
|
||||
return Single.fromCallable {
|
||||
SignalDatabase.groups.getPushGroupsContainingMember(recipientId).size
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2023 Signal Messenger, LLC
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
package org.thoughtcrime.securesms.recipients.ui.about
|
||||
|
||||
import androidx.compose.runtime.IntState
|
||||
import androidx.compose.runtime.MutableIntState
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.rxjava3.disposables.Disposable
|
||||
import io.reactivex.rxjava3.kotlin.subscribeBy
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import java.util.Optional
|
||||
|
||||
class AboutSheetViewModel(
|
||||
recipientId: RecipientId,
|
||||
repository: AboutSheetRepository = AboutSheetRepository()
|
||||
) : ViewModel() {
|
||||
|
||||
private val _recipient: MutableState<Optional<Recipient>> = mutableStateOf(Optional.empty())
|
||||
val recipient: State<Optional<Recipient>> = _recipient
|
||||
|
||||
private val _groupsInCommonCount: MutableIntState = mutableIntStateOf(0)
|
||||
val groupsInCommonCount: IntState = _groupsInCommonCount
|
||||
|
||||
private val recipientDisposable: Disposable = Recipient
|
||||
.observable(recipientId)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeBy {
|
||||
_recipient.value = Optional.of(it)
|
||||
}
|
||||
|
||||
private val groupsInCommonDisposable: Disposable = repository
|
||||
.getGroupsInCommonCount(recipientId)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeBy {
|
||||
_groupsInCommonCount.intValue = it
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
recipientDisposable.dispose()
|
||||
groupsInCommonDisposable.dispose()
|
||||
}
|
||||
}
|
|
@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.recipients.Recipient;
|
|||
import org.thoughtcrime.securesms.recipients.RecipientExporter;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId;
|
||||
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.DrawableUtil;
|
||||
|
@ -192,7 +193,13 @@ public final class RecipientBottomSheetDialogFragment extends BottomSheetDialogF
|
|||
} else if (recipient.showVerified()) {
|
||||
SpanUtil.appendCenteredImageSpan(nameBuilder, ContextUtil.requireDrawable(requireContext(), R.drawable.ic_official_28), 28, 28);
|
||||
}
|
||||
|
||||
SpanUtil.appendCenteredImageSpan(nameBuilder, ContextUtil.requireDrawable(requireContext(), R.drawable.symbol_chevron_right_24_color_on_secondary_container), 24, 24);
|
||||
fullName.setText(nameBuilder);
|
||||
fullName.setOnClickListener(v -> {
|
||||
dismiss();
|
||||
AboutSheet.create(recipient).show(getParentFragmentManager(), null);
|
||||
});
|
||||
|
||||
String aboutText = recipient.getCombinedAboutAndEmoji();
|
||||
if (recipient.isReleaseNotes()) {
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="@color/signal_colorOnSecondaryContainer"
|
||||
android:pathData="M8.881,4.381a0.875,0.875 0,0 1,1.238 0l7,7a0.875,0.875 0,0 1,0 1.238l-7,7A0.875,0.875 0,0 1,8.88 18.38L15.263,12 8.88,5.619a0.875,0.875 0,0 1,0 -1.238Z" />
|
||||
</vector>
|
24
app/src/main/res/drawable/symbol_connections_24.xml
Normal file
24
app/src/main/res/drawable/symbol_connections_24.xml
Normal file
|
@ -0,0 +1,24 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="40dp"
|
||||
android:height="40dp"
|
||||
android:viewportWidth="40"
|
||||
android:viewportHeight="40">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M13.5 2.5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6Zm-4 6c0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4-4-1.8-4-4Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M13.5 25.5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6Zm-4 6c0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4-4-1.8-4-4Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M20.5 8.5c0-3.31 2.69-6 6-6s6 2.69 6 6-2.69 6-6 6-6-2.69-6-6Zm6-4c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M26.5 25.5c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6Zm-4 6c0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4-4-1.8-4-4Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M27 20c0-3.31 2.69-6 6-6s6 2.69 6 6-2.69 6-6 6-6-2.69-6-6Zm6-4c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4Z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M7 14c-3.31 0-6 2.69-6 6s2.69 6 6 6 6-2.69 6-6-2.69-6-6-6Zm-4 6c0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4-4-1.8-4-4Z"/>
|
||||
</vector>
|
|
@ -1,10 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:viewBindingIgnore="true"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
tools:viewBindingIgnore="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -1879,6 +1879,18 @@
|
|||
<!-- An accessibility label for screen readers on a view that can be expanded -->
|
||||
<string name="CallOverflowPopupWindow__expand_snackbar_accessibility_label">Expand raised hand view</string>
|
||||
|
||||
<!-- AboutSheet -->
|
||||
<!-- Displayed in a sheet row and allows user to open signal connection explanation on tap -->
|
||||
<string name="AboutSheet__signal_connection">Signal connection</string>
|
||||
<!-- Explains that the given user (placeholder is short name) is in the users system contact -->
|
||||
<string name="AboutSheet__s_is_in_your_system_contacts">%1$s is in your system contacts</string>
|
||||
<!-- Notice in a row when user has no groups in common -->
|
||||
<string name="AboutSheet__you_have_no_groups_in_common">You have no groups in common</string>
|
||||
<!-- Notice when a user is not a connection to review requests carefully -->
|
||||
<string name="AboutSheet__review_requests_carefully">Review requests carefully</string>
|
||||
<!-- Text used when user has groups in common. Placeholder is the count -->
|
||||
<string name="AboutSheet__d_groups_in_common">%1$d groups in common</string>
|
||||
|
||||
<!-- CallParticipantsListDialog -->
|
||||
<plurals name="CallParticipantsListDialog_in_this_call">
|
||||
<item quantity="one">In this call (%1$d)</item>
|
||||
|
|
Loading…
Add table
Reference in a new issue