Copy code from SetPassword fragment to avoid it using the wrong view model

This commit is contained in:
ameba23
2021-04-22 10:56:20 +02:00
parent 2e03967519
commit 41c13f80f4
6 changed files with 235 additions and 4 deletions

View File

@@ -29,6 +29,7 @@ import static org.briarproject.briar.android.account.SetupViewModel.State.SET_PA
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public
class SetupViewModel extends AndroidViewModel {
enum State {AUTHOR_NAME, SET_PASSWORD, DOZE, CREATED, FAILED}

View File

@@ -95,6 +95,7 @@ import org.briarproject.briar.android.socialbackup.ShardsSentFragment;
import org.briarproject.briar.android.socialbackup.ThresholdSelectorFragment;
import org.briarproject.briar.android.socialbackup.creation.CreateBackupModule;
import org.briarproject.briar.android.socialbackup.recover.RestoreAccountActivity;
import org.briarproject.briar.android.socialbackup.recover.RestoreAccountSetPasswordFragment;
import org.briarproject.briar.android.splash.SplashScreenActivity;
import org.briarproject.briar.android.test.TestDataActivity;
import org.briarproject.briar.api.socialbackup.recovery.RestoreAccount;
@@ -291,4 +292,6 @@ public interface ActivityComponent {
void inject(OwnerReturnShardFragment ownerReturnShardFragment);
void inject(CustodianReturnShardSuccessFragment custodianReturnShardSuccessFragment);
void inject(RestoreAccountSetPasswordFragment restoreAccountSetPasswordFragment);
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.briar.android.socialbackup.recover;
import org.briarproject.briar.android.viewmodel.ViewModelKey;
import org.briarproject.briar.api.socialbackup.recovery.RestoreAccount;
import androidx.lifecycle.ViewModel;
import dagger.Binds;
@@ -17,4 +18,9 @@ public abstract class OwnerReturnShardModule {
abstract ViewModel bindOwnerReturnShardViewModel(
OwnerReturnShardViewModel ownerReturnShardViewModel);
@Binds
@IntoMap
@ViewModelKey(RestoreAccountViewModel.class)
abstract ViewModel bindRestoreAccountViewModel(
RestoreAccountViewModel restoreAccountViewModel);
}

View File

@@ -8,7 +8,6 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.account.DozeFragment;
import org.briarproject.briar.android.account.SetPasswordFragment;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.fragment.BaseFragment;
@@ -50,10 +49,10 @@ public class RestoreAccountActivity extends BaseActivity
}
private void onStateChanged(RestoreAccountViewModel.State state) {
if (state == RestoreAccountViewModel.State.SET_PASSWORD) {
showInitialFragment(SetPasswordFragment.newInstance());
if (state == State.SET_PASSWORD) {
showInitialFragment(RestoreAccountSetPasswordFragment.newInstance());
} else if (state == State.DOZE) {
showDozeFragment();
// showDozeFragment();
} else if (state == State.CREATED || state == State.FAILED) {
// TODO: Show an error if failed
showApp();

View File

@@ -0,0 +1,91 @@
package org.briarproject.briar.android.socialbackup.recover;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.fragment.BaseFragment;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
import static android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
import static org.briarproject.briar.android.util.UiUtils.enterPressed;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
abstract class RestoreAccountFragment extends BaseFragment implements TextWatcher,
TextView.OnEditorActionListener, View.OnClickListener {
private final static String STATE_KEY_CLICKED = "setupFragmentClicked";
@Inject
ViewModelProvider.Factory viewModelFactory;
RestoreAccountViewModel viewModel;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(requireActivity())
.get(RestoreAccountViewModel.class);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.help_action, menu);
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == R.id.action_help) {
showOnboardingDialog(getContext(), getHelpText());
return true;
} else {
return super.onOptionsItemSelected(item);
}
}
protected abstract String getHelpText();
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// noop
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
// noop
}
@Override
public boolean onEditorAction(TextView textView, int actionId,
@Nullable KeyEvent keyEvent) {
if (actionId == IME_ACTION_NEXT || actionId == IME_ACTION_DONE ||
enterPressed(actionId, keyEvent)) {
onClick(textView);
return true;
}
return false;
}
@Override
public void afterTextChanged(Editable editable) {
// noop
}
}

View File

@@ -0,0 +1,131 @@
package org.briarproject.briar.android.socialbackup.recover;
import android.os.Bundle;
import android.os.IBinder;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.ProgressBar;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.login.StrengthMeter;
import javax.annotation.Nullable;
import static android.content.Context.INPUT_METHOD_SERVICE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static android.view.inputmethod.EditorInfo.IME_ACTION_DONE;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
import static org.briarproject.briar.android.util.UiUtils.setError;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class RestoreAccountSetPasswordFragment extends RestoreAccountFragment {
private final static String TAG = RestoreAccountSetPasswordFragment.class.getName();
private TextInputLayout passwordEntryWrapper;
private TextInputLayout passwordConfirmationWrapper;
private TextInputEditText passwordEntry;
private TextInputEditText passwordConfirmation;
private StrengthMeter strengthMeter;
private Button nextButton;
public static RestoreAccountSetPasswordFragment newInstance() {
return new RestoreAccountSetPasswordFragment();
}
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
}
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
requireActivity().setTitle(getString(R.string.setup_password_intro));
View v = inflater.inflate(R.layout.fragment_setup_password, container,
false);
strengthMeter = v.findViewById(R.id.strength_meter);
passwordEntryWrapper = v.findViewById(R.id.password_entry_wrapper);
passwordEntry = v.findViewById(R.id.password_entry);
passwordConfirmationWrapper =
v.findViewById(R.id.password_confirm_wrapper);
passwordConfirmation = v.findViewById(R.id.password_confirm);
nextButton = v.findViewById(R.id.next);
ProgressBar progressBar = v.findViewById(R.id.progress);
passwordEntry.addTextChangedListener(this);
passwordConfirmation.addTextChangedListener(this);
nextButton.setOnClickListener(this);
if (!viewModel.needToShowDozeFragment()) {
nextButton.setText(R.string.create_account_button);
passwordConfirmation.setImeOptions(IME_ACTION_DONE);
}
viewModel.getIsCreatingAccount()
.observe(getViewLifecycleOwner(), isCreatingAccount -> {
if (isCreatingAccount) {
nextButton.setVisibility(INVISIBLE);
progressBar.setVisibility(VISIBLE);
// this also avoids the keyboard popping up
passwordEntry.setFocusable(false);
passwordConfirmation.setFocusable(false);
}
});
return v;
}
@Override
public String getUniqueTag() {
return TAG;
}
@Override
protected String getHelpText() {
return getString(R.string.setup_password_explanation);
}
@Override
public void onTextChanged(CharSequence authorName, int i, int i1, int i2) {
String password1 = passwordEntry.getText().toString();
String password2 = passwordConfirmation.getText().toString();
boolean passwordsMatch = password1.equals(password2);
strengthMeter
.setVisibility(password1.length() > 0 ? VISIBLE : INVISIBLE);
float strength = viewModel.estimatePasswordStrength(password1);
strengthMeter.setStrength(strength);
boolean strongEnough = strength >= QUITE_WEAK;
setError(passwordEntryWrapper, getString(R.string.password_too_weak),
password1.length() > 0 && !strongEnough);
setError(passwordConfirmationWrapper,
getString(R.string.passwords_do_not_match),
password2.length() > 0 && !passwordsMatch);
boolean enabled = passwordsMatch && strongEnough;
nextButton.setEnabled(enabled);
passwordConfirmation.setOnEditorActionListener(enabled ? this : null);
}
@Override
public void onClick(View view) {
IBinder token = passwordEntry.getWindowToken();
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
viewModel.setPassword(passwordEntry.getText().toString());
}
}