Convert InviteActivity to a fragment.

This commit is contained in:
Michelle Tang
2025-05-01 14:23:57 -04:00
committed by Cody Henthorne
parent 524ffd9d79
commit 866c232045
14 changed files with 157 additions and 453 deletions

View File

@@ -146,17 +146,6 @@
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
android:exported="false" />
<activity android:name=".InviteActivity"
android:theme="@style/Signal.Light.NoActionBar.Invite"
android:windowSoftInputMode="stateHidden"
android:parentActivityName=".MainActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
android:exported="false">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".MainActivity" />
</activity>
<activity android:name=".DeviceProvisioningActivity"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
android:exported="true">

View File

@@ -1,267 +0,0 @@
package org.thoughtcrime.securesms;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.AnimRes;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.Toolbar;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.signal.core.util.concurrent.ListenableFuture.Listener;
import org.thoughtcrime.securesms.components.ContactFilterView;
import org.thoughtcrime.securesms.components.ContactFilterView.OnFilterChangedListener;
import org.thoughtcrime.securesms.contacts.ContactSelectionDisplayMode;
import org.thoughtcrime.securesms.contacts.SelectedContact;
import org.thoughtcrime.securesms.contacts.paged.ChatType;
import org.thoughtcrime.securesms.groups.SelectionLimits;
import org.thoughtcrime.securesms.mms.OutgoingMessage;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.sms.MessageSender;
import org.thoughtcrime.securesms.util.DynamicNoActionBarInviteTheme;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
import org.thoughtcrime.securesms.util.text.AfterTextChanged;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
public class InviteActivity extends PassphraseRequiredActivity implements ContactSelectionListFragment.OnContactSelectedListener {
private ContactSelectionListFragment contactsFragment;
private EditText inviteText;
private ViewGroup smsSendFrame;
private Button smsSendButton;
private Animation slideInAnimation;
private Animation slideOutAnimation;
private final DynamicTheme dynamicTheme = new DynamicNoActionBarInviteTheme();
@Override
protected void onPreCreate() {
super.onPreCreate();
dynamicTheme.onCreate(this);
}
@Override
protected void onCreate(Bundle savedInstanceState, boolean ready) {
getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, ContactSelectionDisplayMode.FLAG_SMS);
getIntent().putExtra(ContactSelectionListFragment.SELECTION_LIMITS, SelectionLimits.NO_LIMITS);
getIntent().putExtra(ContactSelectionListFragment.HIDE_COUNT, true);
getIntent().putExtra(ContactSelectionListFragment.REFRESHABLE, false);
setContentView(R.layout.invite_activity);
initializeAppBar();
initializeResources();
}
@Override
protected void onResume() {
super.onResume();
dynamicTheme.onResume(this);
}
private void initializeAppBar() {
final Toolbar primaryToolbar = findViewById(R.id.toolbar);
setSupportActionBar(primaryToolbar);
assert getSupportActionBar() != null;
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.AndroidManifest__invite_friends);
}
private void initializeResources() {
slideInAnimation = loadAnimation(R.anim.slide_from_bottom);
slideOutAnimation = loadAnimation(R.anim.slide_to_bottom);
View shareButton = findViewById(R.id.share_button);
TextView shareText = findViewById(R.id.share_text);
View smsButton = findViewById(R.id.sms_button);
Button smsCancelButton = findViewById(R.id.cancel_sms_button);
ContactFilterView contactFilter = findViewById(R.id.contact_filter_edit_text);
inviteText = findViewById(R.id.invite_text);
smsSendFrame = findViewById(R.id.sms_send_frame);
smsSendButton = findViewById(R.id.send_sms_button);
contactsFragment = (ContactSelectionListFragment)getSupportFragmentManager().findFragmentById(R.id.contact_selection_list_fragment);
inviteText.setText(getString(R.string.InviteActivity_lets_switch_to_signal, getString(R.string.install_url)));
inviteText.addTextChangedListener(new AfterTextChanged(editable -> {
boolean isEnabled = editable.length() > 0;
smsButton.setEnabled(isEnabled);
shareButton.setEnabled(isEnabled);
smsButton.animate().alpha(isEnabled ? 1f : 0.5f);
shareButton.animate().alpha(isEnabled ? 1f : 0.5f);
}));
updateSmsButtonText(contactsFragment.getSelectedContacts().size());
smsCancelButton.setOnClickListener(new SmsCancelClickListener());
smsSendButton.setOnClickListener(new SmsSendClickListener());
contactFilter.setOnFilterChangedListener(new ContactFilterChangedListener());
smsButton.setVisibility(View.GONE);
shareText.setText(R.string.InviteActivity_share);
shareButton.setOnClickListener(new ShareClickListener());
}
private Animation loadAnimation(@AnimRes int animResId) {
final Animation animation = AnimationUtils.loadAnimation(this, animResId);
animation.setInterpolator(new FastOutSlowInInterpolator());
return animation;
}
@Override
public void onBeforeContactSelected(boolean isFromUnknownSearchKey, @NonNull Optional<RecipientId> recipientId, String number, @NonNull Optional<ChatType> chatType, @NonNull Consumer<Boolean> callback) {
updateSmsButtonText(contactsFragment.getSelectedContacts().size() + 1);
callback.accept(true);
}
@Override
public void onContactDeselected(@NonNull Optional<RecipientId> recipientId, String number, @NonNull Optional<ChatType> chatType) {
updateSmsButtonText(contactsFragment.getSelectedContacts().size());
}
@Override
public void onSelectionChanged() {
}
private void sendSmsInvites() {
new SendSmsInvitesAsyncTask(this, inviteText.getText().toString())
.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,
contactsFragment.getSelectedContacts()
.toArray(new SelectedContact[0]));
}
private void updateSmsButtonText(int count) {
smsSendButton.setText(getResources().getString(R.string.InviteActivity_send_sms, count));
smsSendButton.setEnabled(count > 0);
}
@Override public void onBackPressed() {
if (smsSendFrame.getVisibility() == View.VISIBLE) {
cancelSmsSelection();
} else {
super.onBackPressed();
}
}
@Override public boolean onSupportNavigateUp() {
if (smsSendFrame.getVisibility() == View.VISIBLE) {
cancelSmsSelection();
return false;
} else {
return super.onSupportNavigateUp();
}
}
private void cancelSmsSelection() {
contactsFragment.reset();
updateSmsButtonText(contactsFragment.getSelectedContacts().size());
ViewUtil.animateOut(smsSendFrame, slideOutAnimation, View.GONE);
}
private class ShareClickListener implements OnClickListener {
@Override
public void onClick(View v) {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, inviteText.getText().toString());
sendIntent.setType("text/plain");
if (sendIntent.resolveActivity(getPackageManager()) != null) {
startActivity(Intent.createChooser(sendIntent, getString(R.string.InviteActivity_invite_to_signal)));
} else {
Toast.makeText(InviteActivity.this, R.string.InviteActivity_no_app_to_share_to, Toast.LENGTH_LONG).show();
}
}
}
private class SmsCancelClickListener implements OnClickListener {
@Override
public void onClick(View v) {
cancelSmsSelection();
}
}
private class SmsSendClickListener implements OnClickListener {
@Override
public void onClick(View v) {
new MaterialAlertDialogBuilder(InviteActivity.this)
.setTitle(getResources().getQuantityString(R.plurals.InviteActivity_send_sms_invites,
contactsFragment.getSelectedContacts().size(),
contactsFragment.getSelectedContacts().size()))
.setMessage(inviteText.getText().toString())
.setPositiveButton(R.string.yes, (dialog, which) -> sendSmsInvites())
.setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss())
.show();
}
}
private class ContactFilterChangedListener implements OnFilterChangedListener {
@Override
public void onFilterChanged(String filter) {
contactsFragment.setQueryFilter(filter);
}
}
@SuppressLint("StaticFieldLeak")
private class SendSmsInvitesAsyncTask extends ProgressDialogAsyncTask<SelectedContact,Void,Void> {
private final String message;
SendSmsInvitesAsyncTask(Context context, String message) {
super(context, R.string.InviteActivity_sending, R.string.InviteActivity_sending);
this.message = message;
}
@Override
protected Void doInBackground(SelectedContact... contacts) {
final Context context = getContext();
if (context == null) return null;
for (SelectedContact contact : contacts) {
RecipientId recipientId = contact.getOrCreateRecipientId();
Recipient recipient = Recipient.resolved(recipientId);
MessageSender.send(context, OutgoingMessage.sms(recipient, message), -1L, MessageSender.SendType.SMS, null, null);
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
final Context context = getContext();
if (context == null) return;
ViewUtil.animateOut(smsSendFrame, slideOutAnimation, View.GONE).addListener(new Listener<Boolean>() {
@Override
public void onSuccess(Boolean result) {
contactsFragment.reset();
}
@Override
public void onFailure(ExecutionException e) {}
});
Toast.makeText(context, R.string.InviteActivity_invitations_sent, Toast.LENGTH_LONG).show();
}
}
}

