verify activity

This commit is contained in:
Daniel Gultsch 2018-10-20 16:37:59 +02:00
parent 954acb377e
commit 5695236838
11 changed files with 365 additions and 4 deletions

View file

@ -54,6 +54,7 @@ public class Account extends AbstractEntity {
public static final int OPTION_REQUIRES_ACCESS_MODE_CHANGE = 5; public static final int OPTION_REQUIRES_ACCESS_MODE_CHANGE = 5;
public static final int OPTION_LOGGED_IN_SUCCESSFULLY = 6; public static final int OPTION_LOGGED_IN_SUCCESSFULLY = 6;
public static final int OPTION_HTTP_UPLOAD_AVAILABLE = 7; 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_SIGNATURE = "pgp_signature";
private static final String KEY_PGP_ID = "pgp_id"; private static final String KEY_PGP_ID = "pgp_id";
public final HashSet<Pair<String, String>> inProgressDiscoFetches = new HashSet<>(); public final HashSet<Pair<String, String>> inProgressDiscoFetches = new HashSet<>();

View file

@ -32,6 +32,14 @@ public class AccountUtils {
return null; return null;
} }
public static Account getFirst(XmppConnectionService service) {
final List<Account> accounts = service.getAccounts();
for(Account account : accounts) {
return account;
}
return null;
}
public static Account getPendingAccount(XmppConnectionService service) { public static Account getPendingAccount(XmppConnectionService service) {
Account pending = null; Account pending = null;
for (Account account : service.getAccounts()) { for (Account account : service.getAccounts()) {
@ -53,7 +61,7 @@ public class AccountUtils {
} }
public static void launchManageAccount(XmppActivity xmppActivity) { public static void launchManageAccount(XmppActivity xmppActivity) {
Account account = getFirstEnabled(xmppActivity.xmppConnectionService); Account account = getFirst(xmppActivity.xmppConnectionService);
xmppActivity.switchToAccount(account); xmppActivity.switchToAccount(account);
} }

View file

@ -759,4 +759,9 @@
<string name="not_a_valid_phone_number">%s is not a valid phone number.</string> <string name="not_a_valid_phone_number">%s is not a valid phone number.</string>
<string name="please_enter_your_phone_number">Please enter your phone number.</string> <string name="please_enter_your_phone_number">Please enter your phone number.</string>
<string name="search_countries">Search countries</string> <string name="search_countries">Search countries</string>
<string name="verify_x">Verify %s</string>
<string name="we_have_sent_you_an_sms"><![CDATA[We have sent you an SMS to <b>%s</b>.]]></string>
<string name="please_enter_pin">Please enter the 6 digit pin below.</string>
<string name="resend_sms">Resend SMS</string>
<string name="back">back</string>
</resources> </resources>

View file

@ -14,5 +14,10 @@
android:label="@string/choose_a_country" android:label="@string/choose_a_country"
android:launchMode="singleTask" /> android:launchMode="singleTask" />
<activity
android:name=".ui.VerifyActivity"
android:launchMode="singleTask"
android:label="@string/verify_your_phone_number"/>
</application> </application>
</manifest> </manifest>

View file

@ -3,12 +3,14 @@ package eu.siacs.conversations.services;
import android.util.Log; import android.util.Log;
import java.security.SecureRandom;
import java.util.Collections; import java.util.Collections;
import java.util.Set; import java.util.Set;
import java.util.WeakHashMap; import java.util.WeakHashMap;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.PhoneNumberUtilWrapper; import eu.siacs.conversations.utils.PhoneNumberUtilWrapper;
import io.michaelrocks.libphonenumber.android.Phonenumber; import io.michaelrocks.libphonenumber.android.Phonenumber;
import rocks.xmpp.addr.Jid; import rocks.xmpp.addr.Jid;
@ -39,7 +41,9 @@ public class QuickConversationsService {
public void requestVerification(Phonenumber.PhoneNumber phoneNumber) { public void requestVerification(Phonenumber.PhoneNumber phoneNumber) {
String local = PhoneNumberUtilWrapper.normalize(service, phoneNumber); String local = PhoneNumberUtilWrapper.normalize(service, phoneNumber);
Log.d(Config.LOGTAG,"requesting verification for "+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); service.createAccount(account);
synchronized (mOnVerificationRequested) { synchronized (mOnVerificationRequested) {
for(OnVerificationRequested onVerificationRequested : mOnVerificationRequested) { for(OnVerificationRequested onVerificationRequested : mOnVerificationRequested) {

View file

@ -165,6 +165,9 @@ public class EnterPhoneNumberActivity extends XmppActivity implements QuickConve
@Override @Override
public void onVerificationRequested() { public void onVerificationRequested() {
Log.d(Config.LOGTAG,"requested"); runOnUiThread(() -> {
startActivity(new Intent(this,VerifyActivity.class));
finish();
});
} }
} }

View file

@ -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()))));
}
}

View file

@ -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<EditText> 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);
}
}
}

