Redesign FTUX to use Material Design 3.
This commit is contained in:
parent
0303467c91
commit
150bbf181d
25 changed files with 842 additions and 918 deletions
|
@ -0,0 +1,56 @@
|
|||
package org.thoughtcrime.securesms.components.registration
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import org.thoughtcrime.securesms.R
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class ActionCountDownButton @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyle: Int = 0
|
||||
) : MaterialButton(context, attrs, defStyle) {
|
||||
private var countDownToTime: Long = 0
|
||||
private var listener: Listener? = null
|
||||
|
||||
/**
|
||||
* Starts a count down to the specified {@param time}.
|
||||
*/
|
||||
fun startCountDownTo(time: Long) {
|
||||
if (time > 0) {
|
||||
countDownToTime = time
|
||||
updateCountDown()
|
||||
}
|
||||
}
|
||||
|
||||
fun setCallEnabled() {
|
||||
setText(R.string.RegistrationActivity_call)
|
||||
isEnabled = true
|
||||
alpha = 1.0f
|
||||
}
|
||||
|
||||
private fun updateCountDown() {
|
||||
val remainingMillis = countDownToTime - System.currentTimeMillis()
|
||||
if (remainingMillis > 0) {
|
||||
isEnabled = false
|
||||
alpha = 0.5f
|
||||
val totalRemainingSeconds = TimeUnit.MILLISECONDS.toSeconds(remainingMillis).toInt()
|
||||
val minutesRemaining = totalRemainingSeconds / 60
|
||||
val secondsRemaining = totalRemainingSeconds % 60
|
||||
text = resources.getString(R.string.RegistrationActivity_call_me_instead_available_in, minutesRemaining, secondsRemaining)
|
||||
listener?.onRemaining(this, totalRemainingSeconds)
|
||||
postDelayed({ updateCountDown() }, 250)
|
||||
} else {
|
||||
setCallEnabled()
|
||||
}
|
||||
}
|
||||
|
||||
fun setListener(listener: Listener?) {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
fun onRemaining(view: ActionCountDownButton, secondsRemaining: Int)
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
package org.thoughtcrime.securesms.components.registration;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class CallMeCountDownView extends MaterialButton {
|
||||
|
||||
private long countDownToTime;
|
||||
@Nullable
|
||||
private Listener listener;
|
||||
|
||||
public CallMeCountDownView(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public CallMeCountDownView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public CallMeCountDownView(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a count down to the specified {@param time}.
|
||||
*/
|
||||
public void startCountDownTo(long time) {
|
||||
if (time > 0) {
|
||||
this.countDownToTime = time;
|
||||
updateCountDown();
|
||||
}
|
||||
}
|
||||
|
||||
public void setCallEnabled() {
|
||||
setText(R.string.RegistrationActivity_call);
|
||||
setEnabled(true);
|
||||
setAlpha(1.0f);
|
||||
}
|
||||
|
||||
private void updateCountDown() {
|
||||
final long remainingMillis = countDownToTime - System.currentTimeMillis();
|
||||
|
||||
if (remainingMillis > 0) {
|
||||
setEnabled(false);
|
||||
setAlpha(0.5f);
|
||||
|
||||
int totalRemainingSeconds = (int) TimeUnit.MILLISECONDS.toSeconds(remainingMillis);
|
||||
int minutesRemaining = totalRemainingSeconds / 60;
|
||||
int secondsRemaining = totalRemainingSeconds % 60;
|
||||
|
||||
setText(getResources().getString(R.string.RegistrationActivity_call_me_instead_available_in, minutesRemaining, secondsRemaining));
|
||||
|
||||
if (listener != null) {
|
||||
listener.onRemaining(this, totalRemainingSeconds);
|
||||
}
|
||||
|
||||
postDelayed(this::updateCountDown, 250);
|
||||
} else {
|
||||
setCallEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener(@Nullable Listener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public interface Listener {
|
||||
void onRemaining(@NonNull CallMeCountDownView view, int secondsRemaining);
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
package org.thoughtcrime.securesms.components.registration;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationSet;
|
||||
import android.view.animation.OvershootInterpolator;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.MainThread;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.annimon.stream.Collectors;
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class VerificationCodeView extends FrameLayout {
|
||||
|
||||
private final List<TextView> codes = new ArrayList<>(6);
|
||||
private final List<View> containers = new ArrayList<>(6);
|
||||
|
||||
private OnCodeEnteredListener listener;
|
||||
private int index;
|
||||
|
||||
public VerificationCodeView(Context context) {
|
||||
super(context);
|
||||
initialize(context);
|
||||
}
|
||||
|
||||
public VerificationCodeView(Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
initialize(context);
|
||||
}
|
||||
|
||||
public VerificationCodeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
initialize(context);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public VerificationCodeView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
initialize(context);
|
||||
}
|
||||
|
||||
private void initialize(@NonNull Context context) {
|
||||
inflate(context, R.layout.verification_code_view, this);
|
||||
|
||||
codes.add(findViewById(R.id.code_zero));
|
||||
codes.add(findViewById(R.id.code_one));
|
||||
codes.add(findViewById(R.id.code_two));
|
||||
codes.add(findViewById(R.id.code_three));
|
||||
codes.add(findViewById(R.id.code_four));
|
||||
codes.add(findViewById(R.id.code_five));
|
||||
|
||||
containers.add(findViewById(R.id.container_zero));
|
||||
containers.add(findViewById(R.id.container_one));
|
||||
containers.add(findViewById(R.id.container_two));
|
||||
containers.add(findViewById(R.id.container_three));
|
||||
containers.add(findViewById(R.id.container_four));
|
||||
containers.add(findViewById(R.id.container_five));
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public void setOnCompleteListener(OnCodeEnteredListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public void append(int value) {
|
||||
if (index >= codes.size()) return;
|
||||
|
||||
setInactive(containers);
|
||||
setActive(containers.get(index));
|
||||
|
||||
TextView codeView = codes.get(index++);
|
||||
|
||||
Animation translateIn = new TranslateAnimation(0, 0, codeView.getHeight(), 0);
|
||||
translateIn.setInterpolator(new OvershootInterpolator());
|
||||
translateIn.setDuration(500);
|
||||
|
||||
Animation fadeIn = new AlphaAnimation(0, 1);
|
||||
fadeIn.setDuration(200);
|
||||
|
||||
AnimationSet animationSet = new AnimationSet(false);
|
||||
animationSet.addAnimation(fadeIn);
|
||||
animationSet.addAnimation(translateIn);
|
||||
animationSet.reset();
|
||||
animationSet.setStartTime(0);
|
||||
|
||||
codeView.setText(String.valueOf(value));
|
||||
codeView.clearAnimation();
|
||||
codeView.startAnimation(animationSet);
|
||||
|
||||
if (index == codes.size() && listener != null) {
|
||||
listener.onCodeComplete(Stream.of(codes).map(TextView::getText).collect(Collectors.joining()));
|
||||
}
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public void delete() {
|
||||
if (index <= 0) return;
|
||||
codes.get(--index).setText("");
|
||||
setInactive(containers);
|
||||
setActive(containers.get(index));
|
||||
}
|
||||
|
||||
@MainThread
|
||||
public void clear() {
|
||||
if (index != 0) {
|
||||
Stream.of(codes).forEach(code -> code.setText(""));
|
||||
index = 0;
|
||||
}
|
||||
setInactive(containers);
|
||||
}
|
||||
|
||||
private static void setInactive(List<View> views) {
|
||||
Stream.of(views).forEach(c -> c.setBackgroundResource(R.drawable.labeled_edit_text_background_inactive));
|
||||
}
|
||||
|
||||
private static void setActive(@NonNull View container) {
|
||||
container.setBackgroundResource(R.drawable.labeled_edit_text_background_active);
|
||||
}
|
||||
|
||||
public interface OnCodeEnteredListener {
|
||||
void onCodeComplete(@NonNull String code);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package org.thoughtcrime.securesms.components.registration
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.widget.FrameLayout
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import org.thoughtcrime.securesms.R
|
||||
|
||||
class VerificationCodeView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0) :
|
||||
FrameLayout(context, attrs, defStyleAttr, defStyleRes) {
|
||||
private val containers: MutableList<TextInputLayout> = ArrayList(6)
|
||||
private var listener: OnCodeEnteredListener? = null
|
||||
private var index = 0
|
||||
init {
|
||||
inflate(context, R.layout.verification_code_view, this)
|
||||
containers.add(findViewById(R.id.container_zero))
|
||||
containers.add(findViewById(R.id.container_one))
|
||||
containers.add(findViewById(R.id.container_two))
|
||||
containers.add(findViewById(R.id.container_three))
|
||||
containers.add(findViewById(R.id.container_four))
|
||||
containers.add(findViewById(R.id.container_five))
|
||||
}
|
||||
|
||||
fun setOnCompleteListener(listener: OnCodeEnteredListener?) {
|
||||
this.listener = listener
|
||||
}
|
||||
|
||||
fun append(digit: Int) {
|
||||
if (index >= containers.size) return
|
||||
containers[index++].editText?.setText(digit.toString())
|
||||
|
||||
if (index == containers.size) {
|
||||
listener?.onCodeComplete(containers.joinToString("") { it.editText?.text.toString() })
|
||||
}
|
||||
}
|
||||
|
||||
fun delete() {
|
||||
if (index <= 0) return
|
||||
containers[--index].editText?.setText("")
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
if (index != 0) {
|
||||
containers.forEach { it.editText?.setText("") }
|
||||
index = 0
|
||||
}
|
||||
}
|
||||
|
||||
interface OnCodeEnteredListener {
|
||||
fun onCodeComplete(code: String)
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ import org.thoughtcrime.securesms.components.settings.app.changenumber.ChangeNum
|
|||
import org.thoughtcrime.securesms.components.settings.app.changenumber.ChangeNumberViewModel.ContinueStatus
|
||||
import org.thoughtcrime.securesms.registration.fragments.CountryPickerFragment
|
||||
import org.thoughtcrime.securesms.registration.fragments.CountryPickerFragmentArgs
|
||||
import org.thoughtcrime.securesms.registration.util.RegistrationNumberInputController
|
||||
import org.thoughtcrime.securesms.registration.util.ChangeNumberInputController
|
||||
import org.thoughtcrime.securesms.util.Dialogs
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
|
@ -54,13 +54,13 @@ class ChangeNumberEnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_c
|
|||
oldNumberCountryCode = view.findViewById(R.id.change_number_enter_phone_number_old_number_country_code)
|
||||
oldNumber = view.findViewById(R.id.change_number_enter_phone_number_old_number_number)
|
||||
|
||||
val oldController = RegistrationNumberInputController(
|
||||
val oldController = ChangeNumberInputController(
|
||||
requireContext(),
|
||||
oldNumberCountryCode,
|
||||
oldNumber,
|
||||
oldNumberCountrySpinner,
|
||||
false,
|
||||
object : RegistrationNumberInputController.Callbacks {
|
||||
object : ChangeNumberInputController.Callbacks {
|
||||
override fun onNumberFocused() {
|
||||
scrollView.postDelayed({ scrollView.smoothScrollTo(0, oldNumber.bottom) }, 250)
|
||||
}
|
||||
|
@ -91,13 +91,13 @@ class ChangeNumberEnterPhoneNumberFragment : LoggingFragment(R.layout.fragment_c
|
|||
newNumberCountryCode = view.findViewById(R.id.change_number_enter_phone_number_new_number_country_code)
|
||||
newNumber = view.findViewById(R.id.change_number_enter_phone_number_new_number_number)
|
||||
|
||||
val newController = RegistrationNumberInputController(
|
||||
val newController = ChangeNumberInputController(
|
||||
requireContext(),
|
||||
newNumberCountryCode,
|
||||
newNumber,
|
||||
newNumberCountrySpinner,
|
||||
true,
|
||||
object : RegistrationNumberInputController.Callbacks {
|
||||
object : ChangeNumberInputController.Callbacks {
|
||||
override fun onNumberFocused() {
|
||||
scrollView.postDelayed({ scrollView.smoothScrollTo(0, newNumber.bottom) }, 250)
|
||||
}
|
||||
|
|
|
@ -17,10 +17,6 @@ import android.widget.TextView;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
|
||||
import org.thoughtcrime.securesms.LoggingFragment;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
@ -29,19 +25,18 @@ import org.thoughtcrime.securesms.pin.PinOptOutDialog;
|
|||
import org.thoughtcrime.securesms.registration.RegistrationUtil;
|
||||
import org.thoughtcrime.securesms.util.CommunicationActions;
|
||||
import org.thoughtcrime.securesms.util.text.AfterTextChanged;
|
||||
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
|
||||
import org.thoughtcrime.securesms.util.views.LearnMoreTextView;
|
||||
|
||||
abstract class BaseKbsPinFragment<ViewModel extends BaseKbsPinViewModel> extends LoggingFragment {
|
||||
public abstract class BaseKbsPinFragment<ViewModel extends BaseKbsPinViewModel> extends LoggingFragment {
|
||||
|
||||
private TextView title;
|
||||
private LearnMoreTextView description;
|
||||
private EditText input;
|
||||
private TextView label;
|
||||
private TextView keyboardToggle;
|
||||
private TextView confirm;
|
||||
private LottieAnimationView lottieProgress;
|
||||
private LottieAnimationView lottieEnd;
|
||||
private ViewModel viewModel;
|
||||
private TextView title;
|
||||
private LearnMoreTextView description;
|
||||
private EditText input;
|
||||
private TextView label;
|
||||
private TextView keyboardToggle;
|
||||
private CircularProgressMaterialButton confirm;
|
||||
private ViewModel viewModel;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
|
@ -78,10 +73,6 @@ abstract class BaseKbsPinFragment<ViewModel extends BaseKbsPinViewModel> extends
|
|||
CommunicationActions.openBrowserLink(requireContext(), getString(R.string.BaseKbsPinFragment__learn_more_url));
|
||||
});
|
||||
|
||||
Toolbar toolbar = view.findViewById(R.id.kbs_pin_toolbar);
|
||||
((AppCompatActivity) requireActivity()).setSupportActionBar(toolbar);
|
||||
((AppCompatActivity) requireActivity()).getSupportActionBar().setTitle(null);
|
||||
|
||||
initializeListeners();
|
||||
}
|
||||
|
||||
|
@ -137,13 +128,6 @@ abstract class BaseKbsPinFragment<ViewModel extends BaseKbsPinViewModel> extends
|
|||
return input;
|
||||
}
|
||||
|
||||
protected LottieAnimationView getLottieProgress() {
|
||||
return lottieProgress;
|
||||
}
|
||||
|
||||
protected LottieAnimationView getLottieEnd() {
|
||||
return lottieEnd;
|
||||
}
|
||||
|
||||
protected TextView getLabel() {
|
||||
return label;
|
||||
|
@ -153,7 +137,7 @@ abstract class BaseKbsPinFragment<ViewModel extends BaseKbsPinViewModel> extends
|
|||
return keyboardToggle;
|
||||
}
|
||||
|
||||
protected TextView getConfirm() {
|
||||
protected CircularProgressMaterialButton getConfirm() {
|
||||
return confirm;
|
||||
}
|
||||
|
||||
|
@ -173,8 +157,6 @@ abstract class BaseKbsPinFragment<ViewModel extends BaseKbsPinViewModel> extends
|
|||
label = view.findViewById(R.id.edit_kbs_pin_input_label);
|
||||
keyboardToggle = view.findViewById(R.id.edit_kbs_pin_keyboard_toggle);
|
||||
confirm = view.findViewById(R.id.edit_kbs_pin_confirm);
|
||||
lottieProgress = view.findViewById(R.id.edit_kbs_pin_lottie_progress);
|
||||
lottieEnd = view.findViewById(R.id.edit_kbs_pin_lottie_end);
|
||||
|
||||
initializeViewStates();
|
||||
}
|
||||
|
|
|
@ -1,189 +0,0 @@
|
|||
package org.thoughtcrime.securesms.lock.v2;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.app.Activity;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.RawRes;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.autofill.HintConstants;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import com.airbnb.lottie.LottieAnimationView;
|
||||
import com.airbnb.lottie.LottieDrawable;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.animation.AnimationCompleteListener;
|
||||
import org.thoughtcrime.securesms.animation.AnimationRepeatListener;
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies;
|
||||
import org.thoughtcrime.securesms.megaphone.Megaphones;
|
||||
import org.thoughtcrime.securesms.registration.RegistrationUtil;
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper;
|
||||
import org.thoughtcrime.securesms.util.SpanUtil;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ConfirmKbsPinFragment extends BaseKbsPinFragment<ConfirmKbsPinViewModel> {
|
||||
|
||||
private ConfirmKbsPinViewModel viewModel;
|
||||
|
||||
@Override
|
||||
protected void initializeViewStates() {
|
||||
ConfirmKbsPinFragmentArgs args = ConfirmKbsPinFragmentArgs.fromBundle(requireArguments());
|
||||
|
||||
if (args.getIsPinChange()) {
|
||||
initializeViewStatesForPinChange();
|
||||
} else {
|
||||
initializeViewStatesForPinCreate();
|
||||
}
|
||||
ViewCompat.setAutofillHints(getInput(), HintConstants.AUTOFILL_HINT_NEW_PASSWORD);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ConfirmKbsPinViewModel initializeViewModel() {
|
||||
ConfirmKbsPinFragmentArgs args = ConfirmKbsPinFragmentArgs.fromBundle(requireArguments());
|
||||
KbsPin userEntry = Objects.requireNonNull(args.getUserEntry());
|
||||
PinKeyboardType keyboard = args.getKeyboard();
|
||||
ConfirmKbsPinRepository repository = new ConfirmKbsPinRepository();
|
||||
ConfirmKbsPinViewModel.Factory factory = new ConfirmKbsPinViewModel.Factory(userEntry, keyboard, repository);
|
||||
|
||||
viewModel = new ViewModelProvider(this, factory).get(ConfirmKbsPinViewModel.class);
|
||||
|
||||
viewModel.getLabel().observe(getViewLifecycleOwner(), this::updateLabel);
|
||||
viewModel.getSaveAnimation().observe(getViewLifecycleOwner(), this::updateSaveAnimation);
|
||||
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
private void initializeViewStatesForPinCreate() {
|
||||
getTitle().setText(R.string.CreateKbsPinFragment__create_your_pin);
|
||||
getDescription().setText(R.string.ConfirmKbsPinFragment__confirm_your_pin);
|
||||
getKeyboardToggle().setVisibility(View.INVISIBLE);
|
||||
getLabel().setText("");
|
||||
getDescription().setLearnMoreVisible(false);
|
||||
}
|
||||
|
||||
private void initializeViewStatesForPinChange() {
|
||||
getTitle().setText(R.string.CreateKbsPinFragment__create_a_new_pin);
|
||||
getDescription().setText(R.string.ConfirmKbsPinFragment__confirm_your_pin);
|
||||
getDescription().setLearnMoreVisible(false);
|
||||
getKeyboardToggle().setVisibility(View.INVISIBLE);
|
||||
getLabel().setText("");
|
||||
}
|
||||
|
||||
private void updateLabel(@NonNull ConfirmKbsPinViewModel.Label label) {
|
||||
switch (label) {
|
||||
case EMPTY:
|
||||
getLabel().setText("");
|
||||
break;
|
||||
case CREATING_PIN:
|
||||
getLabel().setText(R.string.ConfirmKbsPinFragment__creating_pin);
|
||||
getInput().setEnabled(false);
|
||||
break;
|
||||
case RE_ENTER_PIN:
|
||||
getLabel().setText(R.string.ConfirmKbsPinFragment__re_enter_your_pin);
|
||||
break;
|
||||
case PIN_DOES_NOT_MATCH:
|
||||
getLabel().setText(SpanUtil.color(ContextCompat.getColor(requireContext(), R.color.red_500),
|
||||
getString(R.string.ConfirmKbsPinFragment__pins_dont_match)));
|
||||
getInput().getText().clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSaveAnimation(@NonNull ConfirmKbsPinViewModel.SaveAnimation animation) {
|
||||
updateAnimationAndInputVisibility(animation);
|
||||
LottieAnimationView lottieProgress = getLottieProgress();
|
||||
|
||||
switch (animation) {
|
||||
case NONE:
|
||||
lottieProgress.cancelAnimation();
|
||||
break;
|
||||
case LOADING:
|
||||
lottieProgress.setAnimation(R.raw.lottie_kbs_loading);
|
||||
lottieProgress.setRepeatMode(LottieDrawable.RESTART);
|
||||
lottieProgress.setRepeatCount(LottieDrawable.INFINITE);
|
||||
lottieProgress.playAnimation();
|
||||
break;
|
||||
case SUCCESS:
|
||||
startEndAnimationOnNextProgressRepetition(R.raw.lottie_kbs_success, new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
requireActivity().setResult(Activity.RESULT_OK);
|
||||
closeNavGraphBranch();
|
||||
RegistrationUtil.maybeMarkRegistrationComplete(requireContext());
|
||||
StorageSyncHelper.scheduleSyncForDataChange();
|
||||
}
|
||||
});
|
||||
break;
|
||||
case FAILURE:
|
||||
startEndAnimationOnNextProgressRepetition(R.raw.lottie_kbs_fail, new AnimationCompleteListener() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
RegistrationUtil.maybeMarkRegistrationComplete(requireContext());
|
||||
displayFailedDialog();
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void startEndAnimationOnNextProgressRepetition(@RawRes int lottieAnimationId,
|
||||
@NonNull AnimationCompleteListener listener)
|
||||
{
|
||||
LottieAnimationView lottieProgress = getLottieProgress();
|
||||
LottieAnimationView lottieEnd = getLottieEnd();
|
||||
|
||||
lottieEnd.setAnimation(lottieAnimationId);
|
||||
lottieEnd.removeAllAnimatorListeners();
|
||||
lottieEnd.setRepeatCount(0);
|
||||
lottieEnd.addAnimatorListener(listener);
|
||||
|
||||
if (lottieProgress.isAnimating()) {
|
||||
lottieProgress.addAnimatorListener(new AnimationRepeatListener(animator ->
|
||||
hideProgressAndStartEndAnimation(lottieProgress, lottieEnd)
|
||||
));
|
||||
} else {
|
||||
hideProgressAndStartEndAnimation(lottieProgress, lottieEnd);
|
||||
}
|
||||
}
|
||||
|
||||
private void hideProgressAndStartEndAnimation(@NonNull LottieAnimationView lottieProgress,
|
||||
@NonNull LottieAnimationView lottieEnd)
|
||||
{
|
||||
viewModel.onLoadingAnimationComplete();
|
||||
lottieProgress.setVisibility(View.GONE);
|
||||
lottieEnd.setVisibility(View.VISIBLE);
|
||||
lottieEnd.playAnimation();
|
||||
}
|
||||
|
||||
private void updateAnimationAndInputVisibility(ConfirmKbsPinViewModel.SaveAnimation saveAnimation) {
|
||||
if (saveAnimation == ConfirmKbsPinViewModel.SaveAnimation.NONE) {
|
||||
getInput().setVisibility(View.VISIBLE);
|
||||
getLottieProgress().setVisibility(View.GONE);
|
||||
} else {
|
||||
getInput().setVisibility(View.GONE);
|
||||
getLottieProgress().setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void displayFailedDialog() {
|
||||
new AlertDialog.Builder(requireContext()).setTitle(R.string.ConfirmKbsPinFragment__pin_creation_failed)
|
||||
.setMessage(R.string.ConfirmKbsPinFragment__your_pin_was_not_saved)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.ok, (d, w) -> {
|
||||
d.dismiss();
|
||||
markMegaphoneSeenIfNecessary();
|
||||
requireActivity().setResult(Activity.RESULT_CANCELED);
|
||||
closeNavGraphBranch();
|
||||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
private void markMegaphoneSeenIfNecessary() {
|
||||
ApplicationDependencies.getMegaphoneRepository().markSeen(Megaphones.Event.PINS_FOR_ALL);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package org.thoughtcrime.securesms.lock.v2
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.DialogInterface
|
||||
import android.view.View
|
||||
import androidx.autofill.HintConstants
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.lock.v2.ConfirmKbsPinViewModel.SaveAnimation
|
||||
import org.thoughtcrime.securesms.megaphone.Megaphones
|
||||
import org.thoughtcrime.securesms.registration.RegistrationUtil
|
||||
import org.thoughtcrime.securesms.storage.StorageSyncHelper
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
|
||||
internal class ConfirmKbsPinFragment : BaseKbsPinFragment<ConfirmKbsPinViewModel>() {
|
||||
|
||||
override fun initializeViewStates() {
|
||||
val args = ConfirmKbsPinFragmentArgs.fromBundle(requireArguments())
|
||||
if (args.isPinChange) {
|
||||
initializeViewStatesForPinChange()
|
||||
} else {
|
||||
initializeViewStatesForPinCreate()
|
||||
}
|
||||
ViewCompat.setAutofillHints(input, HintConstants.AUTOFILL_HINT_NEW_PASSWORD)
|
||||
}
|
||||
|
||||
override fun initializeViewModel(): ConfirmKbsPinViewModel {
|
||||
val args = ConfirmKbsPinFragmentArgs.fromBundle(requireArguments())
|
||||
val userEntry = args.userEntry!!
|
||||
val keyboard = args.keyboard
|
||||
val repository = ConfirmKbsPinRepository()
|
||||
val factory = ConfirmKbsPinViewModel.Factory(userEntry, keyboard, repository)
|
||||
val viewModel = ViewModelProvider(this, factory)[ConfirmKbsPinViewModel::class.java]
|
||||
viewModel.label.observe(viewLifecycleOwner) { label: ConfirmKbsPinViewModel.LabelState -> updateLabel(label) }
|
||||
viewModel.saveAnimation.observe(viewLifecycleOwner) { animation: SaveAnimation -> updateSaveAnimation(animation) }
|
||||
return viewModel
|
||||
}
|
||||
|
||||
private fun initializeViewStatesForPinCreate() {
|
||||
title.setText(R.string.ConfirmKbsPinFragment__confirm_your_pin)
|
||||
description.setText(R.string.ConfirmKbsPinFragment__re_enter_the_pin_you_just_created)
|
||||
keyboardToggle.visibility = View.INVISIBLE
|
||||
description.setLearnMoreVisible(false)
|
||||
label.text = ""
|
||||
confirm.isEnabled = true
|
||||
}
|
||||
|
||||
private fun initializeViewStatesForPinChange() {
|
||||
title.setText(R.string.ConfirmKbsPinFragment__confirm_your_pin)
|
||||
description.setText(R.string.ConfirmKbsPinFragment__re_enter_the_pin_you_just_created)
|
||||
description.setLearnMoreVisible(false)
|
||||
keyboardToggle.visibility = View.INVISIBLE
|
||||
label.text = ""
|
||||
confirm.isEnabled = true
|
||||
}
|
||||
|
||||
private fun updateLabel(labelState: ConfirmKbsPinViewModel.LabelState) {
|
||||
when (labelState) {
|
||||
ConfirmKbsPinViewModel.LabelState.EMPTY -> label.text = ""
|
||||
ConfirmKbsPinViewModel.LabelState.CREATING_PIN -> {
|
||||
label.setText(R.string.ConfirmKbsPinFragment__creating_pin)
|
||||
input.isEnabled = false
|
||||
}
|
||||
ConfirmKbsPinViewModel.LabelState.RE_ENTER_PIN -> label.setText(R.string.ConfirmKbsPinFragment__re_enter_your_pin)
|
||||
ConfirmKbsPinViewModel.LabelState.PIN_DOES_NOT_MATCH -> {
|
||||
label.text = SpanUtil.color(
|
||||
ContextCompat.getColor(requireContext(), R.color.red_500),
|
||||
getString(R.string.ConfirmKbsPinFragment__pins_dont_match)
|
||||
)
|
||||
input.text.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateSaveAnimation(animation: SaveAnimation) {
|
||||
updateInputVisibility(animation)
|
||||
when (animation) {
|
||||
SaveAnimation.NONE -> confirm.cancelSpinning()
|
||||
SaveAnimation.LOADING -> confirm.setSpinning()
|
||||
SaveAnimation.SUCCESS -> {
|
||||
confirm.cancelSpinning()
|
||||
requireActivity().setResult(Activity.RESULT_OK)
|
||||
closeNavGraphBranch()
|
||||
RegistrationUtil.maybeMarkRegistrationComplete(requireContext())
|
||||
StorageSyncHelper.scheduleSyncForDataChange()
|
||||
}
|
||||
SaveAnimation.FAILURE -> {
|
||||
confirm.cancelSpinning()
|
||||
RegistrationUtil.maybeMarkRegistrationComplete(requireContext())
|
||||
displayFailedDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateInputVisibility(saveAnimation: SaveAnimation) {
|
||||
if (saveAnimation == SaveAnimation.NONE) {
|
||||
input.visibility = View.VISIBLE
|
||||
} else {
|
||||
input.visibility = View.GONE
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayFailedDialog() {
|
||||
MaterialAlertDialogBuilder(requireContext()).setTitle(R.string.ConfirmKbsPinFragment__pin_creation_failed)
|
||||
.setMessage(R.string.ConfirmKbsPinFragment__your_pin_was_not_saved)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.ok) { d: DialogInterface, w: Int ->
|
||||
d.dismiss()
|
||||
markMegaphoneSeenIfNecessary()
|
||||
requireActivity().setResult(Activity.RESULT_CANCELED)
|
||||
closeNavGraphBranch()
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun markMegaphoneSeenIfNecessary() {
|
||||
ApplicationDependencies.getMegaphoneRepository().markSeen(Megaphones.Event.PINS_FOR_ALL)
|
||||
}
|
||||
}
|
|
@ -16,8 +16,8 @@ final class ConfirmKbsPinViewModel extends ViewModel implements BaseKbsPinViewMo
|
|||
|
||||
private final DefaultValueLiveData<KbsPin> userEntry = new DefaultValueLiveData<>(KbsPin.EMPTY);
|
||||
private final DefaultValueLiveData<PinKeyboardType> keyboard = new DefaultValueLiveData<>(PinKeyboardType.NUMERIC);
|
||||
private final DefaultValueLiveData<SaveAnimation> saveAnimation = new DefaultValueLiveData<>(SaveAnimation.NONE);
|
||||
private final DefaultValueLiveData<Label> label = new DefaultValueLiveData<>(Label.RE_ENTER_PIN);
|
||||
private final DefaultValueLiveData<SaveAnimation> saveAnimation = new DefaultValueLiveData<>(SaveAnimation.NONE);
|
||||
private final DefaultValueLiveData<LabelState> label = new DefaultValueLiveData<>(LabelState.EMPTY);
|
||||
|
||||
private final KbsPin pinToConfirm;
|
||||
|
||||
|
@ -35,29 +35,25 @@ final class ConfirmKbsPinViewModel extends ViewModel implements BaseKbsPinViewMo
|
|||
return Transformations.distinctUntilChanged(saveAnimation);
|
||||
}
|
||||
|
||||
LiveData<Label> getLabel() {
|
||||
LiveData<LabelState> getLabel() {
|
||||
return Transformations.distinctUntilChanged(label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void confirm() {
|
||||
KbsPin userEntry = this.userEntry.getValue();
|
||||
this.userEntry.setValue(KbsPin.EMPTY);
|
||||
|
||||
if (pinToConfirm.toString().equals(userEntry.toString())) {
|
||||
this.label.setValue(Label.CREATING_PIN);
|
||||
this.label.setValue(LabelState.CREATING_PIN);
|
||||
this.saveAnimation.setValue(SaveAnimation.LOADING);
|
||||
|
||||
repository.setPin(pinToConfirm, this.keyboard.getValue(), this::handleResult);
|
||||
} else {
|
||||
this.label.setValue(Label.PIN_DOES_NOT_MATCH);
|
||||
this.userEntry.setValue(KbsPin.EMPTY);
|
||||
this.label.setValue(LabelState.PIN_DOES_NOT_MATCH);
|
||||
}
|
||||
}
|
||||
|
||||
void onLoadingAnimationComplete() {
|
||||
this.label.setValue(Label.EMPTY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LiveData<KbsPin> getUserEntry() {
|
||||
return userEntry;
|
||||
|
@ -91,7 +87,7 @@ final class ConfirmKbsPinViewModel extends ViewModel implements BaseKbsPinViewMo
|
|||
}
|
||||
}
|
||||
|
||||
enum Label {
|
||||
enum LabelState {
|
||||
RE_ENTER_PIN,
|
||||
PIN_DOES_NOT_MATCH,
|
||||
CREATING_PIN,
|
||||
|
|
|
@ -1,112 +0,0 @@
|
|||
package org.thoughtcrime.securesms.lock.v2;
|
||||
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.PluralsRes;
|
||||
import androidx.autofill.HintConstants;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.navigation.Navigation;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.util.SpanUtil;
|
||||
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
|
||||
|
||||
public class CreateKbsPinFragment extends BaseKbsPinFragment<CreateKbsPinViewModel> {
|
||||
|
||||
@Override
|
||||
protected void initializeViewStates() {
|
||||
CreateKbsPinFragmentArgs args = CreateKbsPinFragmentArgs.fromBundle(requireArguments());
|
||||
|
||||
if (args.getIsPinChange()) {
|
||||
initializeViewStatesForPinChange(args.getIsForgotPin());
|
||||
} else {
|
||||
initializeViewStatesForPinCreate();
|
||||
}
|
||||
|
||||
getLabel().setText(getPinLengthRestrictionText(R.plurals.CreateKbsPinFragment__pin_must_be_at_least_digits));
|
||||
getConfirm().setEnabled(false);
|
||||
ViewCompat.setAutofillHints(getInput(), HintConstants.AUTOFILL_HINT_NEW_PASSWORD);
|
||||
}
|
||||
|
||||
private void initializeViewStatesForPinChange(boolean isForgotPin) {
|
||||
getTitle().setText(R.string.CreateKbsPinFragment__create_a_new_pin);
|
||||
|
||||
getDescription().setText(R.string.CreateKbsPinFragment__you_can_choose_a_new_pin_as_long_as_this_device_is_registered);
|
||||
getDescription().setLearnMoreVisible(true);
|
||||
}
|
||||
|
||||
private void initializeViewStatesForPinCreate() {
|
||||
getTitle().setText(R.string.CreateKbsPinFragment__create_your_pin);
|
||||
getDescription().setText(R.string.CreateKbsPinFragment__pins_keep_information_stored_with_signal_encrypted);
|
||||
getDescription().setLearnMoreVisible(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CreateKbsPinViewModel initializeViewModel() {
|
||||
CreateKbsPinViewModel viewModel = new ViewModelProvider(this).get(CreateKbsPinViewModel.class);
|
||||
CreateKbsPinFragmentArgs args = CreateKbsPinFragmentArgs.fromBundle(requireArguments());
|
||||
|
||||
viewModel.getNavigationEvents().observe(getViewLifecycleOwner(), e -> onConfirmPin(e.getUserEntry(), e.getKeyboard(), args.getIsPinChange()));
|
||||
viewModel.getErrorEvents().observe(getViewLifecycleOwner(), e -> {
|
||||
if (e == CreateKbsPinViewModel.PinErrorEvent.WEAK_PIN) {
|
||||
getLabel().setText(SpanUtil.color(ContextCompat.getColor(requireContext(), R.color.red_500),
|
||||
getString(R.string.CreateKbsPinFragment__choose_a_stronger_pin)));
|
||||
shake(getInput(), () -> getInput().getText().clear());
|
||||
} else {
|
||||
throw new AssertionError("Unexpected PIN error!");
|
||||
}
|
||||
});
|
||||
viewModel.getKeyboard().observe(getViewLifecycleOwner(), k -> {
|
||||
getLabel().setText(getLabelText(k));
|
||||
getInput().getText().clear();
|
||||
});
|
||||
|
||||
return viewModel;
|
||||
}
|
||||
|
||||
private void onConfirmPin(@NonNull KbsPin userEntry, @NonNull PinKeyboardType keyboard, boolean isPinChange) {
|
||||
CreateKbsPinFragmentDirections.ActionConfirmPin action = CreateKbsPinFragmentDirections.actionConfirmPin();
|
||||
|
||||
action.setUserEntry(userEntry);
|
||||
action.setKeyboard(keyboard);
|
||||
action.setIsPinChange(isPinChange);
|
||||
|
||||
SafeNavigation.safeNavigate(Navigation.findNavController(requireView()), action);
|
||||
}
|
||||
|
||||
private String getLabelText(@NonNull PinKeyboardType keyboard) {
|
||||
if (keyboard == PinKeyboardType.ALPHA_NUMERIC) {
|
||||
return getPinLengthRestrictionText(R.plurals.CreateKbsPinFragment__pin_must_be_at_least_characters);
|
||||
} else {
|
||||
return getPinLengthRestrictionText(R.plurals.CreateKbsPinFragment__pin_must_be_at_least_digits);
|
||||
}
|
||||
}
|
||||
|
||||
private String getPinLengthRestrictionText(@PluralsRes int plurals) {
|
||||
return requireContext().getResources().getQuantityString(plurals, KbsConstants.MINIMUM_PIN_LENGTH, KbsConstants.MINIMUM_PIN_LENGTH);
|
||||
}
|
||||
|
||||
private static void shake(@NonNull EditText view, @NonNull Runnable afterwards) {
|
||||
TranslateAnimation shake = new TranslateAnimation(0, 30, 0, 0);
|
||||
shake.setDuration(50);
|
||||
shake.setRepeatCount(7);
|
||||
shake.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
afterwards.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {}
|
||||
});
|
||||
view.startAnimation(shake);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package org.thoughtcrime.securesms.lock.v2
|
||||
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.TranslateAnimation
|
||||
import android.widget.EditText
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.autofill.HintConstants
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.Navigation.findNavController
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.lock.v2.CreateKbsPinViewModel.NavigationEvent
|
||||
import org.thoughtcrime.securesms.lock.v2.CreateKbsPinViewModel.PinErrorEvent
|
||||
import org.thoughtcrime.securesms.util.SpanUtil
|
||||
import org.thoughtcrime.securesms.util.navigation.safeNavigate
|
||||
|
||||
class CreateKbsPinFragment : BaseKbsPinFragment<CreateKbsPinViewModel?>() {
|
||||
override fun initializeViewStates() {
|
||||
val args = CreateKbsPinFragmentArgs.fromBundle(requireArguments())
|
||||
if (args.isPinChange) {
|
||||
initializeViewStatesForPinChange(args.isForgotPin)
|
||||
} else {
|
||||
initializeViewStatesForPinCreate()
|
||||
}
|
||||
label.text = getPinLengthRestrictionText(R.plurals.CreateKbsPinFragment__pin_must_be_at_least_digits)
|
||||
confirm.isEnabled = false
|
||||
ViewCompat.setAutofillHints(input, HintConstants.AUTOFILL_HINT_NEW_PASSWORD)
|
||||
}
|
||||
|
||||
private fun initializeViewStatesForPinChange(isForgotPin: Boolean) {
|
||||
title.setText(R.string.CreateKbsPinFragment__create_a_new_pin)
|
||||
description.setText(R.string.CreateKbsPinFragment__you_can_choose_a_new_pin_as_long_as_this_device_is_registered)
|
||||
description.setLearnMoreVisible(true)
|
||||
}
|
||||
|
||||
private fun initializeViewStatesForPinCreate() {
|
||||
title.setText(R.string.CreateKbsPinFragment__create_your_pin)
|
||||
description.setText(R.string.CreateKbsPinFragment__pins_can_help_you_restore_your_account)
|
||||
description.setLearnMoreVisible(true)
|
||||
}
|
||||
|
||||
override fun initializeViewModel(): CreateKbsPinViewModel {
|
||||
val viewModel = ViewModelProvider(this)[CreateKbsPinViewModel::class.java]
|
||||
val args = CreateKbsPinFragmentArgs.fromBundle(requireArguments())
|
||||
viewModel.navigationEvents.observe(viewLifecycleOwner) { e: NavigationEvent -> onConfirmPin(e.userEntry, e.keyboard, args.isPinChange) }
|
||||
viewModel.errorEvents.observe(viewLifecycleOwner) { e: PinErrorEvent ->
|
||||
if (e == PinErrorEvent.WEAK_PIN) {
|
||||
label.text = SpanUtil.color(
|
||||
ContextCompat.getColor(requireContext(), R.color.red_500),
|
||||
getString(R.string.CreateKbsPinFragment__choose_a_stronger_pin)
|
||||
)
|
||||
shake(input) { input.text.clear() }
|
||||
} else {
|
||||
throw AssertionError("Unexpected PIN error!")
|
||||
}
|
||||
}
|
||||
viewModel.keyboard.observe(viewLifecycleOwner) { k: PinKeyboardType ->
|
||||
label.text = getLabelText(k)
|
||||
input.text.clear()
|
||||
}
|
||||
return viewModel
|
||||
}
|
||||
|
||||
private fun onConfirmPin(userEntry: KbsPin, keyboard: PinKeyboardType, isPinChange: Boolean) {
|
||||
val action = CreateKbsPinFragmentDirections.actionConfirmPin()
|
||||
action.userEntry = userEntry
|
||||
action.keyboard = keyboard
|
||||
action.isPinChange = isPinChange
|
||||
findNavController(requireView()).safeNavigate(action)
|
||||
}
|
||||
|
||||
private fun getLabelText(keyboard: PinKeyboardType): String {
|
||||
return if (keyboard == PinKeyboardType.ALPHA_NUMERIC) {
|
||||
getPinLengthRestrictionText(R.plurals.CreateKbsPinFragment__pin_must_be_at_least_characters)
|
||||
} else {
|
||||
getPinLengthRestrictionText(R.plurals.CreateKbsPinFragment__pin_must_be_at_least_digits)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getPinLengthRestrictionText(@PluralsRes plurals: Int): String {
|
||||
return resources.getQuantityString(plurals, KbsConstants.MINIMUM_PIN_LENGTH, KbsConstants.MINIMUM_PIN_LENGTH)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun shake(view: EditText, afterwards: Runnable) {
|
||||
val shake = TranslateAnimation(0F, 30F, 0F, 0F)
|
||||
shake.duration = 50
|
||||
shake.repeatCount = 7
|
||||
shake.setAnimationListener(object : Animation.AnimationListener {
|
||||
override fun onAnimationStart(animation: Animation) {}
|
||||
override fun onAnimationEnd(animation: Animation) {
|
||||
afterwards.run()
|
||||
}
|
||||
|
||||
override fun onAnimationRepeat(animation: Animation) {}
|
||||
})
|
||||
view.startAnimation(shake)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ import org.greenrobot.eventbus.ThreadMode;
|
|||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.LoggingFragment;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.registration.CallMeCountDownView;
|
||||
import org.thoughtcrime.securesms.components.registration.ActionCountDownButton;
|
||||
import org.thoughtcrime.securesms.components.registration.VerificationCodeView;
|
||||
import org.thoughtcrime.securesms.components.registration.VerificationPinKeyboard;
|
||||
import org.thoughtcrime.securesms.registration.ReceivedSmsEvent;
|
||||
|
@ -55,13 +55,11 @@ public abstract class BaseEnterSmsCodeFragment<ViewModel extends BaseRegistratio
|
|||
private static final String TAG = Log.tag(BaseEnterSmsCodeFragment.class);
|
||||
|
||||
private ScrollView scrollView;
|
||||
private TextView header;
|
||||
private TextView subheader;
|
||||
private VerificationCodeView verificationCodeView;
|
||||
private VerificationPinKeyboard keyboard;
|
||||
private CallMeCountDownView callMeCountDown;
|
||||
private ActionCountDownButton callMeCountDown;
|
||||
private View wrongNumber;
|
||||
private View noCodeReceivedHelp;
|
||||
private View serviceWarning;
|
||||
private boolean autoCompleting;
|
||||
|
||||
private ViewModel viewModel;
|
||||
|
@ -80,13 +78,11 @@ public abstract class BaseEnterSmsCodeFragment<ViewModel extends BaseRegistratio
|
|||
setDebugLogSubmitMultiTapView(view.findViewById(R.id.verify_header));
|
||||
|
||||
scrollView = view.findViewById(R.id.scroll_view);
|
||||
header = view.findViewById(R.id.verify_header);
|
||||
subheader = view.findViewById(R.id.verification_subheader);
|
||||
verificationCodeView = view.findViewById(R.id.code);
|
||||
keyboard = view.findViewById(R.id.keyboard);
|
||||
callMeCountDown = view.findViewById(R.id.call_me_count_down);
|
||||
wrongNumber = view.findViewById(R.id.wrong_number);
|
||||
noCodeReceivedHelp = view.findViewById(R.id.no_code);
|
||||
serviceWarning = view.findViewById(R.id.cell_service_warning);
|
||||
|
||||
new SignalStrengthPhoneStateListener(this, this);
|
||||
|
||||
|
@ -106,14 +102,12 @@ public abstract class BaseEnterSmsCodeFragment<ViewModel extends BaseRegistratio
|
|||
}
|
||||
});
|
||||
|
||||
noCodeReceivedHelp.setOnClickListener(v -> sendEmailToSupport());
|
||||
|
||||
disposables.bindTo(getViewLifecycleOwner().getLifecycle());
|
||||
viewModel = getViewModel();
|
||||
viewModel.getSuccessfulCodeRequestAttempts().observe(getViewLifecycleOwner(), (attempts) -> {
|
||||
if (attempts >= 3) {
|
||||
noCodeReceivedHelp.setVisibility(View.VISIBLE);
|
||||
scrollView.postDelayed(() -> scrollView.smoothScrollTo(0, noCodeReceivedHelp.getBottom()), 15000);
|
||||
// TODO Add bottom sheet for help
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -330,7 +324,7 @@ public abstract class BaseEnterSmsCodeFragment<ViewModel extends BaseRegistratio
|
|||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
header.setText(requireContext().getString(R.string.RegistrationActivity_enter_the_code_we_sent_to_s, viewModel.getNumber().getFullFormattedNumber()));
|
||||
subheader.setText(requireContext().getString(R.string.RegistrationActivity_enter_the_code_we_sent_to_s, viewModel.getNumber().getFullFormattedNumber()));
|
||||
|
||||
viewModel.getCanCallAtTime().observe(getViewLifecycleOwner(), callAtTime -> callMeCountDown.startCountDownTo(callAtTime));
|
||||
}
|
||||
|
@ -348,40 +342,11 @@ public abstract class BaseEnterSmsCodeFragment<ViewModel extends BaseRegistratio
|
|||
|
||||
@Override
|
||||
public void onNoCellSignalPresent() {
|
||||
if (serviceWarning.getVisibility() == View.VISIBLE) {
|
||||
return;
|
||||
}
|
||||
serviceWarning.setVisibility(View.VISIBLE);
|
||||
serviceWarning.animate()
|
||||
.alpha(1)
|
||||
.setListener(null)
|
||||
.start();
|
||||
|
||||
scrollView.postDelayed(() -> {
|
||||
if (serviceWarning.getVisibility() == View.VISIBLE) {
|
||||
scrollView.smoothScrollTo(0, serviceWarning.getBottom());
|
||||
}
|
||||
}, 1000);
|
||||
// TODO animate in bottom sheet
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCellSignalPresent() {
|
||||
if (serviceWarning.getVisibility() != View.VISIBLE) {
|
||||
return;
|
||||
}
|
||||
serviceWarning.animate()
|
||||
.alpha(0)
|
||||
.setListener(new Animator.AnimatorListener() {
|
||||
@Override public void onAnimationEnd(Animator animation) {
|
||||
serviceWarning.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override public void onAnimationStart(Animator animation) {}
|
||||
|
||||
@Override public void onAnimationCancel(Animator animation) {}
|
||||
|
||||
@Override public void onAnimationRepeat(Animator animation) {}
|
||||
})
|
||||
.start();
|
||||
// TODO animate away bottom sheet
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,10 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.Spinner;
|
||||
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
@ -27,6 +28,7 @@ import com.google.android.gms.common.ConnectionResult;
|
|||
import com.google.android.gms.common.GoogleApiAvailability;
|
||||
import com.google.android.gms.tasks.Task;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
import com.google.i18n.phonenumbers.NumberParseException;
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
import com.google.i18n.phonenumbers.Phonenumber;
|
||||
|
@ -35,7 +37,6 @@ import org.signal.core.util.ThreadUtil;
|
|||
import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.LoggingFragment;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.LabeledEditText;
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore;
|
||||
import org.thoughtcrime.securesms.registration.VerifyAccountRepository.Mode;
|
||||
import org.thoughtcrime.securesms.registration.util.RegistrationNumberInputController;
|
||||
|
@ -51,6 +52,7 @@ import org.thoughtcrime.securesms.util.ViewUtil;
|
|||
import org.thoughtcrime.securesms.util.navigation.SafeNavigation;
|
||||
import org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
@ -64,10 +66,9 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
|
|||
|
||||
private static final String TAG = Log.tag(EnterPhoneNumberFragment.class);
|
||||
|
||||
private LabeledEditText countryCode;
|
||||
private LabeledEditText number;
|
||||
private TextInputLayout countryCode;
|
||||
private TextInputLayout number;
|
||||
private CircularProgressMaterialButton register;
|
||||
private Spinner countrySpinner;
|
||||
private View cancel;
|
||||
private ScrollView scrollView;
|
||||
private RegistrationViewModel viewModel;
|
||||
|
@ -91,20 +92,16 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
|
|||
|
||||
setDebugLogSubmitMultiTapView(view.findViewById(R.id.verify_header));
|
||||
|
||||
countryCode = view.findViewById(R.id.country_code);
|
||||
number = view.findViewById(R.id.number);
|
||||
countrySpinner = view.findViewById(R.id.country_spinner);
|
||||
cancel = view.findViewById(R.id.cancel_button);
|
||||
scrollView = view.findViewById(R.id.scroll_view);
|
||||
register = view.findViewById(R.id.registerButton);
|
||||
countryCode = view.findViewById(R.id.country_code);
|
||||
number = view.findViewById(R.id.number);
|
||||
cancel = view.findViewById(R.id.cancel_button);
|
||||
scrollView = view.findViewById(R.id.scroll_view);
|
||||
register = view.findViewById(R.id.registerButton);
|
||||
|
||||
RegistrationNumberInputController controller = new RegistrationNumberInputController(requireContext(),
|
||||
countryCode,
|
||||
number,
|
||||
countrySpinner,
|
||||
true,
|
||||
this);
|
||||
|
||||
this,
|
||||
Objects.requireNonNull(number.getEditText()),
|
||||
countryCode);
|
||||
register.setOnClickListener(v -> handleRegister(requireContext()));
|
||||
|
||||
disposables.bindTo(getViewLifecycleOwner().getLifecycle());
|
||||
|
@ -125,7 +122,10 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
|
|||
|
||||
Toolbar toolbar = view.findViewById(R.id.toolbar);
|
||||
((AppCompatActivity) requireActivity()).setSupportActionBar(toolbar);
|
||||
((AppCompatActivity) requireActivity()).getSupportActionBar().setTitle(null);
|
||||
final ActionBar supportActionBar = ((AppCompatActivity) requireActivity()).getSupportActionBar();
|
||||
if (supportActionBar != null) {
|
||||
supportActionBar.setTitle(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -144,13 +144,13 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
|
|||
}
|
||||
|
||||
private void handleRegister(@NonNull Context context) {
|
||||
if (TextUtils.isEmpty(countryCode.getText())) {
|
||||
if (TextUtils.isEmpty(countryCode.getEditText().getText())) {
|
||||
showErrorDialog(context, getString(R.string.RegistrationActivity_you_must_specify_your_country_code));
|
||||
return;
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(this.number.getText())) {
|
||||
showErrorDialog(context, getString(R.string.RegistrationActivity_you_must_specify_your_phone_number));
|
||||
if (TextUtils.isEmpty(this.number.getEditText().getText())) {
|
||||
showErrorDialog(context, getString(R.string.RegistrationActivity_please_enter_a_valid_phone_number_to_register));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -184,8 +184,8 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
|
|||
disableAllEntries();
|
||||
|
||||
if (fcmSupported) {
|
||||
SmsRetrieverClient client = SmsRetriever.getClient(context);
|
||||
Task<Void> task = client.startSmsRetriever();
|
||||
SmsRetrieverClient client = SmsRetriever.getClient(context);
|
||||
Task<Void> task = client.startSmsRetriever();
|
||||
AtomicBoolean handled = new AtomicBoolean(false);
|
||||
|
||||
Debouncer debouncer = new Debouncer(TimeUnit.SECONDS.toMillis(5));
|
||||
|
@ -224,14 +224,12 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
|
|||
private void disableAllEntries() {
|
||||
countryCode.setEnabled(false);
|
||||
number.setEnabled(false);
|
||||
countrySpinner.setEnabled(false);
|
||||
cancel.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
private void enableAllEntries() {
|
||||
countryCode.setEnabled(true);
|
||||
number.setEnabled(true);
|
||||
countrySpinner.setEnabled(true);
|
||||
if (viewModel.isReregister()) {
|
||||
cancel.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
@ -283,22 +281,12 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
|
|||
scrollView.postDelayed(() -> scrollView.smoothScrollTo(0, register.getBottom()), 250);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNumberInputNext(@NonNull View view) {
|
||||
// Intentionally left blank
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNumberInputDone(@NonNull View view) {
|
||||
ViewUtil.hideKeyboard(requireContext(), view);
|
||||
handleRegister(requireContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPickCountry(@NonNull View view) {
|
||||
SafeNavigation.safeNavigate(Navigation.findNavController(view), R.id.action_pickCountry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNationalNumber(@NonNull String number) {
|
||||
viewModel.setNationalNumber(number);
|
||||
|
@ -325,8 +313,8 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
|
|||
d.dismiss();
|
||||
})
|
||||
.setPositiveButton(R.string.yes, (d, i) -> {
|
||||
countryCode.setText(String.valueOf(phoneNumber.getCountryCode()));
|
||||
number.setText(String.valueOf(phoneNumber.getNationalNumber()));
|
||||
countryCode.getEditText().setText(String.valueOf(phoneNumber.getCountryCode()));
|
||||
number.getEditText().setText(String.valueOf(phoneNumber.getNationalNumber()));
|
||||
requestVerificationCode(mode);
|
||||
d.dismiss();
|
||||
})
|
||||
|
@ -357,9 +345,9 @@ public final class EnterPhoneNumberFragment extends LoggingFragment implements R
|
|||
R.string.RegistrationActivity_a_verification_code_will_be_sent_to,
|
||||
e164number,
|
||||
() -> {
|
||||
ViewUtil.hideKeyboard(context, number.getInput());
|
||||
ViewUtil.hideKeyboard(context, number.getEditText());
|
||||
onConfirmed.run();
|
||||
},
|
||||
() -> number.focusAndMoveCursorToEndAndOpenKeyboard());
|
||||
() -> ViewUtil.focusAndMoveCursorToEndAndOpenKeyboard(this.number.getEditText()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ import org.thoughtcrime.securesms.components.LabeledEditText;
|
|||
import org.thoughtcrime.securesms.registration.viewmodel.NumberViewState;
|
||||
|
||||
/**
|
||||
* Handle the logic and formatting of phone number input for registration/change number flows.
|
||||
* Handle the logic and formatting of phone number input specifically for change number flows.
|
||||
*/
|
||||
public final class RegistrationNumberInputController {
|
||||
public final class ChangeNumberInputController {
|
||||
|
||||
private final Context context;
|
||||
private final LabeledEditText countryCode;
|
||||
|
@ -38,12 +38,12 @@ public final class RegistrationNumberInputController {
|
|||
private AsYouTypeFormatter countryFormatter;
|
||||
private boolean isUpdating = true;
|
||||
|
||||
public RegistrationNumberInputController(@NonNull Context context,
|
||||
@NonNull LabeledEditText countryCode,
|
||||
@NonNull LabeledEditText number,
|
||||
@NonNull Spinner countrySpinner,
|
||||
boolean lastInput,
|
||||
@NonNull Callbacks callbacks)
|
||||
public ChangeNumberInputController(@NonNull Context context,
|
||||
@NonNull LabeledEditText countryCode,
|
||||
@NonNull LabeledEditText number,
|
||||
@NonNull Spinner countrySpinner,
|
||||
boolean lastInput,
|
||||
@NonNull Callbacks callbacks)
|
||||
{
|
||||
this.context = context;
|
||||
this.countryCode = countryCode;
|
|
@ -0,0 +1,155 @@
|
|||
package org.thoughtcrime.securesms.registration.util
|
||||
|
||||
import android.content.Context
|
||||
import android.text.Editable
|
||||
import android.text.TextUtils
|
||||
import android.text.TextWatcher
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
import android.view.View.OnFocusChangeListener
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
import com.google.android.material.textfield.TextInputLayout
|
||||
import com.google.i18n.phonenumbers.AsYouTypeFormatter
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.registration.viewmodel.NumberViewState
|
||||
|
||||
/**
|
||||
* Handle the logic and formatting of phone number input specifically for registration number the flow.
|
||||
*/
|
||||
class RegistrationNumberInputController(
|
||||
val context: Context,
|
||||
val callbacks: Callbacks,
|
||||
private val phoneNumberInputLayout: EditText,
|
||||
countryCodeInputLayout: TextInputLayout
|
||||
) {
|
||||
private val spinnerView: MaterialAutoCompleteTextView = countryCodeInputLayout.editText as MaterialAutoCompleteTextView
|
||||
private val supportedCountryPrefixes: List<CountryPrefix> = PhoneNumberUtil.getInstance().supportedCallingCodes
|
||||
.map { CountryPrefix(it, PhoneNumberUtil.getInstance().getRegionCodeForCountryCode(it)) }
|
||||
.sortedBy { it.digits }
|
||||
private val spinnerAdapter: ArrayAdapter<CountryPrefix> = ArrayAdapter<CountryPrefix>(context, R.layout.registration_country_code_dropdown_item, supportedCountryPrefixes)
|
||||
|
||||
private var countryFormatter: AsYouTypeFormatter? = null
|
||||
private var isUpdating = true
|
||||
|
||||
init {
|
||||
setUpNumberInput()
|
||||
|
||||
spinnerView.setAdapter(spinnerAdapter)
|
||||
spinnerView.addTextChangedListener(CountryCodeEntryListener())
|
||||
}
|
||||
|
||||
private fun advanceToPhoneNumberInput() {
|
||||
if (!isUpdating) {
|
||||
phoneNumberInputLayout.requestFocus()
|
||||
}
|
||||
val numberLength: Int = phoneNumberInputLayout.text?.length ?: 0
|
||||
phoneNumberInputLayout.setSelection(numberLength, numberLength)
|
||||
}
|
||||
|
||||
private fun setUpNumberInput() {
|
||||
phoneNumberInputLayout.addTextChangedListener(NumberChangedListener())
|
||||
phoneNumberInputLayout.onFocusChangeListener = OnFocusChangeListener { v: View?, hasFocus: Boolean ->
|
||||
if (hasFocus) {
|
||||
callbacks.onNumberFocused()
|
||||
}
|
||||
}
|
||||
phoneNumberInputLayout.imeOptions = EditorInfo.IME_ACTION_DONE
|
||||
phoneNumberInputLayout.setOnEditorActionListener { v: TextView?, actionId: Int, _: KeyEvent? ->
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
callbacks.onNumberInputDone(v!!)
|
||||
return@setOnEditorActionListener true
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun updateNumber(numberViewState: NumberViewState) {
|
||||
val countryCode = numberViewState.countryCode
|
||||
|
||||
isUpdating = true
|
||||
val regionCode = PhoneNumberUtil.getInstance().getRegionCodeForCountryCode(countryCode)
|
||||
setCountryFormatter(regionCode)
|
||||
|
||||
isUpdating = false
|
||||
}
|
||||
|
||||
private fun setCountryFormatter(regionCode: String?) {
|
||||
val util = PhoneNumberUtil.getInstance()
|
||||
countryFormatter = if (regionCode != null) util.getAsYouTypeFormatter(regionCode) else null
|
||||
reformatText(phoneNumberInputLayout.text)
|
||||
}
|
||||
|
||||
private fun reformatText(editable: Editable): String? {
|
||||
if (TextUtils.isEmpty(editable)) {
|
||||
return null
|
||||
}
|
||||
val countryFormatter: AsYouTypeFormatter = countryFormatter ?: return null
|
||||
countryFormatter.clear()
|
||||
var formattedNumber: String? = null
|
||||
val justDigits = StringBuilder()
|
||||
for (character in editable) {
|
||||
if (Character.isDigit(character)) {
|
||||
formattedNumber = countryFormatter.inputDigit(character)
|
||||
justDigits.append(character)
|
||||
}
|
||||
}
|
||||
if (formattedNumber != null && editable.toString() != formattedNumber) {
|
||||
editable.replace(0, editable.length, formattedNumber)
|
||||
}
|
||||
return if (justDigits.isEmpty()) {
|
||||
null
|
||||
} else justDigits.toString()
|
||||
}
|
||||
|
||||
inner class NumberChangedListener : TextWatcher {
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
val number: String = reformatText(s) ?: return
|
||||
if (!isUpdating) {
|
||||
callbacks.setNationalNumber(number)
|
||||
}
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
|
||||
}
|
||||
|
||||
inner class CountryCodeEntryListener : TextWatcher {
|
||||
|
||||
override fun afterTextChanged(s: Editable?) {
|
||||
if (s.isNullOrEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (s[0] != '+') {
|
||||
s.insert(0, "+")
|
||||
}
|
||||
|
||||
supportedCountryPrefixes.firstOrNull { it.toString() == s.toString() }?.let {
|
||||
setCountryFormatter(it.regionCode)
|
||||
callbacks.setCountry(it.digits)
|
||||
advanceToPhoneNumberInput()
|
||||
}
|
||||
}
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||
}
|
||||
|
||||
interface Callbacks {
|
||||
fun onNumberFocused()
|
||||
fun onNumberInputDone(view: View)
|
||||
fun setNationalNumber(number: String)
|
||||
fun setCountry(countryCode: Int)
|
||||
}
|
||||
}
|
||||
|
||||
data class CountryPrefix(val digits: Int, val regionCode: String) {
|
||||
override fun toString(): String {
|
||||
return "+$digits"
|
||||
}
|
||||
}
|
|
@ -1,71 +1,66 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:viewBindingIgnore="true"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:attr/windowBackground"
|
||||
android:fillViewport="true">
|
||||
android:fillViewport="true"
|
||||
tools:viewBindingIgnore="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/kbs_pin_toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/edit_kbs_pin_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAppearance="@style/TextAppearance.Signal.Title1"
|
||||
app:layout_constraintBottom_toTopOf="@id/edit_kbs_pin_keyboard_toggle"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:textAppearance="@style/Signal.Text.HeadlineMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.20"
|
||||
tools:text="@string/CreateKbsPinFragment__create_your_pin" />
|
||||
|
||||
<org.thoughtcrime.securesms.util.views.LearnMoreTextView
|
||||
android:id="@+id/edit_kbs_pin_description"
|
||||
style="@style/Signal.Text.BodyLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="27dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="27dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:minHeight="66dp"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:textColor="@color/signal_text_secondary"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edit_kbs_pin_title"
|
||||
tools:text="@string/CreateKbsPinFragment__pins_keep_information_stored_with_signal_encrypted" />
|
||||
tools:text="@string/CreateKbsPinFragment__pins_can_help_you_restore_your_account" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_kbs_pin_input"
|
||||
android:layout_width="wrap_content"
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/edit_kbs_textinputlayout"
|
||||
style="@style/Widget.Signal.TextInputLayout.Registration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:inputType="numberPassword"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:minWidth="210dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edit_kbs_pin_description" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/edit_kbs_pin_description">
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/edit_kbs_pin_lottie_progress"
|
||||
android:layout_width="57dp"
|
||||
android:layout_height="57dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edit_kbs_pin_description" />
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/edit_kbs_pin_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="numberPassword" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.airbnb.lottie.LottieAnimationView
|
||||
android:id="@+id/edit_kbs_pin_lottie_end"
|
||||
|
@ -85,7 +80,7 @@
|
|||
android:gravity="center_horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/edit_kbs_pin_input"
|
||||
app:layout_constraintTop_toBottomOf="@id/edit_kbs_textinputlayout"
|
||||
app:layout_goneMarginTop="65dp"
|
||||
tools:text="PIN must be at least 4 digits" />
|
||||
|
||||
|
@ -94,22 +89,25 @@
|
|||
style="@style/Signal.Widget.Button.Large.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/edit_kbs_pin_input_label"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/edit_kbs_pin_confirm"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
app:layout_constraintTop_toBottomOf="@id/edit_kbs_pin_input_label"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
tools:layout_editor_absoluteX="32dp"
|
||||
tools:text="Create Alphanumeric Pin" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
<org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
|
||||
android:id="@+id/edit_kbs_pin_confirm"
|
||||
style="@style/Signal.Widget.Button.Large.Tonal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="@string/BaseKbsPinFragment__next"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
app:circularProgressMaterialButton__label="@string/BaseKbsPinFragment__next"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:materialThemeOverlay="@style/ThemeOverlay.Signal.CircularProgressIndicator.Tonal" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
|
@ -1,12 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:viewBindingIgnore="true"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".registration.fragments.EnterSmsCodeFragment">
|
||||
tools:context=".registration.fragments.EnterSmsCodeFragment"
|
||||
tools:viewBindingIgnore="true">
|
||||
|
||||
<ScrollView
|
||||
android:id="@+id/scroll_view"
|
||||
|
@ -25,52 +25,45 @@
|
|||
style="@style/Signal.Widget.Button.Large.Secondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_toEndOf="@id/call_me_count_down"
|
||||
android:layout_marginStart="22dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="@dimen/registrationactivity_text_view_padding"
|
||||
android:hyphenationFrequency="normal"
|
||||
android:maxWidth="150dp"
|
||||
android:text="@string/RegistrationActivity_wrong_number"
|
||||
android:textColor="@color/signal_text_secondary"
|
||||
android:textColor="@color/signal_colorPrimary"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/call_me_count_down"
|
||||
app:layout_constraintTop_toBottomOf="@+id/code" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/no_code"
|
||||
style="@style/Signal.Widget.Button.Large.Secondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_toEndOf="@id/call_me_count_down"
|
||||
android:hyphenationFrequency="normal"
|
||||
android:text="@string/RegistrationActivity_contact_signal_support"
|
||||
android:textColor="@color/signal_text_secondary"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/call_me_count_down"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/wrong_number"
|
||||
tools:visibility="visible" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/verification_subheader" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/verify_header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="40dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:gravity="center"
|
||||
android:gravity="start"
|
||||
android:text="@string/RegistrationActivity_verification_code"
|
||||
android:textAppearance="@style/Signal.Text.HeadlineMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/verification_subheader"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="@+id/verify_header"
|
||||
app:layout_constraintTop_toBottomOf="@+id/verify_header"
|
||||
tools:text="@string/RegistrationActivity_enter_the_code_we_sent_to_s" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.registration.CallMeCountDownView
|
||||
<org.thoughtcrime.securesms.components.registration.ActionCountDownButton
|
||||
android:id="@+id/call_me_count_down"
|
||||
style="@style/Signal.Widget.Button.Large.Secondary"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -79,66 +72,39 @@
|
|||
android:hyphenationFrequency="normal"
|
||||
android:maxWidth="150dp"
|
||||
android:textColor="@color/signal_text_secondary"
|
||||
app:layout_constraintEnd_toStartOf="@+id/wrong_number"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/resend_sms_count_down"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/wrong_number"
|
||||
app:layout_constraintTop_toBottomOf="@+id/code"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
tools:text="@string/RegistrationActivity_call" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.registration.ActionCountDownButton
|
||||
android:id="@+id/resend_sms_count_down"
|
||||
style="@style/Signal.Widget.Button.Large.Secondary"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/code"
|
||||
android:hyphenationFrequency="normal"
|
||||
android:maxWidth="150dp"
|
||||
android:textColor="@color/signal_text_secondary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/code"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
tools:text="@string/RegistrationActivity_resend_code" />
|
||||
|
||||
<org.thoughtcrime.securesms.components.registration.VerificationCodeView
|
||||
android:id="@+id/code"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/verify_header" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/cell_service_warning"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:alpha="0"
|
||||
android:background="@drawable/registration_no_cell_service_warning_border"
|
||||
android:gravity="center"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="8dp"
|
||||
android:paddingBottom="4dp"
|
||||
android:text="@string/RegistrationActivity_make_sure_your_phone_has_a_cellular_signal"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/no_code"
|
||||
tools:alpha="1"
|
||||
tools:visibility="visible">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:layout_margin="2dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:srcCompat="@drawable/ic_error_outline_14"
|
||||
app:tint="@color/core_ultramarine" />
|
||||
|
||||
<TextView
|
||||
style="@style/Signal.Text.Body.Registration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/RegistrationActivity_make_sure_your_phone_has_a_cellular_signal"
|
||||
android:textAlignment="center"
|
||||
android:textColor="@color/core_ultramarine"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
app:layout_constraintTop_toBottomOf="@id/wrong_number" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
@ -147,6 +113,7 @@
|
|||
<org.thoughtcrime.securesms.components.registration.VerificationPinKeyboard
|
||||
android:id="@+id/keyboard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
android:layout_height="wrap_content"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</LinearLayout>
|
|
@ -1,13 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:viewBindingIgnore="true"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/scroll_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
tools:context=".registration.fragments.EnterPhoneNumberFragment">
|
||||
tools:context=".registration.fragments.EnterPhoneNumberFragment"
|
||||
tools:viewBindingIgnore="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -19,59 +19,57 @@
|
|||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/country_spinner_frame"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:background="@drawable/labeled_edit_text_background_inactive"
|
||||
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/verify_subheader">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/country_spinner"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp"
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layoutDirection="ltr"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/country_spinner_frame">
|
||||
app:layout_constraintTop_toBottomOf="@id/verify_subheader">
|
||||
|
||||
<org.thoughtcrime.securesms.components.LabeledEditText
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/country_code"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_weight="1"
|
||||
app:labeledEditText_background="@color/white"
|
||||
app:labeledEditText_textLayout="@layout/country_code_text" />
|
||||
style="@style/Widget.Signal.TextInputLayout.Registration.Dropdown"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
app:errorEnabled="false"
|
||||
app:hintEnabled="false">
|
||||
|
||||
<org.thoughtcrime.securesms.components.LabeledEditText
|
||||
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:digits="+1234567890"
|
||||
android:drawablePadding="-24dp"
|
||||
android:hint="@string/Registration_country_code_entry_hint"
|
||||
android:imeOptions="actionNext"
|
||||
android:maxLength="4"
|
||||
android:maxLines="1"
|
||||
android:padding="0dp"
|
||||
android:singleLine="true"
|
||||
tools:text="+1" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/number"
|
||||
style="@style/Widget.Signal.TextInputLayout.Registration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="3"
|
||||
app:labeledEditText_background="@color/white"
|
||||
app:labeledEditText_label="@string/RegistrationActivity_phone_number_description"
|
||||
app:labeledEditText_textLayout="@layout/phone_text" />
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/RegistrationActivity_phone_number_description">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="phone" />
|
||||
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
|
@ -81,8 +79,7 @@
|
|||
android:layout_gravity="center"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/RegistrationActivity_enter_your_phone_number_to_get_started"
|
||||
android:text="@string/RegistrationActivity_enter_your_phone_number"
|
||||
android:textAppearance="@style/Signal.Text.HeadlineMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
|
@ -91,14 +88,14 @@
|
|||
|
||||
<TextView
|
||||
android:id="@+id/verify_subheader"
|
||||
style="@style/Signal.Text.Body.Registration"
|
||||
style="@style/Signal.Text.BodyLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/RegistrationActivity_you_will_receive_a_verification_code"
|
||||
android:textColor="@color/core_grey_60"
|
||||
app:layout_constraintTop_toBottomOf="@+id/verify_header"
|
||||
tools:layout_editor_absoluteX="0dp" />
|
||||
|
||||
|
@ -126,14 +123,12 @@
|
|||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:materialThemeOverlay="@style/ThemeOverlay.Signal.CircularProgressIndicator.Tonal"
|
||||
app:circularProgressMaterialButton__label="@string/RegistrationActivity_next"
|
||||
app:circularProgressMaterialButton__label="@string/RegistrationActivity_continue"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/linearLayout"
|
||||
app:layout_constraintVertical_bias="0" />
|
||||
app:layout_constraintVertical_bias="0"
|
||||
app:materialThemeOverlay="@style/ThemeOverlay.Signal.CircularProgressIndicator.Tonal" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
tools:viewBindingIgnore="true"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
android:fillViewport="true"
|
||||
tools:viewBindingIgnore="true">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -54,8 +54,8 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:textAppearance="@style/Signal.Text.BodyMedium"
|
||||
android:gravity="center_horizontal"
|
||||
android:textAppearance="@style/Signal.Text.BodyMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/kbs_lock_pin_input"
|
||||
|
@ -78,25 +78,26 @@
|
|||
style="@style/Signal.Widget.Button.Large.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/kbs_lock_pin_confirm"
|
||||
app:layout_constraintTop_toBottomOf="@id/kbs_lock_forgot_pin"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
tools:layout_editor_absoluteX="32dp"
|
||||
tools:text="Create Alphanumeric Pin" />
|
||||
|
||||
<org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
|
||||
android:id="@+id/kbs_lock_pin_confirm"
|
||||
android:layout_width="0dp"
|
||||
style="@style/Signal.Widget.Button.Large.Tonal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:materialThemeOverlay="@style/ThemeOverlay.Signal.CircularProgressIndicator.Primary"
|
||||
app:circularProgressMaterialButton__label="@string/RegistrationActivity_continue"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:materialThemeOverlay="@style/ThemeOverlay.Signal.CircularProgressIndicator.Tonal" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
|
@ -15,39 +15,53 @@
|
|||
android:id="@+id/pin_restore_pin_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:text="@string/RegistrationLockFragment__enter_your_pin"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:textAppearance="@style/Signal.Text.HeadlineMedium"
|
||||
app:layout_constraintBottom_toTopOf="@id/pin_restore_keyboard_toggle"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:text="@string/RegistrationLockFragment__enter_your_pin"
|
||||
app:layout_constraintBottom_toTopOf="@id/pin_restore_pin_description"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.20" />
|
||||
app:layout_constraintVertical_bias="0.0" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pin_restore_pin_description"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="27dp"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginEnd="27dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:minHeight="66dp"
|
||||
android:text="@string/RegistrationLockFragment__enter_the_pin_you_created"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
android:textColor="@color/core_grey_60"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/pin_restore_pin_title" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/pin_restore_pin_input"
|
||||
android:layout_width="wrap_content"
|
||||
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/edit_kbs_textinputlayout"
|
||||
style="@style/Widget.Signal.TextInputLayout.Registration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="12dp"
|
||||
android:gravity="center_horizontal"
|
||||
android:inputType="numberPassword"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
android:minWidth="210dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/pin_restore_pin_description" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/pin_restore_pin_description">
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/pin_restore_pin_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="numberPassword" />
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/pin_restore_pin_input_label"
|
||||
|
@ -58,7 +72,7 @@
|
|||
android:textAppearance="@style/Signal.Text.BodyMedium"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/pin_restore_pin_input"
|
||||
app:layout_constraintTop_toBottomOf="@id/edit_kbs_textinputlayout"
|
||||
tools:text="@string/RegistrationLockFragment__incorrect_pin_try_again" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
|
@ -80,25 +94,25 @@
|
|||
style="@style/Signal.Widget.Button.Large.Secondary"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
app:layout_constraintBottom_toTopOf="@id/pin_restore_pin_confirm"
|
||||
app:layout_constraintTop_toBottomOf="@id/pin_restore_forgot_pin"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
app:layout_constraintVertical_bias="0.0"
|
||||
tools:layout_editor_absoluteX="32dp"
|
||||
tools:text="Create Alphanumeric Pin" />
|
||||
|
||||
<org.thoughtcrime.securesms.util.views.CircularProgressMaterialButton
|
||||
android:id="@+id/pin_restore_pin_confirm"
|
||||
android:layout_width="0dp"
|
||||
style="@style/Signal.Widget.Button.Large.Tonal"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="32dp"
|
||||
android:layout_marginEnd="32dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:materialThemeOverlay="@style/ThemeOverlay.Signal.CircularProgressIndicator.Primary"
|
||||
app:circularProgressMaterialButton__label="@string/RegistrationActivity_continue"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:materialThemeOverlay="@style/ThemeOverlay.Signal.CircularProgressIndicator.Tonal" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/pin_restore_skip_button"
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/text1"
|
||||
style="?android:attr/spinnerDropDownItemStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:gravity="center"
|
||||
android:singleLine="true" />
|
|
@ -8,76 +8,85 @@
|
|||
android:layoutDirection="ltr"
|
||||
tools:viewBindingIgnore="true">
|
||||
|
||||
<FrameLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/container_zero"
|
||||
style="@style/Widget.Signal.TextInputLayout.Registration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/labeled_edit_text_background_inactive"
|
||||
app:errorEnabled="false"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintDimensionRatio="w,1:1"
|
||||
app:layout_constraintEnd_toStartOf="@+id/container_one"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/code_zero"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:importantForAccessibility="yes"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
android:padding="0dp"
|
||||
android:textSize="16sp"
|
||||
tools:text="0" />
|
||||
|
||||
</FrameLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<FrameLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/container_one"
|
||||
style="@style/Widget.Signal.TextInputLayout.Registration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:background="@drawable/labeled_edit_text_background_inactive"
|
||||
app:errorEnabled="false"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintDimensionRatio="w,1:1"
|
||||
app:layout_constraintEnd_toStartOf="@+id/container_two"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/container_zero"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/code_one"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:importantForAccessibility="yes"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
android:padding="0dp"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
tools:text="1" />
|
||||
|
||||
</FrameLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<FrameLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/container_two"
|
||||
style="@style/Widget.Signal.TextInputLayout.Registration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:background="@drawable/labeled_edit_text_background_inactive"
|
||||
app:errorEnabled="false"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintDimensionRatio="w,1:1"
|
||||
app:layout_constraintEnd_toStartOf="@+id/separator"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/container_one"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/code_two"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:importantForAccessibility="yes"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
android:padding="0dp"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
tools:text="2" />
|
||||
|
||||
</FrameLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/separator"
|
||||
|
@ -87,83 +96,92 @@
|
|||
android:layout_marginStart="4dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:text="-"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/container_three"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/container_two"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="HardcodedText" />
|
||||
|
||||
<FrameLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/container_three"
|
||||
style="@style/Widget.Signal.TextInputLayout.Registration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:background="@drawable/labeled_edit_text_background_inactive"
|
||||
app:errorEnabled="false"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintDimensionRatio="w,1:1"
|
||||
app:layout_constraintEnd_toStartOf="@+id/container_four"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/separator"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/code_three"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:importantForAccessibility="yes"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
android:padding="0dp"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
tools:text="3" />
|
||||
|
||||
</FrameLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<FrameLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/container_four"
|
||||
style="@style/Widget.Signal.TextInputLayout.Registration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:background="@drawable/labeled_edit_text_background_inactive"
|
||||
app:errorEnabled="false"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintDimensionRatio="w,1:1"
|
||||
app:layout_constraintEnd_toStartOf="@+id/container_five"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/container_three"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/code_four"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:importantForAccessibility="yes"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
android:padding="0dp"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
tools:text="4" />
|
||||
|
||||
</FrameLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
<FrameLayout
|
||||
<com.google.android.material.textfield.TextInputLayout
|
||||
android:id="@+id/container_five"
|
||||
style="@style/Widget.Signal.TextInputLayout.Registration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="4dp"
|
||||
android:background="@drawable/labeled_edit_text_background_inactive"
|
||||
app:errorEnabled="false"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintDimensionRatio="w,1:1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toEndOf="@+id/container_four"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/code_five"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_gravity="center"
|
||||
android:textColor="@color/signal_inverse_primary"
|
||||
android:textSize="28sp"
|
||||
android:gravity="center"
|
||||
android:padding="0dp"
|
||||
android:textAppearance="@style/Signal.Text.BodyLarge"
|
||||
tools:text="5" />
|
||||
|
||||
</FrameLayout>
|
||||
</com.google.android.material.textfield.TextInputLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -219,4 +219,5 @@
|
|||
<dimen name="media_preview_lottie_button_dimen">36dp</dimen>
|
||||
<dimen name="media_rail_item_size">46dp</dimen>
|
||||
<dimen name="media_rail_thumbnail_size">44dp</dimen>
|
||||
<dimen name="registrationactivity_text_view_padding">32dp</dimen>
|
||||
</resources>
|
||||
|
|
|
@ -1696,9 +1696,7 @@
|
|||
<string name="RegistrationActivity_you_must_specify_your_country_code">You must specify your
|
||||
country code
|
||||
</string>
|
||||
<string name="RegistrationActivity_you_must_specify_your_phone_number">You must specify your
|
||||
phone number
|
||||
</string>
|
||||
<string name="RegistrationActivity_please_enter_a_valid_phone_number_to_register">Please enter a valid phone number to register.</string>
|
||||
<string name="RegistrationActivity_invalid_number">Invalid number</string>
|
||||
<string name="RegistrationActivity_the_number_you_specified_s_is_invalid">The number you
|
||||
specified (%s) is invalid.
|
||||
|
@ -1729,15 +1727,17 @@
|
|||
<string name="RegistrationActivity_next">Next</string>
|
||||
<string name="RegistrationActivity_continue">Continue</string>
|
||||
<string name="RegistrationActivity_take_privacy_with_you_be_yourself_in_every_message">Take privacy with you.\nBe yourself in every message.</string>
|
||||
<string name="RegistrationActivity_enter_your_phone_number_to_get_started">Enter your phone number to get started</string>
|
||||
<string name="RegistrationActivity_enter_your_phone_number">Enter your phone number</string>
|
||||
<string name="RegistrationActivity_you_will_receive_a_verification_code">You will receive a verification code. Carrier rates may apply.</string>
|
||||
<string name="RegistrationActivity_you_will_receive_a_verification_code">You will receive a verification code.\nCarrier rates may apply.</string>
|
||||
<string name="RegistrationActivity_enter_the_code_we_sent_to_s">Enter the code we sent to %s</string>
|
||||
<string name="RegistrationActivity_make_sure_your_phone_has_a_cellular_signal">Make sure your phone has a cellular signal to receive your SMS or call</string>
|
||||
|
||||
<string name="RegistrationActivity_phone_number_description">Phone number</string>
|
||||
<string name="RegistrationActivity_country_code_description">Country code</string>
|
||||
<string name="RegistrationActivity_country_code_hint">Country</string>
|
||||
<string name="RegistrationActivity_call">Call</string>
|
||||
<string name="RegistrationActivity_verification_code">Verification Code</string>
|
||||
<string name="RegistrationActivity_resend_code">Resend Code</string>
|
||||
|
||||
<!-- RegistrationLockV2Dialog -->
|
||||
<string name="RegistrationLockV2Dialog_turn_on_registration_lock">Turn on Registration Lock?</string>
|
||||
|
@ -3180,11 +3180,13 @@
|
|||
<string name="CreateKbsPinFragment__create_a_new_pin">Create a new PIN</string>
|
||||
<string name="CreateKbsPinFragment__you_can_choose_a_new_pin_as_long_as_this_device_is_registered">You can change your PIN as long as this device is registered.</string>
|
||||
<string name="CreateKbsPinFragment__create_your_pin">Create your PIN</string>
|
||||
<string name="CreateKbsPinFragment__pins_keep_information_stored_with_signal_encrypted">PINs keep information stored with Signal encrypted so only you can access it. Your profile, settings, and contacts will restore when you reinstall. You won\'t need your PIN to open the app.</string>
|
||||
<string name="CreateKbsPinFragment__pins_can_help_you_restore_your_account">PINs can help you restore your account and keep your info encrypted with Signal. </string>
|
||||
<string name="CreateKbsPinFragment__choose_a_stronger_pin">Choose a stronger PIN</string>
|
||||
|
||||
<!-- ConfirmKbsPinFragment -->
|
||||
<string name="ConfirmKbsPinFragment__pins_dont_match">PINs don\'t match. Try again.</string>
|
||||
<!-- Prompt for the user to repeat entering the PIN in order to help them remember it correctly. -->
|
||||
<string name="ConfirmKbsPinFragment__re_enter_the_pin_you_just_created">Re-enter the PIN you just created.</string>
|
||||
<string name="ConfirmKbsPinFragment__confirm_your_pin">Confirm your PIN.</string>
|
||||
<string name="ConfirmKbsPinFragment__pin_creation_failed">PIN creation failed</string>
|
||||
<string name="ConfirmKbsPinFragment__your_pin_was_not_saved">Your PIN was not saved. We\'ll prompt you to create a PIN later.</string>
|
||||
|
@ -3324,7 +3326,7 @@
|
|||
<!-- Error message shown if a very large attachment is encountered during the backup creation and causes the backup to fail -->
|
||||
<string name="LocalBackupJobApi29_your_backup_contains_a_very_large_file">Your backup contains a very large file that cannot be backed up. Please delete it and create a new backup.</string>
|
||||
<string name="LocalBackupJobApi29_tap_to_manage_backups">Tap to manage backups.</string>
|
||||
<string name="RegistrationActivity_wrong_number">Wrong number</string>
|
||||
<string name="RegistrationActivity_wrong_number">Wrong number?</string>
|
||||
<string name="RegistrationActivity_call_me_instead_available_in">Call me instead \n (Available in %1$02d:%2$02d)</string>
|
||||
<string name="RegistrationActivity_contact_signal_support">Contact Signal Support</string>
|
||||
<string name="RegistrationActivity_code_support_subject">Signal Registration - Verification Code for Android</string>
|
||||
|
@ -5467,6 +5469,7 @@
|
|||
<string name="GroupStoryEducationSheet__all_group_chat_members">All group chat members can view story replies.</string>
|
||||
<!-- Button label to dismiss sheet -->
|
||||
<string name="GroupStoryEducationSheet__next">Next</string>
|
||||
<string name="Registration_country_code_entry_hint">+0</string>
|
||||
|
||||
<!-- EOF -->
|
||||
|
||||
|
|
|
@ -500,6 +500,25 @@
|
|||
<item name="hintTextAppearance">@style/Signal.Text.LabelMedium</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.Signal.TextInputLayout.Registration" parent="Widget.MaterialComponents.TextInputLayout.FilledBox">
|
||||
<item name="boxBackgroundColor">@color/signal_colorSurfaceVariant</item>
|
||||
<item name="boxCornerRadiusTopEnd">4dp</item>
|
||||
<item name="boxCornerRadiusTopStart">4dp</item>
|
||||
<item name="hintTextColor">@color/signal_colorPrimary</item>
|
||||
<item name="android:textColorHint">@color/signal_colorPrimary</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="Widget.Signal.TextInputLayout.Registration.Dropdown" parent="Widget.MaterialComponents.TextInputLayout.FilledBox.ExposedDropdownMenu">
|
||||
<item name="android:paddingStart">12dp</item>
|
||||
<item name="android:paddingEnd">6dp</item>
|
||||
<item name="boxBackgroundColor">@color/signal_colorSurfaceVariant</item>
|
||||
<item name="boxCornerRadiusTopEnd">2dp</item>
|
||||
<item name="boxCornerRadiusTopStart">2dp</item>
|
||||
<item name="hintTextColor">@color/signal_colorPrimary</item>
|
||||
<item name="android:textColorHint">@color/signal_colorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="Widget.MaterialComponents.Button.TextButton.Dialog">
|
||||
<item name="android:minWidth">@dimen/mtrl_btn_dialog_btn_min_width</item>
|
||||
<!-- Allow buttons to span more than one line so that the end isn't cut
|
||||
|
|
Loading…
Add table
Reference in a new issue