View File

@@ -0,0 +1,123 @@
package org.thoughtcrime.securesms
import android.content.Intent
import android.widget.Toast
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import org.signal.core.ui.compose.Previews
import org.signal.core.ui.compose.Scaffolds
import org.signal.core.ui.compose.SignalPreview
import org.thoughtcrime.securesms.compose.ComposeFragment
/**
* Fragment when inviting someone to use Signal
*/
class InviteFragment : ComposeFragment() {
@Composable
override fun FragmentContent() {
Scaffolds.Settings(
title = stringResource(id = R.string.AndroidManifest__invite_friends),
onNavigationClick = { requireActivity().onNavigateUp() },
navigationIconPainter = painterResource(id = R.drawable.symbol_arrow_start_24),
navigationContentDescription = stringResource(id = R.string.Material3SearchToolbar__close)
) { contentPadding: PaddingValues ->
InviteScreen(
onShare = { inviteText -> onShare(inviteText) },
modifier = Modifier.padding(contentPadding)
)
}
}
private fun onShare(inviteText: String) {
val sendIntent = Intent()
.setAction(Intent.ACTION_SEND)
.putExtra(Intent.EXTRA_TEXT, inviteText)
.setType("text/plain")
if (sendIntent.resolveActivity(requireContext().packageManager) != null) {
startActivity(Intent.createChooser(sendIntent, getString(R.string.InviteActivity_invite_to_signal)))
} else {
Toast.makeText(requireContext(), R.string.InviteActivity_no_app_to_share_to, Toast.LENGTH_LONG).show()
}
}
}
@Composable
fun InviteScreen(
onShare: (String) -> Unit = {},
modifier: Modifier = Modifier
) {
val default = stringResource(R.string.InviteActivity_lets_switch_to_signal, stringResource(R.string.install_url))
var inviteText by remember { mutableStateOf(TextFieldValue(default, TextRange(default.length))) }
Column(
modifier = modifier.padding(16.dp).fillMaxHeight()
) {
TextField(
value = inviteText,
onValueChange = { inviteText = it },
keyboardOptions = KeyboardOptions(capitalization = KeyboardCapitalization.Sentences),
colors = TextFieldDefaults.colors(
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
unfocusedContainerColor = MaterialTheme.colorScheme.surfaceVariant,
focusedContainerColor = MaterialTheme.colorScheme.surfaceVariant
),
modifier = Modifier.fillMaxWidth().padding(bottom = 16.dp),
shape = RoundedCornerShape(12.dp)
)
Row(
modifier = Modifier
.clickable(onClick = { onShare(inviteText.text) })
.fillMaxWidth()
.padding(vertical = 16.dp)
) {
Icon(
imageVector = ImageVector.vectorResource(R.drawable.symbol_share_android_24),
contentDescription = stringResource(R.string.InviteActivity_share)
)
Text(
text = stringResource(id = R.string.InviteActivity_share),
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.padding(horizontal = 16.dp)
)
}
}
}
@SignalPreview
@Composable
private fun InviteScreenPreview() {
Previews.Preview {
InviteScreen()
}
}