View file

@ -10,6 +10,7 @@ import java.util.Locale;
import io.michaelrocks.libphonenumber.android.NumberParseException; import io.michaelrocks.libphonenumber.android.NumberParseException;
import io.michaelrocks.libphonenumber.android.PhoneNumberUtil; import io.michaelrocks.libphonenumber.android.PhoneNumberUtil;
import io.michaelrocks.libphonenumber.android.Phonenumber; import io.michaelrocks.libphonenumber.android.Phonenumber;
import rocks.xmpp.addr.Jid;
public class PhoneNumberUtilWrapper { public class PhoneNumberUtilWrapper {
@ -40,6 +41,16 @@ public class PhoneNumberUtilWrapper {
return locale.getCountry(); 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 { public static String normalize(Context context, String number) throws NumberParseException {
return normalize(context, getInstance(context).parse(number, getUserCountry(context))); return normalize(context, getInstance(context).parse(number, getUserCountry(context)));
} }

View file

@ -5,8 +5,11 @@ import android.content.Intent;
import android.util.Log; import android.util.Log;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.ui.ConversationsActivity; import eu.siacs.conversations.ui.ConversationsActivity;
import eu.siacs.conversations.ui.EnterPhoneNumberActivity; import eu.siacs.conversations.ui.EnterPhoneNumberActivity;
import eu.siacs.conversations.ui.StartConversationActivity;
import eu.siacs.conversations.ui.VerifyActivity;
public class SignupUtils { public class SignupUtils {
@ -16,7 +19,18 @@ public class SignupUtils {
} }
public static Intent getRedirectionIntent(ConversationsActivity activity) { 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); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
return intent; return intent;
} }

View file

@ -0,0 +1,163 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?attr/color_background_primary"
android:orientation="vertical">
<include
android:id="@+id/toolbar"
layout="@layout/toolbar"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/instructions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/we_have_sent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/we_have_sent_you_an_sms"
android:textAppearance="@style/TextAppearance.Conversations.Subhead" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/please_enter_pin"
android:textAppearance="@style/TextAppearance.Conversations.Body1" />
</LinearLayout>
<LinearLayout
android:id="@+id/pin_box"
android:layout_width="230sp"
android:layout_height="wrap_content"
android:layout_below="@+id/instructions"
android:layout_centerHorizontal="true">
<EditText
android:layout_width="35sp"
android:layout_height="wrap_content"
android:digits="1234567890"
android:inputType="number"
android:maxLength="1"
android:textSize="40sp"
android:gravity="center"
android:textIsSelectable="false"
/>
<Space
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<EditText
android:layout_width="35sp"
android:layout_height="wrap_content"
android:digits="1234567890"
android:inputType="number"
android:maxLength="1"
android:textSize="40sp"
android:gravity="center"
android:textIsSelectable="false"
/>
<Space
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<EditText
android:layout_width="35sp"
android:layout_height="wrap_content"
android:digits="1234567890"
android:inputType="number"
android:maxLength="1"
android:textSize="40sp"
android:gravity="center"
android:textIsSelectable="false"
/>
<Space
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<EditText
android:layout_width="35sp"
android:layout_height="wrap_content"
android:digits="1234567890"
android:inputType="number"
android:maxLength="1"
android:textSize="40sp"
android:gravity="center"
android:textIsSelectable="false"
/>
<Space
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<EditText
android:layout_width="35sp"
android:layout_height="wrap_content"
android:digits="1234567890"
android:inputType="number"
android:maxLength="1"
android:textSize="40sp"
android:gravity="center"
android:textIsSelectable="false"
/>
<Space
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1"/>
<EditText
android:layout_width="35sp"
android:layout_height="wrap_content"
android:digits="1234567890"
android:inputType="number"
android:maxLength="1"
android:textSize="40sp"
android:gravity="center"
android:textIsSelectable="false"
/>
</LinearLayout>
<Button
android:id="@+id/next"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
style="@style/Widget.Conversations.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/next"
android:textColor="?colorAccent"/>
<Button
android:id="@+id/back"
android:layout_alignParentBottom="true"
android:layout_alignParentStart="true"
style="@style/Widget.Conversations.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/back"
android:textColor="?android:textColorSecondary" />
<Button
android:layout_centerHorizontal="true"
android:layout_below="@+id/pin_box"
android:id="@+id/resend_sms"
style="@style/Widget.Conversations.Button.Borderless"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/resend_sms"
android:textColor="?android:textColorSecondary"/>
</RelativeLayout>
</ScrollView>
</LinearLayout>
</layout>