Fix progressbar and ikey generation dialog

This commit is contained in:
Paul Schaub 2020-12-02 13:36:04 +01:00
parent c322f321cf
commit 748c77c092
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
12 changed files with 67 additions and 151 deletions

View File

@ -7,7 +7,7 @@ import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.crypto.ikey.IkeyBackupCreationFragment;
import org.mercury_im.messenger.android.ui.account.login.IkeyBackupCreationFragment;
import org.mercury_im.messenger.android.ui.account.login.IkeyBackupRestoreOrSkipFragment;
import org.mercury_im.messenger.android.ui.account.login.IkeyKeyInfoFragment;
import org.mercury_im.messenger.android.ui.account.login.IkeySetupNavigator;

View File

@ -23,7 +23,7 @@ import com.google.android.material.card.MaterialCardView;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.crypto.ikey.IkeyBackupCreationFragment;
import org.mercury_im.messenger.android.ui.account.login.IkeyBackupCreationFragment;
import org.mercury_im.messenger.android.ui.account.login.IkeySetupFragment;
import org.mercury_im.messenger.android.ui.openpgp.ToggleableFingerprintsAdapter;
import org.mercury_im.messenger.android.ui.openpgp.OpenPgpV4FingerprintFormatter;

View File

@ -18,7 +18,6 @@ import com.google.android.material.floatingactionbutton.ExtendedFloatingActionBu
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.ui.account.OnAccountListItemClickListener;
import org.mercury_im.messenger.android.ui.account.login.AddAccountActivity;
import org.mercury_im.messenger.android.ui.account.login.AddAccountDialogFragment;
import java.util.ArrayList;
@ -102,11 +101,6 @@ public class AccountListFragment extends Fragment implements SearchView.OnQueryT
accountClickListener = null;
}
private void displayAddAccountDialog() {
AddAccountDialogFragment addAccountDialogFragment = new AddAccountDialogFragment();
addAccountDialogFragment.show(getParentFragmentManager(), "addAccount");
}
@Override
public boolean onQueryTextSubmit(String query) {
return false;

View File

@ -13,7 +13,6 @@ import androidx.viewpager2.widget.ViewPager2;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.crypto.ikey.IkeyBackupCreationFragment;
import org.mercury_im.messenger.android.di.component.AppComponent;
import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.entity.Account;

View File

@ -1,126 +0,0 @@
package org.mercury_im.messenger.android.ui.account.login;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatDialogFragment;
import com.google.android.material.textfield.TextInputEditText;
import com.google.android.material.textfield.TextInputLayout;
import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.R;
import butterknife.BindView;
import butterknife.ButterKnife;
public class AddAccountDialogFragment extends AppCompatDialogFragment {
@BindView(R.id.username)
TextInputEditText addressView;
@BindView(R.id.username_layout)
TextInputLayout addressLayout;
@BindView(R.id.password)
TextInputEditText passwordView;
@BindView(R.id.password_layout)
TextInputLayout passwordLayout;
private AndroidLoginViewModel viewModel;
@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
LayoutInflater inflater = requireActivity().getLayoutInflater();
View dialogView = inflater.inflate(R.layout.view_account_credentials, null);
ButterKnife.bind(this, dialogView);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.action_add_account)
.setView(dialogView)
.setCancelable(false)
.setPositiveButton(R.string.action_sign_in, null)
.setNegativeButton(R.string.button_cancel, cancelButtonClickListener);
return builder.create();
}
private final DialogInterface.OnClickListener cancelButtonClickListener =
(dialog, which) -> AddAccountDialogFragment.this.onCancel(dialog);
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
@Override
public void onResume() {
super.onResume();
final AlertDialog d = (AlertDialog)getDialog();
if(d == null) {
return;
}
viewModel = new AndroidLoginViewModel(MercuryImApplication.getApplication());
Button positiveButton = d.getButton(Dialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(v -> viewModel.onLoginButtonClicked());
viewModel.getLoginUsernameError().observe(this, error -> addressLayout.setError(error));
viewModel.getLoginPasswordError().observe(this, error -> passwordLayout.setError(error));
viewModel.isLoginButtonEnabled().observe(this, positiveButton::setEnabled);
viewModel.isLoginFinished().observe(this, optAccount -> {
if (optAccount.isPresent()) {
dismiss();
}
});
addressView.addTextChangedListener(viewModel.getUsernameTextChangedListener());
passwordView.addTextChangedListener(viewModel.getPasswordTextChangedListener());
addressView.setOnEditorActionListener(focusPasswordFieldOnEnterPressed);
passwordView.setOnEditorActionListener(loginOnEnterPressed);
}
private final TextView.OnEditorActionListener focusPasswordFieldOnEnterPressed = new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_NEXT) {
passwordView.requestFocus();
return true;
}
return false;
}
};
private final TextView.OnEditorActionListener loginOnEnterPressed = new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
viewModel.getCommonViewModel().login();
return true;
}
return false;
}
};
@Override
public void onDestroy() {
super.onDestroy();
}
}

