Some cleanup

This commit is contained in:
Paul Schaub 2020-07-18 12:47:52 +02:00
parent 69120efb25
commit 40266f8741
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
41 changed files with 258 additions and 200 deletions

View File

@ -14,7 +14,7 @@ import org.mercury_im.messenger.android.di.component.AppComponent;
import org.mercury_im.messenger.android.di.module.AppModule; import org.mercury_im.messenger.android.di.module.AppModule;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.android.service.MercuryForegroundService; import org.mercury_im.messenger.android.service.MercuryForegroundService;
import org.mercury_im.messenger.core.xmpp.CsiManager; import org.mercury_im.messenger.core.connection.CsiManager;
import java.util.List; import java.util.List;

View File

@ -81,6 +81,7 @@ public class AccountDetailsFragment extends Fragment {
this.adapter = new ToggleableFingerprintsAdapter( this.adapter = new ToggleableFingerprintsAdapter(
(fingerprint, checked) -> viewModel.markFingerprintTrusted(fingerprint, checked)); (fingerprint, checked) -> viewModel.markFingerprintTrusted(fingerprint, checked));
this.adapter.setItemLongClickListener(fingerprint -> viewModel.unpublishPublicKey(fingerprint));
} }
private void observe() { private void observe() {

View File

@ -28,6 +28,8 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import io.reactivex.Completable;
public class AndroidAccountDetailsViewModel extends AndroidViewModel implements MercuryAndroidViewModel<AccountDetailsViewModel> { public class AndroidAccountDetailsViewModel extends AndroidViewModel implements MercuryAndroidViewModel<AccountDetailsViewModel> {
private static final Logger LOGGER = Logger.getLogger(AndroidAccountDetailsViewModel.class.getName()); private static final Logger LOGGER = Logger.getLogger(AndroidAccountDetailsViewModel.class.getName());
@ -89,6 +91,14 @@ public class AndroidAccountDetailsViewModel extends AndroidViewModel implements
return remoteFingerprints; return remoteFingerprints;
} }
public void unpublishPublicKey(OpenPgpV4Fingerprint fingerprint) {
addDisposable(getCommonViewModel().unpublishPublicKey(accountId, fingerprint)
.subscribeOn(schedulers.getNewThread())
.observeOn(schedulers.getUiScheduler())
.subscribe(() -> LOGGER.log(Level.INFO, "Successfully unpublished fingerprint " + fingerprint),
e -> LOGGER.log(Level.SEVERE, "Error unpublishing fingerprint " + fingerprint, e)));
}
public static class AndroidAccountDetailsViewModelFactory implements ViewModelProvider.Factory { public static class AndroidAccountDetailsViewModelFactory implements ViewModelProvider.Factory {
private final Application application; private final Application application;

View File

@ -62,8 +62,12 @@ public class AccountListRecyclerViewAdapter extends RecyclerView.Adapter<Account
holder.jid.setText(account.getAddress()); holder.jid.setText(account.getAddress());
holder.avatar.setImageDrawable(new AvatarDrawable(account.getAddress(), account.getAddress())); holder.avatar.setImageDrawable(new AvatarDrawable(account.getAddress(), account.getAddress()));
holder.enabled.setChecked(account.isEnabled()); holder.enabled.setChecked(account.isEnabled());
holder.enabled.setOnCheckedChangeListener((compoundButton, checked) -> holder.enabled.setOnCheckedChangeListener((compoundButton, checked) -> {
viewModel.setAccountEnabled(account, checked)); if (!compoundButton.isPressed()) {
return;
}
viewModel.setAccountEnabled(account, checked);
});
holder.status.setText(viewItem.getConnectivityState().toString()); holder.status.setText(viewItem.getConnectivityState().toString());
holder.mView.setOnLongClickListener(v -> { holder.mView.setOnLongClickListener(v -> {

View File

@ -22,6 +22,7 @@ public class ToggleableFingerprintsAdapter extends RecyclerView.Adapter<Toggleab
private final List<FingerprintViewItem> fingerprints = new ArrayList<>(); private final List<FingerprintViewItem> fingerprints = new ArrayList<>();
private final OnFingerprintItemToggleListener toggleListener; private final OnFingerprintItemToggleListener toggleListener;
private OnFingerprintItemLongClickListener longClickListener = null;
private static final DateFormat dateFormat = SimpleDateFormat.getDateInstance(); private static final DateFormat dateFormat = SimpleDateFormat.getDateInstance();
@ -59,6 +60,13 @@ public class ToggleableFingerprintsAdapter extends RecyclerView.Adapter<Toggleab
holder.trustSwitch.setOnCheckedChangeListener( holder.trustSwitch.setOnCheckedChangeListener(
(buttonView, isChecked) -> toggleListener.onFingerprintToggled(fingerprint, isChecked)); (buttonView, isChecked) -> toggleListener.onFingerprintToggled(fingerprint, isChecked));
holder.divider.setVisibility(position == fingerprints.size() - 1 ? View.GONE : View.VISIBLE); holder.divider.setVisibility(position == fingerprints.size() - 1 ? View.GONE : View.VISIBLE);
holder.itemView.setOnLongClickListener(v -> {
if (longClickListener != null) {
longClickListener.onFingerprintItemLongClick(fingerprint);
}
return true;
});
} }
} }
@ -83,8 +91,17 @@ public class ToggleableFingerprintsAdapter extends RecyclerView.Adapter<Toggleab
} }
} }
public void setItemLongClickListener(OnFingerprintItemLongClickListener longClickListener) {
this.longClickListener = longClickListener;
}
public interface OnFingerprintItemToggleListener { public interface OnFingerprintItemToggleListener {
void onFingerprintToggled(OpenPgpV4Fingerprint fingerprint, boolean checked); void onFingerprintToggled(OpenPgpV4Fingerprint fingerprint, boolean checked);
} }
public interface OnFingerprintItemLongClickListener {
void onFingerprintItemLongClick(OpenPgpV4Fingerprint fingerprint);
}
} }

