1package eu.siacs.conversations.ui;
2
3import android.app.AlertDialog;
4import android.content.ClipData;
5import android.content.ClipDescription;
6import android.content.ClipboardManager;
7import android.content.Context;
8import android.content.Intent;
9import android.databinding.DataBindingUtil;
10import android.os.Bundle;
11import android.support.design.widget.Snackbar;
12import android.support.v7.widget.Toolbar;
13import android.text.Html;
14import android.view.View;
15
16import eu.siacs.conversations.R;
17import eu.siacs.conversations.databinding.ActivityVerifyBinding;
18import eu.siacs.conversations.entities.Account;
19import eu.siacs.conversations.services.QuickConversationsService;
20import eu.siacs.conversations.ui.util.PinEntryWrapper;
21import eu.siacs.conversations.utils.AccountUtils;
22import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
23
24import static android.content.ClipDescription.MIMETYPE_TEXT_PLAIN;
25
26public class VerifyActivity extends XmppActivity implements ClipboardManager.OnPrimaryClipChangedListener, QuickConversationsService.OnVerification {
27
28 private ActivityVerifyBinding binding;
29 private Account account;
30 private PinEntryWrapper pinEntryWrapper;
31 private ClipboardManager clipboardManager;
32 private String pasted = null;
33 private boolean verifying = false;
34
35
36 @Override
37 protected void onCreate(final Bundle savedInstanceState) {
38 super.onCreate(savedInstanceState);
39 String pin = savedInstanceState != null ? savedInstanceState.getString("pin") : null;
40 boolean verifying = savedInstanceState != null && savedInstanceState.getBoolean("verifying");
41 this.pasted = savedInstanceState != null ? savedInstanceState.getString("pasted") : null;
42 this.binding = DataBindingUtil.setContentView(this, R.layout.activity_verify);
43 setSupportActionBar((Toolbar) this.binding.toolbar);
44 this.pinEntryWrapper = new PinEntryWrapper(binding.pinBox);
45 if (pin != null) {
46 this.pinEntryWrapper.setPin(pin);
47 }
48 binding.back.setOnClickListener(this::onBackButton);
49 binding.next.setOnClickListener(this::onNextButton);
50 clipboardManager = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
51 setVerifyingState(verifying);
52 }
53
54 private void onBackButton(View view) {
55 if (this.verifying) {
56 setVerifyingState(false);
57 return;
58 }
59 final Intent intent = new Intent(this, EnterPhoneNumberActivity.class);
60 if (this.account != null) {
61 AlertDialog.Builder builder = new AlertDialog.Builder(this);
62 builder.setMessage(R.string.abort_registration_procedure);
63 builder.setPositiveButton(R.string.yes, (dialog, which) -> {
64 xmppConnectionService.deleteAccount(account);
65 startActivity(intent);
66 finish();
67 });
68 builder.setNegativeButton(R.string.no, null);
69 builder.create().show();
70 } else {
71 startActivity(intent);
72 finish();
73 }
74 }
75
76 private void onNextButton(View view) {
77 final String pin = pinEntryWrapper.getPin();
78 if (PinEntryWrapper.isValidPin(pin)) {
79 if (account != null && xmppConnectionService != null) {
80 setVerifyingState(true);
81 xmppConnectionService.getQuickConversationsService().verify(account, pin);
82 }
83 } else {
84 AlertDialog.Builder builder = new AlertDialog.Builder(this);
85 builder.setMessage(R.string.please_enter_pin);
86 builder.setPositiveButton(R.string.ok, null);
87 builder.create().show();
88 }
89 }
90
91 private void setVerifyingState(boolean verifying) {
92 this.verifying = verifying;
93 this.binding.back.setText(verifying ? R.string.cancel : R.string.back);
94 this.binding.next.setEnabled(!verifying);
95 this.binding.next.setText(verifying ? R.string.verifying : R.string.next);
96 this.binding.resendSms.setVisibility(verifying ? View.GONE : View.VISIBLE);
97 pinEntryWrapper.setEnabled(!verifying);
98 this.binding.progressBar.setVisibility(verifying ? View.VISIBLE : View.GONE);
99 this.binding.progressBar.setIndeterminate(verifying);
100 }
101
102 @Override
103 protected void refreshUiReal() {
104
105 }
106
107 @Override
108 void onBackendConnected() {
109 xmppConnectionService.getQuickConversationsService().addOnVerificationListener(this);
110 this.account = AccountUtils.getFirst(xmppConnectionService);
111 if (this.account == null) {
112 return;
113 }
114 this.binding.weHaveSent.setText(Html.fromHtml(getString(R.string.we_have_sent_you_an_sms, PhoneNumberUtilWrapper.prettyPhoneNumber(this, this.account.getJid()))));
115 setVerifyingState(xmppConnectionService.getQuickConversationsService().isVerifying());
116 }
117
118 @Override
119 public void onSaveInstanceState(Bundle savedInstanceState) {
120 savedInstanceState.putString("pin", this.pinEntryWrapper.getPin());
121 savedInstanceState.putBoolean("verifying", this.verifying);
122 if (this.pasted != null) {
123 savedInstanceState.putString("pasted", this.pasted);
124 }
125 super.onSaveInstanceState(savedInstanceState);
126 }
127
128 @Override
129 public void onStart() {
130 super.onStart();
131 clipboardManager.addPrimaryClipChangedListener(this);
132 }
133
134 @Override
135 public void onStop() {
136 super.onStop();
137 clipboardManager.removePrimaryClipChangedListener(this);
138 if (xmppConnectionService != null) {
139 xmppConnectionService.getQuickConversationsService().removeOnVerificationListener(this);
140 }
141 }
142
143 @Override
144 public void onResume() {
145 super.onResume();
146 if (pinEntryWrapper.isEmpty()) {
147 pastePinFromClipboard();
148 }
149 }
150
151 private void pastePinFromClipboard() {
152 final ClipDescription description = clipboardManager != null ? clipboardManager.getPrimaryClipDescription() : null;
153 if (description != null && description.hasMimeType(MIMETYPE_TEXT_PLAIN)) {
154 final ClipData primaryClip = clipboardManager.getPrimaryClip();
155 if (primaryClip != null && primaryClip.getItemCount() > 0) {
156 final CharSequence clip = primaryClip.getItemAt(0).getText();
157 if (PinEntryWrapper.isValidPin(clip) && !clip.toString().equals(this.pasted)) {
158 this.pasted = clip.toString();
159 pinEntryWrapper.setPin(clip.toString());
160 final Snackbar snackbar = Snackbar.make(binding.coordinator, R.string.possible_pin, Snackbar.LENGTH_LONG);
161 snackbar.setAction(R.string.undo, v -> pinEntryWrapper.clear());
162 snackbar.show();
163 }
164 }
165 }
166 }
167
168 @Override
169 public void onPrimaryClipChanged() {
170 this.pasted = null;
171 if (pinEntryWrapper.isEmpty()) {
172 pastePinFromClipboard();
173 }
174 }
175
176 @Override
177 public void onVerificationFailed() {
178 runOnUiThread(() -> {
179 setVerifyingState(false);
180 });
181 }
182
183 @Override
184 public void onVerificationSucceeded() {
185
186 }
187}