View File

@@ -586,8 +586,7 @@ class MainActivity : PassphraseRequiredActivity(), VoiceNoteMediaControllerOwner
}
override fun onInviteFriendsClick() {
val intent = Intent(this@MainActivity, InviteActivity::class.java)
startActivity(intent)
openSettings.launch(AppSettingsActivity.invite(this@MainActivity))
}
override fun onFilterUnreadChatsClick() {

View File

@@ -59,11 +59,6 @@ public class MainNavigator {
activity.startActivity(CreateGroupActivity.newIntent(activity));
}
public void goToInvite() {
Intent intent = new Intent(activity, InviteActivity.class);
activity.startActivity(intent);
}
private @NonNull FragmentManager getFragmentManager() {
return activity.getSupportFragmentManager();
}

View File

@@ -42,6 +42,7 @@ import org.signal.core.util.logging.Log;
import org.thoughtcrime.securesms.calls.YouAreAlreadyInACallSnackbar;
import org.thoughtcrime.securesms.components.menu.ActionItem;
import org.thoughtcrime.securesms.components.menu.SignalContextMenu;
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity;
import org.thoughtcrime.securesms.contacts.management.ContactsManagementRepository;
import org.thoughtcrime.securesms.contacts.management.ContactsManagementViewModel;
import org.thoughtcrime.securesms.contacts.paged.ChatType;
@@ -215,7 +216,7 @@ public class NewConversationActivity extends ContactSelectionActivity
}
private void handleInvite() {
startActivity(new Intent(this, InviteActivity.class));
startActivity(AppSettingsActivity.invite(this));
}
@Override