View File

@ -26,6 +26,7 @@ public class AndroidLoginViewModel extends AndroidViewModel implements MercuryAn
private final MutableLiveData<String> loginPasswordError = new MutableLiveData<>();
private final MutableLiveData<Boolean> loginButtonEnabled = new MutableLiveData<>(true);
private final MutableLiveData<Optional<Account>> loginFinished = new MutableLiveData<>(new Optional<>());
private final MutableLiveData<Boolean> displayProgressBar = new MutableLiveData<>(false);
@Inject
LoginViewModel commonViewModel;
@ -49,6 +50,8 @@ public class AndroidLoginViewModel extends AndroidViewModel implements MercuryAn
.subscribe(loginButtonEnabled::setValue));
addDisposable(getCommonViewModel().isLoginSuccessful()
.subscribe(loginFinished::setValue));
addDisposable(getCommonViewModel().isDisplayProgressBar()
.subscribe(displayProgressBar::setValue));
}
private final ObservableTransformer<Optional<UsernameError>, Optional<String>> usernameErrorToErrorMessage =
@ -120,6 +123,10 @@ public class AndroidLoginViewModel extends AndroidViewModel implements MercuryAn
return loginFinished;
}
public LiveData<Boolean> isDisplayProgressBar() {
return displayProgressBar;
}
@Override
public LoginViewModel getCommonViewModel() {
return commonViewModel;

View File

@ -76,8 +76,8 @@ public class EnterAccountDetailsFragment extends Fragment {
viewModel.getLoginUsernameError().observe(this, error -> usernameLayout.setError(error));
viewModel.getLoginPasswordError().observe(this, error -> passwordLayout.setError(error));
viewModel.isLoginButtonEnabled().observe(this, loginButton::setEnabled);
viewModel.isLoginButtonEnabled().observe(this, enabled ->
progressBar.setVisibility(enabled ? View.GONE : View.VISIBLE));
viewModel.isDisplayProgressBar().observe(this, visible ->
progressBar.setVisibility(visible ? View.VISIBLE : View.GONE));
viewModel.isLoginFinished().observe(this, optAccount ->
((AddAccountActivity) getActivity()).loginFinished(optAccount));

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.crypto.ikey;
package org.mercury_im.messenger.android.ui.account.login;
import androidx.lifecycle.ViewModelProvider;
@ -11,16 +11,13 @@ import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import org.bouncycastle.openpgp.PGPException;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.pubsub.PubSubException;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.crypto.ikey.AndroidIkeyBackupCreationViewModel;
import java.io.IOException;
import java.util.UUID;
import butterknife.BindView;
@ -36,6 +33,9 @@ public class IkeyBackupCreationFragment extends Fragment {
@BindView(R.id.qr_code)
ImageView qrCode;
@BindView(R.id.btn_done)
Button doneButton;
private final UUID accountId;
private IkeyBackupCreationFragment(UUID accountId) {
@ -60,10 +60,11 @@ public class IkeyBackupCreationFragment extends Fragment {
viewModel = new ViewModelProvider(this).get(AndroidIkeyBackupCreationViewModel.class);
viewModel.initialize(accountId);
viewModel.uploadBackup();
viewModel.uploadBackup();
viewModel.getPassphrase().observe(getViewLifecycleOwner(), passphrase -> backupCode.setText(passphrase));
viewModel.getPassphraseAsQrCode().observe(getViewLifecycleOwner(), bitmap -> qrCode.setImageBitmap(bitmap));
doneButton.setOnClickListener(v -> getActivity().finish());
}
}

View File

@ -16,8 +16,12 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import org.bouncycastle.openpgp.PGPException;
import org.mercury_im.messenger.R;
import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.UUID;
import butterknife.BindView;
@ -66,8 +70,20 @@ public class IkeyBackupRestoreOrSkipFragment extends Fragment {
viewModel = new ViewModelProvider(requireActivity()).get(AndroidIkeySetupViewModel.class);
restoreButton.setOnClickListener(v -> onRestore());
regenerateButton.setOnClickListener(v ->
((IkeySetupNavigator) getActivity()).generateIkeyBackup(accountId));
regenerateButton.setOnClickListener(v -> {
try {
viewModel.generateIdentityKey();
} catch (PGPException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
((IkeySetupNavigator) getActivity()).displayInfo(accountId);
});
viewModel.getPassphraseError().observe(this, opt -> {
if (opt.isPresent()) {

View File

@ -164,15 +164,18 @@
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="6dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingStart="12dp"
android:paddingEnd="12dp"
android:paddingTop="12dp">
android:padding="8dp">
<TextView
android:id="@+id/title"

View File

@ -4,7 +4,7 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".android.crypto.ikey.IkeyBackupCreationFragment">
tools:context=".android.ui.account.login.IkeyBackupCreationFragment">
<TextView
android:id="@+id/notice"
@ -47,5 +47,19 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/qr_code"
tools:text="TWNK-KD5Y-MT3T-E1GS-DRDB-KVTW" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="end"
app:layout_constraintTop_toBottomOf="@id/backup_code">
<Button
android:id="@+id/btn_done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Done" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -38,6 +38,7 @@ public class LoginViewModel implements MercuryViewModel {
private BehaviorSubject<Optional<PasswordError>> loginPasswordError;
private BehaviorSubject<Boolean> isLoginPossible;
private BehaviorSubject<Optional<Account>> isLoginSuccessful;
private BehaviorSubject<Boolean> displayProgressBar;
private EntityBareJid loginUsernameValue;
private String loginPasswordValue;
@ -59,6 +60,7 @@ public class LoginViewModel implements MercuryViewModel {
loginPasswordError = BehaviorSubject.createDefault(new Optional<>());
isLoginPossible = BehaviorSubject.createDefault(false);
isLoginSuccessful = BehaviorSubject.createDefault(new Optional<>());
displayProgressBar = BehaviorSubject.createDefault(false);
loginUsernameValue = null;
loginPasswordValue = null;
@ -112,6 +114,7 @@ public class LoginViewModel implements MercuryViewModel {
}
public synchronized Account login() {
displayProgressBar.onNext(true);
if (!isLoginPossible.getValue()) {
// Prevent race condition where account would be logged in twice
return account;
@ -145,6 +148,7 @@ public class LoginViewModel implements MercuryViewModel {
.firstOrError()
.compose(schedulers.executeUiSafeSingle())
.subscribe(connectivityState -> {
displayProgressBar.onNext(false);
if (connectivityState == ConnectivityState.disconnectedOnError) {
onLoginFailed(new Exception());
} else {
@ -178,4 +182,8 @@ public class LoginViewModel implements MercuryViewModel {
loginUsernameError.onNext(new Optional<>(UsernameError.unreachableServer));
}
}
public Observable<Boolean> isDisplayProgressBar() {
return displayProgressBar;
}
}