Fix duplicate contacts on rename
This commit is contained in:
parent
647695b081
commit
6504170d58
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 -> {
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue