Prompt to confirm number before SMS or call.
This commit is contained in:
parent
ae676d7486
commit
cb1401f556
6 changed files with 166 additions and 3 deletions
|
@ -8,6 +8,7 @@ import android.text.TextUtils;
|
|||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
@ -91,4 +92,18 @@ public class LabeledEditText extends FrameLayout implements View.OnFocusChangeLi
|
|||
super.setEnabled(enabled);
|
||||
input.setEnabled(enabled);
|
||||
}
|
||||
|
||||
public void focusAndMoveCursorToEndAndOpenKeyboard() {
|
||||
input.requestFocus();
|
||||
|
||||
int numberLength = getText().length();
|
||||
input.setSelection(numberLength, numberLength);
|
||||
|
||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(input, InputMethodManager.SHOW_IMPLICIT);
|
||||
|
||||
if (!imm.isAcceptingText()) {
|
||||
imm.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,27 +4,38 @@ import android.app.Activity;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.SavedStateViewModelFactory;
|
||||
import androidx.lifecycle.ViewModelProviders;
|
||||
|
||||
import com.dd.CircularProgressButton;
|
||||
|
||||
import org.signal.core.util.TranslationDetection;
|
||||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.LoggingFragment;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.logsubmit.SubmitDebugLogActivity;
|
||||
import org.thoughtcrime.securesms.phonenumbers.PhoneNumberFormatter;
|
||||
import org.thoughtcrime.securesms.registration.viewmodel.RegistrationViewModel;
|
||||
import org.thoughtcrime.securesms.util.SpanUtil;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.thoughtcrime.securesms.registration.RegistrationNavigationActivity.RE_REGISTRATION_EXTRA;
|
||||
|
||||
abstract class BaseRegistrationFragment extends LoggingFragment {
|
||||
|
||||
private static final String TAG = Log.tag(BaseRegistrationFragment.class);
|
||||
|
||||
private RegistrationViewModel model;
|
||||
|
||||
@Override
|
||||
|
@ -104,4 +115,45 @@ abstract class BaseRegistrationFragment extends LoggingFragment {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Presents a prompt for the user to confirm their number as long as it can be shown in one of their device languages.
|
||||
*/
|
||||
protected final void showConfirmNumberDialogIfTranslated(@NonNull Context context,
|
||||
@StringRes int firstMessageLine,
|
||||
@NonNull String e164number,
|
||||
@NonNull Runnable onConfirmed,
|
||||
@NonNull Runnable onEditNumber)
|
||||
{
|
||||
TranslationDetection translationDetection = new TranslationDetection(context);
|
||||
|
||||
if (translationDetection.textExistsInUsersLanguage(firstMessageLine) &&
|
||||
translationDetection.textExistsInUsersLanguage(R.string.RegistrationActivity_is_your_phone_number_above_correct) &&
|
||||
translationDetection.textExistsInUsersLanguage(R.string.RegistrationActivity_edit_number))
|
||||
{
|
||||
CharSequence message = new SpannableStringBuilder().append(context.getString(firstMessageLine))
|
||||
.append("\n\n")
|
||||
.append(SpanUtil.bold(PhoneNumberFormatter.prettyPrint(e164number)))
|
||||
.append("\n\n")
|
||||
.append(context.getString(R.string.RegistrationActivity_is_your_phone_number_above_correct));
|
||||
|
||||
Log.i(TAG, "Showing confirm number dialog (" + context.getString(firstMessageLine) + ")");
|
||||
new AlertDialog.Builder(context)
|
||||
.setMessage(message)
|
||||
.setPositiveButton(android.R.string.ok,
|
||||
(a, b) -> {
|
||||
Log.i(TAG, "Number confirmed");
|
||||
onConfirmed.run();
|
||||
})
|
||||
.setNegativeButton(R.string.RegistrationActivity_edit_number,
|
||||
(a, b) -> {
|
||||
Log.i(TAG, "User requested edit number from confirm dialog");
|
||||
onEditNumber.run();
|
||||
})
|
||||
.show();
|
||||
} else {
|
||||
Log.i(TAG, "Confirm number dialog not translated in " + Locale.getDefault() + " skipping");
|
||||
onConfirmed.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,10 +79,11 @@ public final class EnterCodeFragment extends BaseRegistrationFragment
|
|||
signalStrengthListener = new SignalStrengthPhoneStateListener(this, this);
|
||||
|
||||
connectKeyboard(verificationCodeView, keyboard);
|
||||
hideKeyboard(requireContext(), view);
|
||||
|
||||
setOnCodeFullyEnteredListener(verificationCodeView);
|
||||
|
||||
wrongNumber.setOnClickListener(v -> Navigation.findNavController(view).navigate(EnterCodeFragmentDirections.actionWrongNumber()));
|
||||
wrongNumber.setOnClickListener(v -> onWrongNumber());
|
||||
|
||||
callMeCountDown.setOnClickListener(v -> handlePhoneCallRequest());
|
||||
|
||||
|
@ -106,6 +107,11 @@ public final class EnterCodeFragment extends BaseRegistrationFragment
|
|||
model.onStartEnterCode();
|
||||
}
|
||||
|
||||
private void onWrongNumber() {
|
||||
Navigation.findNavController(requireView())
|
||||
.navigate(EnterCodeFragmentDirections.actionWrongNumber());
|
||||
}
|
||||
|
||||
private void setOnCodeFullyEnteredListener(VerificationCodeView verificationCodeView) {
|
||||
verificationCodeView.setOnCompleteListener(code -> {
|
||||
RegistrationViewModel model = getModel();
|
||||
|
@ -261,6 +267,14 @@ public final class EnterCodeFragment extends BaseRegistrationFragment
|
|||
}
|
||||
|
||||
private void handlePhoneCallRequest() {
|
||||
showConfirmNumberDialogIfTranslated(requireContext(),
|
||||
R.string.RegistrationActivity_you_will_receive_a_call_to_verify_this_number,
|
||||
getModel().getNumber().getE164Number(),
|
||||
this::handlePhoneCallRequestAfterConfirm,
|
||||
this::onWrongNumber);
|
||||
}
|
||||
|
||||
private void handlePhoneCallRequestAfterConfirm() {
|
||||
RegistrationViewModel model = getModel();
|
||||
String captcha = model.getCaptchaToken();
|
||||
model.clearCaptchaResponse();
|
||||
|
|
|
@ -147,9 +147,9 @@ public final class EnterPhoneNumberFragment extends BaseRegistrationFragment {
|
|||
PlayServicesUtil.PlayServicesStatus fcmStatus = PlayServicesUtil.getPlayServicesStatus(context);
|
||||
|
||||
if (fcmStatus == PlayServicesUtil.PlayServicesStatus.SUCCESS) {
|
||||
handleRequestVerification(context, e164number, true);
|
||||
confirmNumberPrompt(context, e164number, () -> handleRequestVerification(context, e164number, true));
|
||||
} else if (fcmStatus == PlayServicesUtil.PlayServicesStatus.MISSING) {
|
||||
handlePromptForNoPlayServices(context, e164number);
|
||||
confirmNumberPrompt(context, e164number, () -> handlePromptForNoPlayServices(context, e164number));
|
||||
} else if (fcmStatus == PlayServicesUtil.PlayServicesStatus.NEEDS_UPDATE) {
|
||||
GoogleApiAvailability.getInstance().getErrorDialog(requireActivity(), ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED, 0).show();
|
||||
} else {
|
||||
|
@ -427,4 +427,18 @@ public final class EnterPhoneNumberFragment extends BaseRegistrationFragment {
|
|||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
||||
protected final void confirmNumberPrompt(@NonNull Context context,
|
||||
@NonNull String e164number,
|
||||
@NonNull Runnable onConfirmed)
|
||||
{
|
||||
showConfirmNumberDialogIfTranslated(context,
|
||||
R.string.RegistrationActivity_a_verification_code_will_be_sent_to,
|
||||
e164number,
|
||||
() -> {
|
||||
hideKeyboard(context, number.getInput());
|
||||
onConfirmed.run();
|
||||
},
|
||||
() -> number.focusAndMoveCursorToEndAndOpenKeyboard());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1489,6 +1489,10 @@
|
|||
<string name="RegistrationActivity_the_number_you_specified_s_is_invalid">The number you
|
||||
specified (%s) is invalid.
|
||||
</string>
|
||||
<string name="RegistrationActivity_a_verification_code_will_be_sent_to">A verification code will be sent to:</string>
|
||||
<string name="RegistrationActivity_you_will_receive_a_call_to_verify_this_number">You\'ll receive a call to verify this number.</string>
|
||||
<string name="RegistrationActivity_is_your_phone_number_above_correct">Is your phone number above correct?</string>
|
||||
<string name="RegistrationActivity_edit_number">Edit number</string>
|
||||
<string name="RegistrationActivity_missing_google_play_services">Missing Google Play Services</string>
|
||||
<string name="RegistrationActivity_this_device_is_missing_google_play_services">This device is missing Google Play Services. You can still use Signal, but this configuration may result in reduced reliability or performance.\n\nIf you are not an advanced user, are not running an aftermarket Android ROM, or believe that you are seeing this in error, please contact support@signal.org for help troubleshooting.</string>
|
||||
<string name="RegistrationActivity_i_understand">I understand</string>
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
package org.signal.core.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.StringRes;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Allows you to detect if a string resource is readable by the user according to their language settings.
|
||||
*/
|
||||
public final class TranslationDetection {
|
||||
private final Resources resourcesLocal;
|
||||
private final Resources resourcesEn;
|
||||
private final Configuration configurationLocal;
|
||||
|
||||
/**
|
||||
* @param context Do not pass Application context, as this may not represent the users selected in-app locale.
|
||||
*/
|
||||
public TranslationDetection(@NonNull Context context) {
|
||||
this.resourcesLocal = context.getResources();
|
||||
this.configurationLocal = resourcesLocal.getConfiguration();
|
||||
|
||||
Configuration configurationEn = new Configuration(configurationLocal);
|
||||
configurationEn.setLocale(Locale.ENGLISH);
|
||||
|
||||
this.resourcesEn = context.createConfigurationContext(configurationEn).getResources();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if any of these are true:
|
||||
* - The current locale is English.
|
||||
* - In a multi-locale capable device, the device supports any English locale in any position.
|
||||
* - The text for the current locale does not Equal the English.
|
||||
*/
|
||||
public boolean textExistsInUsersLanguage(@StringRes int resId) {
|
||||
if (configSupportsEnglish()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
String stringEn = resourcesEn.getString(resId);
|
||||
String stringLocal = resourcesLocal.getString(resId);
|
||||
|
||||
return !stringEn.equals(stringLocal);
|
||||
}
|
||||
|
||||
protected boolean configSupportsEnglish() {
|
||||
if (configurationLocal.locale.getLanguage().equals("en")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 24) {
|
||||
Locale firstMatch = configurationLocal.getLocales().getFirstMatch(new String[]{"en"});
|
||||
|
||||
return firstMatch != null && firstMatch.getLanguage().equals("en");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue