Fix duplicate contacts on rename

This commit is contained in:
Paul Schaub 2019-12-22 02:06:51 +01:00
parent 647695b081
commit 6504170d58
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
5 changed files with 73 additions and 73 deletions

View File

@ -44,31 +44,30 @@ public class LoginViewModel extends AndroidViewModel {
public void setUsername(String username) { public void setUsername(String username) {
if (username == null || username.isEmpty()) { if (username == null || username.isEmpty()) {
this.username = null;
usernameError.setValue(new Error(getApplication().getResources().getString(R.string.error_field_required))); usernameError.setValue(new Error(getApplication().getResources().getString(R.string.error_field_required)));
this.username = null; } else {
updateLoginEnabled(); try {
return; this.username = JidCreate.entityBareFrom(username);
} } catch (XmppStringprepException e) {
this.username = null;
try { usernameError.setValue(new Error(getApplication().getResources().getString(R.string.error_invalid_username)));
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();
} }
updateLoginButtonState();
} }
public void setPassword(String password) { public void setPassword(String password) {
this.password = password;
updateLoginEnabled();
if (password == null || password.isEmpty()) { if (password == null || password.isEmpty()) {
this.password = null;
passwordError.setValue(new Error(getApplication().getResources().getString(R.string.error_field_required))); 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())); loginButtonEnabled.setValue(username != null && !(password == null || password.isEmpty()));
} }
@ -81,15 +80,19 @@ public class LoginViewModel extends AndroidViewModel {
disposable.add(messenger.addAccount() disposable.add(messenger.addAccount()
.setAddress(username.asEntityBareJidString()) .setAddress(username.asEntityBareJidString())
.setPassword(password) .setPassword(password)
.loginAndStoreAccountIfSuccessful() .execute()
.subscribeOn(Schedulers.newThread()) .subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread()) .observeOn(AndroidSchedulers.mainThread())
.doOnComplete(() -> loginCompleted.setValue(true)) .doOnComplete(this::signalLoginSuccessful)
.doOnError(this::handleConnectionError) .doOnError(this::signalLoginError)
.subscribe()); .subscribe());
} }
private void handleConnectionError(Throwable error) { private void signalLoginSuccessful() {
loginCompleted.setValue(true);
}
private void signalLoginError(Throwable error) {
if (error instanceof SASLErrorException) { if (error instanceof SASLErrorException) {
passwordError.setValue(new Error(getApplication().getResources().getString(R.string.error_incorrect_password))); passwordError.setValue(new Error(getApplication().getResources().getString(R.string.error_incorrect_password)));
loginButtonEnabled.setValue(true); loginButtonEnabled.setValue(true);
@ -99,12 +102,6 @@ public class LoginViewModel extends AndroidViewModel {
} }
} }
@Override
protected void onCleared() {
super.onCleared();
disposable.clear();
}
public LiveData<Error> getPasswordError() { public LiveData<Error> getPasswordError() {
return passwordError; return passwordError;
} }
@ -121,6 +118,12 @@ public class LoginViewModel extends AndroidViewModel {
return loginButtonEnabled; return loginButtonEnabled;
} }
@Override
protected void onCleared() {
super.onCleared();
disposable.clear();
}
public static class Error { public static class Error {
private String message; private String message;

View File

@ -11,6 +11,7 @@ import io.requery.Convert;
import io.requery.Entity; import io.requery.Entity;
import io.requery.ForeignKey; import io.requery.ForeignKey;
import io.requery.Generated; import io.requery.Generated;
import io.requery.Index;
import io.requery.Key; import io.requery.Key;
import io.requery.ManyToOne; import io.requery.ManyToOne;
import io.requery.Persistable; import io.requery.Persistable;
@ -19,17 +20,19 @@ import io.requery.Table;
import io.requery.converter.UUIDConverter; import io.requery.converter.UUIDConverter;
@Entity @Entity
@Table(name = "contacts") @Table(name = "contacts", uniqueIndexes = "unique_address")
public abstract class AbstractPeerModel implements Persistable { public abstract class AbstractPeerModel implements Persistable {
@Key @Key
@Convert(UUIDConverter.class) @Convert(UUIDConverter.class)
UUID id; UUID id;
@Index("unique_address")
@ManyToOne(cascade = CascadeAction.NONE) @ManyToOne(cascade = CascadeAction.NONE)
@ForeignKey(referencedColumn = "id") @ForeignKey(referencedColumn = "id")
AccountModel account; AccountModel account;
@Index("unique_address")
@Column(nullable = false) @Column(nullable = false)
String address; String address;

View File

@ -107,11 +107,11 @@ public class XmppPeerRepository
public Single<Peer> getOrCreatePeer(Account account, String address) { public Single<Peer> getOrCreatePeer(Account account, String address) {
return getPeerByAddress(account, address) return getPeerByAddress(account, address)
.switchIfEmpty(Single .switchIfEmpty(Single
.just(new IPeer(){ .just(new IPeer())
{ .map(peer -> {
setAccount(account); peer.setAccount(account);
setAddress(address); peer.setAddress(address);
} return peer;
}) })
.flatMap(this::insertPeer)) .flatMap(this::insertPeer))
.subscribeOn(subscriberScheduler()) .subscribeOn(subscriberScheduler())
@ -121,6 +121,7 @@ public class XmppPeerRepository
@Override @Override
public Observable<List<Peer>> observeAllPeers() { public Observable<List<Peer>> observeAllPeers() {
return data().select(PeerModel.class) return data().select(PeerModel.class)
.orderBy(PeerModel.ADDRESS)
.get().observableResult() .get().observableResult()
.map(ResultDelegate::toList) .map(ResultDelegate::toList)
.map(peerModels -> { .map(peerModels -> {

View File

@ -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.AccountRepository;
import org.mercury_im.messenger.data.repository.PeerRepository; import org.mercury_im.messenger.data.repository.PeerRepository;
import org.mercury_im.messenger.entity.Account; 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.Peer;
import org.mercury_im.messenger.entity.contact.SubscriptionDirection; import org.mercury_im.messenger.entity.contact.SubscriptionDirection;
@ -80,7 +79,7 @@ public class MercuryRosterStore implements RosterStore {
@Override @Override
public RosterPacket.Item getEntry(Jid bareJid) { public RosterPacket.Item getEntry(Jid bareJid) {
return itemMap.get(bareJid); return itemMap.get(bareJid.asUnescapedString());
} }
@Override @Override
@ -90,27 +89,30 @@ public class MercuryRosterStore implements RosterStore {
@Override @Override
public boolean addEntry(RosterPacket.Item item, String version) { public boolean addEntry(RosterPacket.Item item, String version) {
LOGGER.log(Level.INFO, "Add entry " + item.toXML().toString()); writeEntryToDatabase(item);
// Update database writeRosterVersionToDatabase(version);
Peer contact = toEntity(item);
disposable.add(peerRepository.upsertPeer(contact) return true;
.map(p -> { }
LOGGER.log(Level.INFO, "Unserted Peer for account " + p.getAccount().getId());
return p; private void writeEntryToDatabase(RosterPacket.Item item) {
}) disposable.add(peerRepository.getOrCreatePeer(account, item.getJid().asUnescapedString())
.map(peer -> toEntity(item, peer))
.flatMap(peerRepository::updatePeer)
.subscribe( .subscribe(
success -> LOGGER.log(Level.FINE, "Upserted contact model " + success + " successfully"), 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) disposable.add(peerRepository.updateRosterVersion(account, version)
.subscribe( .subscribe(
success -> LOGGER.log(Level.FINE, "Upserted roster version to " + rosterVersion + " successfully"), success -> LOGGER.log(Level.FINE, "Upserted roster version to " + rosterVersion + " successfully"),
error -> LOGGER.log(Level.WARNING, "An error occurred upserting roster version", error) error -> LOGGER.log(Level.WARNING, "An error occurred upserting roster version", error)
)); ));
*/ */
return true;
} }
@Override @Override
@ -119,16 +121,7 @@ public class MercuryRosterStore implements RosterStore {
// Update database // Update database
// TODO: Delete other contacts // TODO: Delete other contacts
for (RosterPacket.Item item : items) { for (RosterPacket.Item item : items) {
Peer model = toEntity(item); writeEntryToDatabase(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)
));
} }
/* /*
@ -191,8 +184,7 @@ public class MercuryRosterStore implements RosterStore {
return item; return item;
} }
public Peer toEntity(RosterPacket.Item item) { public Peer toEntity(RosterPacket.Item item, Peer peer) {
Peer peer = new IPeer();
peer.setAccount(account); peer.setAccount(account);
peer.setAddress(item.getJid().asEntityBareJidOrThrow().asEntityBareJidString()); peer.setAddress(item.getJid().asEntityBareJidOrThrow().asEntityBareJidString());
peer.setName(item.getName()); peer.setName(item.getName());

View File

@ -23,6 +23,13 @@ public class AddAccount {
private static final Logger LOGGER = Logger.getLogger(AddAccount.class.getName()); private static final Logger LOGGER = Logger.getLogger(AddAccount.class.getName());
public enum ConnectionResult {
success,
credential_error,
server_error,
other_error
}
private Account account; private Account account;
private MercuryConnection connection; private MercuryConnection connection;
@ -42,22 +49,19 @@ public class AddAccount {
return this; return this;
} }
public boolean isAddressSet() {
return account.getAddress() != null;
}
public AddAccount setPassword(String password) { public AddAccount setPassword(String password) {
this.account.setPassword(password); this.account.setPassword(password);
return this; return this;
} }
public boolean isPasswordSet() { public Completable execute() {
return account.getPassword() != null; return loginAndStoreAccountIfSuccessful();
} }
public Completable loginAndStoreAccountIfSuccessful() { public Completable loginAndStoreAccountIfSuccessful() {
return login().andThen(insertEnabledAccountIntoDatabase()).ignoreElement() return logIntoAccount()
.andThen(Completable.fromAction(() -> messenger.addConnection(connection))); .andThen(insertEnabledAccountIntoDatabase()).ignoreElement()
.andThen(addConnectionToMessenger());
} }
private Single<Account> insertEnabledAccountIntoDatabase() { private Single<Account> insertEnabledAccountIntoDatabase() {
@ -66,6 +70,10 @@ public class AddAccount {
.map(this::updateAccount); .map(this::updateAccount);
} }
private Completable addConnectionToMessenger() {
return Completable.fromAction(() -> messenger.addConnection(connection));
}
private Account updateAccount(Account account) { private Account updateAccount(Account account) {
this.account = account; this.account = account;
updateAccountIdInConnection(account); updateAccountIdInConnection(account);
@ -78,7 +86,7 @@ public class AddAccount {
} }
} }
private Completable login() { private Completable logIntoAccount() {
return Completable.fromAction( return Completable.fromAction(
() -> { () -> {
getOrCreateConnection(); getOrCreateConnection();
@ -117,11 +125,4 @@ public class AddAccount {
((AbstractXMPPConnection) connection.getConnection()).connect().login(); ((AbstractXMPPConnection) connection.getConnection()).connect().login();
} }
} }
public enum ConnectionResult {
success,
credential_error,
server_error,
other_error
}
} }