Account Setup flow rework
This commit is contained in:
parent
7d6b75b326
commit
067ea4b65b
|
@ -104,6 +104,10 @@ dependencies {
|
|||
implementation "com.jakewharton:butterknife:$butterKnifeVersion"
|
||||
annotationProcessor "com.jakewharton:butterknife-compiler:$butterKnifeVersion"
|
||||
|
||||
// RxBinding
|
||||
implementation 'com.jakewharton.rxbinding4:rxbinding:4.0.0'
|
||||
implementation 'com.jakewharton.rxbinding4:rxbinding-core:4.0.0'
|
||||
|
||||
// support libraries
|
||||
implementation "androidx.appcompat:appcompat:$appCompatVersion"
|
||||
implementation 'com.google.android.material:material:1.2.0-alpha03'
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
android:roundIcon="@drawable/ic_mercury_icon"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.Mercury">
|
||||
<activity android:name=".android.ui.ikey.IkeyBackupRestoreActivity"></activity>
|
||||
<activity android:name=".android.crypto.ikey.IkeyBackupRestoreActivity">
|
||||
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.ui.chat.ChatActivity"
|
||||
android:label="Chat" />
|
||||
|
@ -35,6 +37,7 @@
|
|||
android:label="@string/title_activity_settings" />
|
||||
<activity android:name=".android.ui.contacts.detail.ContactDetailActivity" />
|
||||
<activity android:name=".android.ui.account.detail.AccountDetailsActivity" />
|
||||
<activity android:name=".android.ui.account.login.AddAccountActivity" />
|
||||
|
||||
<service android:name=".android.service.MercuryForegroundService" />
|
||||
</application>
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.content.Intent;
|
|||
import android.os.Build;
|
||||
|
||||
import org.jivesoftware.smack.android.AndroidSmackInitializer;
|
||||
import org.jivesoftware.smackx.ping.android.ServerPingWithAlarmManager;
|
||||
import org.mercury_im.messenger.android.di.component.DaggerAppComponent;
|
||||
import org.mercury_im.messenger.android.util.AndroidLoggingHandler;
|
||||
import org.mercury_im.messenger.core.Messenger;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.mercury_im.messenger.android.ui.ikey;
|
||||
package org.mercury_im.messenger.android.crypto.ikey;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
|
@ -11,6 +11,7 @@ import org.mercury_im.messenger.android.MercuryImApplication;
|
|||
import org.mercury_im.messenger.android.ui.MercuryAndroidViewModel;
|
||||
import org.mercury_im.messenger.android.util.QrCodeGenerator;
|
||||
import org.mercury_im.messenger.core.SchedulersFacade;
|
||||
import org.mercury_im.messenger.core.crypto.OpenPgpSecretKeyBackupPassphraseGenerator;
|
||||
import org.mercury_im.messenger.core.util.Optional;
|
||||
import org.mercury_im.messenger.core.viewmodel.ikey.IkeySecretKeyBackupCreationViewModel;
|
||||
|
||||
|
@ -22,9 +23,9 @@ import javax.inject.Inject;
|
|||
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public class IkeyBackupCreationAndroidViewModel extends ViewModel implements MercuryAndroidViewModel<IkeySecretKeyBackupCreationViewModel> {
|
||||
public class AndroidIkeyBackupCreationViewModel extends ViewModel implements MercuryAndroidViewModel<IkeySecretKeyBackupCreationViewModel> {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(IkeyBackupCreationAndroidViewModel.class.getName());
|
||||
private static final Logger LOGGER = Logger.getLogger(AndroidIkeyBackupCreationViewModel.class.getName());
|
||||
|
||||
MutableLiveData<OpenPgpSecretKeyBackupPassphrase> passphrase = new MutableLiveData<>();
|
||||
MutableLiveData<Bitmap> passphraseAsQrCode = new MutableLiveData<>();
|
||||
|
@ -32,10 +33,13 @@ public class IkeyBackupCreationAndroidViewModel extends ViewModel implements Mer
|
|||
@Inject
|
||||
IkeySecretKeyBackupCreationViewModel commonViewModel;
|
||||
|
||||
@Inject
|
||||
OpenPgpSecretKeyBackupPassphraseGenerator passphraseGenerator;
|
||||
|
||||
@Inject
|
||||
SchedulersFacade schedulers;
|
||||
|
||||
public IkeyBackupCreationAndroidViewModel() {
|
||||
public AndroidIkeyBackupCreationViewModel() {
|
||||
MercuryImApplication.getApplication().getAppComponent().inject(this);
|
||||
}
|
||||
|
||||
|
@ -43,8 +47,8 @@ public class IkeyBackupCreationAndroidViewModel extends ViewModel implements Mer
|
|||
getCommonViewModel().setAccountId(accountId);
|
||||
|
||||
Observable<Optional<OpenPgpSecretKeyBackupPassphrase>> passphraseObservable =
|
||||
//getCommonViewModel().getPassphrase()
|
||||
Observable.just(new Optional<>(new OpenPgpSecretKeyBackupPassphrase("71ZA-Y416-UA7A-7NCE-3SNM-88EF")));
|
||||
getCommonViewModel().getPassphrase();
|
||||
//Observable.just(new Optional<>(passphraseGenerator.generateBackupPassphrase()));
|
||||
|
||||
addDisposable(passphraseObservable
|
||||
.subscribeOn(schedulers.getIoScheduler())
|
|
@ -1,4 +1,4 @@
|
|||
package org.mercury_im.messenger.android.ui.ikey;
|
||||
package org.mercury_im.messenger.android.crypto.ikey;
|
||||
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
|
@ -23,7 +23,7 @@ import butterknife.ButterKnife;
|
|||
|
||||
public class IkeyBackupCreationFragment extends Fragment {
|
||||
|
||||
private IkeyBackupCreationAndroidViewModel viewModel;
|
||||
private AndroidIkeyBackupCreationViewModel viewModel;
|
||||
|
||||
@BindView(R.id.backup_code)
|
||||
TextView backupCode;
|
||||
|
@ -52,7 +52,7 @@ public class IkeyBackupCreationFragment extends Fragment {
|
|||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
viewModel = new ViewModelProvider(this).get(IkeyBackupCreationAndroidViewModel.class);
|
||||
viewModel = new ViewModelProvider(this).get(AndroidIkeyBackupCreationViewModel.class);
|
||||
viewModel.initialize(accountId);
|
||||
|
||||
viewModel.getPassphrase().observe(getViewLifecycleOwner(), passphrase -> backupCode.setText(passphrase));
|
|
@ -1,4 +1,4 @@
|
|||
package org.mercury_im.messenger.android.ui.ikey;
|
||||
package org.mercury_im.messenger.android.crypto.ikey;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
|
@ -11,6 +11,6 @@ public class IkeyBackupRestoreActivity extends AppCompatActivity {
|
|||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_ikey_backup_restore);
|
||||
setContentView(R.layout.fragment_ikey_backup_restore);
|
||||
}
|
||||
}
|
|
@ -4,8 +4,12 @@ import org.mercury_im.messenger.android.MercuryImApplication;
|
|||
import org.mercury_im.messenger.android.di.module.AndroidDatabaseModule;
|
||||
import org.mercury_im.messenger.android.di.module.AndroidSchedulersModule;
|
||||
import org.mercury_im.messenger.android.ui.account.detail.AndroidAccountDetailsViewModel;
|
||||
import org.mercury_im.messenger.android.ui.account.login.AddAccountActivity;
|
||||
import org.mercury_im.messenger.android.ui.account.login.EnterAccountDetailsFragment;
|
||||
import org.mercury_im.messenger.android.ui.account.login.IkeySetupViewModel;
|
||||
import org.mercury_im.messenger.android.ui.contacts.AndroidContactListViewModel;
|
||||
import org.mercury_im.messenger.android.ui.ikey.IkeyBackupCreationAndroidViewModel;
|
||||
import org.mercury_im.messenger.android.crypto.ikey.AndroidIkeyBackupCreationViewModel;
|
||||
import org.mercury_im.messenger.core.di.module.IkeyModule;
|
||||
import org.mercury_im.messenger.core.di.module.OpenPgpModule;
|
||||
import org.mercury_im.messenger.core.di.module.RxMercuryMessageStoreFactoryModule;
|
||||
import org.mercury_im.messenger.core.di.module.RxMercuryRosterStoreFactoryModule;
|
||||
|
@ -50,6 +54,7 @@ import dagger.Component;
|
|||
XmppTcpConnectionFactoryModule.class,
|
||||
RxMercuryMessageStoreFactoryModule.class,
|
||||
OpenPgpModule.class,
|
||||
IkeyModule.class,
|
||||
RxMercuryRosterStoreFactoryModule.class,
|
||||
StanzaIdSourceFactoryModule.class
|
||||
})
|
||||
|
@ -70,7 +75,7 @@ public interface AppComponent {
|
|||
|
||||
void inject(ContactDetailActivity contactDetailActivity);
|
||||
|
||||
|
||||
void inject(EnterAccountDetailsFragment enterAccountDetailsFragment);
|
||||
|
||||
// ViewModels
|
||||
|
||||
|
@ -94,10 +99,13 @@ public interface AppComponent {
|
|||
|
||||
void inject(AndroidAccountDetailsViewModel accountDetailsViewModel);
|
||||
|
||||
void inject(IkeyBackupCreationAndroidViewModel ikeyBackupCreationAndroidViewModel);
|
||||
void inject(AndroidIkeyBackupCreationViewModel androidIkeyBackupCreationViewModel);
|
||||
|
||||
void inject(IkeySetupViewModel ikeySetupViewModel);
|
||||
// void inject(AndroidOxSecretKeyBackupRestoreViewModel androidOxSecretKeyBackupRestoreViewModel);
|
||||
|
||||
|
||||
// Common VMs
|
||||
// Common VMs
|
||||
void inject(LoginViewModel loginViewModel);
|
||||
|
||||
void inject(AccountListViewModel accountsViewModel);
|
||||
|
@ -108,4 +116,5 @@ public interface AppComponent {
|
|||
void inject(MercuryForegroundService service);
|
||||
|
||||
void inject(MercuryEntityCapsStore store);
|
||||
|
||||
}
|
||||
|
|
|
@ -11,11 +11,10 @@ import android.view.View;
|
|||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
@ -24,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.ui.ikey.IkeyBackupCreationFragment;
|
||||
import org.mercury_im.messenger.android.crypto.ikey.IkeyBackupCreationFragment;
|
||||
import org.mercury_im.messenger.android.ui.openpgp.ToggleableFingerprintsAdapter;
|
||||
import org.mercury_im.messenger.android.ui.openpgp.OpenPgpV4FingerprintFormatter;
|
||||
import org.mercury_im.messenger.core.util.Optional;
|
||||
|
@ -46,6 +45,9 @@ public class AccountDetailsFragment extends Fragment {
|
|||
@BindView(R.id.jid)
|
||||
TextView jid;
|
||||
|
||||
@BindView(R.id.btn_backup)
|
||||
Button localKeyCreateBackupButton;
|
||||
|
||||
@BindView(R.id.btn_share)
|
||||
Button localFingerprintShareButton;
|
||||
|
||||
|
@ -154,6 +156,15 @@ public class AccountDetailsFragment extends Fragment {
|
|||
getParentFragmentManager().beginTransaction()
|
||||
.replace(R.id.fragment, IkeyBackupCreationFragment.newInstance(accountId)).commit();
|
||||
});
|
||||
|
||||
localKeyCreateBackupButton.setOnClickListener(v -> {
|
||||
Toast.makeText(getContext(), "Not yet implemented.", Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
|
||||
viewModel.isAccountAuthenticated().observe(this, authenticated -> {
|
||||
ikeyCreateBackupButton.setEnabled(authenticated);
|
||||
localKeyCreateBackupButton.setEnabled(authenticated);
|
||||
});
|
||||
}
|
||||
|
||||
private void startShareFingerprintIntent(OpenPgpV4Fingerprint fingerprint) {
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.mercury_im.messenger.core.util.DefaultUtil;
|
|||
import org.mercury_im.messenger.core.util.Optional;
|
||||
import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel;
|
||||
import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
|
||||
import org.mercury_im.messenger.entity.Account;
|
||||
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
@ -46,6 +47,8 @@ public class AndroidAccountDetailsViewModel extends AndroidViewModel implements
|
|||
private MutableLiveData<OpenPgpV4Fingerprint> localFingerprint = new MutableLiveData<>();
|
||||
private MutableLiveData<List<FingerprintViewItem>> remoteFingerprints = new MutableLiveData<>(new ArrayList<>());
|
||||
private MutableLiveData<EntityBareJid> jid = new MutableLiveData<>(DefaultUtil.defaultJid());
|
||||
private MutableLiveData<Boolean> accountEnabled = new MutableLiveData<>(false);
|
||||
private MutableLiveData<Boolean> accountAuthenticated = new MutableLiveData<>(false);
|
||||
|
||||
public AndroidAccountDetailsViewModel(@NonNull Application application, UUID accountId) {
|
||||
super(application);
|
||||
|
@ -75,6 +78,18 @@ public class AndroidAccountDetailsViewModel extends AndroidViewModel implements
|
|||
() -> LOGGER.log(Level.INFO, "observing remote fingerprint onComplete.")));
|
||||
|
||||
addDisposable(getCommonViewModel().getJid(accountId).subscribe(jid::postValue));
|
||||
|
||||
addDisposable(getCommonViewModel().isAccountEnabled(accountId)
|
||||
.compose(schedulers.executeUiSafeObservable())
|
||||
.subscribe(bool -> accountEnabled.postValue(bool),
|
||||
e -> LOGGER.log(Level.SEVERE, "Error subscribing to account enabled state", e),
|
||||
() -> LOGGER.log(Level.INFO, "observing account enabled state onComplete.")));
|
||||
|
||||
addDisposable(getCommonViewModel().isAccountAuthenticated(accountId)
|
||||
.compose(schedulers.executeUiSafeObservable())
|
||||
.subscribe(bool -> accountAuthenticated.postValue(bool),
|
||||
e -> LOGGER.log(Level.SEVERE, "Error subscribing to account authenticated state", e),
|
||||
() -> LOGGER.log(Level.INFO, "observing account authenticated state onComplete.")));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -112,10 +127,10 @@ public class AndroidAccountDetailsViewModel extends AndroidViewModel implements
|
|||
|
||||
public void onGenerateIkey() {
|
||||
addDisposable(getCommonViewModel().generateIkey(accountId)
|
||||
.subscribeOn(schedulers.getNewThread())
|
||||
.observeOn(schedulers.getUiScheduler())
|
||||
.subscribe(() -> LOGGER.log(Level.INFO, "IKey generated for account " + accountId),
|
||||
e -> LOGGER.log(Level.SEVERE, "Could not generate Ikey", e)));
|
||||
.subscribeOn(schedulers.getNewThread())
|
||||
.observeOn(schedulers.getUiScheduler())
|
||||
.subscribe(() -> LOGGER.log(Level.INFO, "IKey generated for account " + accountId),
|
||||
e -> LOGGER.log(Level.SEVERE, "Could not generate Ikey", e)));
|
||||
}
|
||||
|
||||
public void onDeleteIkey() {
|
||||
|
@ -134,6 +149,14 @@ public class AndroidAccountDetailsViewModel extends AndroidViewModel implements
|
|||
e -> LOGGER.log(Level.SEVERE, "Could not restore Ikey backup", e)));
|
||||
}
|
||||
|
||||
public LiveData<Boolean> isAccountEnabled() {
|
||||
return accountEnabled;
|
||||
}
|
||||
|
||||
public LiveData<Boolean> isAccountAuthenticated() {
|
||||
return accountAuthenticated;
|
||||
}
|
||||
|
||||
public static class AndroidAccountDetailsViewModelFactory implements ViewModelProvider.Factory {
|
||||
|
||||
private final Application application;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package org.mercury_im.messenger.android.ui.account.list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
@ -16,6 +17,7 @@ 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;
|
||||
|
@ -58,7 +60,10 @@ public class AccountListFragment extends Fragment implements SearchView.OnQueryT
|
|||
public void onResume() {
|
||||
super.onResume();
|
||||
observeViewModel();
|
||||
fab.setOnClickListener(v -> displayAddAccountDialog());
|
||||
//fab.setOnClickListener(v -> displayAddAccountDialog());
|
||||
fab.setOnClickListener(v -> {
|
||||
startActivity(new Intent(getContext(), AddAccountActivity.class));
|
||||
});
|
||||
}
|
||||
|
||||
private void observeViewModel() {
|
||||
|
|
|
@ -13,6 +13,7 @@ import androidx.recyclerview.widget.RecyclerView;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
import org.mercury_im.messenger.R;
|
||||
import org.mercury_im.messenger.android.ui.account.OnAccountListItemClickListener;
|
||||
import org.mercury_im.messenger.core.connection.state.ConnectivityState;
|
||||
import org.mercury_im.messenger.core.viewmodel.account.list.AccountViewItem;
|
||||
import org.mercury_im.messenger.entity.Account;
|
||||
import org.mercury_im.messenger.android.ui.avatar.AvatarDrawable;
|
||||
|
@ -62,8 +63,9 @@ public class AccountListRecyclerViewAdapter extends RecyclerView.Adapter<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) -> {
|
||||
if (!compoundButton.isPressed()) {
|
||||
holder.enabled.setEnabled(shouldSwitchBeEnabled(viewItem.getConnectivityState()));
|
||||
holder.enabled.setOnCheckedChangeListener((switch_, checked) -> {
|
||||
if (!switch_.isPressed()) {
|
||||
return;
|
||||
}
|
||||
viewModel.setAccountEnabled(account, checked);
|
||||
|
@ -78,6 +80,12 @@ public class AccountListRecyclerViewAdapter extends RecyclerView.Adapter<Account
|
|||
holder.mView.setOnClickListener(v -> onAccountClickListener.onAccountListItemClick(account));
|
||||
}
|
||||
|
||||
private static boolean shouldSwitchBeEnabled(ConnectivityState connectivity) {
|
||||
return connectivity == ConnectivityState.authenticated ||
|
||||
connectivity == ConnectivityState.disconnected ||
|
||||
connectivity == ConnectivityState.disconnectedOnError;
|
||||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
final View mView;
|
||||
final ImageView avatar;
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
package org.mercury_im.messenger.android.ui.account.login;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter;
|
||||
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;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import lombok.Getter;
|
||||
|
||||
public class AddAccountActivity extends AppCompatActivity {
|
||||
|
||||
@BindView(R.id.viewpager)
|
||||
ViewPager2 viewPager;
|
||||
|
||||
private SetupPagerAdapter pagerAdapter;
|
||||
|
||||
private AppComponent appComponent;
|
||||
private IkeySetupViewModel ikeyViewModel;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.layout_viewpager2);
|
||||
ButterKnife.bind(this);
|
||||
appComponent = MercuryImApplication.getApplication().getAppComponent();
|
||||
|
||||
pagerAdapter = new SetupPagerAdapter(this);
|
||||
viewPager.setAdapter(pagerAdapter);
|
||||
viewPager.setUserInputEnabled(false); // disable swiping
|
||||
|
||||
ikeyViewModel = new ViewModelProvider(this).get(IkeySetupViewModel.class); // shared between fragments
|
||||
}
|
||||
|
||||
public void loginFinished(Optional<Account> optionalAccount) {
|
||||
if (optionalAccount.isPresent()) {
|
||||
pagerAdapter.getFragments().put(1, IkeySetupFragment.newInstance(optionalAccount.getItem().getId()));
|
||||
pagerAdapter.notifyDataSetChanged();
|
||||
viewPager.setCurrentItem(1);
|
||||
}
|
||||
}
|
||||
|
||||
public void skipIkeySetup() {
|
||||
finish();
|
||||
}
|
||||
|
||||
public void setupIkey(UUID accountId) {
|
||||
int pos = pagerAdapter.getItemCount();
|
||||
pagerAdapter.getFragments().put(pos, IkeyBackupRestoreOrSkipFragment.newInstance(accountId));
|
||||
pagerAdapter.notifyDataSetChanged();
|
||||
viewPager.setCurrentItem(pos);
|
||||
}
|
||||
|
||||
public void restoreIkeyBackup(UUID accountId) {
|
||||
int pos = pagerAdapter.getItemCount();
|
||||
pagerAdapter.getFragments().put(pos, IkeyBackupRestoreSuccessfulFragment.newInstance(accountId));
|
||||
pagerAdapter.notifyDataSetChanged();
|
||||
viewPager.setCurrentItem(pos);
|
||||
}
|
||||
|
||||
public void generateIkeyBackup(UUID accountId) {
|
||||
int pos = pagerAdapter.getItemCount();
|
||||
pagerAdapter.getFragments().put(pos, IkeyBackupCreationFragment.newInstance(accountId));
|
||||
pagerAdapter.notifyDataSetChanged();
|
||||
viewPager.setCurrentItem(pos);
|
||||
}
|
||||
|
||||
private class SetupPagerAdapter extends FragmentStateAdapter {
|
||||
|
||||
@Getter
|
||||
private final Map<Integer, Fragment> fragments = new LinkedHashMap<>();
|
||||
|
||||
SetupPagerAdapter(@NonNull FragmentActivity fragmentActivity) {
|
||||
super(fragmentActivity);
|
||||
|
||||
fragments.put(0, EnterAccountDetailsFragment.newInstance(appComponent));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Fragment createFragment(int position) {
|
||||
return fragments.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return fragments.size();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -44,7 +44,7 @@ public class AddAccountDialogFragment extends AppCompatDialogFragment {
|
|||
@Override
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
LayoutInflater inflater = requireActivity().getLayoutInflater();
|
||||
View dialogView = inflater.inflate(R.layout.dialog_login, null);
|
||||
View dialogView = inflater.inflate(R.layout.view_account_credentials, null);
|
||||
ButterKnife.bind(this, dialogView);
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
|
@ -83,8 +83,8 @@ public class AddAccountDialogFragment extends AppCompatDialogFragment {
|
|||
viewModel.getLoginPasswordError().observe(this, error -> passwordLayout.setError(error));
|
||||
viewModel.isLoginButtonEnabled().observe(this, positiveButton::setEnabled);
|
||||
|
||||
viewModel.isLoginFinished().observe(this, finished -> {
|
||||
if (finished) {
|
||||
viewModel.isLoginFinished().observe(this, optAccount -> {
|
||||
if (optAccount.isPresent()) {
|
||||
dismiss();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.mercury_im.messenger.core.account.error.PasswordError;
|
|||
import org.mercury_im.messenger.core.account.error.UsernameError;
|
||||
import org.mercury_im.messenger.core.util.Optional;
|
||||
import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
|
||||
import org.mercury_im.messenger.entity.Account;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
@ -24,7 +25,7 @@ public class AndroidLoginViewModel extends AndroidViewModel implements MercuryAn
|
|||
private final MutableLiveData<String> loginUsernameError = new MutableLiveData<>();
|
||||
private final MutableLiveData<String> loginPasswordError = new MutableLiveData<>();
|
||||
private final MutableLiveData<Boolean> loginButtonEnabled = new MutableLiveData<>(true);
|
||||
private final MutableLiveData<Boolean> loginFinished = new MutableLiveData<>(false);
|
||||
private final MutableLiveData<Optional<Account>> loginFinished = new MutableLiveData<>(new Optional<>());
|
||||
|
||||
@Inject
|
||||
LoginViewModel commonViewModel;
|
||||
|
@ -99,8 +100,8 @@ public class AndroidLoginViewModel extends AndroidViewModel implements MercuryAn
|
|||
getCommonViewModel().dispose();
|
||||
}
|
||||
|
||||
public void onLoginButtonClicked() {
|
||||
getCommonViewModel().login();
|
||||
public Account onLoginButtonClicked() {
|
||||
return getCommonViewModel().login();
|
||||
}
|
||||
|
||||
public LiveData<String> getLoginUsernameError() {
|
||||
|
@ -115,7 +116,7 @@ public class AndroidLoginViewModel extends AndroidViewModel implements MercuryAn
|
|||
return loginButtonEnabled;
|
||||
}
|
||||
|
||||
public LiveData<Boolean> isLoginFinished() {
|
||||
public LiveData<Optional<Account>> isLoginFinished() {
|
||||
return loginFinished;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
package org.mercury_im.messenger.android.ui.account.login;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
import com.google.android.material.textfield.TextInputEditText;
|
||||
import com.google.android.material.textfield.TextInputLayout;
|
||||
|
||||
import org.mercury_im.messenger.R;
|
||||
import org.mercury_im.messenger.android.MercuryImApplication;
|
||||
import org.mercury_im.messenger.android.di.component.AppComponent;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class EnterAccountDetailsFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.username_layout)
|
||||
TextInputLayout usernameLayout;
|
||||
|
||||
@BindView(R.id.username)
|
||||
TextInputEditText username;
|
||||
|
||||
@BindView(R.id.password_layout)
|
||||
TextInputLayout passwordLayout;
|
||||
|
||||
@BindView(R.id.password)
|
||||
TextInputEditText password;
|
||||
|
||||
@BindView(R.id.btn_login)
|
||||
Button loginButton;
|
||||
|
||||
@BindView(R.id.btn_cancel)
|
||||
Button cancelButton;
|
||||
|
||||
@BindView(R.id.progress)
|
||||
ProgressBar progressBar;
|
||||
|
||||
@Inject
|
||||
AndroidLoginViewModel viewModel;
|
||||
|
||||
public EnterAccountDetailsFragment(AppComponent appComponent) {
|
||||
appComponent.inject(this);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_enter_account_credentials, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
viewModel = new AndroidLoginViewModel(MercuryImApplication.getApplication());
|
||||
|
||||
loginButton.setOnClickListener(v -> viewModel.onLoginButtonClicked());
|
||||
|
||||
cancelButton.setOnClickListener(v -> getActivity().finish());
|
||||
|
||||
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.isLoginFinished().observe(this, optAccount ->
|
||||
((AddAccountActivity) getActivity()).loginFinished(optAccount));
|
||||
|
||||
username.addTextChangedListener(viewModel.getUsernameTextChangedListener());
|
||||
password.addTextChangedListener(viewModel.getPasswordTextChangedListener());
|
||||
|
||||
username.setOnEditorActionListener(focusPasswordFieldOnEnterPressed);
|
||||
password.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) {
|
||||
password.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.onLoginButtonClicked();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
public static EnterAccountDetailsFragment newInstance(AppComponent appComponent) {
|
||||
return new EnterAccountDetailsFragment(appComponent);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package org.mercury_im.messenger.android.ui.account.login;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import org.mercury_im.messenger.R;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class IkeyBackupRestoreOrSkipFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.btn_restore)
|
||||
Button restoreButton;
|
||||
|
||||
@BindView(R.id.btn_new_key)
|
||||
Button regenerateButton;
|
||||
|
||||
@BindView(R.id.edit_backup_code)
|
||||
EditText backupCodeEditText;
|
||||
|
||||
@BindView(R.id.btn_scan)
|
||||
ImageButton scanButton;
|
||||
|
||||
private final UUID accountId;
|
||||
|
||||
private IkeySetupViewModel viewModel;
|
||||
|
||||
IkeyBackupRestoreOrSkipFragment(UUID accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public static IkeyBackupRestoreOrSkipFragment newInstance(UUID accountId) {
|
||||
return new IkeyBackupRestoreOrSkipFragment(accountId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_ikey_backup_restore, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
viewModel = new ViewModelProvider(requireActivity()).get(IkeySetupViewModel.class);
|
||||
|
||||
restoreButton.setOnClickListener(v ->
|
||||
((AddAccountActivity) getActivity()).restoreIkeyBackup(accountId));
|
||||
regenerateButton.setOnClickListener(v ->
|
||||
((AddAccountActivity) getActivity()).generateIkeyBackup(accountId));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.mercury_im.messenger.android.ui.account.login;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import org.mercury_im.messenger.R;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
|
||||
public class IkeyBackupRestoreSuccessfulFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.btn_done)
|
||||
Button doneButton;
|
||||
|
||||
@BindView(R.id.text)
|
||||
TextView fingerprint;
|
||||
|
||||
private final UUID accountId;
|
||||
private IkeySetupViewModel viewModel;
|
||||
|
||||
IkeyBackupRestoreSuccessfulFragment(UUID accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public static IkeyBackupRestoreSuccessfulFragment newInstance(UUID accountId) {
|
||||
return new IkeyBackupRestoreSuccessfulFragment(accountId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_ikey_backup_restore_success, container);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
viewModel = new ViewModelProvider(requireActivity()).get(IkeySetupViewModel.class);
|
||||
|
||||
doneButton.setOnClickListener(v -> getActivity().finish());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package org.mercury_im.messenger.android.ui.account.login;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.ViewModelProvider;
|
||||
|
||||
import org.mercury_im.messenger.R;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class IkeySetupFragment extends Fragment {
|
||||
|
||||
@BindView(R.id.btn_skip)
|
||||
Button skipButton;
|
||||
|
||||
@BindView(R.id.btn_continue)
|
||||
Button continueButton;
|
||||
|
||||
private final UUID accountId;
|
||||
private IkeySetupViewModel viewModel;
|
||||
|
||||
public IkeySetupFragment(UUID accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.fragment_ikey_setup, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
public static IkeySetupFragment newInstance(UUID accountId) {
|
||||
return new IkeySetupFragment(accountId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
viewModel = new ViewModelProvider(requireActivity()).get(IkeySetupViewModel.class);
|
||||
viewModel.init(accountId);
|
||||
|
||||
skipButton.setOnClickListener(v ->
|
||||
getActivity().finish());
|
||||
|
||||
continueButton.setOnClickListener(v -> {
|
||||
viewModel.fetchBackupElement()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnSuccess(opt -> {
|
||||
if (opt.isPresent()) {
|
||||
((AddAccountActivity) getActivity()).setupIkey(accountId);
|
||||
} else {
|
||||
((AddAccountActivity) getActivity()).generateIkeyBackup(accountId);
|
||||
}
|
||||
})
|
||||
.subscribe();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package org.mercury_im.messenger.android.ui.account.login;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smackx.ikey.IkeyManager;
|
||||
import org.jivesoftware.smackx.ox.element.SecretkeyElement;
|
||||
import org.jivesoftware.smackx.pubsub.PubSubException;
|
||||
import org.mercury_im.messenger.android.MercuryImApplication;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnection;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
|
||||
import org.mercury_im.messenger.core.crypto.ikey.IkeyInitializer;
|
||||
import org.mercury_im.messenger.core.util.Optional;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.MaybeObserver;
|
||||
import io.reactivex.Single;
|
||||
|
||||
public class IkeySetupViewModel extends AndroidViewModel {
|
||||
|
||||
@Inject
|
||||
MercuryConnectionManager connectionManager;
|
||||
|
||||
@Inject
|
||||
IkeyInitializer ikeyInitializer;
|
||||
|
||||
IkeyManager ikeyManager;
|
||||
private SecretkeyElement secretkeyElement;
|
||||
|
||||
public IkeySetupViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
MercuryImApplication.getApplication().getAppComponent().inject(this);
|
||||
}
|
||||
|
||||
public void init(UUID accountId) {
|
||||
MercuryConnection connection = connectionManager.getConnection(accountId);
|
||||
ikeyManager = ikeyInitializer.initFor(connection);
|
||||
}
|
||||
|
||||
public Single<Optional<SecretkeyElement>> fetchBackupElement() {
|
||||
return fetchMaybeBackupElement()
|
||||
.map(Optional::new)
|
||||
.toSingle(new Optional<>());
|
||||
}
|
||||
|
||||
private Maybe<SecretkeyElement> fetchMaybeBackupElement() {
|
||||
return new Maybe<SecretkeyElement>() {
|
||||
@Override
|
||||
protected void subscribeActual(MaybeObserver<? super SecretkeyElement> observer) {
|
||||
try {
|
||||
secretkeyElement = ikeyManager.fetchSecretIdentityKey();
|
||||
if (secretkeyElement != null) {
|
||||
observer.onSuccess(secretkeyElement);
|
||||
} else {
|
||||
observer.onComplete();
|
||||
}
|
||||
} catch (PubSubException.NotALeafNodeException e) {
|
||||
observer.onComplete();
|
||||
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
|
||||
observer.onError(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -6,6 +6,7 @@ import androidx.annotation.NonNull;
|
|||
import androidx.lifecycle.AndroidViewModel;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
import org.mercury_im.messenger.android.MercuryImApplication;
|
||||
import org.mercury_im.messenger.android.ui.MercuryAndroidViewModel;
|
||||
import org.mercury_im.messenger.core.util.Optional;
|
||||
import org.mercury_im.messenger.core.viewmodel.openpgp.OxBackupRestoreError;
|
||||
|
@ -14,12 +15,14 @@ import org.mercury_im.messenger.core.viewmodel.openpgp.OxSecretKeyBackupRestoreV
|
|||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class AndroidOxSecretKeyBackupRestoreViewModel extends AndroidViewModel
|
||||
implements MercuryAndroidViewModel<OxSecretKeyBackupRestoreViewModel> {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(AndroidOxSecretKeyBackupRestoreViewModel.class.getName());
|
||||
|
||||
//@Inject
|
||||
// @Inject
|
||||
OxSecretKeyBackupRestoreViewModel commonViewModel;
|
||||
|
||||
private MutableLiveData<Optional<OxBackupRestoreError>> restoreError =
|
||||
|
@ -27,7 +30,7 @@ public class AndroidOxSecretKeyBackupRestoreViewModel extends AndroidViewModel
|
|||
|
||||
public AndroidOxSecretKeyBackupRestoreViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
//MercuryImApplication.getApplication().getAppComponent().inject(this);
|
||||
// MercuryImApplication.getApplication().getAppComponent().inject(this);
|
||||
|
||||
addDisposable(getCommonViewModel().observeBackupRestoreError()
|
||||
.subscribe(opt -> restoreError.postValue(opt),
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<include layout="@layout/view_account_credentials">
|
||||
</include>
|
||||
|
||||
<ProgressBar android:id="@+id/progress"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_centerInParent="true"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Cancel" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_login"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Login" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -4,7 +4,7 @@
|
|||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".android.ui.ikey.IkeyBackupCreationFragment">
|
||||
tools:context=".android.crypto.ikey.IkeyBackupCreationFragment">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notice"
|
||||
|
@ -17,12 +17,14 @@
|
|||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="You should now write down the code below and store it somewhere safe.\nAlternatively you can scan the code below with another device to copy the identity key over."
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/notice" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/notice"
|
||||
android:gravity="center"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/qr_code"
|
||||
|
@ -32,7 +34,7 @@
|
|||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.497"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/notice"
|
||||
app:layout_constraintTop_toBottomOf="@+id/description"
|
||||
app:srcCompat="@drawable/ic_qr_code_scanner_black_24dp" />
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".android.ui.ikey.IkeyBackupRestoreActivity">
|
||||
android:orientation="vertical"
|
||||
tools:context=".android.crypto.ikey.IkeyBackupRestoreActivity">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/notice"
|
||||
|
@ -16,22 +17,6 @@
|
|||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linearLayout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/notice">
|
||||
|
||||
<include
|
||||
layout="@layout/view_openpgp_4_fingerprint"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:layout_editor_absoluteY="19dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView"
|
||||
|
@ -40,8 +25,7 @@
|
|||
android:text="In order to restore the backup, please enter the backup code below."
|
||||
android:gravity="center"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/linearLayout" />
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
|
@ -54,17 +38,18 @@
|
|||
app:layout_constraintTop_toBottomOf="@+id/textView" >
|
||||
|
||||
<EditText
|
||||
android:id="@+id/edit_backup_code"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="Backup Code"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/imageButton"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btn_scan"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_marginEnd="8dp"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/imageButton"
|
||||
android:id="@+id/btn_scan"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="@android:color/transparent"
|
||||
|
@ -77,4 +62,24 @@
|
|||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_restore"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Restore"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_new_key"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Generate new key"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,33 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Backup restored successfully!\nThis is your Identity Key Fingerprint:"
|
||||
android:gravity="center"
|
||||
/>
|
||||
|
||||
<include layout="@layout/view_openpgp_4_fingerprint" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="This key will help your contacts to decide which keys really belong to you."
|
||||
android:gravity="center"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end">
|
||||
<Button
|
||||
android:id="@+id/btn_done"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Done" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Setup Simplified Encryption Key Management?"
|
||||
android:gravity="center"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Ikey simplifies management of encryption keys when multiple devices are in use."
|
||||
android:gravity="center"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="end">
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_skip"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Skip" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_continue"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Yes, please" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -0,0 +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"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/viewpager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
</LinearLayout>
|
|
@ -5,7 +5,7 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/login_form"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
|
@ -3,7 +3,7 @@
|
|||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/toggle_account_enabled"
|
||||
android:id="@+id/switch_account_enabled"
|
||||
android:title="Enable Account"
|
||||
app:actionLayout="@layout/switch_item"
|
||||
app:showAsAction="always" />
|
||||
|
|
|
@ -99,6 +99,15 @@ public class MercuryConnectionManager {
|
|||
return connectionsMap.get(id);
|
||||
}
|
||||
|
||||
public MercuryConnection createConnection(UUID accountId) {
|
||||
Account account = accountRepository.getAccount(accountId)
|
||||
.blockingGet();
|
||||
if (account == null) {
|
||||
throw new IllegalArgumentException("No account associated with this accountID: " + accountId);
|
||||
}
|
||||
return createConnection(account);
|
||||
}
|
||||
|
||||
public MercuryConnection createConnection(Account account) {
|
||||
return new MercuryConnection(connectionFactory.createConnection(account), account);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package org.mercury_im.messenger.core.crypto;
|
||||
|
||||
public interface LocalOxKeyGenerationStrategy {
|
||||
|
||||
boolean promptForBackupRestoreIfNoLocalKeyPresent();
|
||||
}
|
|
@ -4,6 +4,7 @@ import org.jivesoftware.smack.AbstractConnectionListener;
|
|||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smackx.ox.OpenPgpManager;
|
||||
import org.jivesoftware.smackx.ox.OpenPgpSecretKeyBackupPassphrase;
|
||||
import org.jivesoftware.smackx.ox.callback.SecretKeyPassphraseCallback;
|
||||
import org.jivesoftware.smackx.ox.crypto.OpenPgpProvider;
|
||||
import org.jivesoftware.smackx.ox.crypto.PainlessOpenPgpProvider;
|
||||
import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException;
|
||||
|
@ -35,6 +36,7 @@ public class MercuryOpenPgpManager {
|
|||
private final OpenPgpRepository openPgpRepository;
|
||||
private final SchedulersFacade schedulers;
|
||||
private final OpenPgpSecretKeyBackupPassphraseGenerator passphraseGenerator;
|
||||
private final LocalOxKeyGenerationStrategy keyGenerationStrategy;
|
||||
|
||||
@Inject
|
||||
public MercuryOpenPgpManager(PeerRepository peerRepository,
|
||||
|
@ -42,12 +44,14 @@ public class MercuryOpenPgpManager {
|
|||
MessageRepository messageRepository,
|
||||
OpenPgpRepository openPgpRepository,
|
||||
OpenPgpSecretKeyBackupPassphraseGenerator passphraseGenerator,
|
||||
LocalOxKeyGenerationStrategy keyGenerationStrategy,
|
||||
SchedulersFacade schedulers) {
|
||||
this.peerRepository = peerRepository;
|
||||
this.directChatRepository = directChatRepository;
|
||||
this.messageRepository = messageRepository;
|
||||
this.openPgpRepository = openPgpRepository;
|
||||
this.schedulers = schedulers;
|
||||
this.keyGenerationStrategy = keyGenerationStrategy;
|
||||
this.passphraseGenerator = passphraseGenerator;
|
||||
}
|
||||
|
||||
|
@ -72,8 +76,8 @@ public class MercuryOpenPgpManager {
|
|||
OpenPgpManager oxManager = OpenPgpManager.getInstanceFor(connection.getConnection());
|
||||
oxManager.setOpenPgpProvider(provider);
|
||||
OpenPgpSecretKeyBackupPassphrase passphrase = passphraseGenerator.generateBackupPassphrase();
|
||||
boolean mustGenerate = false;
|
||||
try {
|
||||
boolean mustGenerate = false;
|
||||
if (!oxManager.hasSecretKeysAvailable()) {
|
||||
mustGenerate = true;
|
||||
if (OpenPgpManager.serverSupportsSecretKeyBackups(connection.getConnection())) {
|
||||
|
@ -105,4 +109,8 @@ public class MercuryOpenPgpManager {
|
|||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean mustPromptForRestore() {
|
||||
return keyGenerationStrategy.promptForBackupRestoreIfNoLocalKeyPresent();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package org.mercury_im.messenger.core.crypto;
|
||||
|
||||
public class OxPlusIkeyKeyGenerationStrategy implements LocalOxKeyGenerationStrategy {
|
||||
|
||||
@Override
|
||||
public boolean promptForBackupRestoreIfNoLocalKeyPresent() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package org.mercury_im.messenger.core.di.component;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||
|
||||
@java.lang.annotation.Documented
|
||||
@java.lang.annotation.Retention(RUNTIME)
|
||||
@javax.inject.Qualifier
|
||||
public @interface Account {
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.mercury_im.messenger.core.di.component;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import dagger.BindsInstance;
|
||||
import dagger.Component;
|
||||
|
||||
@Component
|
||||
public interface ConnectionComponent {
|
||||
|
||||
ConnectionComponent getComponent();
|
||||
|
||||
@Component.Builder
|
||||
interface Builder {
|
||||
|
||||
@BindsInstance Builder forAccount(@Account UUID accountId);
|
||||
|
||||
ConnectionComponent build();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package org.mercury_im.messenger.core.di.module;
|
||||
|
||||
import org.mercury_im.messenger.core.crypto.LocalOxKeyGenerationStrategy;
|
||||
import org.mercury_im.messenger.core.crypto.OxPlusIkeyKeyGenerationStrategy;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class IkeyModule {
|
||||
|
||||
@Singleton
|
||||
@Provides
|
||||
static LocalOxKeyGenerationStrategy provideLocalOxKeyGenerationStrategy() {
|
||||
return new OxPlusIkeyKeyGenerationStrategy();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package org.mercury_im.messenger.core.di.module;
|
||||
|
||||
import org.jivesoftware.smackx.ikey.IkeyManager;
|
||||
import org.jivesoftware.smackx.ox.OpenPgpManager;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnection;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
|
||||
import org.mercury_im.messenger.core.di.component.Account;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class MercuryConnectionModule {
|
||||
|
||||
@Provides
|
||||
@Account
|
||||
MercuryConnection provideConnection(MercuryConnectionManager connectionManager, @Account UUID accountId) {
|
||||
MercuryConnection connection = connectionManager.getConnection(accountId);
|
||||
if (connection == null) {
|
||||
connection = connectionManager.createConnection(accountId);
|
||||
connectionManager.doRegisterConnection(connection);
|
||||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Account
|
||||
OpenPgpManager provideOpenPgpManager(MercuryConnection connection) {
|
||||
return OpenPgpManager.getInstanceFor(connection.getConnection());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Account
|
||||
IkeyManager provideIkeyManager(MercuryConnection connection) {
|
||||
return IkeyManager.getInstanceFor(connection.getConnection());
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
package org.mercury_im.messenger.core.di.module;
|
||||
|
||||
import org.mercury_im.messenger.core.crypto.InsecureStaticSecretKeyBackupPassphraseGenerator;
|
||||
import org.mercury_im.messenger.core.crypto.LocalOxKeyGenerationStrategy;
|
||||
import org.mercury_im.messenger.core.crypto.OpenPgpSecretKeyBackupPassphraseGenerator;
|
||||
import org.mercury_im.messenger.core.crypto.OxPlusIkeyKeyGenerationStrategy;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
|
@ -17,5 +19,4 @@ public class OpenPgpModule {
|
|||
// TODO: THIS MUST NEVER MAKE IT TO PRODUCTION!!!
|
||||
return new InsecureStaticSecretKeyBackupPassphraseGenerator();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,15 +7,17 @@ import org.jxmpp.stringprep.XmppStringprepException;
|
|||
import org.mercury_im.messenger.core.SchedulersFacade;
|
||||
import org.mercury_im.messenger.core.account.error.PasswordError;
|
||||
import org.mercury_im.messenger.core.account.error.UsernameError;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnection;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
|
||||
import org.mercury_im.messenger.core.connection.exception.InvalidCredentialsException;
|
||||
import org.mercury_im.messenger.core.connection.exception.ServerUnreachableException;
|
||||
import org.mercury_im.messenger.core.connection.state.ConnectionState;
|
||||
import org.mercury_im.messenger.core.connection.state.ConnectivityState;
|
||||
import org.mercury_im.messenger.core.data.repository.AccountRepository;
|
||||
import org.mercury_im.messenger.core.util.Optional;
|
||||
import org.mercury_im.messenger.core.viewmodel.MercuryViewModel;
|
||||
import org.mercury_im.messenger.entity.Account;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -35,10 +37,11 @@ public class LoginViewModel implements MercuryViewModel {
|
|||
private BehaviorSubject<Optional<UsernameError>> loginUsernameError;
|
||||
private BehaviorSubject<Optional<PasswordError>> loginPasswordError;
|
||||
private BehaviorSubject<Boolean> isLoginPossible;
|
||||
private BehaviorSubject<Boolean> isLoginSuccessful;
|
||||
private BehaviorSubject<Optional<Account>> isLoginSuccessful;
|
||||
|
||||
private EntityBareJid loginUsernameValue;
|
||||
private String loginPasswordValue;
|
||||
private Account account;
|
||||
|
||||
@Inject
|
||||
public LoginViewModel(MercuryConnectionManager connectionManager,
|
||||
|
@ -55,7 +58,7 @@ public class LoginViewModel implements MercuryViewModel {
|
|||
loginUsernameError = BehaviorSubject.createDefault(new Optional<>());
|
||||
loginPasswordError = BehaviorSubject.createDefault(new Optional<>());
|
||||
isLoginPossible = BehaviorSubject.createDefault(false);
|
||||
isLoginSuccessful = BehaviorSubject.createDefault(false);
|
||||
isLoginSuccessful = BehaviorSubject.createDefault(new Optional<>());
|
||||
|
||||
loginUsernameValue = null;
|
||||
loginPasswordValue = null;
|
||||
|
@ -73,7 +76,7 @@ public class LoginViewModel implements MercuryViewModel {
|
|||
return isLoginPossible;
|
||||
}
|
||||
|
||||
public Observable<Boolean> isLoginSuccessful() {
|
||||
public Observable<Optional<Account>> isLoginSuccessful() {
|
||||
return isLoginSuccessful;
|
||||
}
|
||||
|
||||
|
@ -108,26 +111,48 @@ public class LoginViewModel implements MercuryViewModel {
|
|||
isLoginPossible.onNext(loginUsernameValue != null && loginPasswordValue != null);
|
||||
}
|
||||
|
||||
public synchronized void login() {
|
||||
public synchronized Account login() {
|
||||
if (!isLoginPossible.getValue()) {
|
||||
// Prevent race condition where account would be logged in twice
|
||||
return;
|
||||
return account;
|
||||
}
|
||||
isLoginPossible.onNext(false);
|
||||
|
||||
Account account = createAccountEntity();
|
||||
account = createAccountEntity();
|
||||
|
||||
//MercuryConnection connection = connectionManager.createConnection(account);
|
||||
addDisposable(accountRepository.upsertAccount(account).ignoreElement()
|
||||
addDisposable(accountRepository.upsertAccount(account)
|
||||
//.andThen(connection.connect())
|
||||
//.andThen(connection.login())
|
||||
//.andThen(connectionManager.registerConnection(connection))
|
||||
.subscribeOn(schedulers.getNewThread())
|
||||
.observeOn(schedulers.getUiScheduler())
|
||||
.subscribe(
|
||||
this::onLoginSuccessful,
|
||||
a -> LOGGER.log(Level.INFO, "Account " + a + " successfully inserted."),
|
||||
this::onLoginFailed
|
||||
));
|
||||
|
||||
addDisposable(connectionManager.observeConnectionPool()
|
||||
.map(cp -> {
|
||||
ConnectionState state = cp.getConnectionStates().get(account.getId());
|
||||
if (state == null) {
|
||||
return ConnectivityState.disconnected;
|
||||
} else {
|
||||
return state.getConnectivity();
|
||||
}
|
||||
})
|
||||
.filter(s -> s == ConnectivityState.disconnectedOnError || s == ConnectivityState.authenticated)
|
||||
.firstOrError()
|
||||
.compose(schedulers.executeUiSafeSingle())
|
||||
.subscribe(connectivityState -> {
|
||||
if (connectivityState == ConnectivityState.disconnectedOnError) {
|
||||
onLoginFailed(new Exception());
|
||||
} else {
|
||||
onLoginSuccessful(account);
|
||||
}
|
||||
}));
|
||||
|
||||
return account;
|
||||
}
|
||||
|
||||
private Account createAccountEntity() {
|
||||
|
@ -139,11 +164,13 @@ public class LoginViewModel implements MercuryViewModel {
|
|||
return account;
|
||||
}
|
||||
|
||||
private void onLoginSuccessful() {
|
||||
isLoginSuccessful.onNext(true);
|
||||
private void onLoginSuccessful(Account account) {
|
||||
LOGGER.log(Level.INFO, "Login successful.");
|
||||
isLoginSuccessful.onNext(new Optional<>(account));
|
||||
}
|
||||
|
||||
private void onLoginFailed(Throwable error) {
|
||||
LOGGER.log(Level.INFO, "Login failed!");
|
||||
isLoginPossible.onNext(true);
|
||||
if (error instanceof InvalidCredentialsException) {
|
||||
loginPasswordError.onNext(new Optional<>(PasswordError.incorrectPassword));
|
||||
|
|
|
@ -14,6 +14,8 @@ import org.jxmpp.jid.EntityBareJid;
|
|||
import org.mercury_im.messenger.core.SchedulersFacade;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnection;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
|
||||
import org.mercury_im.messenger.core.connection.state.ConnectionState;
|
||||
import org.mercury_im.messenger.core.connection.state.ConnectivityState;
|
||||
import org.mercury_im.messenger.core.crypto.ikey.IkeyInitializer;
|
||||
import org.mercury_im.messenger.core.crypto.ikey.IkeyRepository;
|
||||
import org.mercury_im.messenger.core.data.repository.AccountRepository;
|
||||
|
@ -27,15 +29,12 @@ import org.pgpainless.key.OpenPgpV4Fingerprint;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
|
||||
import static org.jivesoftware.smackx.ox.util.OpenPgpPubSubUtil.PEP_NODE_PUBLIC_KEYS;
|
||||
|
||||
|
@ -155,4 +154,18 @@ public class AccountDetailsViewModel implements MercuryViewModel {
|
|||
SecretkeyElement secretkeyElement = ikeyManager.fetchSecretIdentityKey();
|
||||
});
|
||||
}
|
||||
|
||||
public Observable<Boolean> isAccountEnabled(UUID accountId) {
|
||||
return accountRepository.observeAccount(accountId)
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::getItem)
|
||||
.map(Account::isEnabled);
|
||||
}
|
||||
|
||||
public Observable<Boolean> isAccountAuthenticated(UUID accountId) {
|
||||
return connectionManager.getConnection(accountId)
|
||||
.observeConnection()
|
||||
.map(ConnectionState::getConnectivity)
|
||||
.map(connectivity -> connectivity == ConnectivityState.authenticated);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ public class OxSecretKeyBackupRestoreViewModel implements MercuryViewModel {
|
|||
private BehaviorSubject<Optional<OxBackupRestoreError>> backupRestoreError = BehaviorSubject.createDefault(new Optional<>());
|
||||
private BehaviorSubject<Boolean> finished = BehaviorSubject.createDefault(false);
|
||||
|
||||
@Inject
|
||||
//@Inject
|
||||
public OxSecretKeyBackupRestoreViewModel(OpenPgpManager openPgpManager) {
|
||||
this.openPgpManager = openPgpManager;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue