More account management refactoring

This commit is contained in:
Paul Schaub 2019-12-21 04:08:59 +01:00
parent ba7d983b95
commit 7e2fe55b56
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
7 changed files with 62 additions and 96 deletions

View File

@ -54,6 +54,10 @@ public class AccountsFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
observeViewModel();
}
private void observeViewModel() {
viewModel.getAccounts().observe(this, adapter::setValues);
}

View File

@ -1,6 +1,5 @@
package org.mercury_im.messenger.ui.account;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -11,7 +10,6 @@ import android.widget.TextView;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import org.mercury_im.messenger.Messenger;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.ui.avatar.AvatarDrawable;
@ -23,13 +21,12 @@ import java.util.List;
public class AccountsRecyclerViewAdapter extends RecyclerView.Adapter<AccountsRecyclerViewAdapter.ViewHolder> {
private final List<Account> mValues;
private final OnAccountListItemClickListener mListener;
private final List<Account> accounts = new ArrayList<>();
private final OnAccountListItemClickListener onAccountClickListener;
private final AccountsViewModel viewModel;
public AccountsRecyclerViewAdapter(AccountsViewModel viewModel, OnAccountListItemClickListener listener) {
mValues = new ArrayList<>();
mListener = listener;
onAccountClickListener = listener;
this.viewModel = viewModel;
}
@ -40,43 +37,40 @@ public class AccountsRecyclerViewAdapter extends RecyclerView.Adapter<AccountsRe
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Account account = mValues.get(position);
holder.jid.setText(account.getAddress());
holder.avatar.setImageDrawable(new AvatarDrawable(account.getAddress(), account.getAddress()));
holder.enabled.setChecked(account.isEnabled());
holder.account = account;
holder.enabled.setOnCheckedChangeListener((compoundButton, b) -> {
viewModel.toggleAccountEnabled(account);
});
holder.mView.setOnClickListener(v -> {
if (null != mListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onAccountListItemClick(holder.account);
}
});
holder.mView.setOnLongClickListener(v -> {
if (null != mListener) {
mListener.onAccountListItemLongClick(holder.account);
}
return true;
});
}
public void setValues(List<Account> values) {
Log.d("AAAAA", "New values: " + values.size());
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new AccountsDiffCallback(values, mValues), true);
mValues.clear();
mValues.addAll(values);
DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new AccountsDiffCallback(values, accounts), true);
accounts.clear();
accounts.addAll(values);
diffResult.dispatchUpdatesTo(this);
}
@Override
public int getItemCount() {
Log.d(Messenger.TAG, "Accounts Item Count: " + mValues.size());
return mValues.size();
return accounts.size();
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Account account = accounts.get(position);
holder.account = account;
holder.jid.setText(account.getAddress());
holder.avatar.setImageDrawable(new AvatarDrawable(account.getAddress(), account.getAddress()));
holder.enabled.setChecked(account.isEnabled());
holder.enabled.setOnCheckedChangeListener((compoundButton, checked) -> viewModel.setAccountEnabled(account, checked));
holder.mView.setOnClickListener(v -> {
if (null != onAccountClickListener) {
onAccountClickListener.onAccountListItemClick(holder.account);
}
});
holder.mView.setOnLongClickListener(v -> {
if (null != onAccountClickListener) {
onAccountClickListener.onAccountListItemLongClick(holder.account);
}
return true;
});
}
public class ViewHolder extends RecyclerView.ViewHolder {

View File

@ -42,16 +42,8 @@ public class AccountsViewModel extends AndroidViewModel {
return accounts;
}
public void toggleAccountEnabled(Account accountModel) {
/*
MercuryConnection connection = connectionCenter.getConnection(accountModel);
if (connection == null) {
Toast.makeText(this.getApplication(), "MercuryConnection is null!", Toast.LENGTH_LONG).show();
return;
}
*/
accountModel.setEnabled(!accountModel.isEnabled());
public void setAccountEnabled(Account accountModel, boolean enabled) {
accountModel.setEnabled(enabled);
repository.upsertAccount(accountModel)
.subscribe();
}

View File

@ -1,21 +0,0 @@
package org.mercury_im.messenger.ui.account;
import android.content.Context;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
public class AddAccountDialog extends AlertDialog {
protected AddAccountDialog(@NonNull Context context, int themeResId) {
super(context, themeResId);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
}

View File

@ -118,22 +118,6 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito
}
}
private void displayCredentials(LiveData<Account> account) {
account.observe(this, accountEvent -> {
if (accountEvent == null) {
return;
}
if (accountEvent.getAddress() != null) {
addressView.setText(accountEvent.getAddress());
}
if (accountEvent.getPassword() != null) {
passwordView.setText(accountEvent.getPassword());
}
});
}
private void setupTextInputListeners() {
addressView.setOnEditorActionListener(this);
passwordView.setOnEditorActionListener(this);

View File

@ -19,14 +19,17 @@ import org.mercury_im.messenger.R;
import javax.inject.Inject;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
public class LoginViewModel extends AndroidViewModel {
private MutableLiveData<Error> usernameError = new MutableLiveData<>(new Error());
private MutableLiveData<Error> passwordError = new MutableLiveData<>(new Error());
private MutableLiveData<Boolean> loginEnabled = new MutableLiveData<>(false);
private MutableLiveData<Boolean> loginSuccessful = new MutableLiveData<>(false);
private MutableLiveData<Boolean> loginButtonEnabled = new MutableLiveData<>(false);
private MutableLiveData<Boolean> loginCompleted = new MutableLiveData<>(false);
private final CompositeDisposable disposable = new CompositeDisposable();
private EntityBareJid username;
private String password;
@ -66,36 +69,42 @@ public class LoginViewModel extends AndroidViewModel {
}
private void updateLoginEnabled() {
loginEnabled.setValue(username != null && !(password == null || password.isEmpty()));
loginButtonEnabled.setValue(username != null && !(password == null || password.isEmpty()));
}
public synchronized void login() {
if (!loginEnabled.getValue()) {
if (!loginButtonEnabled.getValue()) {
// Prevent race condition where account would be logged in twice
return;
}
loginEnabled.setValue(false);
messenger.addAccount()
loginButtonEnabled.setValue(false);
disposable.add(messenger.addAccount()
.setAddress(username.asEntityBareJidString())
.setPassword(password)
.loginAndStoreAccountIfSuccessful()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.doOnComplete(() -> loginSuccessful.setValue(true))
.doOnComplete(() -> loginCompleted.setValue(true))
.doOnError(this::handleConnectionError)
.subscribe();
.subscribe());
}
private void handleConnectionError(Throwable error) {
if (error instanceof SASLErrorException) {
passwordError.setValue(new Error(getApplication().getResources().getString(R.string.error_incorrect_password)));
loginEnabled.setValue(true);
loginButtonEnabled.setValue(true);
} else {
Toast.makeText(getApplication(), "A connection error occurred", Toast.LENGTH_LONG).show();
loginEnabled.setValue(true);
loginButtonEnabled.setValue(true);
}
}
@Override
protected void onCleared() {
super.onCleared();
disposable.clear();
}
public LiveData<Error> getPasswordError() {
return passwordError;
}
@ -105,11 +114,11 @@ public class LoginViewModel extends AndroidViewModel {
}
public LiveData<Boolean> isLoginSuccessful() {
return loginSuccessful;
return loginCompleted;
}
public LiveData<Boolean> isLoginEnabled() {
return loginEnabled;
return loginButtonEnabled;
}
public static class Error {

View File

@ -30,4 +30,8 @@ public interface Account {
void setEnabled(boolean enabled);
boolean isEnabled();
default String displayName() {
return getAddress();
}
}