add AccountRepository
This commit is contained in:
parent
359ef330df
commit
d25cc059c5
|
@ -29,27 +29,36 @@
|
||||||
|
|
||||||
package eu.siacs.conversations.ui.util;
|
package eu.siacs.conversations.ui.util;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public class PendingItem<T> {
|
public class PendingItem<T> {
|
||||||
|
|
||||||
private T item = null;
|
private T item = null;
|
||||||
|
|
||||||
public synchronized void push(T item) {
|
public synchronized void push(T item) {
|
||||||
this.item = item;
|
this.item = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized T pop() {
|
public synchronized T pop() {
|
||||||
final T item = this.item;
|
final T item = this.item;
|
||||||
this.item = null;
|
this.item = null;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized T peek() {
|
public synchronized T peek() {
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized boolean clear() {
|
public synchronized T peekOrCreate(final Supplier<T> supplier) {
|
||||||
boolean notNull = this.item != null;
|
if (this.item == null) {
|
||||||
this.item = null;
|
this.item = supplier.get();
|
||||||
return notNull;
|
}
|
||||||
}
|
return this.item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized boolean clear() {
|
||||||
|
boolean notNull = this.item != null;
|
||||||
|
this.item = null;
|
||||||
|
return notNull;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package im.conversations.android.repository;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import im.conversations.android.database.ConversationsDatabase;
|
||||||
|
|
||||||
|
public abstract class AbstractRepository {
|
||||||
|
|
||||||
|
protected final Context context;
|
||||||
|
protected final ConversationsDatabase database;
|
||||||
|
|
||||||
|
protected AbstractRepository(final Context context) {
|
||||||
|
this.context = context;
|
||||||
|
this.database = ConversationsDatabase.getInstance(context);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package im.conversations.android.repository;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import eu.siacs.conversations.xmpp.Jid;
|
||||||
|
import im.conversations.android.IDs;
|
||||||
|
import im.conversations.android.database.CredentialStore;
|
||||||
|
import im.conversations.android.database.entity.AccountEntity;
|
||||||
|
import im.conversations.android.database.model.Account;
|
||||||
|
|
||||||
|
public class AccountRepository extends AbstractRepository {
|
||||||
|
|
||||||
|
public AccountRepository(final Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Account createAccount(@NonNull final Jid address, final String password) {
|
||||||
|
Preconditions.checkArgument(
|
||||||
|
address.isBareJid(), "Account should be specified without resource");
|
||||||
|
Preconditions.checkArgument(password != null, "Missing password");
|
||||||
|
final byte[] randomSeed = IDs.seed();
|
||||||
|
final var entity = new AccountEntity();
|
||||||
|
entity.address = address;
|
||||||
|
entity.enabled = true;
|
||||||
|
entity.randomSeed = randomSeed;
|
||||||
|
final long id = database.accountDao().insert(entity);
|
||||||
|
final var account = new Account(id, address, entity.randomSeed);
|
||||||
|
try {
|
||||||
|
CredentialStore.getInstance(context).setPassword(account, password);
|
||||||
|
} catch (final Exception e) {
|
||||||
|
throw new IllegalStateException("Could not store password", e);
|
||||||
|
}
|
||||||
|
return account;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package im.conversations.android.xmpp;
|
||||||
|
|
||||||
|
public class ConnectionException extends Exception {
|
||||||
|
|
||||||
|
private final ConnectionState connectionState;
|
||||||
|
|
||||||
|
public ConnectionException(ConnectionState state) {
|
||||||
|
this.connectionState = state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ import eu.siacs.conversations.persistance.FileBackend;
|
||||||
import eu.siacs.conversations.services.MemorizingTrustManager;
|
import eu.siacs.conversations.services.MemorizingTrustManager;
|
||||||
import eu.siacs.conversations.services.MessageArchiveService;
|
import eu.siacs.conversations.services.MessageArchiveService;
|
||||||
import eu.siacs.conversations.services.NotificationService;
|
import eu.siacs.conversations.services.NotificationService;
|
||||||
|
import eu.siacs.conversations.ui.util.PendingItem;
|
||||||
import eu.siacs.conversations.utils.Patterns;
|
import eu.siacs.conversations.utils.Patterns;
|
||||||
import eu.siacs.conversations.utils.PhoneHelper;
|
import eu.siacs.conversations.utils.PhoneHelper;
|
||||||
import eu.siacs.conversations.utils.Resolver;
|
import eu.siacs.conversations.utils.Resolver;
|
||||||
|
@ -160,6 +161,7 @@ public class XmppConnection implements Runnable {
|
||||||
private final Consumer<Jid> bindConsumer;
|
private final Consumer<Jid> bindConsumer;
|
||||||
private final ClassToInstanceMap<AbstractManager> managers;
|
private final ClassToInstanceMap<AbstractManager> managers;
|
||||||
private Consumer<XmppConnection> statusListener = null;
|
private Consumer<XmppConnection> statusListener = null;
|
||||||
|
private PendingItem<SettableFuture<XmppConnection>> connectedFuture = new PendingItem<>();
|
||||||
private SaslMechanism saslMechanism;
|
private SaslMechanism saslMechanism;
|
||||||
private HashedToken.Mechanism hashTokenRequest;
|
private HashedToken.Mechanism hashTokenRequest;
|
||||||
private HttpUrl redirectionUrl = null;
|
private HttpUrl redirectionUrl = null;
|
||||||
|
@ -244,6 +246,16 @@ public class XmppConnection implements Runnable {
|
||||||
if (nextStatus.isError() || nextStatus == ConnectionState.ONLINE) {
|
if (nextStatus.isError() || nextStatus == ConnectionState.ONLINE) {
|
||||||
this.recentErrorConnectionState = nextStatus;
|
this.recentErrorConnectionState = nextStatus;
|
||||||
}
|
}
|
||||||
|
if (nextStatus != ConnectionState.CONNECTING && nextStatus != ConnectionState.OFFLINE) {
|
||||||
|
final var future = this.connectedFuture.pop();
|
||||||
|
if (future != null) {
|
||||||
|
if (nextStatus == ConnectionState.ONLINE) {
|
||||||
|
future.set(this);
|
||||||
|
} else {
|
||||||
|
future.setException(new ConnectionException(nextStatus));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (statusListener != null) {
|
if (statusListener != null) {
|
||||||
statusListener.accept(this);
|
statusListener.accept(this);
|
||||||
|
@ -2225,6 +2237,15 @@ public class XmppConnection implements Runnable {
|
||||||
this.statusListener = listener;
|
this.statusListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ListenableFuture<XmppConnection> asConnectedFuture() {
|
||||||
|
synchronized (this) {
|
||||||
|
if (this.connectionState == ConnectionState.ONLINE) {
|
||||||
|
return Futures.immediateFuture(this);
|
||||||
|
}
|
||||||
|
return this.connectedFuture.peekOrCreate(SettableFuture::create);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void forceCloseSocket() {
|
private void forceCloseSocket() {
|
||||||
FileBackend.close(this.socket);
|
FileBackend.close(this.socket);
|
||||||
FileBackend.close(this.tagReader);
|
FileBackend.close(this.tagReader);
|
||||||
|
|
Loading…
Reference in a new issue