View File

@ -10,7 +10,7 @@ import org.mercury_im.messenger.cli.di.component.CliComponent;
import org.mercury_im.messenger.cli.di.component.DaggerCliComponent; import org.mercury_im.messenger.cli.di.component.DaggerCliComponent;
import org.mercury_im.messenger.core.Messenger; import org.mercury_im.messenger.core.Messenger;
import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel; import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
import org.mercury_im.messenger.core.xmpp.MercuryConnection; import org.mercury_im.messenger.core.connection.MercuryConnection;
import java.util.List; import java.util.List;

View File

@ -5,7 +5,7 @@ import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smack.util.TLSUtils; import org.jivesoftware.smack.util.TLSUtils;
import org.jxmpp.stringprep.XmppStringprepException; import org.jxmpp.stringprep.XmppStringprepException;
import org.mercury_im.messenger.core.xmpp.XmppConnectionFactory; import org.mercury_im.messenger.core.connection.XmppConnectionFactory;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
public class X509WorkaroundConnectionFactory implements XmppConnectionFactory { public class X509WorkaroundConnectionFactory implements XmppConnectionFactory {

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.cli.di.module; package org.mercury_im.messenger.cli.di.module;
import org.mercury_im.messenger.cli.X509WorkaroundConnectionFactory; import org.mercury_im.messenger.cli.X509WorkaroundConnectionFactory;
import org.mercury_im.messenger.core.xmpp.XmppConnectionFactory; import org.mercury_im.messenger.core.connection.XmppConnectionFactory;
import javax.inject.Singleton; import javax.inject.Singleton;

View File

@ -1,8 +0,0 @@
package org.mercury_im.messenger.data.enums;
public enum MessageContentType {
/**
* Content is a message body.
*/
body
}

View File

@ -11,11 +11,11 @@ import org.jivesoftware.smackx.ox_im.OXInstantMessagingManager;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException; import org.jxmpp.stringprep.XmppStringprepException;
import org.mercury_im.messenger.core.connection.MercuryConnection;
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
import org.mercury_im.messenger.core.data.repository.Repositories; import org.mercury_im.messenger.core.data.repository.Repositories;
import org.mercury_im.messenger.core.exception.ConnectionNotFoundException; import org.mercury_im.messenger.core.exception.ConnectionNotFoundException;
import org.mercury_im.messenger.core.exception.ContactAlreadyAddedException; import org.mercury_im.messenger.core.exception.ContactAlreadyAddedException;
import org.mercury_im.messenger.core.xmpp.MercuryConnection;
import org.mercury_im.messenger.core.xmpp.MercuryConnectionManager;
import org.mercury_im.messenger.entity.contact.Peer; import org.mercury_im.messenger.entity.contact.Peer;
import java.io.IOException; import java.io.IOException;

View File

@ -5,8 +5,6 @@ import javax.inject.Named;
import io.reactivex.CompletableTransformer; import io.reactivex.CompletableTransformer;
import io.reactivex.MaybeTransformer; import io.reactivex.MaybeTransformer;
import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer; import io.reactivex.ObservableTransformer;
import io.reactivex.Scheduler; import io.reactivex.Scheduler;
import io.reactivex.SingleTransformer; import io.reactivex.SingleTransformer;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.xmpp; package org.mercury_im.messenger.core.connection;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smackx.csi.ClientStateIndicationManager; import org.jivesoftware.smackx.csi.ClientStateIndicationManager;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.xmpp; package org.mercury_im.messenger.core.connection;
import org.jivesoftware.smack.AbstractXMPPConnection; import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.ConnectionListener;
@ -8,15 +8,15 @@ import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.sasl.SASLErrorException; import org.jivesoftware.smack.sasl.SASLErrorException;
import org.mercury_im.messenger.core.xmpp.exception.InvalidCredentialsException; import org.mercury_im.messenger.core.connection.exception.InvalidCredentialsException;
import org.mercury_im.messenger.core.xmpp.exception.ServerUnreachableException; import org.mercury_im.messenger.core.connection.exception.ServerUnreachableException;
import org.mercury_im.messenger.core.xmpp.state.ConnectivityState; import org.mercury_im.messenger.core.connection.state.ConnectionState;
import org.mercury_im.messenger.core.connection.state.ConnectivityState;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.core.xmpp.state.ConnectionState;
import java.io.IOException; import java.io.IOException;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -28,7 +28,6 @@ import lombok.Getter;
public class MercuryConnection { public class MercuryConnection {
private static final Logger LOGGER = Logger.getLogger(MercuryConnection.class.getName()); private static final Logger LOGGER = Logger.getLogger(MercuryConnection.class.getName());
private AtomicBoolean connecting = new AtomicBoolean(false);
@Getter @Getter
private XMPPConnection connection; private XMPPConnection connection;
@ -36,15 +35,21 @@ public class MercuryConnection {
@Getter @Getter
private final Account account; private final Account account;
private final BehaviorSubject<ConnectionState> stateObservable; private final MercuryConnectionListener connectionListener;
public MercuryConnection(XMPPConnection connection, Account account) { public MercuryConnection(XMPPConnection connection, Account account) {
this.connection = connection; this.connection = connection;
this.account = account; this.account = account;
this.stateObservable = BehaviorSubject.createDefault(new ConnectionState(account.getId(), this, if (connection.isConnected()) {
ConnectivityState.disconnected, false, false)); throw new IllegalStateException("Connection" + account.getJid() + " MUST NOT be connected at this point.");
}
connectionListener = new MercuryConnectionListener(account.getId(), this);
connection.addConnectionListener(connectionListener); connection.addConnectionListener(connectionListener);
initialConnectionSetup();
} }
public UUID getAccountId() { public UUID getAccountId() {
@ -52,34 +57,31 @@ public class MercuryConnection {
} }
public Observable<ConnectionState> observeConnection() { public Observable<ConnectionState> observeConnection() {
return stateObservable; return connectionListener.connectionState;
} }
public Completable connect() { public Completable connect() {
return Completable.fromAction(this::doConnect) return Completable.fromAction(this::doConnect)
.doOnError(error -> LOGGER.log(Level.WARNING, "Connection error for account " + account, error)); .doOnError(error -> LOGGER.log(Level.WARNING, "connect(): Connection error for account " + account, error));
} }
private synchronized void doConnect() throws ServerUnreachableException { private synchronized void doConnect() throws ServerUnreachableException {
if (connecting.compareAndSet(false, true)) { ConnectivityState connectivity = connectionListener.connectivity.get();
AbstractXMPPConnection connection = (AbstractXMPPConnection) getConnection(); if (connectivity != ConnectivityState.disconnected) {
if (connection.isConnected()) { LOGGER.log(Level.WARNING, "doConnect(): Connection " + account.getJid() + " is not disconnected: " + connectivity);
return; return;
}
try {
connection.connect();
connecting.set(false);
} catch (SmackException.EndpointConnectionException e) {
connection.disconnect();
throw new ServerUnreachableException("Cannot connect to server " + connection.getXMPPServiceDomain().asUnescapedString(), e);
} catch (IOException | InterruptedException | XMPPException | SmackException e) {
throw new AssertionError("Unexpected exception.", e);
}
stateObservable.onNext(stateObservable.getValue().withConnectivity(ConnectivityState.connecting));
LOGGER.log(Level.INFO, "Connected!");
} else {
LOGGER.log(Level.INFO, "Already connecting.");
} }
AbstractXMPPConnection connection = (AbstractXMPPConnection) getConnection();
try {
connection.connect();
} catch (SmackException.EndpointConnectionException e) {
connection.disconnect();
throw new ServerUnreachableException("doConnect(): Cannot connect to server " + connection.getXMPPServiceDomain().asUnescapedString(), e);
} catch (IOException | InterruptedException | XMPPException | SmackException e) {
throw new AssertionError("Unexpected exception.", e);
}
LOGGER.log(Level.INFO, "Connected!");
} }
public Completable login() { public Completable login() {
@ -88,8 +90,9 @@ public class MercuryConnection {
} }
private synchronized void doLogin() throws InvalidCredentialsException { private synchronized void doLogin() throws InvalidCredentialsException {
if (connection.isAuthenticated()) { ConnectivityState connectivity = connectionListener.connectivity.get();
return; if (connectivity != ConnectivityState.connected) {
LOGGER.log(Level.WARNING, "doLogin(): Connection " + account.getJid() + " is not connected: " + connectivity);
} }
try { try {
((AbstractXMPPConnection) getConnection()).login(); ((AbstractXMPPConnection) getConnection()).login();
@ -102,7 +105,7 @@ public class MercuryConnection {
public Completable shutdown() { public Completable shutdown() {
return Completable.fromAction(this::doShutdown) return Completable.fromAction(this::doShutdown)
.doOnError(error -> LOGGER.log(Level.WARNING, "Shutdown error for account " + account, error)); .doOnError(error -> LOGGER.log(Level.WARNING, "Shutdown error for account " + account.getJid(), error));
} }
public synchronized void doShutdown() { public synchronized void doShutdown() {
@ -113,43 +116,6 @@ public class MercuryConnection {
} }
} }
private final ConnectionListener connectionListener = new ConnectionListener() {
@Override
public void connected(XMPPConnection connection) {
connecting.set(false);
stateObservable.onNext(stateObservable.getValue()
.withConnectivity(ConnectivityState.connected)
.withAuthenticated(false));
}
@Override
public void authenticated(XMPPConnection connection, boolean isResumed) {
stateObservable.onNext(stateObservable.getValue()
.withConnectivity(ConnectivityState.connected)
.withAuthenticated(true)
.withResumed(isResumed));
if (!isResumed) {
initialConnectionSetup();
}
}
@Override
public void connectionClosed() {
connecting.set(false);
stateObservable.onNext(stateObservable.getValue()
.withConnectivity(ConnectivityState.disconnected)
.withAuthenticated(false));
}
@Override
public void connectionClosedOnError(Exception e) {
connecting.set(false);
stateObservable.onNext(stateObservable.getValue()
.withConnectivity(ConnectivityState.disconnected)
.withAuthenticated(false));
}
};
private void initialConnectionSetup() { private void initialConnectionSetup() {
ReconnectionManager.getInstanceFor((AbstractXMPPConnection) getConnection()) ReconnectionManager.getInstanceFor((AbstractXMPPConnection) getConnection())
.addReconnectionListener(new ReconnectionListener() { .addReconnectionListener(new ReconnectionListener() {
@ -164,4 +130,55 @@ public class MercuryConnection {
} }
}); });
} }
private class MercuryConnectionListener implements ConnectionListener {
private final AtomicReference<ConnectivityState> connectivity;
private final BehaviorSubject<ConnectionState> connectionState;
public MercuryConnectionListener(UUID accountId, MercuryConnection connection) {
this.connectionState = BehaviorSubject.createDefault(new ConnectionState(accountId, connection));
this.connectivity = new AtomicReference<>(ConnectivityState.disconnected);
}
@Override
public void connecting(XMPPConnection connection) {
changeConnectivity(ConnectivityState.connecting);
}
@Override
public void connected(XMPPConnection connection) {
changeConnectivity(ConnectivityState.connected);
}
@Override
public void authenticated(XMPPConnection connection, boolean resumed) {
connectivity.set(ConnectivityState.authenticated);
ConnectionState state = connectionState.getValue()
.withConnectivity(ConnectivityState.authenticated)
.withResumed(resumed);
connectionState.onNext(state);
}
@Override
public void connectionClosed() {
changeConnectivity(ConnectivityState.disconnected);
}
@Override
public void connectionClosedOnError(Exception e) {
changeConnectivity(ConnectivityState.disconnectedOnError);
}
private void changeConnectivity(ConnectivityState newConnectivity) {
connectivity.set(newConnectivity);
ConnectionState state = connectionState.getValue()
.withConnectivity(newConnectivity);
connectionState.onNext(state);
}
}
} }

View File

@ -1,22 +1,19 @@
package org.mercury_im.messenger.core.xmpp; package org.mercury_im.messenger.core.connection;
import org.jivesoftware.smack.chat2.ChatManager; import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smackx.caps.EntityCapsManager; import org.jivesoftware.smackx.caps.EntityCapsManager;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.connection.state.ConnectionPoolState;
import org.mercury_im.messenger.core.connection.state.ConnectionState;
import org.mercury_im.messenger.core.crypto.MercuryOpenPgpManager; import org.mercury_im.messenger.core.crypto.MercuryOpenPgpManager;
import org.mercury_im.messenger.core.data.repository.AccountRepository; import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.data.repository.MessageRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.data.repository.Repositories; import org.mercury_im.messenger.core.data.repository.Repositories;
import org.mercury_im.messenger.core.store.message.MercuryMessageStoreFactory;
import org.mercury_im.messenger.core.xmpp.state.ConnectionPoolState;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.core.store.caps.MercuryEntityCapsStore; import org.mercury_im.messenger.core.store.caps.MercuryEntityCapsStore;
import org.mercury_im.messenger.core.store.message.MercuryMessageStore; import org.mercury_im.messenger.core.store.message.MercuryMessageStore;
import org.mercury_im.messenger.core.store.message.MercuryMessageStoreFactory;
import org.mercury_im.messenger.core.usecase.RosterStoreBinder; import org.mercury_im.messenger.core.usecase.RosterStoreBinder;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.xmpp.state.ConnectionState; import org.mercury_im.messenger.entity.Account;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -33,6 +30,7 @@ import io.reactivex.Completable;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable; import io.reactivex.disposables.Disposable;
import io.reactivex.functions.BiPredicate;
import io.reactivex.schedulers.Schedulers; import io.reactivex.schedulers.Schedulers;
import io.reactivex.subjects.BehaviorSubject; import io.reactivex.subjects.BehaviorSubject;
@ -45,10 +43,6 @@ public class MercuryConnectionManager {
private final MercuryMessageStoreFactory messageStoreFactory; private final MercuryMessageStoreFactory messageStoreFactory;
private final AccountRepository accountRepository; private final AccountRepository accountRepository;
private final RosterStoreBinder rosterStoreBinder; private final RosterStoreBinder rosterStoreBinder;
private final MercuryEntityCapsStore entityCapsStore;
private final PeerRepository peerRepository;
private final DirectChatRepository directChatRepository;
private final MessageRepository messageRepository;
private final MercuryOpenPgpManager cryptoManager; private final MercuryOpenPgpManager cryptoManager;
private final SchedulersFacade schedulers; private final SchedulersFacade schedulers;
@ -73,21 +67,18 @@ public class MercuryConnectionManager {
SchedulersFacade schedulers) { SchedulersFacade schedulers) {
this.accountRepository = repositories.getAccountRepository(); this.accountRepository = repositories.getAccountRepository();
this.rosterStoreBinder = rosterStoreBinder; this.rosterStoreBinder = rosterStoreBinder;
this.entityCapsStore = entityCapsStore;
this.peerRepository = repositories.getPeerRepository();
this.directChatRepository = repositories.getDirectChatRepository();
this.messageRepository = repositories.getMessageRepository();
this.connectionFactory = connectionFactory; this.connectionFactory = connectionFactory;
this.messageStoreFactory = messageStoreFactory; this.messageStoreFactory = messageStoreFactory;
this.cryptoManager = cryptoManager; this.cryptoManager = cryptoManager;
this.schedulers = schedulers; this.schedulers = schedulers;
EntityCapsManager.setPersistentCache(entityCapsStore); EntityCapsManager.setPersistentCache(entityCapsStore);
start(); registerNewConnections();
} }
public synchronized void start() { public synchronized void registerNewConnections() {
disposable.add(accountRepository.observeAllAccounts() disposable.add(accountRepository.observeAllAccounts()
.distinctUntilChanged((a,b) -> a.size() != b.size())
.subscribeOn(schedulers.getIoScheduler()) .subscribeOn(schedulers.getIoScheduler())
.subscribe(this::doRegisterConnections)); .subscribe(this::doRegisterConnections));
} }
@ -131,21 +122,27 @@ public class MercuryConnectionManager {
putConnection(connection); putConnection(connection);
disposable.add(accountRepository disposable.add(accountRepository
.observeAccount(connection.getAccountId()) .observeAccount(connection.getAccountId())
.subscribeOn(Schedulers.newThread()) .subscribeOn(schedulers.getNewThread())
.observeOn(Schedulers.newThread()) .observeOn(schedulers.getNewThread())
.subscribe(event -> .distinctUntilChanged(accountNotToggledNorRemoved)
handleOptionalAccountChangedEvent(connection, event))); .subscribe(event -> handleOptionalAccountChangedEvent(connection, event)));
} }
private BiPredicate<Optional<Account>, Optional<Account>> accountNotToggledNorRemoved = (first, second) ->
// Account not removed
first.isPresent() == second.isPresent()
// If account is not removed check if not toggled
&& (!first.isPresent() || first.getItem().isEnabled() == second.getItem().isEnabled());
private synchronized void putConnection(MercuryConnection connection) { private synchronized void putConnection(MercuryConnection connection) {
connectionsMap.put(connection.getAccountId(), connection); connectionsMap.put(connection.getAccountId(), connection);
connectionDisposables.put(connection.getAccountId(), connection.observeConnection() connectionDisposables.put(connection.getAccountId(),
.subscribe(this::insertConnectionToPoolState)); connection.observeConnection().subscribe(this::insertConnectionToPoolState));
bindConnection(connection); bindConnection(connection);
} }
private void insertConnectionToPoolState(ConnectionState s) { private void insertConnectionToPoolState(ConnectionState s) {
LOGGER.log(Level.INFO, "Insert new connection to pool state: " + s); LOGGER.log(Level.INFO, "Insert new connection to pool state: " + s + " " + s.getConnection().getAccount().getJid());
connectionPoolObservable.onNext(updatePoolState(connectionPoolObservable.getValue(), s)); connectionPoolObservable.onNext(updatePoolState(connectionPoolObservable.getValue(), s));
} }
@ -168,17 +165,16 @@ public class MercuryConnectionManager {
cryptoManager.initialize(connection); cryptoManager.initialize(connection);
} }
private void handleOptionalAccountChangedEvent(MercuryConnection connection, Optional<Account> event) { private synchronized void handleOptionalAccountChangedEvent(MercuryConnection connection, Optional<Account> event) {
synchronized (connection) { if (event.isPresent()) {
if (event.isPresent()) { handleAccountChangedEvent(connection, event.getItem());
handleAccountChangedEvent(connection, event.getItem()); } else {
} else { handleAccountRemoved(connection);
handleAccountRemoved(connection);
}
} }
} }
private synchronized void handleAccountChangedEvent(MercuryConnection connection, Account account) { private synchronized void handleAccountChangedEvent(MercuryConnection connection, Account account) {
LOGGER.log(Level.INFO, "handleAccountChangedEvent: " + account);
if (account.isEnabled()) { if (account.isEnabled()) {
handleAccountEnabled(connection); handleAccountEnabled(connection);
} else { } else {

View File

@ -1,7 +1,6 @@
package org.mercury_im.messenger.core.xmpp; package org.mercury_im.messenger.core.connection;
import org.jivesoftware.smack.ReconnectionManager; import org.jivesoftware.smack.ReconnectionManager;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smackx.carbons.CarbonManager; import org.jivesoftware.smackx.carbons.CarbonManager;
import org.jivesoftware.smackx.iqversion.VersionManager; import org.jivesoftware.smackx.iqversion.VersionManager;
@ -11,7 +10,7 @@ import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager;
public class SmackConfig { public class SmackConfig {
static void staticConfiguration() { static void staticConfiguration() {
SmackConfiguration.DEBUG = false; //SmackConfiguration.DEBUG = true;
ReconnectionManager.setEnabledPerDefault(true); ReconnectionManager.setEnabledPerDefault(true);
ReconnectionManager.setDefaultReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY); ReconnectionManager.setDefaultReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.xmpp; package org.mercury_im.messenger.core.connection;
import org.jivesoftware.smack.AbstractXMPPConnection; import org.jivesoftware.smack.AbstractXMPPConnection;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.xmpp; package org.mercury_im.messenger.core.connection;
import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.chat2.Chat; import org.jivesoftware.smack.chat2.Chat;
@ -15,10 +15,10 @@ import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.data.repository.MessageRepository; import org.mercury_im.messenger.core.data.repository.MessageRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository; import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.data.repository.Repositories; import org.mercury_im.messenger.core.data.repository.Repositories;
import org.mercury_im.messenger.core.listener.IncomingDirectMessageListener;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.entity.chat.DirectChat; import org.mercury_im.messenger.entity.chat.DirectChat;
import org.mercury_im.messenger.entity.message.Message; import org.mercury_im.messenger.entity.message.Message;
import org.mercury_im.messenger.core.listener.IncomingDirectMessageListener;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;

View File

@ -1,9 +1,8 @@
package org.mercury_im.messenger.core.xmpp; package org.mercury_im.messenger.core.connection;
import org.jivesoftware.smack.AbstractXMPPConnection; import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smack.util.TLSUtils;
import org.jxmpp.stringprep.XmppStringprepException; import org.jxmpp.stringprep.XmppStringprepException;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.xmpp.exception; package org.mercury_im.messenger.core.connection.exception;
public class InvalidCredentialsException extends Exception { public class InvalidCredentialsException extends Exception {

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.xmpp.exception; package org.mercury_im.messenger.core.connection.exception;
public class ServerUnreachableException extends Exception { public class ServerUnreachableException extends Exception {

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.xmpp.state; package org.mercury_im.messenger.core.connection.state;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.core.xmpp.state; package org.mercury_im.messenger.core.connection.state;
import org.mercury_im.messenger.core.xmpp.MercuryConnection; import org.mercury_im.messenger.core.connection.MercuryConnection;
import java.util.UUID; import java.util.UUID;
@ -19,15 +19,16 @@ public class ConnectionState {
@With @With
ConnectivityState connectivity; ConnectivityState connectivity;
@With @With
boolean authenticated;
@With
boolean resumed; boolean resumed;
public ConnectionState(UUID id, MercuryConnection connection, ConnectivityState connectivity, boolean authenticated, boolean resumed) { public ConnectionState(UUID id, MercuryConnection connection, ConnectivityState connectivity, boolean resumed) {
this.id = id; this.id = id;
this.connection = connection; this.connection = connection;
this.connectivity = connectivity; this.connectivity = connectivity;
this.authenticated = authenticated;
this.resumed = resumed; this.resumed = resumed;
} }
public ConnectionState(UUID accountId, MercuryConnection connection) {
this(accountId, connection, ConnectivityState.disconnected, false);
}
} }

View File

@ -0,0 +1,9 @@
package org.mercury_im.messenger.core.connection.state;
public enum ConnectivityState {
disconnected,
connecting,
connected,
authenticated,
disconnectedOnError
}

View File

@ -12,11 +12,11 @@ import org.jivesoftware.smackx.ox.util.SecretKeyBackupHelper;
import org.jivesoftware.smackx.ox_im.OXInstantMessagingManager; import org.jivesoftware.smackx.ox_im.OXInstantMessagingManager;
import org.jivesoftware.smackx.pubsub.PubSubException; import org.jivesoftware.smackx.pubsub.PubSubException;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.connection.MercuryConnection;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.data.repository.Repositories; import org.mercury_im.messenger.core.data.repository.Repositories;
import org.mercury_im.messenger.core.store.crypto.MercuryOpenPgpStore; import org.mercury_im.messenger.core.store.crypto.MercuryOpenPgpStore;
import org.mercury_im.messenger.core.store.message.MercuryMessageStore; import org.mercury_im.messenger.core.store.message.MercuryMessageStore;
import org.mercury_im.messenger.core.xmpp.MercuryConnection;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -56,14 +56,14 @@ public class MercuryOpenPgpManager {
} }
private void setup(MercuryConnection connection) { private void setup(MercuryConnection connection) {
final String temporaryFixedTestingPassword = "71ZA-Y416-UA7A-7NCE-3SNM-88EF";
OpenPgpStore store = new MercuryOpenPgpStore(connection.getAccountId(), openPgpRepository, schedulers); OpenPgpStore store = new MercuryOpenPgpStore(connection.getAccountId(), openPgpRepository, schedulers);
OpenPgpProvider provider = new PainlessOpenPgpProvider(store); OpenPgpProvider provider = new PainlessOpenPgpProvider(store);
OpenPgpManager oxManager = OpenPgpManager.getInstanceFor(connection.getConnection()); OpenPgpManager oxManager = OpenPgpManager.getInstanceFor(connection.getConnection());
oxManager.setOpenPgpProvider(provider); oxManager.setOpenPgpProvider(provider);
SecretKeyBackupHelper.setBackupCodeGenerator( SecretKeyBackupHelper.setBackupCodeGenerator(
// TODO: REMOVE IN PRODUCTION!!! // TODO: REMOVE IN PRODUCTION!!!
() -> "71ZA-Y416-UA7A-7NCE-3SNM-88EF" () -> temporaryFixedTestingPassword);
);
try { try {
boolean mustGenerate = false; boolean mustGenerate = false;
if (!oxManager.hasSecretKeysAvailable()) { if (!oxManager.hasSecretKeysAvailable()) {
@ -71,9 +71,7 @@ public class MercuryOpenPgpManager {
if (OpenPgpManager.serverSupportsSecretKeyBackups(connection.getConnection())) { if (OpenPgpManager.serverSupportsSecretKeyBackups(connection.getConnection())) {
try { try {
oxManager.restoreSecretKeyServerBackup( oxManager.restoreSecretKeyServerBackup(
//() -> "RW8X-367S-A2C3-QYAL-VG6E-Z2IM"); () -> temporaryFixedTestingPassword);
//() -> "KISJ-5Z1T-FGDW-WMDK-SC2U-SQUA");
() -> "71ZA-Y416-UA7A-7NCE-3SNM-88EF");
mustGenerate = false; mustGenerate = false;
LOGGER.log(Level.INFO, "Successfully restored secret key backup!"); LOGGER.log(Level.INFO, "Successfully restored secret key backup!");
} catch (NoBackupFoundException | PubSubException.NotALeafNodeException | InvalidBackupCodeException e) { } catch (NoBackupFoundException | PubSubException.NotALeafNodeException | InvalidBackupCodeException e) {

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.core.data.repository; package org.mercury_im.messenger.core.data.repository;
import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.entity.Account;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;

View File

@ -1,8 +1,8 @@
package org.mercury_im.messenger.core.data.repository; package org.mercury_im.messenger.core.data.repository;
import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.entity.chat.GroupChat; import org.mercury_im.messenger.entity.chat.GroupChat;
import org.mercury_im.messenger.core.util.Optional;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;

View File

@ -5,7 +5,6 @@ import org.mercury_im.messenger.entity.chat.GroupChat;
import org.mercury_im.messenger.entity.message.Message; import org.mercury_im.messenger.entity.message.Message;
import java.util.List; import java.util.List;
import java.util.UUID;
import io.reactivex.Completable; import io.reactivex.Completable;
import io.reactivex.Observable; import io.reactivex.Observable;

View File

@ -1,8 +1,8 @@
package org.mercury_im.messenger.core.di.component; package org.mercury_im.messenger.core.di.component;
import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel; import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel;
import org.mercury_im.messenger.core.viewmodel.account.list.AccountListViewModel; import org.mercury_im.messenger.core.viewmodel.account.list.AccountListViewModel;
import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
import org.mercury_im.messenger.core.viewmodel.chat.ChatViewModel; import org.mercury_im.messenger.core.viewmodel.chat.ChatViewModel;
import org.mercury_im.messenger.core.viewmodel.openpgp.OxSecretKeyBackupRestoreViewModel; import org.mercury_im.messenger.core.viewmodel.openpgp.OxSecretKeyBackupRestoreViewModel;

View File

@ -2,18 +2,17 @@ package org.mercury_im.messenger.core.di.module;
import org.mercury_im.messenger.core.Messenger; import org.mercury_im.messenger.core.Messenger;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
import org.mercury_im.messenger.core.data.repository.AccountRepository; import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository; import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.data.repository.MessageRepository; import org.mercury_im.messenger.core.data.repository.MessageRepository;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository; import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.data.repository.Repositories; import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel; import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel;
import org.mercury_im.messenger.core.viewmodel.account.list.AccountListViewModel; import org.mercury_im.messenger.core.viewmodel.account.list.AccountListViewModel;
import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
import org.mercury_im.messenger.core.viewmodel.chat.ChatListViewModel; import org.mercury_im.messenger.core.viewmodel.chat.ChatListViewModel;
import org.mercury_im.messenger.core.viewmodel.chat.ChatViewModel; import org.mercury_im.messenger.core.viewmodel.chat.ChatViewModel;
import org.mercury_im.messenger.core.xmpp.MercuryConnectionManager;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -42,10 +41,11 @@ public class ViewModelModule {
@Provides @Provides
@Singleton @Singleton
static AccountDetailsViewModel provideAccountDetailsViewModel(OpenPgpRepository openPgpRepository, static AccountDetailsViewModel provideAccountDetailsViewModel(MercuryConnectionManager connectionManager,
OpenPgpRepository openPgpRepository,
AccountRepository accountRepository, AccountRepository accountRepository,
SchedulersFacade schedulers) { SchedulersFacade schedulers) {
return new AccountDetailsViewModel(openPgpRepository, accountRepository, schedulers); return new AccountDetailsViewModel(connectionManager, openPgpRepository, accountRepository, schedulers);
} }
@Provides @Provides
@ -60,8 +60,8 @@ public class ViewModelModule {
@Provides @Provides
@Singleton @Singleton
static ChatListViewModel provideChatListViewModel(DirectChatRepository directChatRepository, SchedulersFacade schedulers) { static ChatListViewModel provideChatListViewModel(DirectChatRepository directChatRepository) {
return new ChatListViewModel(directChatRepository, schedulers); return new ChatListViewModel(directChatRepository);
} }
/* /*

View File

@ -1,7 +1,7 @@
package org.mercury_im.messenger.core.di.module; package org.mercury_im.messenger.core.di.module;
import org.mercury_im.messenger.core.xmpp.XmppConnectionFactory; import org.mercury_im.messenger.core.connection.XmppConnectionFactory;
import org.mercury_im.messenger.core.xmpp.XmppTcpConnectionFactory; import org.mercury_im.messenger.core.connection.XmppTcpConnectionFactory;
import javax.inject.Singleton; import javax.inject.Singleton;

View File

@ -1,8 +0,0 @@
package org.mercury_im.messenger.core.exception;
public class IllegalUsernameException extends RuntimeException {
public IllegalUsernameException(Throwable cause) {
super(cause);
}
}

View File

@ -1,9 +0,0 @@
package org.mercury_im.messenger.core.logging;
public class Tags {
public static final String TAG_XMPP = "MercuryXMPP";
public static final String TAG_DB = "MercuryDB";
public static final String TAG_ANDROID = "MercuryAndroid";
public static final String TAG_DOMAIN = "MercuryDomain";
}

View File

@ -7,7 +7,6 @@ import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.data.repository.EntityCapsRepository; import org.mercury_im.messenger.core.data.repository.EntityCapsRepository;
import org.mercury_im.messenger.entity.caps.EntityCapsRecord; import org.mercury_im.messenger.entity.caps.EntityCapsRecord;
import org.mercury_im.messenger.core.logging.Tags;
import java.io.StringReader; import java.io.StringReader;
import java.util.logging.Level; import java.util.logging.Level;
@ -21,7 +20,7 @@ import io.reactivex.disposables.CompositeDisposable;
@Singleton @Singleton
public class MercuryEntityCapsStore implements EntityCapsPersistentCache { public class MercuryEntityCapsStore implements EntityCapsPersistentCache {
private static final Logger LOGGER = Logger.getLogger(Tags.TAG_DOMAIN); private static final Logger LOGGER = Logger.getLogger(MercuryEntityCapsStore.class.getName());
private final CompositeDisposable disposable = new CompositeDisposable(); private final CompositeDisposable disposable = new CompositeDisposable();
private final EntityCapsRepository repository; private final EntityCapsRepository repository;

View File

@ -10,9 +10,9 @@ import org.jivesoftware.smack.roster.SubscribeListener;
import org.jxmpp.jid.BareJid; import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.FullJid; import org.jxmpp.jid.FullJid;
import org.jxmpp.jid.Jid; import org.jxmpp.jid.Jid;
import org.mercury_im.messenger.core.connection.MercuryConnection;
import org.mercury_im.messenger.core.store.roster.MercuryRosterStore; import org.mercury_im.messenger.core.store.roster.MercuryRosterStore;
import org.mercury_im.messenger.core.store.roster.MercuryRosterStoreFactory; import org.mercury_im.messenger.core.store.roster.MercuryRosterStoreFactory;
import org.mercury_im.messenger.core.xmpp.MercuryConnection;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;

View File

@ -7,13 +7,13 @@ import org.jxmpp.stringprep.XmppStringprepException;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.account.error.PasswordError; import org.mercury_im.messenger.core.account.error.PasswordError;
import org.mercury_im.messenger.core.account.error.UsernameError; 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.data.repository.AccountRepository; import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.MercuryViewModel; import org.mercury_im.messenger.core.viewmodel.MercuryViewModel;
import org.mercury_im.messenger.core.xmpp.MercuryConnection;
import org.mercury_im.messenger.core.xmpp.MercuryConnectionManager;
import org.mercury_im.messenger.core.xmpp.exception.InvalidCredentialsException;
import org.mercury_im.messenger.core.xmpp.exception.ServerUnreachableException;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import java.util.logging.Logger; import java.util.logging.Logger;

View File

@ -1,8 +1,16 @@
package org.mercury_im.messenger.core.viewmodel.account.detail; package org.mercury_im.messenger.core.viewmodel.account.detail;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smackx.ox.element.PublicKeysListElement;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore; import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore;
import org.jivesoftware.smackx.ox.util.OpenPgpPubSubUtil;
import org.jivesoftware.smackx.pep.PepManager;
import org.jivesoftware.smackx.pubsub.LeafNode;
import org.jivesoftware.smackx.pubsub.PayloadItem;
import org.jivesoftware.smackx.pubsub.PubSubManager;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
import org.mercury_im.messenger.core.data.repository.AccountRepository; import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
@ -15,16 +23,24 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.inject.Inject;
import io.reactivex.Completable;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.Single; import io.reactivex.Single;
import static org.jivesoftware.smackx.ox.util.OpenPgpPubSubUtil.PEP_NODE_PUBLIC_KEYS;
public class AccountDetailsViewModel implements MercuryViewModel { public class AccountDetailsViewModel implements MercuryViewModel {
private MercuryConnectionManager connectionManager;
private final OpenPgpRepository openPgpRepository; private final OpenPgpRepository openPgpRepository;
private final AccountRepository accountRepository; private final AccountRepository accountRepository;
private final SchedulersFacade schedulers; private final SchedulersFacade schedulers;
public AccountDetailsViewModel(OpenPgpRepository openPgpRepository, AccountRepository accountRepository, SchedulersFacade schedulers) { @Inject
public AccountDetailsViewModel(MercuryConnectionManager connectionManager, OpenPgpRepository openPgpRepository, AccountRepository accountRepository, SchedulersFacade schedulers) {
this.connectionManager = connectionManager;
this.openPgpRepository = openPgpRepository; this.openPgpRepository = openPgpRepository;
this.accountRepository = accountRepository; this.accountRepository = accountRepository;
this.schedulers = schedulers; this.schedulers = schedulers;
@ -64,4 +80,37 @@ public class AccountDetailsViewModel implements MercuryViewModel {
return remoteFingerprints; return remoteFingerprints;
}))); })));
} }
public Completable unpublishPublicKey(UUID accountId, OpenPgpV4Fingerprint fingerprint) {
return deletePublicKeyNode(accountId, fingerprint)
.andThen(removePublicKeyFromPubKeyList(accountId, fingerprint));
}
private Completable removePublicKeyFromPubKeyList(UUID accountId, OpenPgpV4Fingerprint fingerprint) {
return Completable.fromAction(() -> {
XMPPConnection xmppConnection = connectionManager.getConnection(accountId).getConnection();
PepManager pepManager = PepManager.getInstanceFor(xmppConnection);
PubSubManager pubSubManager = pepManager.getPepPubSubManager();
PublicKeysListElement publishedKeys = OpenPgpPubSubUtil.fetchPubkeysList(xmppConnection);
PublicKeysListElement.Builder builder = PublicKeysListElement.builder();
for (PublicKeysListElement.PubkeyMetadataElement meta : publishedKeys.getMetadata().values()) {
if (meta.getV4Fingerprint().equals(fingerprint)) {
continue;
}
builder.addMetadata(meta);
}
publishedKeys = builder.build();
LeafNode metadataNode = pubSubManager.getOrCreateLeafNode(PEP_NODE_PUBLIC_KEYS);
metadataNode.publish(new PayloadItem<>(publishedKeys));
});
}
private Completable deletePublicKeyNode(UUID accountId, OpenPgpV4Fingerprint fingerprint) {
return Completable.fromAction(() -> {
XMPPConnection xmppConnection = connectionManager.getConnection(accountId).getConnection();
PepManager pepManager = PepManager.getInstanceFor(xmppConnection);
OpenPgpPubSubUtil.deletePublicKeyNode(pepManager, fingerprint);
});
}
} }

View File

@ -2,12 +2,12 @@ package org.mercury_im.messenger.core.viewmodel.account.list;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
import org.mercury_im.messenger.core.connection.state.ConnectionPoolState;
import org.mercury_im.messenger.core.connection.state.ConnectionState;
import org.mercury_im.messenger.core.data.repository.AccountRepository; import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.viewmodel.MercuryViewModel; 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.mercury_im.messenger.entity.Account;
import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.key.OpenPgpV4Fingerprint;

View File

@ -1,6 +1,6 @@
package org.mercury_im.messenger.core.viewmodel.account.list; package org.mercury_im.messenger.core.viewmodel.account.list;
import org.mercury_im.messenger.core.xmpp.state.ConnectivityState; import org.mercury_im.messenger.core.connection.state.ConnectivityState;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.key.OpenPgpV4Fingerprint;

View File

@ -1,6 +1,5 @@
package org.mercury_im.messenger.core.viewmodel.chat; package org.mercury_im.messenger.core.viewmodel.chat;
import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository; import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.viewmodel.MercuryViewModel; import org.mercury_im.messenger.core.viewmodel.MercuryViewModel;
import org.mercury_im.messenger.entity.chat.DirectChat; import org.mercury_im.messenger.entity.chat.DirectChat;
@ -14,15 +13,13 @@ import io.reactivex.subjects.BehaviorSubject;
public class ChatListViewModel implements MercuryViewModel { public class ChatListViewModel implements MercuryViewModel {
private final SchedulersFacade schedulers;
private final DirectChatRepository directChatRepository; private final DirectChatRepository directChatRepository;
private final BehaviorSubject<Observable<List<DirectChat>>> chatSourceObservable; private final BehaviorSubject<Observable<List<DirectChat>>> chatSourceObservable;
@Inject @Inject
public ChatListViewModel(DirectChatRepository directChatRepository, SchedulersFacade schedulers) { public ChatListViewModel(DirectChatRepository directChatRepository) {
this.directChatRepository = directChatRepository; this.directChatRepository = directChatRepository;
this.schedulers = schedulers;
chatSourceObservable = BehaviorSubject.createDefault(directChatRepository.observeAllDirectChats()); chatSourceObservable = BehaviorSubject.createDefault(directChatRepository.observeAllDirectChats());
} }

View File

@ -6,8 +6,6 @@ import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository; import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.data.repository.MessageRepository; import org.mercury_im.messenger.core.data.repository.MessageRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository; import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.data.repository.Repositories;
import org.mercury_im.messenger.core.store.message.MercuryMessageStore;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.MercuryViewModel; import org.mercury_im.messenger.core.viewmodel.MercuryViewModel;
import org.mercury_im.messenger.entity.chat.DirectChat; import org.mercury_im.messenger.entity.chat.DirectChat;

View File

@ -1,8 +0,0 @@
package org.mercury_im.messenger.core.xmpp.state;
public enum ConnectivityState {
disconnected,
connecting,
connected,
disconnecting
}