Temp
This commit is contained in:
parent
d80099b2cf
commit
41b116719f
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/classes" />
|
||||
</component>
|
||||
</project>
|
|
@ -2,7 +2,6 @@ package org.mercury_im.messenger.di.component;
|
|||
|
||||
import org.mercury_im.messenger.MercuryImApplication;
|
||||
import org.mercury_im.messenger.di.module.AppModule;
|
||||
import org.mercury_im.messenger.handler.AvatarHandler;
|
||||
import org.mercury_im.messenger.handler.RoomPlainMessageHandler;
|
||||
import org.mercury_im.messenger.persistence.room.RoomModule;
|
||||
import org.mercury_im.messenger.service.XmppConnectionService;
|
||||
|
@ -71,6 +70,4 @@ public interface AppComponent {
|
|||
// Connectors
|
||||
|
||||
void inject(RoomPlainMessageHandler messageHandler);
|
||||
|
||||
void inject(AvatarHandler avatarHandler);
|
||||
}
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
package org.mercury_im.messenger.handler;
|
||||
|
||||
import org.jivesoftware.smackx.avatar.UserAvatarManager;
|
||||
import org.jivesoftware.smackx.avatar.element.MetadataExtension;
|
||||
import org.jivesoftware.smackx.avatar.listener.AvatarListener;
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.MercuryImApplication;
|
||||
import org.mercury_im.messenger.persistence.repository.AvatarRepository;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomAvatarModel;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class AvatarHandler implements AvatarListener {
|
||||
|
||||
private final long accountId;
|
||||
|
||||
@Inject
|
||||
AvatarRepository avatarRepository;
|
||||
|
||||
private UserAvatarManager avatarManager;
|
||||
|
||||
public AvatarHandler(long accountId, UserAvatarManager avatarManager) {
|
||||
this.accountId = accountId;
|
||||
this.avatarManager = avatarManager;
|
||||
|
||||
MercuryImApplication.getApplication().getAppComponent().inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAvatarUpdateReceived(EntityBareJid user, MetadataExtension metadata) {
|
||||
|
||||
}
|
||||
}
|
|
@ -29,7 +29,6 @@ public class RoomPlainMessageHandler implements PlainMessageHandler {
|
|||
|
||||
public RoomPlainMessageHandler(long accountId) {
|
||||
this.accountId = accountId;
|
||||
|
||||
MercuryImApplication.getApplication().getAppComponent().inject(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ import android.view.MenuItem;
|
|||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
|
@ -14,6 +15,7 @@ import org.mercury_im.messenger.MercuryImApplication;
|
|||
import org.mercury_im.messenger.R;
|
||||
import org.mercury_im.messenger.ui.login.AccountsActivity;
|
||||
import org.mercury_im.messenger.ui.login.LoginActivity;
|
||||
import org.mercury_im.messenger.ui.roster.RosterFragment;
|
||||
import org.mercury_im.messenger.ui.settings.SettingsActivity;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
@ -27,6 +29,11 @@ public class MainActivity extends AppCompatActivity {
|
|||
|
||||
MercuryImApplication.getApplication().getAppComponent().inject(this);
|
||||
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
fm.beginTransaction()
|
||||
.replace(R.id.fragment, new RosterFragment())
|
||||
.commit();
|
||||
|
||||
FloatingActionButton fab = findViewById(R.id.fab);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,15 @@
|
|||
package org.mercury_im.messenger;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.mercury_im.messenger.core.ConnectionState;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.observers.TestObserver;
|
||||
import io.reactivex.schedulers.TestScheduler;
|
||||
import io.reactivex.subjects.BehaviorSubject;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
|
@ -14,4 +21,16 @@ public class ExampleUnitTest {
|
|||
public void addition_isCorrect() {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
TestScheduler testScheduler = new TestScheduler();
|
||||
BehaviorSubject<ConnectionState> state = BehaviorSubject.createDefault(ConnectionState.DISCONNECTED);
|
||||
TestObserver<ConnectionState> observable = state.test();
|
||||
assertEquals(ConnectionState.DISCONNECTED, state.getValue());
|
||||
state.onNext(ConnectionState.CONNECTING);
|
||||
assertEquals(ConnectionState.CONNECTING, state.getValue());
|
||||
observable.assertValues(ConnectionState.DISCONNECTED, ConnectionState.CONNECTING).dispose();
|
||||
}
|
||||
}
|
|
@ -9,9 +9,13 @@ import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
|||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
@ -23,6 +27,8 @@ import io.reactivex.schedulers.Schedulers;
|
|||
@Singleton
|
||||
public class ConnectionCenter {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(ConnectionCenter.class.getName());
|
||||
|
||||
// Injected
|
||||
private final AccountRepository accountRepository;
|
||||
private final EntityCapsStore entityCapsStore;
|
||||
|
@ -38,10 +44,12 @@ public class ConnectionCenter {
|
|||
|
||||
@Inject
|
||||
public ConnectionCenter(EntityCapsStore capsStore, AccountRepository accountRepository) {
|
||||
LOGGER.log(Level.INFO, "ConnectionCenter initialized");
|
||||
this.accountRepository = accountRepository;
|
||||
this.entityCapsStore = capsStore;
|
||||
|
||||
EntityCapsManager.setPersistentCache(capsStore);
|
||||
startUp();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -62,12 +70,29 @@ public class ConnectionCenter {
|
|||
.observeOn(Schedulers.io())
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.subscribe((Consumer<List<? extends AccountModel>>) accounts -> {
|
||||
Set<Long> accountIds = new HashSet<>();
|
||||
// Add missing connections to the map
|
||||
for (AccountModel account : accounts) {
|
||||
accountIds.add(account.getId());
|
||||
if (connectionMap.get(account.getId()) != null) {
|
||||
continue;
|
||||
}
|
||||
MercuryConnection connection = createConnection(account);
|
||||
connectionMap.put(account.getId(), connection);
|
||||
|
||||
if (account.getEnabled()) {
|
||||
connection.connect();
|
||||
}
|
||||
}
|
||||
|
||||
// Remove unwanted connections from the map
|
||||
for (long connectionId : connectionMap.keySet()) {
|
||||
if (!accountIds.contains(connectionId)) {
|
||||
AbstractXMPPConnection con =
|
||||
(AbstractXMPPConnection) connectionMap.get(connectionId).getConnection();
|
||||
con.disconnect();
|
||||
connectionMap.remove(connectionId);
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -85,12 +110,13 @@ public class ConnectionCenter {
|
|||
}
|
||||
|
||||
public MercuryConnection createConnection(AccountModel accountModel) {
|
||||
LOGGER.log(Level.INFO, "Create Connection for " + accountModel.getJid().toString());
|
||||
XMPPTCPConnectionConfiguration configuration = XMPPTCPConnectionConfiguration.builder()
|
||||
.setHost(accountModel.getJid().getDomain().toString())
|
||||
.setXmppAddressAndPassword(accountModel.getJid(), accountModel.getPassword())
|
||||
.setConnectTimeout(2 * 60 * 1000)
|
||||
.setEnabledSSLCiphers(MercuryConfiguration.enabledCiphers)
|
||||
.setEnabledSSLProtocols(MercuryConfiguration.enabledProtocols)
|
||||
//.setEnabledSSLCiphers(MercuryConfiguration.enabledCiphers)
|
||||
//.setEnabledSSLProtocols(MercuryConfiguration.enabledProtocols)
|
||||
.build();
|
||||
|
||||
AbstractXMPPConnection tcpConnection = new XMPPTCPConnection(configuration);
|
||||
|
|
|
@ -21,10 +21,15 @@ public enum ConnectionState {
|
|||
|
||||
/**
|
||||
* The connection is successfully connected to the server and the stream has been initiated.
|
||||
* In this state the connection is ready to send and receive stanzas.
|
||||
*/
|
||||
CONNECTED,
|
||||
|
||||
/**
|
||||
* THe connection is authenticated.
|
||||
* In this state the connection is ready to send and receive stanzas.
|
||||
*/
|
||||
AUTHENTICATED,
|
||||
|
||||
/**
|
||||
* The connection is in the process of shutting down.
|
||||
*/
|
||||
|
|
|
@ -3,23 +3,25 @@ package org.mercury_im.messenger.core;
|
|||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
import org.jivesoftware.smack.ConnectionListener;
|
||||
import org.jivesoftware.smack.ReconnectionManager;
|
||||
import org.jivesoftware.smack.SmackException;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.XMPPException;
|
||||
import org.jivesoftware.smack.chat2.ChatManager;
|
||||
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
||||
import org.jivesoftware.smack.iqrequest.IQRequestHandler;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.Presence;
|
||||
import org.jivesoftware.smack.roster.Roster;
|
||||
import org.jivesoftware.smackx.caps.EntityCapsManager;
|
||||
import org.jivesoftware.smackx.carbons.CarbonManager;
|
||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;
|
||||
import org.jivesoftware.smackx.iqversion.VersionManager;
|
||||
import org.jivesoftware.smackx.iqversion.packet.Version;
|
||||
import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class MercuryConnection implements ConnectionListener {
|
||||
import io.reactivex.subjects.BehaviorSubject;
|
||||
|
||||
public class MercuryConnection {
|
||||
|
||||
public static final String TAG = "Mercury";
|
||||
|
||||
|
@ -35,9 +37,12 @@ public class MercuryConnection implements ConnectionListener {
|
|||
protected final StableUniqueStanzaIdManager stanzaIdManager;
|
||||
protected final ServiceDiscoveryManager serviceDiscoveryManager;
|
||||
|
||||
BehaviorSubject<ConnectionState> state = BehaviorSubject.createDefault(ConnectionState.DISCONNECTED);
|
||||
|
||||
|
||||
public MercuryConnection(AbstractXMPPConnection connection, long accountId) {
|
||||
this.connection = connection;
|
||||
connection.addConnectionListener(this);
|
||||
connection.addConnectionListener(connectionListener);
|
||||
this.accountId = accountId;
|
||||
|
||||
reconnectionManager = ReconnectionManager.getInstanceFor(connection);
|
||||
|
@ -55,6 +60,34 @@ public class MercuryConnection implements ConnectionListener {
|
|||
roster.setRosterLoadedAtLogin(true);
|
||||
}
|
||||
|
||||
public void connect() {
|
||||
LOGGER.log(Level.INFO, "Connecting...");
|
||||
state.onNext(ConnectionState.CONNECTING);
|
||||
AbstractXMPPConnection con = (AbstractXMPPConnection) getConnection();
|
||||
try {
|
||||
con.connect().login();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SmackException e) {
|
||||
e.printStackTrace();
|
||||
} catch (XMPPException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void disconnect() {
|
||||
AbstractXMPPConnection con = (AbstractXMPPConnection) getConnection();
|
||||
state.onNext(ConnectionState.DISCONNECTING);
|
||||
try {
|
||||
con.disconnect(new Presence(Presence.Type.unavailable));
|
||||
} catch (SmackException.NotConnectedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
state.onNext(ConnectionState.DISCONNECTED);
|
||||
}
|
||||
|
||||
public XMPPConnection getConnection() {
|
||||
return connection;
|
||||
}
|
||||
|
@ -73,31 +106,35 @@ public class MercuryConnection implements ConnectionListener {
|
|||
return roster;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connected(XMPPConnection connection) {
|
||||
LOGGER.info("Connection " + getAccountId() + " connected.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authenticated(XMPPConnection connection, boolean resumed) {
|
||||
LOGGER.info("Connection " + getAccountId() + " authenticated (" + (resumed ? "resumed" : "first time") + ")");
|
||||
if (connection == this.connection && !resumed) {
|
||||
LOGGER.info("Enabling carbons!");
|
||||
carbonManager.enableCarbonsAsync(exception -> {
|
||||
LOGGER.severe("Could not enable carbons for connection " + accountId + ": " + exception.getMessage());
|
||||
exception.printStackTrace();
|
||||
});
|
||||
private final ConnectionListener connectionListener = new ConnectionListener() {
|
||||
|
||||
@Override
|
||||
public void connected(XMPPConnection connection) {
|
||||
state.onNext(ConnectionState.CONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionClosed() {
|
||||
LOGGER.fine("Connection " + accountId + " closed.");
|
||||
}
|
||||
@Override
|
||||
public void authenticated(XMPPConnection connection, boolean resumed) {
|
||||
state.onNext(ConnectionState.AUTHENTICATED);
|
||||
LOGGER.info("Connection " + getAccountId() + " authenticated (" + (resumed ? "resumed" : "initially") + ")");
|
||||
if (!resumed) {
|
||||
LOGGER.info("Enabling carbons!");
|
||||
carbonManager.enableCarbonsAsync(exception -> {
|
||||
LOGGER.severe("Could not enable carbons for connection " + accountId + ": " + exception.getMessage());
|
||||
exception.printStackTrace();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionClosedOnError(Exception e) {
|
||||
LOGGER.severe("Connection " + accountId + " closed on error: " + e.getMessage());
|
||||
}
|
||||
@Override
|
||||
public void connectionClosed() {
|
||||
state.onNext(ConnectionState.DISCONNECTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connectionClosedOnError(Exception e) {
|
||||
state.onNext(ConnectionState.DISCONNECTED);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
package org.mercury_im.messenger.core;
|
||||
|
||||
import org.jivesoftware.smack.roster.packet.RosterPacket;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
import org.mercury_im.messenger.persistence.repository.ContactRepository;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.reactivex.MaybeObserver;
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.Scheduler;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.RosterStore {
|
||||
|
||||
private final ContactRepository contactRepository;
|
||||
|
||||
private long accountId;
|
||||
|
||||
@Inject
|
||||
public RosterStore(ContactRepository contactRepository) {
|
||||
this.contactRepository = contactRepository;
|
||||
|
||||
contactRepository.getAllContactsOfAccount(accountId)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(Schedulers.computation())
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
public void setAccountId(long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RosterPacket.Item> getEntries() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public RosterPacket.Item getEntry(Jid bareJid) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRosterVersion() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addEntry(RosterPacket.Item item, String version) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean resetEntries(Collection<RosterPacket.Item> items, String version) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeEntry(Jid bareJid, String version) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetStore() {
|
||||
|
||||
}
|
||||
|
||||
public RosterPacket.Item fromModel(ContactModel contactModel) {
|
||||
RosterPacket.Item item = new RosterPacket.Item(contactModel.getEntity().getJid(), contactModel.getContact().getRosterName());
|
||||
item.setItemType(convert(contactModel.getContact().getDirection()));
|
||||
item.setApproved(contactModel.getContact().isApproved());
|
||||
item.setSubscriptionPending(contactModel.getContact().isSubscriptionPending());
|
||||
return item;
|
||||
}
|
||||
|
||||
public ContactModel toModel(RosterPacket.Item item) {
|
||||
ContactModel contact = contactRepository.newContactModel();
|
||||
|
||||
ContactAttributes attributes = contactRepository.newAttributesModel();
|
||||
attributes.setRosterName(item.getName());
|
||||
attributes.setDirection(convert(item.getItemType()));
|
||||
attributes.setApproved(item.isApproved());
|
||||
attributes.setSubscriptionPending(item.isSubscriptionPending());
|
||||
|
||||
EntityModel entity = contactRepository.newEntityModel();
|
||||
entity.setJid(item.getJid().asEntityBareJidOrThrow());
|
||||
|
||||
contact.setContact(attributes);
|
||||
contact.setEntity(entity);
|
||||
|
||||
return contact;
|
||||
}
|
||||
|
||||
public ContactAttributes.DIRECTION convert(RosterPacket.ItemType type) {
|
||||
return ContactAttributes.DIRECTION.valueOf(type.toString());
|
||||
}
|
||||
|
||||
public RosterPacket.ItemType convert(ContactAttributes.DIRECTION direction) {
|
||||
return RosterPacket.ItemType.fromString(direction.toString());
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package org.mercury_im.messenger.core.di;
|
|||
|
||||
import org.mercury_im.messenger.core.ConnectionCenter;
|
||||
import org.mercury_im.messenger.core.EntityCapsStore;
|
||||
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||
import org.mercury_im.messenger.persistence.repository.EntityCapsRepository;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -15,8 +16,8 @@ public class CenterModule {
|
|||
|
||||
@Singleton
|
||||
@Provides
|
||||
static ConnectionCenter provideConnectionCenter(EntityCapsStore capsStore) {
|
||||
return new ConnectionCenter(capsStore);
|
||||
static ConnectionCenter provideConnectionCenter(EntityCapsStore capsStore, AccountRepository accountRepository) {
|
||||
return new ConnectionCenter(capsStore, accountRepository);
|
||||
}
|
||||
|
||||
@Singleton
|
||||
|
|
|
@ -1,19 +1,23 @@
|
|||
package org.mercury_im.messenger.persistence.room.dao;
|
||||
|
||||
import androidx.room.Dao;
|
||||
import androidx.room.Insert;
|
||||
import androidx.room.Query;
|
||||
import androidx.room.TypeConverters;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomEntityModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomRosterInformation;
|
||||
import org.mercury_im.messenger.persistence.room.type_converter.EntityBareJidConverter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
import static androidx.room.OnConflictStrategy.REPLACE;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.PREFIX;
|
||||
|
||||
@Dao
|
||||
|
@ -45,4 +49,13 @@ public interface ContactDao {
|
|||
"entities." + RoomEntityModel.KEY_AVATAR + " AS " + PREFIX + RoomEntityModel.KEY_AVATAR + " " +
|
||||
"FROM contacts INNER JOIN entities ON contacts.fk_entity_id = entities.pk_entity_id")
|
||||
Observable<List<RoomContactModel>> getAllContactAndEntities();
|
||||
|
||||
@Query("SELECT * FROM roster_information")
|
||||
Observable<List<RoomRosterInformation>> getAllRosterInformation();
|
||||
|
||||
@Query("SELECT * FROM roster_information WHERE pk_account_id = :accountId")
|
||||
Maybe<RoomRosterInformation> getRosterInformation(long accountId);
|
||||
|
||||
@Insert(onConflict = REPLACE)
|
||||
Completable insertRosterInformation(RoomRosterInformation information);
|
||||
}
|
||||
|
|
|
@ -26,8 +26,14 @@ public interface EntityCapsDao {
|
|||
Single<List<RoomEntityCapsModel>> getAllEntityCaps();
|
||||
|
||||
@Insert(onConflict = REPLACE)
|
||||
Completable insert(RoomEntityCapsModel... models);
|
||||
Completable insert(List<RoomEntityCapsModel> models);
|
||||
|
||||
@Insert(onConflict = REPLACE)
|
||||
Completable insert(RoomEntityCapsModel model);
|
||||
|
||||
@Delete
|
||||
Completable delete(RoomEntityCapsModel... models);
|
||||
Completable delete(List<RoomEntityCapsModel> models);
|
||||
|
||||
@Delete
|
||||
Completable delete(RoomEntityCapsModel model);
|
||||
}
|
||||
|
|
|
@ -6,8 +6,11 @@ import androidx.room.Entity;
|
|||
import androidx.room.ForeignKey;
|
||||
import androidx.room.Index;
|
||||
import androidx.room.PrimaryKey;
|
||||
import androidx.room.TypeConverter;
|
||||
import androidx.room.TypeConverters;
|
||||
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.room.type_converter.DirectionConverter;
|
||||
|
||||
import static androidx.room.ForeignKey.CASCADE;
|
||||
import static androidx.room.ForeignKey.RESTRICT;
|
||||
|
@ -40,6 +43,9 @@ public class RoomContactAttributes implements ContactAttributes {
|
|||
public static final String KEY_ENTITY_ID = "fk_entity_id";
|
||||
public static final String KEY_ROSTER_NAME = "rostername";
|
||||
public static final String KEY_NICKNAME = "nickname";
|
||||
public static final String KEY_DIRECTION = "direction";
|
||||
public static final String KEY_SUB_PENDING = "sub_pending";
|
||||
public static final String KEY_APPROVED = "approved";
|
||||
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = KEY_ID)
|
||||
|
@ -57,25 +63,15 @@ public class RoomContactAttributes implements ContactAttributes {
|
|||
@ColumnInfo(name = KEY_NICKNAME)
|
||||
private String nickname;
|
||||
|
||||
@Override
|
||||
public String getRosterName() {
|
||||
return rosterName;
|
||||
}
|
||||
@ColumnInfo(name = KEY_DIRECTION)
|
||||
@TypeConverters(DirectionConverter.class)
|
||||
private DIRECTION direction;
|
||||
|
||||
@Override
|
||||
public void setRosterName(String rosterName) {
|
||||
this.rosterName = rosterName;
|
||||
}
|
||||
@ColumnInfo(name = KEY_SUB_PENDING)
|
||||
private boolean subscriptionPending;
|
||||
|
||||
@Override
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
@ColumnInfo(name = KEY_APPROVED)
|
||||
private boolean approved;
|
||||
|
||||
@Override
|
||||
public long getId() {
|
||||
|
@ -106,4 +102,54 @@ public class RoomContactAttributes implements ContactAttributes {
|
|||
public void setEntityId(long id) {
|
||||
this.entityId = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRosterName() {
|
||||
return rosterName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRosterName(String rosterName) {
|
||||
this.rosterName = rosterName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DIRECTION getDirection() {
|
||||
return direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDirection(DIRECTION direction) {
|
||||
this.direction = direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSubscriptionPending() {
|
||||
return subscriptionPending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSubscriptionPending(boolean pending) {
|
||||
this.subscriptionPending = pending;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isApproved() {
|
||||
return approved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApproved(boolean approved) {
|
||||
this.approved = approved;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package org.mercury_im.messenger.persistence.room.model;
|
||||
|
||||
import androidx.room.ColumnInfo;
|
||||
import androidx.room.Entity;
|
||||
import androidx.room.Index;
|
||||
import androidx.room.PrimaryKey;
|
||||
|
||||
import org.mercury_im.messenger.persistence.model.RosterInformationModel;
|
||||
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomRosterInformation.KEY_ID;
|
||||
import static org.mercury_im.messenger.persistence.room.model.RoomRosterInformation.TABLE;
|
||||
|
||||
@Entity(tableName = TABLE, indices = {
|
||||
@Index(value = KEY_ID, unique = true)
|
||||
})
|
||||
public class RoomRosterInformation implements RosterInformationModel {
|
||||
|
||||
public static final String TABLE = "roster_information";
|
||||
public static final String KEY_ID = "pk_account_id";
|
||||
public static final String KEY_ROSTER_VERSION = "roster_version";
|
||||
|
||||
@PrimaryKey
|
||||
@ColumnInfo(name = KEY_ID)
|
||||
private long accountId;
|
||||
|
||||
@ColumnInfo(name = KEY_ROSTER_VERSION)
|
||||
private String rosterVersion;
|
||||
|
||||
@Override
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccountId(long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRosterVersion() {
|
||||
return rosterVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRosterVersion(String rosterVersion) {
|
||||
this.rosterVersion = rosterVersion;
|
||||
}
|
||||
}
|
|
@ -1,19 +1,25 @@
|
|||
package org.mercury_im.messenger.persistence.room.repository;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
import org.mercury_im.messenger.persistence.model.RosterInformationModel;
|
||||
import org.mercury_im.messenger.persistence.repository.ContactRepository;
|
||||
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomContactModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomEntityModel;
|
||||
import org.mercury_im.messenger.persistence.room.model.RoomRosterInformation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public class IContactRepository implements ContactRepository<RoomContactModel> {
|
||||
public class IContactRepository implements ContactRepository<RoomContactModel, RoomRosterInformation> {
|
||||
|
||||
private final ContactDao dao;
|
||||
|
||||
|
@ -27,6 +33,16 @@ public class IContactRepository implements ContactRepository<RoomContactModel> {
|
|||
return new RoomContactModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContactAttributes newAttributesModel() {
|
||||
return new RoomContactAttributes();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityModel newEntityModel() {
|
||||
return new RoomEntityModel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomContactModel> getContact(long accountId, EntityBareJid jid) {
|
||||
return dao.getContactAndEntity(accountId, jid);
|
||||
|
@ -46,4 +62,19 @@ public class IContactRepository implements ContactRepository<RoomContactModel> {
|
|||
public Observable<List<RoomContactModel>> getAllContacts() {
|
||||
return dao.getAllContactAndEntities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Observable<List<RoomRosterInformation>> getAllRosterInformation() {
|
||||
return dao.getAllRosterInformation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Completable insertRosterInformation(RoomRosterInformation rosterInfo) {
|
||||
return dao.insertRosterInformation(rosterInfo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Maybe<RoomRosterInformation> getRosterInformation(long accountId) {
|
||||
return dao.getRosterInformation(accountId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,12 +39,22 @@ public class IEntityCapsRepository implements EntityCapsRepository<RoomEntityCap
|
|||
}
|
||||
|
||||
@Override
|
||||
public Completable insertOrReplaceEntityCaps(RoomEntityCapsModel... entityCaps) {
|
||||
public Completable insertOrReplaceEntityCaps(List<RoomEntityCapsModel> entityCaps) {
|
||||
return dao.insert(entityCaps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Completable deleteOrReplaceEntityCaps(RoomEntityCapsModel... entityCaps) {
|
||||
public Completable insertOrReplaceEntityCaps(RoomEntityCapsModel entityCaps) {
|
||||
return dao.insert(entityCaps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Completable deleteOrReplaceEntityCaps(List<RoomEntityCapsModel> entityCaps) {
|
||||
return dao.delete(entityCaps);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Completable deleteOrReplaceEntityCaps(RoomEntityCapsModel entityCaps) {
|
||||
return dao.delete(entityCaps);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package org.mercury_im.messenger.persistence.room.type_converter;
|
||||
|
||||
import androidx.room.TypeConverter;
|
||||
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
|
||||
public class DirectionConverter {
|
||||
|
||||
@TypeConverter
|
||||
public static String toString(ContactAttributes.DIRECTION direction) {
|
||||
return direction.toString();
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
public static ContactAttributes.DIRECTION fromString(String string) {
|
||||
return ContactAttributes.DIRECTION.valueOf(string);
|
||||
}
|
||||
}
|
|
@ -21,4 +21,24 @@ public interface ContactAttributes {
|
|||
String getNickname();
|
||||
|
||||
void setNickname(String nickname);
|
||||
|
||||
DIRECTION getDirection();
|
||||
|
||||
void setDirection(DIRECTION direction);
|
||||
|
||||
boolean isSubscriptionPending();
|
||||
|
||||
void setSubscriptionPending(boolean pending);
|
||||
|
||||
boolean isApproved();
|
||||
|
||||
void setApproved(boolean approved);
|
||||
|
||||
enum DIRECTION {
|
||||
none,
|
||||
to,
|
||||
from,
|
||||
both,
|
||||
remove
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,5 +4,9 @@ public interface ContactModel<C extends ContactAttributes, E extends EntityModel
|
|||
|
||||
C getContact();
|
||||
|
||||
void setContact(C contact);
|
||||
|
||||
E getEntity();
|
||||
|
||||
void setEntity(E entity);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package org.mercury_im.messenger.persistence.model;
|
||||
|
||||
public interface RosterInformationModel {
|
||||
|
||||
long getAccountId();
|
||||
|
||||
void setAccountId(long accountId);
|
||||
|
||||
String getRosterVersion();
|
||||
|
||||
void setRosterVersion(String rosterVersion);
|
||||
}
|
|
@ -4,16 +4,22 @@ import org.jxmpp.jid.EntityBareJid;
|
|||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||
import org.mercury_im.messenger.persistence.model.ContactAttributes;
|
||||
import org.mercury_im.messenger.persistence.model.EntityModel;
|
||||
import org.mercury_im.messenger.persistence.model.RosterInformationModel;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Maybe;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public interface ContactRepository<CE extends ContactModel<? extends ContactAttributes, ? extends EntityModel>> {
|
||||
public interface ContactRepository<CE extends ContactModel<? extends ContactAttributes, ? extends EntityModel>, I extends RosterInformationModel> {
|
||||
|
||||
CE newContactModel();
|
||||
|
||||
ContactAttributes newAttributesModel();
|
||||
|
||||
EntityModel newEntityModel();
|
||||
|
||||
Maybe<CE> getContact(long accountId, EntityBareJid jid);
|
||||
|
||||
Maybe<CE> getContactForEntity(EntityModel entityModel);
|
||||
|
@ -21,4 +27,10 @@ public interface ContactRepository<CE extends ContactModel<? extends ContactAttr
|
|||
Observable<List<CE>> getAllContactsOfAccount(long accountId);
|
||||
|
||||
Observable<List<CE>> getAllContacts();
|
||||
|
||||
Observable<List<I>> getAllRosterInformation();
|
||||
|
||||
Maybe<I> getRosterInformation(long accountId);
|
||||
|
||||
Completable insertRosterInformation(I rosterInfo);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,11 @@ public interface EntityCapsRepository<E extends EntityCapsModel> {
|
|||
|
||||
Single<E> getEntityCapsForNodeVer(String nodeVer);
|
||||
|
||||
Completable insertOrReplaceEntityCaps(E... entityCaps);
|
||||
Completable insertOrReplaceEntityCaps(List<E> entityCaps);
|
||||
|
||||
Completable deleteOrReplaceEntityCaps(E... entityCaps);
|
||||
Completable insertOrReplaceEntityCaps(E entityCaps);
|
||||
|
||||
Completable deleteOrReplaceEntityCaps(List<E> entityCaps);
|
||||
|
||||
Completable deleteOrReplaceEntityCaps(E entityCaps);
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,2 @@
|
|||
Manifest-Version: 1.0
|
||||
|
Loading…
Reference in New Issue