From 6504170d5870425e147611d38495c84ba8a536a0 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sun, 22 Dec 2019 02:06:51 +0100 Subject: [PATCH] Fix duplicate contacts on rename --- .../messenger/ui/account/LoginViewModel.java | 53 ++++++++++--------- .../data/model/AbstractPeerModel.java | 5 +- .../data/repository/XmppPeerRepository.java | 11 ++-- .../messenger/store/MercuryRosterStore.java | 44 +++++++-------- .../messenger/usecase/AddAccount.java | 33 ++++++------ 5 files changed, 73 insertions(+), 73 deletions(-) diff --git a/app/src/main/java/org/mercury_im/messenger/ui/account/LoginViewModel.java b/app/src/main/java/org/mercury_im/messenger/ui/account/LoginViewModel.java index 9e21544..4e5e8ea 100644 --- a/app/src/main/java/org/mercury_im/messenger/ui/account/LoginViewModel.java +++ b/app/src/main/java/org/mercury_im/messenger/ui/account/LoginViewModel.java @@ -44,31 +44,30 @@ public class LoginViewModel extends AndroidViewModel { public void setUsername(String username) { if (username == null || username.isEmpty()) { + this.username = null; usernameError.setValue(new Error(getApplication().getResources().getString(R.string.error_field_required))); - this.username = null; - updateLoginEnabled(); - return; - } - - try { - this.username = JidCreate.entityBareFrom(username); - updateLoginEnabled(); - } catch (XmppStringprepException e) { - usernameError.setValue(new Error(getApplication().getResources().getString(R.string.error_invalid_username))); - this.username = null; - updateLoginEnabled(); + } else { + try { + this.username = JidCreate.entityBareFrom(username); + } catch (XmppStringprepException e) { + this.username = null; + usernameError.setValue(new Error(getApplication().getResources().getString(R.string.error_invalid_username))); + } } + updateLoginButtonState(); } public void setPassword(String password) { - this.password = password; - updateLoginEnabled(); if (password == null || password.isEmpty()) { + this.password = null; passwordError.setValue(new Error(getApplication().getResources().getString(R.string.error_field_required))); + } else { + this.password = password; } + updateLoginButtonState(); } - private void updateLoginEnabled() { + private void updateLoginButtonState() { loginButtonEnabled.setValue(username != null && !(password == null || password.isEmpty())); } @@ -81,15 +80,19 @@ public class LoginViewModel extends AndroidViewModel { disposable.add(messenger.addAccount() .setAddress(username.asEntityBareJidString()) .setPassword(password) - .loginAndStoreAccountIfSuccessful() + .execute() .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) - .doOnComplete(() -> loginCompleted.setValue(true)) - .doOnError(this::handleConnectionError) + .doOnComplete(this::signalLoginSuccessful) + .doOnError(this::signalLoginError) .subscribe()); } - private void handleConnectionError(Throwable error) { + private void signalLoginSuccessful() { + loginCompleted.setValue(true); + } + + private void signalLoginError(Throwable error) { if (error instanceof SASLErrorException) { passwordError.setValue(new Error(getApplication().getResources().getString(R.string.error_incorrect_password))); loginButtonEnabled.setValue(true); @@ -99,12 +102,6 @@ public class LoginViewModel extends AndroidViewModel { } } - @Override - protected void onCleared() { - super.onCleared(); - disposable.clear(); - } - public LiveData getPasswordError() { return passwordError; } @@ -121,6 +118,12 @@ public class LoginViewModel extends AndroidViewModel { return loginButtonEnabled; } + @Override + protected void onCleared() { + super.onCleared(); + disposable.clear(); + } + public static class Error { private String message; diff --git a/data/src/main/java/org/mercury_im/messenger/data/model/AbstractPeerModel.java b/data/src/main/java/org/mercury_im/messenger/data/model/AbstractPeerModel.java index 0029a06..5a4e13e 100644 --- a/data/src/main/java/org/mercury_im/messenger/data/model/AbstractPeerModel.java +++ b/data/src/main/java/org/mercury_im/messenger/data/model/AbstractPeerModel.java @@ -11,6 +11,7 @@ import io.requery.Convert; import io.requery.Entity; import io.requery.ForeignKey; import io.requery.Generated; +import io.requery.Index; import io.requery.Key; import io.requery.ManyToOne; import io.requery.Persistable; @@ -19,17 +20,19 @@ import io.requery.Table; import io.requery.converter.UUIDConverter; @Entity -@Table(name = "contacts") +@Table(name = "contacts", uniqueIndexes = "unique_address") public abstract class AbstractPeerModel implements Persistable { @Key @Convert(UUIDConverter.class) UUID id; + @Index("unique_address") @ManyToOne(cascade = CascadeAction.NONE) @ForeignKey(referencedColumn = "id") AccountModel account; + @Index("unique_address") @Column(nullable = false) String address; diff --git a/data/src/main/java/org/mercury_im/messenger/data/repository/XmppPeerRepository.java b/data/src/main/java/org/mercury_im/messenger/data/repository/XmppPeerRepository.java index f297825..bd3bb96 100644 --- a/data/src/main/java/org/mercury_im/messenger/data/repository/XmppPeerRepository.java +++ b/data/src/main/java/org/mercury_im/messenger/data/repository/XmppPeerRepository.java @@ -107,11 +107,11 @@ public class XmppPeerRepository public Single getOrCreatePeer(Account account, String address) { return getPeerByAddress(account, address) .switchIfEmpty(Single - .just(new IPeer(){ - { - setAccount(account); - setAddress(address); - } + .just(new IPeer()) + .map(peer -> { + peer.setAccount(account); + peer.setAddress(address); + return peer; }) .flatMap(this::insertPeer)) .subscribeOn(subscriberScheduler()) @@ -121,6 +121,7 @@ public class XmppPeerRepository @Override public Observable> observeAllPeers() { return data().select(PeerModel.class) + .orderBy(PeerModel.ADDRESS) .get().observableResult() .map(ResultDelegate::toList) .map(peerModels -> { diff --git a/domain/src/main/java/org/mercury_im/messenger/store/MercuryRosterStore.java b/domain/src/main/java/org/mercury_im/messenger/store/MercuryRosterStore.java index 71e94f2..c5b8ad5 100644 --- a/domain/src/main/java/org/mercury_im/messenger/store/MercuryRosterStore.java +++ b/domain/src/main/java/org/mercury_im/messenger/store/MercuryRosterStore.java @@ -7,7 +7,6 @@ import org.jxmpp.jid.impl.JidCreate; import org.mercury_im.messenger.data.repository.AccountRepository; import org.mercury_im.messenger.data.repository.PeerRepository; import org.mercury_im.messenger.entity.Account; -import org.mercury_im.messenger.entity.contact.IPeer; import org.mercury_im.messenger.entity.contact.Peer; import org.mercury_im.messenger.entity.contact.SubscriptionDirection; @@ -80,7 +79,7 @@ public class MercuryRosterStore implements RosterStore { @Override public RosterPacket.Item getEntry(Jid bareJid) { - return itemMap.get(bareJid); + return itemMap.get(bareJid.asUnescapedString()); } @Override @@ -90,27 +89,30 @@ public class MercuryRosterStore implements RosterStore { @Override public boolean addEntry(RosterPacket.Item item, String version) { - LOGGER.log(Level.INFO, "Add entry " + item.toXML().toString()); - // Update database - Peer contact = toEntity(item); - disposable.add(peerRepository.upsertPeer(contact) - .map(p -> { - LOGGER.log(Level.INFO, "Unserted Peer for account " + p.getAccount().getId()); - return p; - }) + writeEntryToDatabase(item); + writeRosterVersionToDatabase(version); + + return true; + } + + private void writeEntryToDatabase(RosterPacket.Item item) { + disposable.add(peerRepository.getOrCreatePeer(account, item.getJid().asUnescapedString()) + .map(peer -> toEntity(item, peer)) + .flatMap(peerRepository::updatePeer) .subscribe( success -> LOGGER.log(Level.FINE, "Upserted contact model " + success + " successfully"), - error -> LOGGER.log(Level.WARNING, "An error occurred upserting contact " + contact, error) + error -> LOGGER.log(Level.WARNING, "An error occurred upserting contact " + item.getJid().asUnescapedString(), error) )); - /* + } + + private void writeRosterVersionToDatabase(String version) { + /* disposable.add(peerRepository.updateRosterVersion(account, version) .subscribe( success -> LOGGER.log(Level.FINE, "Upserted roster version to " + rosterVersion + " successfully"), error -> LOGGER.log(Level.WARNING, "An error occurred upserting roster version", error) )); */ - - return true; } @Override @@ -119,16 +121,7 @@ public class MercuryRosterStore implements RosterStore { // Update database // TODO: Delete other contacts for (RosterPacket.Item item : items) { - Peer model = toEntity(item); - disposable.add(peerRepository.upsertPeer(model) - .map(p -> { - LOGGER.log(Level.INFO, "Unserted Peer for account " + p.getAccount().getId()); - return p; - }) - .subscribe( - success -> LOGGER.log(Level.FINE, "Upserted contact model " + success + " successfully"), - error -> LOGGER.log(Level.WARNING, "An error occurred upserting contact " + model, error) - )); + writeEntryToDatabase(item); } /* @@ -191,8 +184,7 @@ public class MercuryRosterStore implements RosterStore { return item; } - public Peer toEntity(RosterPacket.Item item) { - Peer peer = new IPeer(); + public Peer toEntity(RosterPacket.Item item, Peer peer) { peer.setAccount(account); peer.setAddress(item.getJid().asEntityBareJidOrThrow().asEntityBareJidString()); peer.setName(item.getName()); diff --git a/domain/src/main/java/org/mercury_im/messenger/usecase/AddAccount.java b/domain/src/main/java/org/mercury_im/messenger/usecase/AddAccount.java index 80d2d5c..8e3fc8c 100644 --- a/domain/src/main/java/org/mercury_im/messenger/usecase/AddAccount.java +++ b/domain/src/main/java/org/mercury_im/messenger/usecase/AddAccount.java @@ -23,6 +23,13 @@ public class AddAccount { private static final Logger LOGGER = Logger.getLogger(AddAccount.class.getName()); + public enum ConnectionResult { + success, + credential_error, + server_error, + other_error + } + private Account account; private MercuryConnection connection; @@ -42,22 +49,19 @@ public class AddAccount { return this; } - public boolean isAddressSet() { - return account.getAddress() != null; - } - public AddAccount setPassword(String password) { this.account.setPassword(password); return this; } - public boolean isPasswordSet() { - return account.getPassword() != null; + public Completable execute() { + return loginAndStoreAccountIfSuccessful(); } public Completable loginAndStoreAccountIfSuccessful() { - return login().andThen(insertEnabledAccountIntoDatabase()).ignoreElement() - .andThen(Completable.fromAction(() -> messenger.addConnection(connection))); + return logIntoAccount() + .andThen(insertEnabledAccountIntoDatabase()).ignoreElement() + .andThen(addConnectionToMessenger()); } private Single insertEnabledAccountIntoDatabase() { @@ -66,6 +70,10 @@ public class AddAccount { .map(this::updateAccount); } + private Completable addConnectionToMessenger() { + return Completable.fromAction(() -> messenger.addConnection(connection)); + } + private Account updateAccount(Account account) { this.account = account; updateAccountIdInConnection(account); @@ -78,7 +86,7 @@ public class AddAccount { } } - private Completable login() { + private Completable logIntoAccount() { return Completable.fromAction( () -> { getOrCreateConnection(); @@ -117,11 +125,4 @@ public class AddAccount { ((AbstractXMPPConnection) connection.getConnection()).connect().login(); } } - - public enum ConnectionResult { - success, - credential_error, - server_error, - other_error - } }