155 lines
5.6 KiB
Java
155 lines
5.6 KiB
Java
package org.mercury_im.messenger.core.viewmodel.account;
|
|
|
|
import org.jivesoftware.smack.util.StringUtils;
|
|
import org.jxmpp.jid.EntityBareJid;
|
|
import org.jxmpp.jid.impl.JidCreate;
|
|
import org.jxmpp.stringprep.XmppStringprepException;
|
|
import org.mercury_im.messenger.core.SchedulersFacade;
|
|
import org.mercury_im.messenger.core.account.error.PasswordError;
|
|
import org.mercury_im.messenger.core.account.error.UsernameError;
|
|
import org.mercury_im.messenger.core.data.repository.AccountRepository;
|
|
import org.mercury_im.messenger.core.util.Optional;
|
|
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 java.util.logging.Logger;
|
|
|
|
import javax.inject.Inject;
|
|
|
|
import io.reactivex.Observable;
|
|
import io.reactivex.subjects.BehaviorSubject;
|
|
|
|
public class LoginViewModel implements MercuryViewModel {
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(LoginViewModel.class.getName());
|
|
|
|
private final MercuryConnectionManager connectionManager;
|
|
private final AccountRepository accountRepository;
|
|
|
|
private final SchedulersFacade schedulers;
|
|
|
|
private BehaviorSubject<Optional<UsernameError>> loginUsernameError;
|
|
private BehaviorSubject<Optional<PasswordError>> loginPasswordError;
|
|
private BehaviorSubject<Boolean> isLoginPossible;
|
|
private BehaviorSubject<Boolean> isLoginSuccessful;
|
|
|
|
private EntityBareJid loginUsernameValue;
|
|
private String loginPasswordValue;
|
|
|
|
@Inject
|
|
public LoginViewModel(MercuryConnectionManager connectionManager,
|
|
AccountRepository accountRepository,
|
|
SchedulersFacade schedulers) {
|
|
this.connectionManager = connectionManager;
|
|
this.accountRepository = accountRepository;
|
|
this.schedulers = schedulers;
|
|
|
|
reset();
|
|
}
|
|
|
|
public void reset() {
|
|
loginUsernameError = BehaviorSubject.createDefault(new Optional<>());
|
|
loginPasswordError = BehaviorSubject.createDefault(new Optional<>());
|
|
isLoginPossible = BehaviorSubject.createDefault(false);
|
|
isLoginSuccessful = BehaviorSubject.createDefault(false);
|
|
|
|
loginUsernameValue = null;
|
|
loginPasswordValue = null;
|
|
}
|
|
|
|
public Observable<Optional<UsernameError>> getLoginUsernameError() {
|
|
return loginUsernameError;
|
|
}
|
|
|
|
public Observable<Optional<PasswordError>> getLoginPasswordError() {
|
|
return loginPasswordError;
|
|
}
|
|
|
|
public Observable<Boolean> isLoginPossible() {
|
|
return isLoginPossible;
|
|
}
|
|
|
|
public Observable<Boolean> isLoginSuccessful() {
|
|
return isLoginSuccessful;
|
|
}
|
|
|
|
public synchronized void onLoginUsernameChanged(String username) {
|
|
if (StringUtils.isNullOrEmpty(username)) {
|
|
loginUsernameValue = null;
|
|
loginUsernameError.onNext(new Optional<>(UsernameError.emptyUsername));
|
|
} else {
|
|
try {
|
|
loginUsernameValue = JidCreate.entityBareFrom(username);
|
|
loginUsernameError.onNext(new Optional<>());
|
|
} catch (XmppStringprepException e) {
|
|
loginUsernameValue = null;
|
|
loginUsernameError.onNext(new Optional<>(UsernameError.invalidUsername));
|
|
}
|
|
}
|
|
updateLoginPossible();
|
|
}
|
|
|
|
public synchronized void onLoginPasswordChanged(String password) {
|
|
if (StringUtils.isNullOrEmpty(password)) {
|
|
loginPasswordValue = null;
|
|
loginPasswordError.onNext(new Optional<>(PasswordError.emptyPassword));
|
|
} else {
|
|
loginPasswordValue = password;
|
|
loginPasswordError.onNext(new Optional<>());
|
|
}
|
|
updateLoginPossible();
|
|
}
|
|
|
|
private synchronized void updateLoginPossible() {
|
|
isLoginPossible.onNext(loginUsernameValue != null && loginPasswordValue != null);
|
|
}
|
|
|
|
public synchronized void login() {
|
|
if (!isLoginPossible.getValue()) {
|
|
// Prevent race condition where account would be logged in twice
|
|
return;
|
|
}
|
|
isLoginPossible.onNext(false);
|
|
|
|
Account account = createAccountEntity();
|
|
|
|
MercuryConnection connection = connectionManager.createConnection(account);
|
|
addDisposable(accountRepository.upsertAccount(account).ignoreElement()
|
|
.andThen(connection.connect())
|
|
.andThen(connection.login())
|
|
.andThen(connectionManager.registerConnection(connection))
|
|
.subscribeOn(schedulers.getNewThread())
|
|
.observeOn(schedulers.getUiScheduler())
|
|
.subscribe(
|
|
this::onLoginSuccessful,
|
|
this::onLoginFailed
|
|
));
|
|
}
|
|
|
|
private Account createAccountEntity() {
|
|
Account account = new Account();
|
|
account.setAddress(loginUsernameValue.asEntityBareJidString());
|
|
account.setPassword(loginPasswordValue);
|
|
account.setEnabled(true);
|
|
|
|
return account;
|
|
}
|
|
|
|
private void onLoginSuccessful() {
|
|
isLoginSuccessful.onNext(true);
|
|
}
|
|
|
|
private void onLoginFailed(Throwable error) {
|
|
isLoginPossible.onNext(true);
|
|
if (error instanceof InvalidCredentialsException) {
|
|
loginPasswordError.onNext(new Optional<>(PasswordError.incorrectPassword));
|
|
} else if (error instanceof ServerUnreachableException) {
|
|
loginUsernameError.onNext(new Optional<>(UsernameError.unreachableServer));
|
|
}
|
|
}
|
|
}
|