That fuck shit the fascists are using
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}