View File

@@ -13,9 +13,9 @@ import org.signal.core.util.concurrent.SimpleTask
import org.signal.core.util.logging.Log
import org.thoughtcrime.securesms.ContactSelectionActivity
import org.thoughtcrime.securesms.ContactSelectionListFragment
import org.thoughtcrime.securesms.InviteActivity
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.calls.YouAreAlreadyInACallSnackbar
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
import org.thoughtcrime.securesms.contacts.ContactSelectionDisplayMode
import org.thoughtcrime.securesms.contacts.paged.ChatType
import org.thoughtcrime.securesms.keyvalue.SignalStore
@@ -111,7 +111,7 @@ class NewCallActivity : ContactSelectionActivity(), ContactSelectionListFragment
}
override fun onInvite() {
startActivity(Intent(this, InviteActivity::class.java))
startActivity(AppSettingsActivity.invite(this))
}
private fun handleManualRefresh() {
@@ -130,7 +130,7 @@ class NewCallActivity : ContactSelectionActivity(), ContactSelectionListFragment
when (menuItem.itemId) {
android.R.id.home -> ActivityCompat.finishAfterTransition(this@NewCallActivity)
R.id.menu_refresh -> handleManualRefresh()
R.id.menu_invite -> startActivity(Intent(this@NewCallActivity, InviteActivity::class.java))
R.id.menu_invite -> startActivity(AppSettingsActivity.invite(this@NewCallActivity))
}
return true

View File

@@ -78,6 +78,7 @@ class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
)
StartLocation.BACKUPS_SETTINGS -> AppSettingsFragmentDirections.actionDirectToBackupsSettingsFragment()
StartLocation.INVITE -> AppSettingsFragmentDirections.actionDirectToInviteFragment()
}
}
@@ -223,6 +224,9 @@ class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
@JvmStatic
fun backupsSettings(context: Context): Intent = getIntentForStartLocation(context, StartLocation.BACKUPS_SETTINGS)
@JvmStatic
fun invite(context: Context): Intent = getIntentForStartLocation(context, StartLocation.INVITE)
private fun getIntentForStartLocation(context: Context, startLocation: StartLocation): Intent {
return Intent(context, AppSettingsActivity::class.java)
.putExtra(ARG_NAV_GRAPH, R.navigation.app_settings_with_change_number)
@@ -250,7 +254,8 @@ class AppSettingsActivity : DSLSettingsActivity(), GooglePayComponent {
REMOTE_BACKUPS(16),
CHAT_FOLDERS(17),
CREATE_CHAT_FOLDER(18),
BACKUPS_SETTINGS(19);
BACKUPS_SETTINGS(19),
INVITE(20);
companion object {
fun fromCode(code: Int?): StartLocation {

View File

@@ -468,7 +468,7 @@ private fun AppSettingsContent(
text = stringResource(R.string.AppSettingsFragment__invite_your_friends),
icon = painterResource(R.drawable.symbol_invite_24),
onClick = {
callbacks.navigate(R.id.action_appSettingsFragment_to_inviteActivity)
callbacks.navigate(R.id.action_appSettingsFragment_to_inviteFragment)
}
)
}

View File

@@ -36,7 +36,6 @@ import org.signal.core.util.getParcelableArrayListExtraCompat
import org.signal.donations.InAppPaymentType
import org.thoughtcrime.securesms.AvatarPreviewActivity
import org.thoughtcrime.securesms.BlockUnblockDialog
import org.thoughtcrime.securesms.InviteActivity
import org.thoughtcrime.securesms.MuteDialog
import org.thoughtcrime.securesms.PushContactSelectionActivity
import org.thoughtcrime.securesms.R
@@ -389,7 +388,7 @@ class ConversationSettingsFragment : DSLSettingsFragment(
LegacyGroupPreference.Model(
state = groupState.legacyGroupState,
onLearnMoreClick = { GroupsLearnMoreBottomSheetDialogFragment.show(parentFragmentManager) },
onMmsWarningClick = { startActivity(Intent(requireContext(), InviteActivity::class.java)) }
onMmsWarningClick = { startActivity(AppSettingsActivity.invite(requireContext())) }
)
)
}

View File

@@ -24,9 +24,9 @@ import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import org.thoughtcrime.securesms.InviteActivity;
import org.thoughtcrime.securesms.LoggingFragment;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.ThemeUtil;
@@ -152,7 +152,7 @@ public class CameraContactSelectionFragment extends LoggingFragment implements C
@Override
public void onInviteContactsClicked() {
startActivity(new Intent(requireContext(), InviteActivity.class));
startActivity(AppSettingsActivity.invite(requireContext()));
}
private void initViewModel() {

View File

@@ -5,7 +5,6 @@
package org.thoughtcrime.securesms.megaphone
import android.content.Intent
import androidx.annotation.ColorRes
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
@@ -48,8 +47,8 @@ import androidx.compose.ui.unit.dp
import org.signal.core.ui.compose.IconButtons
import org.signal.core.ui.compose.Previews
import org.signal.core.ui.compose.SignalPreview
import org.thoughtcrime.securesms.InviteActivity
import org.thoughtcrime.securesms.R
import org.thoughtcrime.securesms.components.settings.app.AppSettingsActivity
import org.thoughtcrime.securesms.groups.ui.creategroup.CreateGroupActivity
import org.thoughtcrime.securesms.keyvalue.SignalStore
import org.thoughtcrime.securesms.main.EmptyMegaphoneActionController
@@ -313,7 +312,7 @@ abstract class OnboardingState private constructor(
override fun onItemActionClick(onboardingListItem: OnboardingListItem) {
when (onboardingListItem) {
OnboardingListItem.GROUP -> megaphoneActionController.onMegaphoneNavigationRequested(CreateGroupActivity.newIntent(megaphoneActionController.megaphoneActivity))
OnboardingListItem.INVITE -> megaphoneActionController.onMegaphoneNavigationRequested(Intent(megaphoneActionController.megaphoneActivity, InviteActivity::class.java))
OnboardingListItem.INVITE -> megaphoneActionController.onMegaphoneNavigationRequested(AppSettingsActivity.invite(megaphoneActionController.megaphoneActivity))
OnboardingListItem.ADD_PHOTO -> {
megaphoneActionController.onMegaphoneNavigationRequested(EditProfileActivity.getIntentForAvatarEdit(megaphoneActionController.megaphoneActivity))
SignalStore.onboarding.setShowAddPhoto(false)

View File

@@ -1,148 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
tools:viewBindingIgnore="true"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.appcompat.widget.Toolbar
style="?actionBarStyle"
android:theme="?actionBarStyle"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:titleTextAppearance="@style/TextSecure.TitleTextStyle"
app:subtitleTextAppearance="@style/TextSecure.SubtitleTextStyle"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ScrollView android:layout_width="match_parent"
android:layout_height="0dp"
android:fillViewport="true"
android:clickable="false"
app:layout_constraintTop_toBottomOf="@id/toolbar"
app:layout_constraintBottom_toBottomOf="parent"
tools:visibility="gone">
<LinearLayout android:layout_gravity="center"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:orientation="vertical"
android:paddingTop="14dp"
android:paddingStart="28dp"
android:paddingEnd="28dp">
<EditText android:id="@+id/invite_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minLines="2"
tools:text="Let's switch to Signal: https://sgnl.link/asdfdfsa"
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
android:background="@drawable/invite_edit_text_background"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:textColor="@color/signal_text_primary"
android:paddingStart="10dp"
android:paddingEnd="20dp"
android:minHeight="@dimen/invite_edit_text_min_height"
android:gravity="top"
android:inputType="textShortMessage|textMultiLine"/>
<LinearLayout android:id="@+id/sms_button"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="16dp"
android:background="?attr/selectableItemBackground">
<ImageView android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
app:srcCompat="@drawable/ic_invite_inverse_28" />
<TextView style="@style/Signal.Text.Body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="26dp"
android:text="@string/InviteActivity_share_with_contacts" />
</LinearLayout>
<LinearLayout android:id="@+id/share_button"
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_marginTop="16dp"
android:background="?attr/selectableItemBackground">
<ImageView android:layout_width="24dp"
android:layout_height="24dp"
android:layout_gravity="center_vertical"
app:srcCompat="@drawable/ic_share_24_tinted" />
<TextView android:id="@+id/share_text"
style="@style/Signal.Text.Body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="26dp"
android:text="@string/InviteActivity_share_via" />
</LinearLayout>
</LinearLayout>
</ScrollView>
<LinearLayout android:id="@+id/sms_send_frame"
android:layout_width="match_parent"
android:layout_height="0dp"
android:background="?android:windowBackground"
android:orientation="vertical"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar"
tools:visibility="visible">
<org.thoughtcrime.securesms.components.ContactFilterView
android:id="@+id/contact_filter_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dsl_settings_gutter"
android:layout_marginTop="4dp"
android:layout_marginBottom="12dp"
android:layout_marginRight="@dimen/dsl_settings_gutter"
android:minHeight="44dp" />
<fragment android:id="@+id/contact_selection_list_fragment"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment"
tools:layout="@layout/contact_selection_list_fragment"/>
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:padding="10dp"
android:orientation="horizontal">
<Button android:id="@+id/cancel_sms_button"
style="@style/Signal.Widget.Button.Large.Primary.Inverse"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="@string/InviteActivity_cancel" />
<Button android:id="@+id/send_sms_button"
style="@style/Signal.Widget.Button.Large.Primary.Inverse"
android:enabled="false"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:text="Send SMS (0)"/>
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@@ -114,8 +114,8 @@
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit" />
<action
android:id="@+id/action_appSettingsFragment_to_inviteActivity"
app:destination="@id/inviteActivity"
android:id="@+id/action_appSettingsFragment_to_inviteFragment"
app:destination="@id/inviteFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
@@ -560,11 +560,10 @@
android:label="submit_debug_log_activity" />
<!-- endregion -->
<activity
android:id="@+id/inviteActivity"
android:name="org.thoughtcrime.securesms.InviteActivity"
android:label="invite_activity"
tools:layout="@layout/invite_activity" />
<fragment
android:id="@+id/inviteFragment"
android:name="org.thoughtcrime.securesms.InviteFragment"
android:label="invite_fragment" />
<!-- region Direct-To-Page actions -->
@@ -740,6 +739,16 @@
app:popUpTo="@id/app_settings"
app:popUpToInclusive="true" />
<action
android:id="@+id/action_direct_to_inviteFragment"
app:destination="@id/inviteFragment"
app:enterAnim="@anim/fragment_open_enter"
app:exitAnim="@anim/fragment_open_exit"
app:popEnterAnim="@anim/fragment_close_enter"
app:popExitAnim="@anim/fragment_close_exit"
app:popUpTo="@id/app_settings"
app:popUpToInclusive="true" />
<!-- endregion -->
<!-- Internal Settings -->