package org.mercury_im.messenger.core.viewmodel.accounts; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.data.repository.AccountRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository; import org.mercury_im.messenger.core.viewmodel.MercuryViewModel; import org.mercury_im.messenger.core.xmpp.MercuryConnectionManager; import org.mercury_im.messenger.core.xmpp.state.ConnectionPoolState; import org.mercury_im.messenger.core.xmpp.state.ConnectionState; import org.mercury_im.messenger.entity.Account; import org.pgpainless.key.OpenPgpV4Fingerprint; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; import javax.inject.Inject; import io.reactivex.Observable; import io.reactivex.ObservableSource; import io.reactivex.ObservableTransformer; public class AccountsViewModel implements MercuryViewModel { private static final Logger LOGGER = Logger.getLogger(AccountsViewModel.class.getName()); private final MercuryConnectionManager connectionManager; private final AccountRepository accountRepository; private final OpenPgpRepository openPgpRepository; private final SchedulersFacade schedulers; @Inject public AccountsViewModel(MercuryConnectionManager connectionManager, AccountRepository accountRepository, OpenPgpRepository openPgpRepository, SchedulersFacade schedulers) { this.connectionManager = connectionManager; this.accountRepository = accountRepository; this.openPgpRepository = openPgpRepository; this.schedulers = schedulers; } public Observable> observeAccounts() { return connectionManager.observeConnectionPool() .compose(toAccountViewItems); } public void onToggleAccountEnabled(Account account, boolean enabled) { account.setEnabled(enabled); addDisposable(accountRepository.upsertAccount(account) .subscribeOn(schedulers.getIoScheduler()) .observeOn(schedulers.getUiScheduler()) .subscribe( success -> logAccountToggledSuccess(success, enabled), error -> logAccountToggleError(account, enabled, error) ) ); } private void logAccountToggledSuccess(Account account, boolean enabled) { LOGGER.log(Level.INFO, "Account " + account.getAddress() + (enabled ? " enabled" : " disabled")); } private void logAccountToggleError(Account account, boolean enabled, Throwable error) { LOGGER.log(Level.SEVERE, "Account " + account.getAddress() + " could not be " + (enabled ? "enabled" : "disabled"), error); } private final ObservableTransformer> toAccountViewItems = new ObservableTransformer>() { @Override public ObservableSource> apply(Observable upstream) { return upstream.map(state -> { List viewItems = new ArrayList<>(); for (Map.Entry entry : state.getConnectionStates().entrySet()) { ConnectionState connectionState = entry.getValue(); Account account = accountRepository.getAccount(entry.getKey()).blockingGet(); OpenPgpV4Fingerprint fingerprint = null; try { PGPSecretKeyRingCollection secretKeyRings = openPgpRepository.loadSecretKeysOf(account.getId(), account.getJid()).blockingGet(); fingerprint = new OpenPgpV4Fingerprint(secretKeyRings.getKeyRings().next()); } catch (NoSuchElementException e) { LOGGER.log(Level.INFO, "No fingerprint found for " + account.getAddress()); } viewItems.add(new AccountViewItem(account, connectionState.getConnectivity(), fingerprint)); } return viewItems; }); } }; public void onDeleteAccount(UUID accountId) { addDisposable(accountRepository.deleteAccount(accountId) .subscribe(() -> LOGGER.log(Level.INFO, "Account " + accountId + " successfully deleted."), e -> LOGGER.log(Level.SEVERE, "Could not delete account " + accountId, e))); } }