Fix message adapter
This commit is contained in:
parent
6efd8a1940
commit
d8076ddcac
|
@ -85,7 +85,7 @@ public class AndroidChatViewModel extends ViewModel implements MercuryAndroidVie
|
||||||
.doOnNext(m -> LOGGER.log(Level.INFO, "NEW MESSAGES."))
|
.doOnNext(m -> LOGGER.log(Level.INFO, "NEW MESSAGES."))
|
||||||
.subscribe(messageList -> {
|
.subscribe(messageList -> {
|
||||||
|
|
||||||
AndroidChatViewModel.this.messages.setValue(messageList);
|
AndroidChatViewModel.this.messages.postValue(messageList);
|
||||||
},
|
},
|
||||||
error -> LOGGER.log(Level.SEVERE, "Error subscribing to messages", error)));
|
error -> LOGGER.log(Level.SEVERE, "Error subscribing to messages", error)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,9 @@ public class ContactListViewModel extends ViewModel {
|
||||||
Log.d("ContactListViewModel", "Start observing database");
|
Log.d("ContactListViewModel", "Start observing database");
|
||||||
// Subscribe to changes to the contacts table and update the LiveData object for the UI.
|
// Subscribe to changes to the contacts table and update the LiveData object for the UI.
|
||||||
compositeDisposable.add(xmppContactRepository.observeAllPeers()
|
compositeDisposable.add(xmppContactRepository.observeAllPeers()
|
||||||
.subscribe(rosterEntryList::setValue));
|
.subscribe(rosterEntryList::postValue));
|
||||||
compositeDisposable.add(accountRepository.observeAllAccounts()
|
compositeDisposable.add(accountRepository.observeAllAccounts()
|
||||||
.subscribe(accounts::setValue));
|
.subscribe(accounts::postValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -37,6 +37,7 @@ allprojects {
|
||||||
// https://stackoverflow.com/questions/48488563/gradle-xpp3-error/48746294#48746294
|
// https://stackoverflow.com/questions/48488563/gradle-xpp3-error/48746294#48746294
|
||||||
all {
|
all {
|
||||||
exclude group: 'xpp3', module: 'xpp3_min'
|
exclude group: 'xpp3', module: 'xpp3_min'
|
||||||
|
exclude group: 'xpp3', module: 'xpp3'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,9 +4,7 @@ import org.mercury_im.messenger.data.mapping.AccountMapping;
|
||||||
import org.mercury_im.messenger.data.mapping.DirectChatMapping;
|
import org.mercury_im.messenger.data.mapping.DirectChatMapping;
|
||||||
import org.mercury_im.messenger.data.mapping.EntityCapsMapping;
|
import org.mercury_im.messenger.data.mapping.EntityCapsMapping;
|
||||||
import org.mercury_im.messenger.data.mapping.GroupChatMapping;
|
import org.mercury_im.messenger.data.mapping.GroupChatMapping;
|
||||||
import org.mercury_im.messenger.data.mapping.MessagePayloadMapping;
|
|
||||||
import org.mercury_im.messenger.data.mapping.MessageMapping;
|
import org.mercury_im.messenger.data.mapping.MessageMapping;
|
||||||
import org.mercury_im.messenger.data.mapping.MessagePayloadContainerMapping;
|
|
||||||
import org.mercury_im.messenger.data.mapping.PeerMapping;
|
import org.mercury_im.messenger.data.mapping.PeerMapping;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -44,19 +42,7 @@ public class MappingModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
static MessageMapping provideMessageMapping() {
|
static MessageMapping provideMessageMapping() {
|
||||||
return new MessageMapping(provideMessagePayloadMapping());
|
return new MessageMapping();
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
static MessagePayloadContainerMapping provideMessagePayloadMapping() {
|
|
||||||
return new MessagePayloadContainerMapping(provideMessageContentMapping());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Provides
|
|
||||||
@Singleton
|
|
||||||
static MessagePayloadMapping provideMessageContentMapping() {
|
|
||||||
return new MessagePayloadMapping();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
package org.mercury_im.messenger.data.mapping;
|
package org.mercury_im.messenger.data.mapping;
|
||||||
|
|
||||||
import org.mercury_im.messenger.data.model.MessageModel;
|
import org.mercury_im.messenger.data.model.MessageModel;
|
||||||
import org.mercury_im.messenger.data.model.MessagePayloadContainerModel;
|
|
||||||
import org.mercury_im.messenger.entity.message.Message;
|
import org.mercury_im.messenger.entity.message.Message;
|
||||||
import org.mercury_im.messenger.entity.message.PayloadContainer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
public class MessageMapping extends AbstractMapping<Message, MessageModel> {
|
public class MessageMapping extends AbstractMapping<Message, MessageModel> {
|
||||||
|
|
||||||
private final MessagePayloadContainerMapping messagePayloadContainerMapping;
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public MessageMapping(MessagePayloadContainerMapping messagePayloadContainerMapping) {
|
public MessageMapping() {
|
||||||
this.messagePayloadContainerMapping = messagePayloadContainerMapping;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
package org.mercury_im.messenger.data.mapping;
|
|
||||||
|
|
||||||
import org.mercury_im.messenger.data.model.MessagePayloadModel;
|
|
||||||
import org.mercury_im.messenger.data.model.MessagePayloadContainerModel;
|
|
||||||
import org.mercury_im.messenger.entity.message.PayloadContainer;
|
|
||||||
import org.mercury_im.messenger.entity.message.content.Payload;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
public class MessagePayloadContainerMapping extends AbstractMapping<PayloadContainer, MessagePayloadContainerModel> {
|
|
||||||
|
|
||||||
private final MessagePayloadMapping messagePayloadMapping;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
public MessagePayloadContainerMapping(MessagePayloadMapping messagePayloadMapping) {
|
|
||||||
this.messagePayloadMapping = messagePayloadMapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PayloadContainer newEntity(MessagePayloadContainerModel model) {
|
|
||||||
return new PayloadContainer();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MessagePayloadContainerModel newModel(PayloadContainer entity) {
|
|
||||||
return new MessagePayloadContainerModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MessagePayloadContainerModel mapToModel(PayloadContainer entity, MessagePayloadContainerModel model) {
|
|
||||||
model.getContents().clear();
|
|
||||||
for (Payload contentEntity : entity.getMessageContents()) {
|
|
||||||
MessagePayloadModel contentModel = messagePayloadMapping.toModel(contentEntity, new MessagePayloadModel());
|
|
||||||
contentModel.setPayloadContainer(model);
|
|
||||||
model.getContents().add(contentModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public PayloadContainer mapToEntity(MessagePayloadContainerModel model, PayloadContainer entity) {
|
|
||||||
entity.setId(model.getId());
|
|
||||||
|
|
||||||
List<Payload> contents = new ArrayList<>(model.getContents().size());
|
|
||||||
for (MessagePayloadModel contentModel : model.getContents()) {
|
|
||||||
Payload contentEntity = messagePayloadMapping.toEntity(contentModel, null);
|
|
||||||
contents.add(contentEntity);
|
|
||||||
}
|
|
||||||
entity.setMessageContents(contents);
|
|
||||||
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package org.mercury_im.messenger.data.mapping;
|
|
||||||
|
|
||||||
import org.mercury_im.messenger.data.model.MessagePayloadModel;
|
|
||||||
import org.mercury_im.messenger.entity.message.content.Payload;
|
|
||||||
import org.mercury_im.messenger.entity.message.content.TextPayload;
|
|
||||||
|
|
||||||
import static org.mercury_im.messenger.data.enums.MessageContentType.body;
|
|
||||||
|
|
||||||
public class MessagePayloadMapping extends AbstractMapping<Payload, MessagePayloadModel> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Payload newEntity(MessagePayloadModel model) {
|
|
||||||
switch (model.getType()) {
|
|
||||||
case body:
|
|
||||||
return new TextPayload();
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MessagePayloadModel newModel(Payload entity) {
|
|
||||||
return new MessagePayloadModel();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public MessagePayloadModel mapToModel(Payload entity, MessagePayloadModel model) {
|
|
||||||
if (entity instanceof TextPayload) {
|
|
||||||
model.setType(body);
|
|
||||||
model.setBody(((TextPayload) entity).getBody());
|
|
||||||
}
|
|
||||||
// else if (...)
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Payload mapToEntity(MessagePayloadModel model, Payload entity) {
|
|
||||||
entity.setId(model.getId());
|
|
||||||
switch (model.getType()) {
|
|
||||||
case body:
|
|
||||||
TextPayload body = (TextPayload) entity;
|
|
||||||
body.setBody(model.getBody());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
package org.mercury_im.messenger.data.model;
|
|
||||||
|
|
||||||
import io.requery.CascadeAction;
|
|
||||||
import io.requery.Entity;
|
|
||||||
import io.requery.ForeignKey;
|
|
||||||
import io.requery.Generated;
|
|
||||||
import io.requery.Key;
|
|
||||||
import io.requery.ManyToOne;
|
|
||||||
import io.requery.ReferentialAction;
|
|
||||||
import io.requery.Table;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "direct_messages")
|
|
||||||
public abstract class AbstractDirectMessagesRelation {
|
|
||||||
|
|
||||||
@Key @Generated
|
|
||||||
long id;
|
|
||||||
|
|
||||||
@ManyToOne(cascade = {CascadeAction.SAVE})
|
|
||||||
@ForeignKey(referencedColumn = "id", delete = ReferentialAction.CASCADE)
|
|
||||||
DirectChatModel chat;
|
|
||||||
|
|
||||||
@ManyToOne(cascade = {CascadeAction.SAVE, CascadeAction.DELETE})
|
|
||||||
@ForeignKey(referencedColumn = "id", delete = ReferentialAction.CASCADE)
|
|
||||||
MessageModel message;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package org.mercury_im.messenger.data.model;
|
|
||||||
|
|
||||||
import io.requery.CascadeAction;
|
|
||||||
import io.requery.Entity;
|
|
||||||
import io.requery.ForeignKey;
|
|
||||||
import io.requery.Generated;
|
|
||||||
import io.requery.Key;
|
|
||||||
import io.requery.ManyToOne;
|
|
||||||
import io.requery.OneToOne;
|
|
||||||
import io.requery.ReferentialAction;
|
|
||||||
import io.requery.Table;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "group_messages")
|
|
||||||
public abstract class AbstractGroupMessagesRelation {
|
|
||||||
|
|
||||||
@Key @Generated
|
|
||||||
long id;
|
|
||||||
|
|
||||||
@ManyToOne(cascade = {CascadeAction.SAVE})
|
|
||||||
@ForeignKey(referencedColumn = "id", delete = ReferentialAction.CASCADE)
|
|
||||||
GroupChatModel chat;
|
|
||||||
|
|
||||||
@ManyToOne(cascade = {CascadeAction.SAVE, CascadeAction.DELETE})
|
|
||||||
@ForeignKey(referencedColumn = "id", delete = ReferentialAction.CASCADE)
|
|
||||||
MessageModel message;
|
|
||||||
}
|
|
|
@ -2,17 +2,15 @@ package org.mercury_im.messenger.data.model;
|
||||||
|
|
||||||
import org.mercury_im.messenger.data.converter.MessageDirectionConverter;
|
import org.mercury_im.messenger.data.converter.MessageDirectionConverter;
|
||||||
import org.mercury_im.messenger.entity.message.MessageDirection;
|
import org.mercury_im.messenger.entity.message.MessageDirection;
|
||||||
|
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import io.requery.Column;
|
import io.requery.Column;
|
||||||
import io.requery.Convert;
|
import io.requery.Convert;
|
||||||
import io.requery.Entity;
|
import io.requery.Entity;
|
||||||
import io.requery.Generated;
|
|
||||||
import io.requery.Key;
|
import io.requery.Key;
|
||||||
import io.requery.OneToMany;
|
|
||||||
import io.requery.Persistable;
|
import io.requery.Persistable;
|
||||||
import io.requery.Table;
|
import io.requery.Table;
|
||||||
import io.requery.converter.UUIDConverter;
|
import io.requery.converter.UUIDConverter;
|
||||||
|
@ -25,6 +23,9 @@ public abstract class AbstractMessageModel implements Persistable {
|
||||||
@Convert(UUIDConverter.class)
|
@Convert(UUIDConverter.class)
|
||||||
UUID id;
|
UUID id;
|
||||||
|
|
||||||
|
@Column(nullable = false)
|
||||||
|
UUID chatId;
|
||||||
|
|
||||||
@Column(nullable = false)
|
@Column(nullable = false)
|
||||||
String sender;
|
String sender;
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ public abstract class AbstractMessageModel implements Persistable {
|
||||||
@Column
|
@Column
|
||||||
String legacyId;
|
String legacyId;
|
||||||
|
|
||||||
@Column
|
@Column(unique = true)
|
||||||
String originId;
|
String originId;
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
|
@ -52,4 +53,7 @@ public abstract class AbstractMessageModel implements Persistable {
|
||||||
|
|
||||||
@Column
|
@Column
|
||||||
String stanzaIdBy;
|
String stanzaIdBy;
|
||||||
|
|
||||||
|
@Column
|
||||||
|
OpenPgpV4Fingerprint senderOXFingerprint;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
package org.mercury_im.messenger.data.model;
|
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import io.requery.Entity;
|
|
||||||
import io.requery.Generated;
|
|
||||||
import io.requery.Key;
|
|
||||||
import io.requery.ManyToOne;
|
|
||||||
import io.requery.OneToMany;
|
|
||||||
import io.requery.Table;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "msg_payload_containers")
|
|
||||||
public abstract class AbstractMessagePayloadContainerModel {
|
|
||||||
|
|
||||||
@Key @Generated
|
|
||||||
long id;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
MessageModel message;
|
|
||||||
|
|
||||||
@OneToMany
|
|
||||||
Set<MessagePayloadModel> contents;
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package org.mercury_im.messenger.data.model;
|
|
||||||
|
|
||||||
import org.mercury_im.messenger.data.enums.MessageContentType;
|
|
||||||
|
|
||||||
import io.requery.Column;
|
|
||||||
import io.requery.Entity;
|
|
||||||
import io.requery.Generated;
|
|
||||||
import io.requery.Key;
|
|
||||||
import io.requery.ManyToOne;
|
|
||||||
import io.requery.Table;
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table(name = "msg_payloads")
|
|
||||||
public abstract class AbstractMessagePayloadModel {
|
|
||||||
|
|
||||||
@Key @Generated
|
|
||||||
long id;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
MessagePayloadContainerModel payloadContainer;
|
|
||||||
|
|
||||||
@Column
|
|
||||||
String body;
|
|
||||||
|
|
||||||
@Column(nullable = false)
|
|
||||||
MessageContentType type;
|
|
||||||
}
|
|
|
@ -4,10 +4,6 @@ import org.mercury_im.messenger.core.data.repository.MessageRepository;
|
||||||
import org.mercury_im.messenger.data.mapping.DirectChatMapping;
|
import org.mercury_im.messenger.data.mapping.DirectChatMapping;
|
||||||
import org.mercury_im.messenger.data.mapping.GroupChatMapping;
|
import org.mercury_im.messenger.data.mapping.GroupChatMapping;
|
||||||
import org.mercury_im.messenger.data.mapping.MessageMapping;
|
import org.mercury_im.messenger.data.mapping.MessageMapping;
|
||||||
import org.mercury_im.messenger.data.model.DirectChatModel;
|
|
||||||
import org.mercury_im.messenger.data.model.DirectMessagesRelation;
|
|
||||||
import org.mercury_im.messenger.data.model.GroupChatModel;
|
|
||||||
import org.mercury_im.messenger.data.model.GroupMessagesRelation;
|
|
||||||
import org.mercury_im.messenger.data.model.MessageModel;
|
import org.mercury_im.messenger.data.model.MessageModel;
|
||||||
import org.mercury_im.messenger.data.repository.dao.DirectChatDao;
|
import org.mercury_im.messenger.data.repository.dao.DirectChatDao;
|
||||||
import org.mercury_im.messenger.data.repository.dao.GroupChatDao;
|
import org.mercury_im.messenger.data.repository.dao.GroupChatDao;
|
||||||
|
@ -60,9 +56,12 @@ public class RxMessageRepository
|
||||||
public Single<Message> insertMessage(DirectChat chat, Message message) {
|
public Single<Message> insertMessage(DirectChat chat, Message message) {
|
||||||
return directChatDao.get(chat.getId()).maybe()
|
return directChatDao.get(chat.getId()).maybe()
|
||||||
.switchIfEmpty(directChatDao.insert(directChatMapping.toModel(chat)))
|
.switchIfEmpty(directChatDao.insert(directChatMapping.toModel(chat)))
|
||||||
.map(chatModel -> toRelation(chatModel, messageMapping.toModel(message)))
|
.map(chatModel -> {
|
||||||
.flatMap(data()::insert)
|
MessageModel messageModel = messageMapping.toModel(message);
|
||||||
.map(DirectMessagesRelation::getMessage)
|
messageModel.setChatId(chat.getId());
|
||||||
|
return messageModel;
|
||||||
|
})
|
||||||
|
.flatMap(messageModel -> data().upsert(messageModel))
|
||||||
.map(messageModel -> messageMapping.toEntity(messageModel, message));
|
.map(messageModel -> messageMapping.toEntity(messageModel, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,9 +69,12 @@ public class RxMessageRepository
|
||||||
public Single<Message> insertMessage(GroupChat chat, Message message) {
|
public Single<Message> insertMessage(GroupChat chat, Message message) {
|
||||||
return groupChatDao.get(chat.getId()).maybe()
|
return groupChatDao.get(chat.getId()).maybe()
|
||||||
.switchIfEmpty(groupChatDao.insert(groupChatMapping.toModel(chat)))
|
.switchIfEmpty(groupChatDao.insert(groupChatMapping.toModel(chat)))
|
||||||
.map(chatModel -> toRelation(chatModel, messageMapping.toModel(message)))
|
.map(chatModel -> {
|
||||||
.flatMap(data()::insert)
|
MessageModel messageModel = messageMapping.toModel(message);
|
||||||
.map(GroupMessagesRelation::getMessage)
|
messageModel.setChatId(chat.getId());
|
||||||
|
return messageModel;
|
||||||
|
})
|
||||||
|
.flatMap(data()::upsert)
|
||||||
.map(messageModel -> messageMapping.toEntity(messageModel, message));
|
.map(messageModel -> messageMapping.toEntity(messageModel, message));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,9 +82,6 @@ public class RxMessageRepository
|
||||||
public Observable<List<Message>> observeMessages(DirectChat chat) {
|
public Observable<List<Message>> observeMessages(DirectChat chat) {
|
||||||
return data().select(MessageModel.class)
|
return data().select(MessageModel.class)
|
||||||
.from(MessageModel.class)
|
.from(MessageModel.class)
|
||||||
.join(DirectMessagesRelation.class)
|
|
||||||
.on(DirectMessagesRelation.MESSAGE_ID.eq(MessageModel.ID))
|
|
||||||
.where(DirectMessagesRelation.CHAT_ID.eq(chat.getId()))
|
|
||||||
.get().observableResult()
|
.get().observableResult()
|
||||||
.map(ResultDelegate::toList)
|
.map(ResultDelegate::toList)
|
||||||
.map(this::messageModelsToEntities);
|
.map(this::messageModelsToEntities);
|
||||||
|
@ -100,9 +99,6 @@ public class RxMessageRepository
|
||||||
public Observable<List<Message>> observeMessages(GroupChat chat) {
|
public Observable<List<Message>> observeMessages(GroupChat chat) {
|
||||||
return data().select(MessageModel.class)
|
return data().select(MessageModel.class)
|
||||||
.from(MessageModel.class)
|
.from(MessageModel.class)
|
||||||
.join(GroupMessagesRelation.class)
|
|
||||||
.on(GroupMessagesRelation.MESSAGE_ID.eq(MessageModel.ID))
|
|
||||||
.where(GroupMessagesRelation.CHAT_ID.eq(chat.getId()))
|
|
||||||
.get().observableResult()
|
.get().observableResult()
|
||||||
.map(ResultDelegate::toList)
|
.map(ResultDelegate::toList)
|
||||||
.map(this::messageModelsToEntities);
|
.map(this::messageModelsToEntities);
|
||||||
|
@ -123,11 +119,9 @@ public class RxMessageRepository
|
||||||
return data().select(MessageModel.class)
|
return data().select(MessageModel.class)
|
||||||
|
|
||||||
.from(MessageModel.class)
|
.from(MessageModel.class)
|
||||||
.join(DirectMessagesRelation.class)
|
|
||||||
.on(DirectMessagesRelation.MESSAGE_ID.eq(MessageModel.ID))
|
|
||||||
|
|
||||||
.where(MessageModel.BODY.eq(body))
|
.where(MessageModel.BODY.eq(body))
|
||||||
.and(DirectMessagesRelation.CHAT_ID.eq(chat.getId()))
|
.and(MessageModel.SENDER.eq(chat.getPeer().getAddress())
|
||||||
|
.or(MessageModel.RECIPIENT.eq(chat.getPeer().getAddress())))
|
||||||
.get().observableResult()
|
.get().observableResult()
|
||||||
.map(ResultDelegate::toList)
|
.map(ResultDelegate::toList)
|
||||||
.map(this::messageModelsToEntities);
|
.map(this::messageModelsToEntities);
|
||||||
|
@ -138,11 +132,8 @@ public class RxMessageRepository
|
||||||
return data().select(MessageModel.class)
|
return data().select(MessageModel.class)
|
||||||
|
|
||||||
.from(MessageModel.class)
|
.from(MessageModel.class)
|
||||||
.join(GroupMessagesRelation.class)
|
|
||||||
.on(GroupMessagesRelation.MESSAGE_ID.eq(MessageModel.ID))
|
|
||||||
|
|
||||||
.where(MessageModel.BODY.eq(body))
|
.where(MessageModel.BODY.eq(body))
|
||||||
.and(GroupMessagesRelation.CHAT_ID.eq(chat.getId()))
|
.and(MessageModel.SENDER.eq(chat.getRoomName()))
|
||||||
.get().observableResult()
|
.get().observableResult()
|
||||||
.map(ResultDelegate::toList)
|
.map(ResultDelegate::toList)
|
||||||
.map(this::messageModelsToEntities);
|
.map(this::messageModelsToEntities);
|
||||||
|
@ -173,20 +164,6 @@ public class RxMessageRepository
|
||||||
.get().single().ignoreElement();
|
.get().single().ignoreElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
private DirectMessagesRelation toRelation(DirectChatModel chat, MessageModel message) {
|
|
||||||
DirectMessagesRelation relation = new DirectMessagesRelation();
|
|
||||||
relation.setChat(chat);
|
|
||||||
relation.setMessage(message);
|
|
||||||
return relation;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GroupMessagesRelation toRelation(GroupChatModel chat, MessageModel message) {
|
|
||||||
GroupMessagesRelation relation = new GroupMessagesRelation();
|
|
||||||
relation.setChat(chat);
|
|
||||||
relation.setMessage(message);
|
|
||||||
return relation;
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<Message> messageModelsToEntities(List<MessageModel> models) {
|
private List<Message> messageModelsToEntities(List<MessageModel> models) {
|
||||||
List<Message> entities = new ArrayList<>(models.size());
|
List<Message> entities = new ArrayList<>(models.size());
|
||||||
for (MessageModel model : models) {
|
for (MessageModel model : models) {
|
||||||
|
|
|
@ -88,14 +88,14 @@ public class RxPeerRepository
|
||||||
@Override
|
@Override
|
||||||
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(
|
||||||
.just(new Peer())
|
Single.just(new Peer())
|
||||||
.map(peer -> {
|
.map(peer -> {
|
||||||
peer.setAccount(account);
|
peer.setAccount(account);
|
||||||
peer.setAddress(address);
|
peer.setAddress(address);
|
||||||
return peer;
|
return peer;
|
||||||
})
|
})
|
||||||
.flatMap(this::insertPeer));
|
.flatMap(this::upsertPeer));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package org.mercury_im.messenger.data.repository.dao;
|
package org.mercury_im.messenger.data.repository.dao;
|
||||||
|
|
||||||
import org.mercury_im.messenger.data.model.DirectChatModel;
|
import org.mercury_im.messenger.data.model.DirectChatModel;
|
||||||
import org.mercury_im.messenger.data.model.DirectMessagesRelation;
|
|
||||||
import org.mercury_im.messenger.data.model.GroupChatModel;
|
import org.mercury_im.messenger.data.model.GroupChatModel;
|
||||||
import org.mercury_im.messenger.data.model.GroupMessagesRelation;
|
|
||||||
import org.mercury_im.messenger.data.model.MessageModel;
|
import org.mercury_im.messenger.data.model.MessageModel;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
import io.requery.Persistable;
|
import io.requery.Persistable;
|
||||||
import io.requery.reactivex.ReactiveEntityStore;
|
import io.requery.reactivex.ReactiveEntityStore;
|
||||||
|
@ -18,6 +18,7 @@ public class MessageDao extends RequeryDao {
|
||||||
private final DirectChatDao directChatDao;
|
private final DirectChatDao directChatDao;
|
||||||
private final GroupChatDao groupChatDao;
|
private final GroupChatDao groupChatDao;
|
||||||
|
|
||||||
|
@Inject
|
||||||
public MessageDao(ReactiveEntityStore<Persistable> data) {
|
public MessageDao(ReactiveEntityStore<Persistable> data) {
|
||||||
super(data);
|
super(data);
|
||||||
this.directChatDao = new DirectChatDao(data);
|
this.directChatDao = new DirectChatDao(data);
|
||||||
|
@ -33,20 +34,4 @@ public class MessageDao extends RequeryDao {
|
||||||
.where(MessageModel.ID.eq(messageId))
|
.where(MessageModel.ID.eq(messageId))
|
||||||
.get();
|
.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private DirectMessagesRelation toRelation(DirectChatModel chat, MessageModel message) {
|
|
||||||
DirectMessagesRelation relation = new DirectMessagesRelation();
|
|
||||||
relation.setChat(chat);
|
|
||||||
relation.setMessage(message);
|
|
||||||
return relation;
|
|
||||||
}
|
|
||||||
|
|
||||||
private GroupMessagesRelation toRelation(GroupChatModel chat, MessageModel message) {
|
|
||||||
GroupMessagesRelation relation = new GroupMessagesRelation();
|
|
||||||
relation.setChat(chat);
|
|
||||||
relation.setMessage(message);
|
|
||||||
return relation;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,20 +44,12 @@ public class Messenger {
|
||||||
this.repositories = repositories;
|
this.repositories = repositories;
|
||||||
this.connectionManager = connectionManager;
|
this.connectionManager = connectionManager;
|
||||||
this.schedulers = schedulers;
|
this.schedulers = schedulers;
|
||||||
performInitialLogin();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public MercuryConnectionManager getConnectionManager() {
|
public MercuryConnectionManager getConnectionManager() {
|
||||||
return connectionManager;
|
return connectionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void performInitialLogin() {
|
|
||||||
LOGGER.log(Level.INFO, "Perform initial login.");
|
|
||||||
disposable.add(repositories.getAccountRepository().observeAllAccounts().firstOrError()
|
|
||||||
.subscribeOn(schedulers.getIoScheduler())
|
|
||||||
.subscribe(connectionManager::doRegisterConnections));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Completable addContact(UUID accountId, String contactAddress) {
|
public Completable addContact(UUID accountId, String contactAddress) {
|
||||||
return Completable.fromAction(() -> doAddContact(accountId, contactAddress));
|
return Completable.fromAction(() -> doAddContact(accountId, contactAddress));
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,14 @@ import org.jivesoftware.smackx.ox.crypto.PainlessOpenPgpProvider;
|
||||||
import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException;
|
import org.jivesoftware.smackx.ox.exception.InvalidBackupCodeException;
|
||||||
import org.jivesoftware.smackx.ox.exception.NoBackupFoundException;
|
import org.jivesoftware.smackx.ox.exception.NoBackupFoundException;
|
||||||
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
|
import org.jivesoftware.smackx.ox.store.definition.OpenPgpStore;
|
||||||
|
import org.jivesoftware.smackx.ox.util.SecretKeyBackupHelper;
|
||||||
import org.jivesoftware.smackx.ox_im.OXInstantMessagingManager;
|
import org.jivesoftware.smackx.ox_im.OXInstantMessagingManager;
|
||||||
import org.jivesoftware.smackx.pubsub.PubSubException;
|
import org.jivesoftware.smackx.pubsub.PubSubException;
|
||||||
import org.mercury_im.messenger.core.SchedulersFacade;
|
import org.mercury_im.messenger.core.SchedulersFacade;
|
||||||
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
|
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
|
||||||
|
import org.mercury_im.messenger.core.data.repository.Repositories;
|
||||||
import org.mercury_im.messenger.core.store.crypto.MercuryOpenPgpStore;
|
import org.mercury_im.messenger.core.store.crypto.MercuryOpenPgpStore;
|
||||||
|
import org.mercury_im.messenger.core.store.message.MercuryMessageStore;
|
||||||
import org.mercury_im.messenger.core.xmpp.MercuryConnection;
|
import org.mercury_im.messenger.core.xmpp.MercuryConnection;
|
||||||
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -24,13 +27,17 @@ public class MercuryOpenPgpManager {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(MercuryOpenPgpManager.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(MercuryOpenPgpManager.class.getName());
|
||||||
|
|
||||||
|
private final Repositories repositories;
|
||||||
private final OpenPgpRepository openPgpRepository;
|
private final OpenPgpRepository openPgpRepository;
|
||||||
private final SchedulersFacade schedulers;
|
private final SchedulersFacade schedulers;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public MercuryOpenPgpManager(OpenPgpRepository openPgpRepository, SchedulersFacade schedulers) {
|
public MercuryOpenPgpManager(OpenPgpRepository openPgpRepository,
|
||||||
|
SchedulersFacade schedulers,
|
||||||
|
Repositories repositories) {
|
||||||
this.openPgpRepository = openPgpRepository;
|
this.openPgpRepository = openPgpRepository;
|
||||||
this.schedulers = schedulers;
|
this.schedulers = schedulers;
|
||||||
|
this.repositories = repositories;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initialize(MercuryConnection connection) {
|
public void initialize(MercuryConnection connection) {
|
||||||
|
@ -51,9 +58,12 @@ public class MercuryOpenPgpManager {
|
||||||
private void setup(MercuryConnection connection) {
|
private void setup(MercuryConnection connection) {
|
||||||
OpenPgpStore store = new MercuryOpenPgpStore(connection.getAccountId(), openPgpRepository, schedulers);
|
OpenPgpStore store = new MercuryOpenPgpStore(connection.getAccountId(), openPgpRepository, schedulers);
|
||||||
OpenPgpProvider provider = new PainlessOpenPgpProvider(store);
|
OpenPgpProvider provider = new PainlessOpenPgpProvider(store);
|
||||||
|
OpenPgpManager oxManager = OpenPgpManager.getInstanceFor(connection.getConnection());
|
||||||
|
oxManager.setOpenPgpProvider(provider);
|
||||||
|
SecretKeyBackupHelper.setBackupCodeGenerator(
|
||||||
|
() -> "71ZA-Y416-UA7A-7NCE-3SNM-88EF"
|
||||||
|
);
|
||||||
try {
|
try {
|
||||||
OpenPgpManager oxManager = OpenPgpManager.getInstanceFor(connection.getConnection());
|
|
||||||
oxManager.setOpenPgpProvider(provider);
|
|
||||||
if (!oxManager.hasSecretKeysAvailable()) {
|
if (!oxManager.hasSecretKeysAvailable()) {
|
||||||
try {
|
try {
|
||||||
oxManager.restoreSecretKeyServerBackup(
|
oxManager.restoreSecretKeyServerBackup(
|
||||||
|
@ -71,7 +81,9 @@ public class MercuryOpenPgpManager {
|
||||||
}
|
}
|
||||||
oxManager.announceSupportAndPublish();
|
oxManager.announceSupportAndPublish();
|
||||||
OXInstantMessagingManager oximManager = OXInstantMessagingManager.getInstanceFor(connection.getConnection());
|
OXInstantMessagingManager oximManager = OXInstantMessagingManager.getInstanceFor(connection.getConnection());
|
||||||
|
oximManager.addOxMessageListener(new MercuryMessageStore(connection.getAccount(), repositories.getPeerRepository(), repositories.getDirectChatRepository(), repositories.getMessageRepository(), schedulers));
|
||||||
oximManager.announceSupportForOxInstantMessaging();
|
oximManager.announceSupportForOxInstantMessaging();
|
||||||
|
oxManager.stopMetadataListener();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@ import org.jivesoftware.smack.chat2.IncomingChatMessageListener;
|
||||||
import org.jivesoftware.smack.chat2.OutgoingChatMessageListener;
|
import org.jivesoftware.smack.chat2.OutgoingChatMessageListener;
|
||||||
import org.jivesoftware.smack.packet.MessageBuilder;
|
import org.jivesoftware.smack.packet.MessageBuilder;
|
||||||
import org.jivesoftware.smackx.delay.packet.DelayInformation;
|
import org.jivesoftware.smackx.delay.packet.DelayInformation;
|
||||||
|
import org.jivesoftware.smackx.ox.OpenPgpContact;
|
||||||
|
import org.jivesoftware.smackx.ox.element.SigncryptElement;
|
||||||
|
import org.jivesoftware.smackx.ox_im.OxMessageListener;
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
import org.mercury_im.messenger.core.SchedulersFacade;
|
import org.mercury_im.messenger.core.SchedulersFacade;
|
||||||
import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
|
import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
|
||||||
|
@ -12,6 +15,7 @@ import org.mercury_im.messenger.core.data.repository.PeerRepository;
|
||||||
import org.mercury_im.messenger.entity.Account;
|
import org.mercury_im.messenger.entity.Account;
|
||||||
import org.mercury_im.messenger.entity.message.Message;
|
import org.mercury_im.messenger.entity.message.Message;
|
||||||
import org.mercury_im.messenger.entity.message.MessageDirection;
|
import org.mercury_im.messenger.entity.message.MessageDirection;
|
||||||
|
import org.pgpainless.decryption_verification.OpenPgpMetadata;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -24,7 +28,7 @@ import io.reactivex.disposables.CompositeDisposable;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class MercuryMessageStore implements IncomingChatMessageListener, OutgoingChatMessageListener {
|
public class MercuryMessageStore implements IncomingChatMessageListener, OutgoingChatMessageListener, OxMessageListener {
|
||||||
|
|
||||||
private static final Logger LOGGER = Logger.getLogger(MercuryMessageStore.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(MercuryMessageStore.class.getName());
|
||||||
|
|
||||||
|
@ -88,4 +92,23 @@ public class MercuryMessageStore implements IncomingChatMessageListener, Outgoin
|
||||||
.subscribeOn(schedulers.getIoScheduler())
|
.subscribeOn(schedulers.getIoScheduler())
|
||||||
.subscribe(m -> LOGGER.log(Level.INFO, "Message written"), e -> LOGGER.log(Level.SEVERE, "Error: ", e));
|
.subscribe(m -> LOGGER.log(Level.INFO, "Message written"), e -> LOGGER.log(Level.SEVERE, "Error: ", e));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void newIncomingOxMessage(OpenPgpContact contact,
|
||||||
|
org.jivesoftware.smack.packet.Message smackMessage,
|
||||||
|
SigncryptElement decryptedPayload,
|
||||||
|
OpenPgpMetadata metadata) {
|
||||||
|
Message message = new Message();
|
||||||
|
message.setDirection(MessageDirection.incoming);
|
||||||
|
DelayInformation delayInformation = DelayInformation.from(smackMessage);
|
||||||
|
message.setTimestamp(delayInformation != null ? delayInformation.getStamp() : new Date());
|
||||||
|
message.setSender(contact.getJid().toString());
|
||||||
|
message.setRecipient(smackMessage.getTo().asBareJid().toString());
|
||||||
|
org.jivesoftware.smack.packet.Message.Body body = decryptedPayload.getExtension(org.jivesoftware.smack.packet.Message.Body.ELEMENT,
|
||||||
|
org.jivesoftware.smack.packet.Message.Body.NAMESPACE);
|
||||||
|
if (body != null) {
|
||||||
|
message.setBody(body.getMessage());
|
||||||
|
}
|
||||||
|
disposable.add(writeMessageToStore(contact.getJid().toString(), message));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,9 @@ public class CsiManager implements ClientStateListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryCsiActive(MercuryConnection connection) {
|
private void tryCsiActive(MercuryConnection connection) {
|
||||||
|
if (!connection.getConnection().isAuthenticated()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
ClientStateIndicationManager.active(connection.getConnection());
|
ClientStateIndicationManager.active(connection.getConnection());
|
||||||
} catch (SmackException.NotConnectedException | InterruptedException | IllegalArgumentException e) {
|
} catch (SmackException.NotConnectedException | InterruptedException | IllegalArgumentException e) {
|
||||||
|
@ -42,6 +45,9 @@ public class CsiManager implements ClientStateListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryCsiInactive(MercuryConnection connection) {
|
private void tryCsiInactive(MercuryConnection connection) {
|
||||||
|
if (!connection.getConnection().isAuthenticated()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
ClientStateIndicationManager.inactive(connection.getConnection());
|
ClientStateIndicationManager.inactive(connection.getConnection());
|
||||||
} catch (SmackException.NotConnectedException | InterruptedException | IllegalArgumentException e) {
|
} catch (SmackException.NotConnectedException | InterruptedException | IllegalArgumentException e) {
|
||||||
|
|
|
@ -54,9 +54,6 @@ public class MercuryConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Completable connect() {
|
public Completable connect() {
|
||||||
if (getConnection().isConnected()) {
|
|
||||||
return Completable.complete();
|
|
||||||
}
|
|
||||||
return Completable.fromAction(this::doConnect)
|
return Completable.fromAction(this::doConnect)
|
||||||
.doOnError(error -> LOGGER.log(Level.WARNING, "Connection error for account " + account, error));
|
.doOnError(error -> LOGGER.log(Level.WARNING, "Connection error for account " + account, error));
|
||||||
}
|
}
|
||||||
|
@ -64,7 +61,11 @@ public class MercuryConnection {
|
||||||
private void doConnect() throws ServerUnreachableException {
|
private void doConnect() throws ServerUnreachableException {
|
||||||
state.onNext(state.getValue().withConnectivity(ConnectivityState.connecting));
|
state.onNext(state.getValue().withConnectivity(ConnectivityState.connecting));
|
||||||
AbstractXMPPConnection connection = (AbstractXMPPConnection) getConnection();
|
AbstractXMPPConnection connection = (AbstractXMPPConnection) getConnection();
|
||||||
|
if (connection.isConnected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
|
LOGGER.log(Level.INFO, "Connected!");
|
||||||
connection.connect();
|
connection.connect();
|
||||||
} catch (SmackException.EndpointConnectionException e) {
|
} catch (SmackException.EndpointConnectionException e) {
|
||||||
connection.disconnect();
|
connection.disconnect();
|
||||||
|
@ -75,14 +76,14 @@ public class MercuryConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Completable login() {
|
public Completable login() {
|
||||||
if (getConnection().isAuthenticated()) {
|
|
||||||
return Completable.complete();
|
|
||||||
}
|
|
||||||
return Completable.fromAction(this::doLogin)
|
return Completable.fromAction(this::doLogin)
|
||||||
.doOnError(error -> LOGGER.log(Level.WARNING, "Login error for account " + account, error));
|
.doOnError(error -> LOGGER.log(Level.WARNING, "Login error for account " + account, error));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doLogin() throws InvalidCredentialsException {
|
private void doLogin() throws InvalidCredentialsException {
|
||||||
|
if (connection.isAuthenticated()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
((AbstractXMPPConnection) getConnection()).login();
|
((AbstractXMPPConnection) getConnection()).login();
|
||||||
} catch (SASLErrorException e) {
|
} catch (SASLErrorException e) {
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 58ce1dd62f11b40a7063802fa079d827c90b0f84
|
Subproject commit 218403c362d306d38ea791d528f165fc64eb8189
|
Loading…
Reference in New Issue