diff --git a/src/main/java/eu/siacs/conversations/entities/Account.java b/src/main/java/eu/siacs/conversations/entities/Account.java index 29389be04..4fea4d6a1 100644 --- a/src/main/java/eu/siacs/conversations/entities/Account.java +++ b/src/main/java/eu/siacs/conversations/entities/Account.java @@ -54,6 +54,7 @@ public class Account extends AbstractEntity { public static final int OPTION_REQUIRES_ACCESS_MODE_CHANGE = 5; public static final int OPTION_LOGGED_IN_SUCCESSFULLY = 6; public static final int OPTION_HTTP_UPLOAD_AVAILABLE = 7; + public static final int OPTION_UNVERIFIED = 8; private static final String KEY_PGP_SIGNATURE = "pgp_signature"; private static final String KEY_PGP_ID = "pgp_id"; public final HashSet> inProgressDiscoFetches = new HashSet<>(); diff --git a/src/main/java/eu/siacs/conversations/utils/AccountUtils.java b/src/main/java/eu/siacs/conversations/utils/AccountUtils.java index 1d4f4aacb..f546a69e4 100644 --- a/src/main/java/eu/siacs/conversations/utils/AccountUtils.java +++ b/src/main/java/eu/siacs/conversations/utils/AccountUtils.java @@ -32,6 +32,14 @@ public class AccountUtils { return null; } + public static Account getFirst(XmppConnectionService service) { + final List accounts = service.getAccounts(); + for(Account account : accounts) { + return account; + } + return null; + } + public static Account getPendingAccount(XmppConnectionService service) { Account pending = null; for (Account account : service.getAccounts()) { @@ -53,7 +61,7 @@ public class AccountUtils { } public static void launchManageAccount(XmppActivity xmppActivity) { - Account account = getFirstEnabled(xmppActivity.xmppConnectionService); + Account account = getFirst(xmppActivity.xmppConnectionService); xmppActivity.switchToAccount(account); } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index e3c1a567f..6391cf425 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -759,4 +759,9 @@ %s is not a valid phone number. Please enter your phone number. Search countries + Verify %s + %s.]]> + Please enter the 6 digit pin below. + Resend SMS + back diff --git a/src/quick/AndroidManifest.xml b/src/quick/AndroidManifest.xml index 7c12eee04..a6e1e1493 100644 --- a/src/quick/AndroidManifest.xml +++ b/src/quick/AndroidManifest.xml @@ -14,5 +14,10 @@ android:label="@string/choose_a_country" android:launchMode="singleTask" /> + + diff --git a/src/quick/java/eu/siacs/conversations/services/QuickConversationsService.java b/src/quick/java/eu/siacs/conversations/services/QuickConversationsService.java index 36f45f28f..01d7cd661 100644 --- a/src/quick/java/eu/siacs/conversations/services/QuickConversationsService.java +++ b/src/quick/java/eu/siacs/conversations/services/QuickConversationsService.java @@ -3,12 +3,14 @@ package eu.siacs.conversations.services; import android.util.Log; +import java.security.SecureRandom; import java.util.Collections; import java.util.Set; import java.util.WeakHashMap; import eu.siacs.conversations.Config; import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.PhoneNumberUtilWrapper; import io.michaelrocks.libphonenumber.android.Phonenumber; import rocks.xmpp.addr.Jid; @@ -39,7 +41,9 @@ public class QuickConversationsService { public void requestVerification(Phonenumber.PhoneNumber phoneNumber) { String local = PhoneNumberUtilWrapper.normalize(service, phoneNumber); Log.d(Config.LOGTAG,"requesting verification for "+PhoneNumberUtilWrapper.normalize(service,phoneNumber)); - Account account = new Account(Jid.of(local,"quick.conversations.im",null),"foo"); + Account account = new Account(Jid.of(local,"quick.conversations.im",null), CryptoHelper.createPassword(new SecureRandom())); + account.setOption(Account.OPTION_DISABLED, true); + account.setOption(Account.OPTION_UNVERIFIED, true); service.createAccount(account); synchronized (mOnVerificationRequested) { for(OnVerificationRequested onVerificationRequested : mOnVerificationRequested) { diff --git a/src/quick/java/eu/siacs/conversations/ui/EnterPhoneNumberActivity.java b/src/quick/java/eu/siacs/conversations/ui/EnterPhoneNumberActivity.java index 77c5ff423..eae5c7315 100644 --- a/src/quick/java/eu/siacs/conversations/ui/EnterPhoneNumberActivity.java +++ b/src/quick/java/eu/siacs/conversations/ui/EnterPhoneNumberActivity.java @@ -165,6 +165,9 @@ public class EnterPhoneNumberActivity extends XmppActivity implements QuickConve @Override public void onVerificationRequested() { - Log.d(Config.LOGTAG,"requested"); + runOnUiThread(() -> { + startActivity(new Intent(this,VerifyActivity.class)); + finish(); + }); } } diff --git a/src/quick/java/eu/siacs/conversations/ui/VerifyActivity.java b/src/quick/java/eu/siacs/conversations/ui/VerifyActivity.java new file mode 100644 index 000000000..79ffde72f --- /dev/null +++ b/src/quick/java/eu/siacs/conversations/ui/VerifyActivity.java @@ -0,0 +1,54 @@ +package eu.siacs.conversations.ui; + +import android.content.Intent; +import android.databinding.DataBindingUtil; +import android.os.Bundle; +import android.support.v7.widget.Toolbar; +import android.text.Html; +import android.view.View; + +import eu.siacs.conversations.R; +import eu.siacs.conversations.databinding.ActivityVerifyBinding; +import eu.siacs.conversations.entities.Account; +import eu.siacs.conversations.ui.util.PinEntryWrapper; +import eu.siacs.conversations.utils.AccountUtils; +import eu.siacs.conversations.utils.PhoneNumberUtilWrapper; + +public class VerifyActivity extends XmppActivity { + + private ActivityVerifyBinding binding; + private Account account; + private PinEntryWrapper pinEntryWrapper; + + @Override + protected void onCreate(final Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + this.binding = DataBindingUtil.setContentView(this, R.layout.activity_verify); + setSupportActionBar((Toolbar) this.binding.toolbar); + this.pinEntryWrapper = new PinEntryWrapper(binding.pinBox); + binding.back.setOnClickListener(this::onBackButton); + } + + private void onBackButton(View view) { + if (this.account != null) { + xmppConnectionService.deleteAccount(account); + Intent intent = new Intent(this,EnterPhoneNumberActivity.class); + startActivity(intent); + finish(); + } + } + + @Override + protected void refreshUiReal() { + + } + + @Override + void onBackendConnected() { + this.account = AccountUtils.getFirst(xmppConnectionService); + if (this.account == null) { + return; + } + this.binding.weHaveSent.setText(Html.fromHtml(getString(R.string.we_have_sent_you_an_sms, PhoneNumberUtilWrapper.prettyPhoneNumber(this, this.account.getJid())))); + } +} diff --git a/src/quick/java/eu/siacs/conversations/ui/util/PinEntryWrapper.java b/src/quick/java/eu/siacs/conversations/ui/util/PinEntryWrapper.java new file mode 100644 index 000000000..8f22e2981 --- /dev/null +++ b/src/quick/java/eu/siacs/conversations/ui/util/PinEntryWrapper.java @@ -0,0 +1,93 @@ +package eu.siacs.conversations.ui.util; + +import android.text.Editable; +import android.text.TextWatcher; +import android.view.KeyEvent; +import android.view.View; +import android.widget.EditText; +import android.widget.LinearLayout; + +import java.util.ArrayList; +import java.util.List; + +public class PinEntryWrapper { + + private final List digits = new ArrayList<>(); + + private final TextWatcher textWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + int current = -1; + for (int i = 0; i < digits.size(); ++i) { + if (s.hashCode() == digits.get(i).getText().hashCode()) { + current = i; + } + } + if (current == -1) { + return; + } + if (s.length() > 0) { + if (current < digits.size() - 1) { + digits.get(current + 1).requestFocus(); + } + } else { + int focusOn = current; + for (int i = current - 1; i >= 0; --i) { + if (digits.get(i).getText().length() == 0) { + focusOn = i; + } else { + break; + } + } + digits.get(focusOn).requestFocus(); + } + } + }; + + private final View.OnKeyListener keyListener = (v, keyCode, event) -> { + if (event.getAction() != KeyEvent.ACTION_DOWN) { + return false; + } + if (v instanceof EditText) { + final EditText editText = (EditText) v; + if (keyCode == KeyEvent.KEYCODE_DEL && editText.getText().length() == 0) { + final int current = digits.indexOf(editText); + for (int i = current - 1; i >= 0; --i) { + if (digits.get(i).getText().length() > 0) { + digits.get(i).getText().clear(); + return true; + } + } + } + } + return false; + }; + + public PinEntryWrapper(LinearLayout linearLayout) { + for (int i = 0; i < linearLayout.getChildCount(); ++i) { + View view = linearLayout.getChildAt(i); + if (view instanceof EditText) { + this.digits.add((EditText) view); + } + } + registerListeners(); + } + + private void registerListeners() { + for (EditText editText : digits) { + editText.addTextChangedListener(textWatcher); + editText.setOnKeyListener(keyListener); + } + } + +} \ No newline at end of file diff --git a/src/quick/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java b/src/quick/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java index c25424277..650ba7d0f 100644 --- a/src/quick/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java +++ b/src/quick/java/eu/siacs/conversations/utils/PhoneNumberUtilWrapper.java @@ -10,6 +10,7 @@ import java.util.Locale; import io.michaelrocks.libphonenumber.android.NumberParseException; import io.michaelrocks.libphonenumber.android.PhoneNumberUtil; import io.michaelrocks.libphonenumber.android.Phonenumber; +import rocks.xmpp.addr.Jid; public class PhoneNumberUtilWrapper { @@ -40,6 +41,16 @@ public class PhoneNumberUtilWrapper { return locale.getCountry(); } + public static String prettyPhoneNumber(Context context, Jid jid) { + PhoneNumberUtil phoneNumberUtil = getInstance(context); + try { + Phonenumber.PhoneNumber phoneNumber = phoneNumberUtil.parse(jid.getEscapedLocal(), "de"); + return phoneNumberUtil.format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL); + } catch (Exception e) { + return jid.getEscapedLocal(); + } + } + public static String normalize(Context context, String number) throws NumberParseException { return normalize(context, getInstance(context).parse(number, getUserCountry(context))); } diff --git a/src/quick/java/eu/siacs/conversations/utils/SignupUtils.java b/src/quick/java/eu/siacs/conversations/utils/SignupUtils.java index 314a8655e..ac796ea99 100644 --- a/src/quick/java/eu/siacs/conversations/utils/SignupUtils.java +++ b/src/quick/java/eu/siacs/conversations/utils/SignupUtils.java @@ -5,8 +5,11 @@ import android.content.Intent; import android.util.Log; import eu.siacs.conversations.Config; +import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.ui.ConversationsActivity; import eu.siacs.conversations.ui.EnterPhoneNumberActivity; +import eu.siacs.conversations.ui.StartConversationActivity; +import eu.siacs.conversations.ui.VerifyActivity; public class SignupUtils { @@ -16,7 +19,18 @@ public class SignupUtils { } public static Intent getRedirectionIntent(ConversationsActivity activity) { - final Intent intent = getSignUpIntent(activity); + final Intent intent; + final Account account = AccountUtils.getFirst(activity.xmppConnectionService); + if (account != null) { + if (account.isOptionSet(Account.OPTION_UNVERIFIED)) { + intent = new Intent(activity, VerifyActivity.class); + } else { + intent = new Intent(activity, StartConversationActivity.class); + } + } else { + intent = getSignUpIntent(activity); + + } intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); return intent; } diff --git a/src/quick/res/layout/activity_verify.xml b/src/quick/res/layout/activity_verify.xml new file mode 100644 index 000000000..578214d98 --- /dev/null +++ b/src/quick/res/layout/activity_verify.xml @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +