[android] Use LiveEvent to communicate password validation and account deletion

This commit is contained in:
Torsten Grote
2019-05-09 15:16:53 -03:00
parent 5676e18a22
commit e37ee7ee04
4 changed files with 36 additions and 30 deletions

View File

@@ -172,6 +172,12 @@ public abstract class BaseActivity extends AppCompatActivity
.commit(); .commit();
} }
protected boolean isFragmentAdded(String fragmentTag) {
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentByTag(fragmentTag);
return f != null && f.isAdded();
}
private boolean showScreenFilterWarning() { private boolean showScreenFilterWarning() {
// If the dialog is already visible, filter the tap // If the dialog is already visible, filter the tap
ScreenFilterDialogFragment f = findDialogFragment(); ScreenFilterDialogFragment f = findDialogFragment();

View File

@@ -35,7 +35,7 @@ import static org.briarproject.briar.android.util.UiUtils.showSoftKeyboard;
@ParametersNotNullByDefault @ParametersNotNullByDefault
public class PasswordFragment extends BaseFragment implements TextWatcher { public class PasswordFragment extends BaseFragment implements TextWatcher {
private final static String TAG = PasswordFragment.class.getName(); final static String TAG = PasswordFragment.class.getName();
@Inject @Inject
ViewModelProvider.Factory viewModelFactory; ViewModelProvider.Factory viewModelFactory;
@@ -60,7 +60,9 @@ public class PasswordFragment extends BaseFragment implements TextWatcher {
viewModel = ViewModelProviders.of(requireActivity(), viewModelFactory) viewModel = ViewModelProviders.of(requireActivity(), viewModelFactory)
.get(StartupViewModel.class); .get(StartupViewModel.class);
viewModel.getPasswordValidated().observe(this, this::onPasswordValidated); viewModel.getPasswordValidated().observeEvent(this, valid -> {
if (!valid) onPasswordInvalid();
});
signInButton = v.findViewById(R.id.btn_sign_in); signInButton = v.findViewById(R.id.btn_sign_in);
signInButton.setOnClickListener(view -> onSignInButtonClicked()); signInButton.setOnClickListener(view -> onSignInButtonClicked());
@@ -103,19 +105,14 @@ public class PasswordFragment extends BaseFragment implements TextWatcher {
viewModel.validatePassword(password.getText().toString()); viewModel.validatePassword(password.getText().toString());
} }
private void onPasswordValidated(@Nullable Boolean valid) { private void onPasswordInvalid() {
if (valid != null && !valid) { setError(input, getString(R.string.try_again), true);
setError(input, getString(R.string.try_again), true); signInButton.setVisibility(VISIBLE);
signInButton.setVisibility(VISIBLE); progress.setVisibility(INVISIBLE);
progress.setVisibility(INVISIBLE); password.setText(null);
password.setText(null);
// show the keyboard again // show the keyboard again
showSoftKeyboard(password); showSoftKeyboard(password);
// reset validation state for configuration changes
viewModel.getPasswordValidated().setValue(null);
}
} }
public void onForgottenPasswordClick() { public void onForgottenPasswordClick() {

View File

@@ -5,8 +5,6 @@ import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent; import android.content.Intent;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
@@ -63,8 +61,8 @@ public class StartupActivity extends BaseActivity implements
onAccountDeleted(); onAccountDeleted();
return; return;
} }
viewModel.getAccountDeleted().observe(this, deleted -> { viewModel.getAccountDeleted().observeEvent(this, deleted -> {
if (deleted != null && deleted) onAccountDeleted(); if (deleted) onAccountDeleted();
}); });
viewModel.getState().observe(this, this::onStateChanged); viewModel.getState().observe(this, this::onStateChanged);
} }
@@ -85,7 +83,12 @@ public class StartupActivity extends BaseActivity implements
private void onStateChanged(State state) { private void onStateChanged(State state) {
if (state == SIGNED_OUT) { if (state == SIGNED_OUT) {
showInitialFragment(new PasswordFragment()); // Configuration changes such as screen rotation
// can cause this to get called again.
// Don't replace the fragment in that case to not lose view state.
if (!isFragmentAdded(PasswordFragment.TAG)) {
showInitialFragment(new PasswordFragment());
}
} else if (state == SIGNED_IN) { } else if (state == SIGNED_IN) {
startService(new Intent(this, BriarService.class)); startService(new Intent(this, BriarService.class));
} else if (state == STARTING) { } else if (state == STARTING) {
@@ -93,9 +96,7 @@ public class StartupActivity extends BaseActivity implements
// This can happen because several LifecycleManager states are // This can happen because several LifecycleManager states are
// mapped to STARTING, so this can get called several times // mapped to STARTING, so this can get called several times
// as the app's lifecycle advances. // as the app's lifecycle advances.
FragmentManager fm = getSupportFragmentManager(); if (!isFragmentAdded(OpenDatabaseFragment.TAG)) {
Fragment f = fm.findFragmentByTag(OpenDatabaseFragment.TAG);
if (f == null || !f.isVisible()) {
showNextFragment(new OpenDatabaseFragment()); showNextFragment(new OpenDatabaseFragment());
} }
} else if (state == STARTED) { } else if (state == STARTED) {

View File

@@ -15,6 +15,8 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState; import org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState;
import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent; import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault; import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.android.viewmodel.LiveEvent;
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
import org.briarproject.briar.api.android.AndroidNotificationManager; import org.briarproject.briar.api.android.AndroidNotificationManager;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -43,10 +45,10 @@ public class StartupViewModel extends AndroidViewModel
@IoExecutor @IoExecutor
private final Executor ioExecutor; private final Executor ioExecutor;
private final MutableLiveData<Boolean> passwordValidated = private final MutableLiveEvent<Boolean> passwordValidated =
new MutableLiveData<>(); new MutableLiveEvent<>();
private final MutableLiveData<Boolean> accountDeleted = private final MutableLiveEvent<Boolean> accountDeleted =
new MutableLiveData<>(); new MutableLiveEvent<>();
private final MutableLiveData<State> state = new MutableLiveData<>(); private final MutableLiveData<State> state = new MutableLiveData<>();
@Inject @Inject
@@ -103,16 +105,16 @@ public class StartupViewModel extends AndroidViewModel
void validatePassword(String password) { void validatePassword(String password) {
ioExecutor.execute(() -> { ioExecutor.execute(() -> {
boolean signedIn = accountManager.signIn(password); boolean signedIn = accountManager.signIn(password);
passwordValidated.postValue(signedIn); passwordValidated.postEvent(signedIn);
if (signedIn) state.postValue(SIGNED_IN); if (signedIn) state.postValue(SIGNED_IN);
}); });
} }
MutableLiveData<Boolean> getPasswordValidated() { LiveEvent<Boolean> getPasswordValidated() {
return passwordValidated; return passwordValidated;
} }
LiveData<Boolean> getAccountDeleted() { LiveEvent<Boolean> getAccountDeleted() {
return accountDeleted; return accountDeleted;
} }
@@ -123,7 +125,7 @@ public class StartupViewModel extends AndroidViewModel
@UiThread @UiThread
void deleteAccount() { void deleteAccount() {
accountManager.deleteAccount(); accountManager.deleteAccount();
accountDeleted.setValue(true); accountDeleted.setEvent(true);
} }
} }