That fuck shit the fascists are using
at master 268 lines 10 kB view raw
1package org.tm.archive; 2 3import android.annotation.SuppressLint; 4import android.content.Context; 5import android.content.Intent; 6import android.os.AsyncTask; 7import android.os.Bundle; 8import android.view.View; 9import android.view.View.OnClickListener; 10import android.view.ViewGroup; 11import android.view.animation.Animation; 12import android.view.animation.AnimationUtils; 13import android.widget.Button; 14import android.widget.EditText; 15import android.widget.TextView; 16import android.widget.Toast; 17 18import androidx.annotation.AnimRes; 19import androidx.annotation.NonNull; 20import androidx.appcompat.widget.Toolbar; 21import androidx.interpolator.view.animation.FastOutSlowInInterpolator; 22 23import com.google.android.material.dialog.MaterialAlertDialogBuilder; 24 25import org.signal.core.util.concurrent.ListenableFuture.Listener; 26import org.tm.archive.components.ContactFilterView; 27import org.tm.archive.components.ContactFilterView.OnFilterChangedListener; 28import org.tm.archive.contacts.ContactSelectionDisplayMode; 29import org.tm.archive.contacts.SelectedContact; 30import org.tm.archive.groups.SelectionLimits; 31import org.tm.archive.keyvalue.SignalStore; 32import org.tm.archive.mms.OutgoingMessage; 33import org.tm.archive.recipients.Recipient; 34import org.tm.archive.recipients.RecipientId; 35import org.tm.archive.sms.MessageSender; 36import org.tm.archive.util.DynamicNoActionBarInviteTheme; 37import org.tm.archive.util.DynamicTheme; 38import org.tm.archive.util.Util; 39import org.tm.archive.util.ViewUtil; 40import org.tm.archive.util.task.ProgressDialogAsyncTask; 41import org.tm.archive.util.text.AfterTextChanged; 42 43import java.util.Optional; 44import java.util.concurrent.ExecutionException; 45import java.util.function.Consumer; 46 47public class InviteActivity extends PassphraseRequiredActivity implements ContactSelectionListFragment.OnContactSelectedListener { 48 49 private ContactSelectionListFragment contactsFragment; 50 private EditText inviteText; 51 private ViewGroup smsSendFrame; 52 private Button smsSendButton; 53 private Animation slideInAnimation; 54 private Animation slideOutAnimation; 55 private final DynamicTheme dynamicTheme = new DynamicNoActionBarInviteTheme(); 56 57 @Override 58 protected void onPreCreate() { 59 super.onPreCreate(); 60 dynamicTheme.onCreate(this); 61 } 62 63 @Override 64 protected void onCreate(Bundle savedInstanceState, boolean ready) { 65 getIntent().putExtra(ContactSelectionListFragment.DISPLAY_MODE, ContactSelectionDisplayMode.FLAG_SMS); 66 getIntent().putExtra(ContactSelectionListFragment.SELECTION_LIMITS, SelectionLimits.NO_LIMITS); 67 getIntent().putExtra(ContactSelectionListFragment.HIDE_COUNT, true); 68 getIntent().putExtra(ContactSelectionListFragment.REFRESHABLE, false); 69 70 setContentView(R.layout.invite_activity); 71 72 initializeAppBar(); 73 initializeResources(); 74 } 75 76 @Override 77 protected void onResume() { 78 super.onResume(); 79 dynamicTheme.onResume(this); 80 } 81 82 private void initializeAppBar() { 83 final Toolbar primaryToolbar = findViewById(R.id.toolbar); 84 setSupportActionBar(primaryToolbar); 85 86 assert getSupportActionBar() != null; 87 88 getSupportActionBar().setDisplayHomeAsUpEnabled(true); 89 getSupportActionBar().setTitle(R.string.AndroidManifest__invite_friends); 90 } 91 92 private void initializeResources() { 93 slideInAnimation = loadAnimation(R.anim.slide_from_bottom); 94 slideOutAnimation = loadAnimation(R.anim.slide_to_bottom); 95 96 View shareButton = findViewById(R.id.share_button); 97 TextView shareText = findViewById(R.id.share_text); 98 View smsButton = findViewById(R.id.sms_button); 99 Button smsCancelButton = findViewById(R.id.cancel_sms_button); 100 ContactFilterView contactFilter = findViewById(R.id.contact_filter_edit_text); 101 102 inviteText = findViewById(R.id.invite_text); 103 smsSendFrame = findViewById(R.id.sms_send_frame); 104 smsSendButton = findViewById(R.id.send_sms_button); 105 contactsFragment = (ContactSelectionListFragment)getSupportFragmentManager().findFragmentById(R.id.contact_selection_list_fragment); 106 107 inviteText.setText(getString(R.string.InviteActivity_lets_switch_to_signal, getString(R.string.install_url))); 108 inviteText.addTextChangedListener(new AfterTextChanged(editable -> { 109 boolean isEnabled = editable.length() > 0; 110 smsButton.setEnabled(isEnabled); 111 shareButton.setEnabled(isEnabled); 112 smsButton.animate().alpha(isEnabled ? 1f : 0.5f); 113 shareButton.animate().alpha(isEnabled ? 1f : 0.5f); 114 })); 115 116 updateSmsButtonText(contactsFragment.getSelectedContacts().size()); 117 118 smsCancelButton.setOnClickListener(new SmsCancelClickListener()); 119 smsSendButton.setOnClickListener(new SmsSendClickListener()); 120 contactFilter.setOnFilterChangedListener(new ContactFilterChangedListener()); 121 122 smsButton.setVisibility(View.GONE); 123 shareText.setText(R.string.InviteActivity_share); 124 shareButton.setOnClickListener(new ShareClickListener()); 125 } 126 127 private Animation loadAnimation(@AnimRes int animResId) { 128 final Animation animation = AnimationUtils.loadAnimation(this, animResId); 129 animation.setInterpolator(new FastOutSlowInInterpolator()); 130 return animation; 131 } 132 133 @Override 134 public void onBeforeContactSelected(boolean isFromUnknownSearchKey, @NonNull Optional<RecipientId> recipientId, String number, @NonNull Consumer<Boolean> callback) { 135 updateSmsButtonText(contactsFragment.getSelectedContacts().size() + 1); 136 callback.accept(true); 137 } 138 139 @Override 140 public void onContactDeselected(@NonNull Optional<RecipientId> recipientId, String number) { 141 updateSmsButtonText(contactsFragment.getSelectedContacts().size()); 142 } 143 144 @Override 145 public void onSelectionChanged() { 146 } 147 148 private void sendSmsInvites() { 149 new SendSmsInvitesAsyncTask(this, inviteText.getText().toString()) 150 .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 151 contactsFragment.getSelectedContacts() 152 .toArray(new SelectedContact[0])); 153 } 154 155 private void updateSmsButtonText(int count) { 156 smsSendButton.setText(getResources().getString(R.string.InviteActivity_send_sms, count)); 157 smsSendButton.setEnabled(count > 0); 158 } 159 160 @Override public void onBackPressed() { 161 if (smsSendFrame.getVisibility() == View.VISIBLE) { 162 cancelSmsSelection(); 163 } else { 164 super.onBackPressed(); 165 } 166 } 167 168 @Override public boolean onSupportNavigateUp() { 169 if (smsSendFrame.getVisibility() == View.VISIBLE) { 170 cancelSmsSelection(); 171 return false; 172 } else { 173 return super.onSupportNavigateUp(); 174 } 175 } 176 177 private void cancelSmsSelection() { 178 contactsFragment.reset(); 179 updateSmsButtonText(contactsFragment.getSelectedContacts().size()); 180 ViewUtil.animateOut(smsSendFrame, slideOutAnimation, View.GONE); 181 } 182 183 private class ShareClickListener implements OnClickListener { 184 @Override 185 public void onClick(View v) { 186 Intent sendIntent = new Intent(); 187 sendIntent.setAction(Intent.ACTION_SEND); 188 sendIntent.putExtra(Intent.EXTRA_TEXT, inviteText.getText().toString()); 189 sendIntent.setType("text/plain"); 190 if (sendIntent.resolveActivity(getPackageManager()) != null) { 191 startActivity(Intent.createChooser(sendIntent, getString(R.string.InviteActivity_invite_to_signal))); 192 } else { 193 Toast.makeText(InviteActivity.this, R.string.InviteActivity_no_app_to_share_to, Toast.LENGTH_LONG).show(); 194 } 195 } 196 } 197 198 private class SmsCancelClickListener implements OnClickListener { 199 @Override 200 public void onClick(View v) { 201 cancelSmsSelection(); 202 } 203 } 204 205 private class SmsSendClickListener implements OnClickListener { 206 @Override 207 public void onClick(View v) { 208 new MaterialAlertDialogBuilder(InviteActivity.this) 209 .setTitle(getResources().getQuantityString(R.plurals.InviteActivity_send_sms_invites, 210 contactsFragment.getSelectedContacts().size(), 211 contactsFragment.getSelectedContacts().size())) 212 .setMessage(inviteText.getText().toString()) 213 .setPositiveButton(R.string.yes, (dialog, which) -> sendSmsInvites()) 214 .setNegativeButton(R.string.no, (dialog, which) -> dialog.dismiss()) 215 .show(); 216 } 217 } 218 219 private class ContactFilterChangedListener implements OnFilterChangedListener { 220 @Override 221 public void onFilterChanged(String filter) { 222 contactsFragment.setQueryFilter(filter); 223 } 224 } 225 226 @SuppressLint("StaticFieldLeak") 227 private class SendSmsInvitesAsyncTask extends ProgressDialogAsyncTask<SelectedContact,Void,Void> { 228 private final String message; 229 230 SendSmsInvitesAsyncTask(Context context, String message) { 231 super(context, R.string.InviteActivity_sending, R.string.InviteActivity_sending); 232 this.message = message; 233 } 234 235 @Override 236 protected Void doInBackground(SelectedContact... contacts) { 237 final Context context = getContext(); 238 if (context == null) return null; 239 240 for (SelectedContact contact : contacts) { 241 RecipientId recipientId = contact.getOrCreateRecipientId(context); 242 Recipient recipient = Recipient.resolved(recipientId); 243 244 MessageSender.send(context, OutgoingMessage.sms(recipient, message), -1L, MessageSender.SendType.SMS, null, null); 245 } 246 247 return null; 248 } 249 250 @Override 251 protected void onPostExecute(Void aVoid) { 252 super.onPostExecute(aVoid); 253 final Context context = getContext(); 254 if (context == null) return; 255 256 ViewUtil.animateOut(smsSendFrame, slideOutAnimation, View.GONE).addListener(new Listener<Boolean>() { 257 @Override 258 public void onSuccess(Boolean result) { 259 contactsFragment.reset(); 260 } 261 262 @Override 263 public void onFailure(ExecutionException e) {} 264 }); 265 Toast.makeText(context, R.string.InviteActivity_invitations_sent, Toast.LENGTH_LONG).show(); 266 } 267 } 268}