EnterPhoneNumberActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.app.AlertDialog;
  4import android.content.Intent;
  5import android.databinding.DataBindingUtil;
  6import android.os.Bundle;
  7import android.support.v7.widget.Toolbar;
  8import android.text.Editable;
  9import android.text.Html;
 10import android.text.TextUtils;
 11import android.text.TextWatcher;
 12import android.util.Log;
 13import android.view.KeyEvent;
 14import android.view.View;
 15import android.widget.EditText;
 16
 17import eu.siacs.conversations.Config;
 18import eu.siacs.conversations.R;
 19import eu.siacs.conversations.databinding.ActivityEnterNumberBinding;
 20import eu.siacs.conversations.services.QuickConversationsService;
 21import eu.siacs.conversations.ui.drawable.TextDrawable;
 22import eu.siacs.conversations.ui.util.ApiDialogHelper;
 23import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
 24import io.michaelrocks.libphonenumber.android.NumberParseException;
 25import io.michaelrocks.libphonenumber.android.PhoneNumberUtil;
 26import io.michaelrocks.libphonenumber.android.Phonenumber;
 27
 28public class EnterPhoneNumberActivity extends XmppActivity implements QuickConversationsService.OnVerificationRequested {
 29
 30    private static final int REQUEST_CHOOSE_COUNTRY = 0x1234;
 31
 32    private ActivityEnterNumberBinding binding;
 33
 34    private String region = null;
 35    private final TextWatcher countryCodeTextWatcher = new TextWatcher() {
 36        @Override
 37        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
 38
 39        }
 40
 41        @Override
 42        public void onTextChanged(CharSequence s, int start, int before, int count) {
 43
 44        }
 45
 46        @Override
 47        public void afterTextChanged(Editable editable) {
 48            final String text = editable.toString();
 49            try {
 50                final int oldCode = region != null ? PhoneNumberUtilWrapper.getInstance(EnterPhoneNumberActivity.this).getCountryCodeForRegion(region) : 0;
 51                final int code = Integer.parseInt(text);
 52                if (oldCode != code) {
 53                    region = PhoneNumberUtilWrapper.getInstance(EnterPhoneNumberActivity.this).getRegionCodeForCountryCode(code);
 54                }
 55                if ("ZZ".equals(region)) {
 56                    binding.country.setText(TextUtils.isEmpty(text) ? R.string.choose_a_country : R.string.invalid_country_code);
 57                } else {
 58                    binding.number.requestFocus();
 59                    binding.country.setText(PhoneNumberUtilWrapper.getCountryForCode(region));
 60                }
 61            } catch (NumberFormatException e) {
 62                binding.country.setText(TextUtils.isEmpty(text) ? R.string.choose_a_country : R.string.invalid_country_code);
 63            }
 64        }
 65    };
 66    private boolean requestingVerification = false;
 67
 68    @Override
 69    protected void refreshUiReal() {
 70
 71    }
 72
 73    @Override
 74    void onBackendConnected() {
 75        xmppConnectionService.getQuickConversationsService().addOnVerificationRequestedListener(this);
 76    }
 77
 78    @Override
 79    protected void onCreate(final Bundle savedInstanceState) {
 80        super.onCreate(savedInstanceState);
 81
 82        String region = savedInstanceState != null ? savedInstanceState.getString("region") : null;
 83        boolean requestingVerification = savedInstanceState != null && savedInstanceState.getBoolean("requesting_verification", false);
 84        if (region != null) {
 85            this.region = region;
 86        } else {
 87            this.region = PhoneNumberUtilWrapper.getUserCountry(this);
 88        }
 89
 90        this.binding = DataBindingUtil.setContentView(this, R.layout.activity_enter_number);
 91        this.binding.countryCode.setCompoundDrawables(new TextDrawable(this.binding.countryCode, "+"), null, null, null);
 92        this.binding.country.setOnClickListener(this::onSelectCountryClick);
 93        this.binding.next.setOnClickListener(this::onNextClick);
 94        setSupportActionBar((Toolbar) this.binding.toolbar);
 95        this.binding.countryCode.addTextChangedListener(this.countryCodeTextWatcher);
 96        this.binding.countryCode.setText(String.valueOf(PhoneNumberUtilWrapper.getInstance(this).getCountryCodeForRegion(this.region)));
 97        this.binding.number.setOnKeyListener((v, keyCode, event) -> {
 98            if (event.getAction() != KeyEvent.ACTION_DOWN) {
 99                return false;
100            }
101            final EditText editText = (EditText) v;
102            final boolean cursorAtZero = editText.getSelectionEnd() == 0 && editText.getSelectionStart() == 0;
103            if (keyCode == KeyEvent.KEYCODE_DEL && (cursorAtZero || editText.getText().length() == 0)) {
104                final Editable countryCode = this.binding.countryCode.getText();
105                if (countryCode.length() > 0) {
106                    countryCode.delete(countryCode.length() - 1, countryCode.length());
107                    this.binding.countryCode.setSelection(countryCode.length());
108                }
109                this.binding.countryCode.requestFocus();
110                return true;
111            }
112            return false;
113        });
114        setRequestingVerificationState(requestingVerification);
115    }
116
117    @Override
118    public void onSaveInstanceState(Bundle savedInstanceState) {
119        if (this.region != null) {
120            savedInstanceState.putString("region", this.region);
121        }
122        savedInstanceState.putBoolean("requesting_verification", this.requestingVerification);
123        super.onSaveInstanceState(savedInstanceState);
124    }
125
126    @Override
127    public void onStop() {
128        if (xmppConnectionService != null) {
129            xmppConnectionService.getQuickConversationsService().removeOnVerificationRequestedListener(this);
130        }
131        super.onStop();
132    }
133
134    private void onNextClick(View v) {
135        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
136        try {
137            final Editable number = this.binding.number.getText();
138            final String input = number.toString();
139            final Phonenumber.PhoneNumber phoneNumber = PhoneNumberUtilWrapper.getInstance(this).parse(input, region);
140            this.binding.countryCode.setText(String.valueOf(phoneNumber.getCountryCode()));
141            number.clear();
142            number.append(String.valueOf(phoneNumber.getNationalNumber()));
143            final String formattedPhoneNumber = PhoneNumberUtilWrapper.getInstance(this).format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL);
144
145            if (PhoneNumberUtilWrapper.getInstance(this).isValidNumber(phoneNumber)) {
146                builder.setMessage(Html.fromHtml(getString(R.string.we_will_be_verifying, formattedPhoneNumber)));
147                builder.setNegativeButton(R.string.edit, null);
148                builder.setPositiveButton(R.string.ok, (dialog, which) -> onPhoneNumberEntered(phoneNumber));
149            } else {
150                builder.setMessage(getString(R.string.not_a_valid_phone_number, formattedPhoneNumber));
151                builder.setPositiveButton(R.string.ok, null);
152            }
153            Log.d(Config.LOGTAG, phoneNumber.toString());
154        } catch (NumberParseException e) {
155            builder.setMessage(R.string.please_enter_your_phone_number);
156            builder.setPositiveButton(R.string.ok, null);
157        }
158        builder.create().show();
159    }
160
161    private void onSelectCountryClick(View view) {
162        Intent intent = new Intent(this, ChooseCountryActivity.class);
163        startActivityForResult(intent, REQUEST_CHOOSE_COUNTRY);
164    }
165
166    private void onPhoneNumberEntered(Phonenumber.PhoneNumber phoneNumber) {
167        setRequestingVerificationState(true);
168        xmppConnectionService.getQuickConversationsService().requestVerification(phoneNumber);
169    }
170
171    private void setRequestingVerificationState(boolean requesting) {
172        this.requestingVerification = requesting;
173        this.binding.countryCode.setEnabled(!requesting);
174        this.binding.country.setEnabled(!requesting);
175        this.binding.number.setEnabled(!requesting);
176        this.binding.next.setEnabled(!requesting);
177        this.binding.next.setText(requesting ? R.string.requesting_sms : R.string.next);
178        this.binding.progressBar.setVisibility(requesting ? View.VISIBLE : View.GONE);
179        this.binding.progressBar.setIndeterminate(requesting);
180    }
181
182    @Override
183    public void onActivityResult(int requestCode, int resultCode, final Intent data) {
184        super.onActivityResult(requestCode, resultCode, data);
185        if (resultCode == RESULT_OK && requestCode == REQUEST_CHOOSE_COUNTRY) {
186            String region = data.getStringExtra("region");
187            if (region != null) {
188                this.region = region;
189                final int countryCode = PhoneNumberUtilWrapper.getInstance(this).getCountryCodeForRegion(region);
190                this.binding.countryCode.setText(String.valueOf(countryCode));
191            }
192        }
193    }
194
195    @Override
196    public void onVerificationRequestFailed(int code) {
197        runOnUiThread(() -> {
198            setRequestingVerificationState(false);
199            ApiDialogHelper.createError(this, code).show();
200        });
201    }
202
203    @Override
204    public void onVerificationRequested() {
205        runOnUiThread(() -> {
206            startActivity(new Intent(this, VerifyActivity.class));
207            finish();
208        });
209    }
210
211    @Override
212    public void onVerificationRequestedRetryAt(long timestamp) {
213        runOnUiThread(() -> {
214            Intent intent = new Intent(this, VerifyActivity.class);
215            intent.putExtra(VerifyActivity.EXTRA_RETRY_SMS_AFTER, timestamp);
216            startActivity(intent);
217            finish();
218        });
219    }
220}