mirror of
https://codeberg.org/Mercury-IM/Mercury-IM
synced 2025-02-07 20:06:24 +01:00
Start work on new message sending logic
This commit is contained in:
parent
9ea08b11da
commit
0adbcc94b0
35 changed files with 517 additions and 142 deletions
|
@ -8,6 +8,7 @@ import org.mercury_im.messenger.android.ui.roster.contacts.AndroidContactListVie
|
|||
import org.mercury_im.messenger.core.di.module.OpenPgpModule;
|
||||
import org.mercury_im.messenger.core.di.module.RxMercuryMessageStoreFactoryModule;
|
||||
import org.mercury_im.messenger.core.di.module.RxMercuryRosterStoreFactoryModule;
|
||||
import org.mercury_im.messenger.core.di.module.StanzaIdSourceFactoryModule;
|
||||
import org.mercury_im.messenger.core.di.module.XmppTcpConnectionFactoryModule;
|
||||
import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel;
|
||||
import org.mercury_im.messenger.core.viewmodel.account.list.AccountListViewModel;
|
||||
|
@ -48,7 +49,8 @@ import dagger.Component;
|
|||
XmppTcpConnectionFactoryModule.class,
|
||||
RxMercuryMessageStoreFactoryModule.class,
|
||||
OpenPgpModule.class,
|
||||
RxMercuryRosterStoreFactoryModule.class
|
||||
RxMercuryRosterStoreFactoryModule.class,
|
||||
StanzaIdSourceFactoryModule.class
|
||||
})
|
||||
public interface AppComponent {
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package org.mercury_im.messenger.data.converter;
|
||||
|
||||
import org.jxmpp.jid.EntityFullJid;
|
||||
import org.jxmpp.jid.EntityJid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
|
||||
|
@ -27,18 +26,15 @@ public class EntityJidConverter implements Converter<EntityJid, String> {
|
|||
|
||||
@Override
|
||||
public String convertToPersisted(EntityJid value) {
|
||||
if (value == null) return null;
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityJid convertToMapped(Class<? extends EntityJid> type, @Nullable String value) {
|
||||
switch (type.getName()) {
|
||||
case "EntityFullJid":
|
||||
return JidCreate.entityFullFromOrThrowUnchecked(value);
|
||||
case "EntityBareJid":
|
||||
return JidCreate.entityBareFromOrThrowUnchecked(value);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown jid type encountered: " + type.getName());
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
return JidCreate.entityFromOrThrowUnchecked(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package org.mercury_im.messenger.data.mapping;
|
||||
|
||||
import org.jivesoftware.smackx.chat_markers.ChatMarkersState;
|
||||
import org.mercury_im.messenger.entity.message.ChatMarkerState;
|
||||
|
||||
public class ChatMarkerMapping {
|
||||
|
||||
public static ChatMarkersState toSmackChatMarker(ChatMarkerState mercuryChatMarker) {
|
||||
switch (mercuryChatMarker) {
|
||||
case markable:
|
||||
return ChatMarkersState.markable;
|
||||
case received:
|
||||
return ChatMarkersState.received;
|
||||
case displayed:
|
||||
return ChatMarkersState.displayed;
|
||||
case acknowledged:
|
||||
return ChatMarkersState.acknowledged;
|
||||
default:
|
||||
throw new IllegalArgumentException("Illegal ChatMarkersState: " + mercuryChatMarker);
|
||||
}
|
||||
}
|
||||
|
||||
public static ChatMarkerState toMercuryChatMarker(ChatMarkersState smackChatMarker) {
|
||||
switch (smackChatMarker) {
|
||||
case markable:
|
||||
return ChatMarkerState.markable;
|
||||
case received:
|
||||
return ChatMarkerState.received;
|
||||
case displayed:
|
||||
return ChatMarkerState.displayed;
|
||||
case acknowledged:
|
||||
return ChatMarkerState.acknowledged;
|
||||
default:
|
||||
throw new IllegalArgumentException("Illegal ChatMarkersState: " + smackChatMarker);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ public class MessageMapping extends AbstractMapping<Message, MessageModel> {
|
|||
@Override
|
||||
public MessageModel mapToModel(Message entity, MessageModel model) {
|
||||
model.setId(entity.getId());
|
||||
model.setChatId(entity.getChatId());
|
||||
model.setSender(entity.getSender());
|
||||
model.setRecipient(entity.getRecipient());
|
||||
model.setTimestamp(entity.getTimestamp());
|
||||
|
@ -42,6 +43,7 @@ public class MessageMapping extends AbstractMapping<Message, MessageModel> {
|
|||
@Override
|
||||
public Message mapToEntity(MessageModel model, Message entity) {
|
||||
entity.setId(model.getId());
|
||||
entity.setChatId(model.getChatId());
|
||||
entity.setSender(model.getSender());
|
||||
entity.setRecipient(model.getRecipient());
|
||||
entity.setTimestamp(model.getTimestamp());
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package org.mercury_im.messenger.data.model;
|
||||
|
||||
import org.jxmpp.jid.EntityFullJid;
|
||||
import org.mercury_im.messenger.data.converter.EntityFullJidConverter;
|
||||
import org.jxmpp.jid.EntityJid;
|
||||
import org.mercury_im.messenger.data.converter.EntityJidConverter;
|
||||
import org.mercury_im.messenger.data.converter.MessageDirectionConverter;
|
||||
import org.mercury_im.messenger.entity.Encryption;
|
||||
import org.mercury_im.messenger.entity.message.ChatMarkerState;
|
||||
import org.mercury_im.messenger.entity.message.MessageDeliveryState;
|
||||
import org.mercury_im.messenger.entity.message.MessageDirection;
|
||||
import org.pgpainless.key.OpenPgpV4Fingerprint;
|
||||
|
||||
|
@ -27,15 +29,16 @@ public abstract class AbstractMessageModel implements Persistable {
|
|||
UUID id;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Convert(UUIDConverter.class)
|
||||
UUID chatId;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Convert(EntityFullJidConverter.class)
|
||||
EntityFullJid sender;
|
||||
@Convert(EntityJidConverter.class)
|
||||
EntityJid sender;
|
||||
|
||||
@Column(nullable = false)
|
||||
@Convert(EntityFullJidConverter.class)
|
||||
EntityFullJid recipient;
|
||||
@Convert(EntityJidConverter.class)
|
||||
EntityJid recipient;
|
||||
|
||||
@Column(name = "\"timestamp\"", nullable = false)
|
||||
Date timestamp;
|
||||
|
@ -68,4 +71,10 @@ public abstract class AbstractMessageModel implements Persistable {
|
|||
@Column
|
||||
OpenPgpV4Fingerprint senderOXFingerprint;
|
||||
|
||||
@Column
|
||||
ChatMarkerState chatMarkerState;
|
||||
|
||||
@Column
|
||||
MessageDeliveryState deliveryState;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.mercury_im.messenger.data.repository;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.core.data.repository.MessageRepository;
|
||||
import org.mercury_im.messenger.data.mapping.DirectChatMapping;
|
||||
import org.mercury_im.messenger.data.mapping.GroupChatMapping;
|
||||
|
@ -10,7 +11,9 @@ import org.mercury_im.messenger.data.repository.dao.GroupChatDao;
|
|||
import org.mercury_im.messenger.data.repository.dao.MessageDao;
|
||||
import org.mercury_im.messenger.entity.chat.DirectChat;
|
||||
import org.mercury_im.messenger.entity.chat.GroupChat;
|
||||
import org.mercury_im.messenger.entity.message.ChatMarkerState;
|
||||
import org.mercury_im.messenger.entity.message.Message;
|
||||
import org.mercury_im.messenger.entity.message.MessageDeliveryState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -105,7 +108,7 @@ public class RxMessageRepository
|
|||
|
||||
.from(MessageModel.class)
|
||||
.where(MessageModel.BODY.like("%" + body + "%")
|
||||
.and(MessageModel.CHAT_ID.eq(chat.getId())))
|
||||
.and(MessageModel.CHAT_ID.eq(chat.getId())))
|
||||
.get().observableResult()
|
||||
.map(ResultDelegate::toList)
|
||||
.map(this::messageModelsToEntities);
|
||||
|
@ -117,7 +120,7 @@ public class RxMessageRepository
|
|||
|
||||
.from(MessageModel.class)
|
||||
.where(MessageModel.BODY.like("%" + body + "%")
|
||||
.and(MessageModel.CHAT_ID.eq(chat.getId())))
|
||||
.and(MessageModel.CHAT_ID.eq(chat.getId())))
|
||||
.get().observableResult()
|
||||
.map(ResultDelegate::toList)
|
||||
.map(this::messageModelsToEntities);
|
||||
|
@ -146,6 +149,24 @@ public class RxMessageRepository
|
|||
.get().single().ignoreElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Completable markMessage(String stanzaId, EntityBareJid recipientJid, ChatMarkerState state) {
|
||||
return data().update(MessageModel.class)
|
||||
.set(MessageModel.CHAT_MARKER_STATE, state)
|
||||
.where(MessageModel.LEGACY_ID.eq(stanzaId)
|
||||
.and(MessageModel.RECIPIENT.eq(recipientJid)))
|
||||
.get().single().ignoreElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Completable updateDeliveryState(UUID messageId, MessageDeliveryState deliveryState) {
|
||||
return data().update(MessageModel.class)
|
||||
.set(MessageModel.DELIVERY_STATE, deliveryState)
|
||||
.where(MessageModel.ID.eq(messageId))
|
||||
.get().single()
|
||||
.ignoreElement();
|
||||
}
|
||||
|
||||
private List<Message> messageModelsToEntities(List<MessageModel> models) {
|
||||
List<Message> entities = new ArrayList<>(models.size());
|
||||
for (MessageModel model : models) {
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
apply plugin: 'java-library'
|
||||
|
||||
sourceSets {
|
||||
//main.java.srcDirs += "${buildDir}/generated/sources/annotationProcessor/java/main/"
|
||||
test.java.srcDirs += "${buildDir}/generated/sources/annotationProcessor/java/test/"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
implementation project(':entity')
|
||||
|
@ -20,7 +25,9 @@ dependencies {
|
|||
|
||||
// Dagger 2 for dependency injection
|
||||
implementation "com.google.dagger:dagger:$daggerVersion"
|
||||
testImplementation "com.google.dagger:dagger:$daggerVersion"
|
||||
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
|
||||
testAnnotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
|
||||
|
||||
compileOnly "org.projectlombok:lombok:$lombokVersion"
|
||||
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
|
||||
|
|
|
@ -13,8 +13,13 @@ import org.jxmpp.jid.impl.JidCreate;
|
|||
import org.jxmpp.stringprep.XmppStringprepException;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnection;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
|
||||
import org.mercury_im.messenger.core.connection.message.MessageConsignor;
|
||||
import org.mercury_im.messenger.core.connection.message.OxMessageConsignor;
|
||||
import org.mercury_im.messenger.core.connection.message.PlaintextMessageConsignor;
|
||||
import org.mercury_im.messenger.core.data.repository.MessageRepository;
|
||||
import org.mercury_im.messenger.core.exception.ConnectionNotFoundException;
|
||||
import org.mercury_im.messenger.core.exception.ContactAlreadyAddedException;
|
||||
import org.mercury_im.messenger.entity.chat.Chat;
|
||||
import org.mercury_im.messenger.entity.contact.Peer;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -34,12 +39,15 @@ public class Messenger {
|
|||
private static final Logger LOGGER = Logger.getLogger(Messenger.class.getName());
|
||||
|
||||
private final MercuryConnectionManager connectionManager;
|
||||
private final MessageRepository messageRepository;
|
||||
private final SchedulersFacade schedulers;
|
||||
|
||||
@Inject
|
||||
public Messenger(MercuryConnectionManager connectionManager,
|
||||
MessageRepository messageRepository,
|
||||
SchedulersFacade schedulers) {
|
||||
this.connectionManager = connectionManager;
|
||||
this.messageRepository = messageRepository;
|
||||
this.schedulers = schedulers;
|
||||
}
|
||||
|
||||
|
@ -127,4 +135,16 @@ public class Messenger {
|
|||
}
|
||||
return connection;
|
||||
}
|
||||
|
||||
public MessageConsignor getMessageConsignor(Chat chat) {
|
||||
switch (chat.getChatPreferences().getEncryption()) {
|
||||
case plain:
|
||||
return new PlaintextMessageConsignor(connectionManager, messageRepository, chat);
|
||||
case ox_sign:
|
||||
case ox_crypt:
|
||||
case ox_signcrypt:
|
||||
return new OxMessageConsignor(connectionManager, messageRepository, chat);
|
||||
}
|
||||
throw new AssertionError("Illegal Encryption Type: " + chat.getChatPreferences().getEncryption());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -159,7 +159,6 @@ public class MercuryConnectionManager {
|
|||
MercuryMessageStore mercuryMessageStore = messageStoreFactory.createMessageStore(account);
|
||||
ChatManager chatManager = ChatManager.getInstanceFor(connection.getConnection());
|
||||
chatManager.addIncomingListener(mercuryMessageStore);
|
||||
chatManager.addOutgoingListener(mercuryMessageStore);
|
||||
}));
|
||||
cryptoManager.initialize(connection);
|
||||
}
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
package org.mercury_im.messenger.core.connection
|
||||
|
||||
|
||||
import org.mercury_im.messenger.entity.message.Message as MercuryMessage;
|
||||
import org.jivesoftware.smack.packet.Message as SmackMessage;
|
||||
|
||||
import java.util.UUID
|
||||
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import org.mercury_im.messenger.core.util.AppendCompletableToSingle
|
||||
import org.mercury_im.messenger.entity.chat.Chat
|
||||
|
||||
class MessageCenter(private val composer: Composer,
|
||||
private val persister: Persister,
|
||||
private val encryptor: Encryptor,
|
||||
private val sender: Sender) {
|
||||
|
||||
fun sendSingleTextMessage(chat: Chat, body: String): Single<UUID> {
|
||||
val messageEntity = composer.createChatMessage(chat, body)
|
||||
val messageId = persister.persistPendingMessage(messageEntity)
|
||||
val smackMessage = encryptor.encrypt(messageEntity)
|
||||
val sendCompletable = sender.send(smackMessage);
|
||||
return messageId.compose(AppendCompletableToSingle(sendCompletable));
|
||||
}
|
||||
|
||||
interface Composer {
|
||||
fun createChatMessage(chat: Chat, body: String): MercuryMessage
|
||||
}
|
||||
|
||||
interface Persister {
|
||||
fun persistPendingMessage(message: MercuryMessage): Single<UUID>
|
||||
}
|
||||
|
||||
interface Encryptor {
|
||||
fun encrypt(message: MercuryMessage): SmackMessage
|
||||
}
|
||||
|
||||
interface Sender {
|
||||
fun send(message: SmackMessage): Completable
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package org.mercury_im.messenger.core.connection;
|
||||
|
||||
import org.mercury_im.messenger.core.data.repository.MessageRepository;
|
||||
import org.mercury_im.messenger.entity.message.Message;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import io.reactivex.Single;
|
||||
|
||||
public class MessagePersister implements MessageCenter.Persister {
|
||||
|
||||
private final MessageRepository messageRepository;
|
||||
|
||||
public MessagePersister(MessageRepository messageRepository) {
|
||||
this.messageRepository = messageRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Single<UUID> persistPendingMessage(Message message) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package org.mercury_im.messenger.core.connection;
|
||||
|
||||
import org.jivesoftware.smack.ReconnectionManager;
|
||||
import org.jivesoftware.smack.SmackConfiguration;
|
||||
import org.jivesoftware.smack.roster.Roster;
|
||||
import org.jivesoftware.smackx.carbons.CarbonManager;
|
||||
import org.jivesoftware.smackx.iqversion.VersionManager;
|
||||
|
@ -10,7 +11,7 @@ import org.jivesoftware.smackx.sid.StableUniqueStanzaIdManager;
|
|||
public class SmackConfig {
|
||||
|
||||
static void staticConfiguration() {
|
||||
//SmackConfiguration.DEBUG = true;
|
||||
SmackConfiguration.DEBUG = true;
|
||||
ReconnectionManager.setEnabledPerDefault(true);
|
||||
ReconnectionManager.setDefaultReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);
|
||||
|
||||
|
|
|
@ -1,19 +1,31 @@
|
|||
package org.mercury_im.messenger.core.connection;
|
||||
|
||||
import org.jivesoftware.smack.AbstractXMPPConnection;
|
||||
import org.jivesoftware.smack.packet.id.StanzaIdSource;
|
||||
import org.jivesoftware.smack.packet.id.StanzaIdSourceFactory;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
||||
import org.jxmpp.stringprep.XmppStringprepException;
|
||||
import org.mercury_im.messenger.entity.Account;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class XmppTcpConnectionFactory implements XmppConnectionFactory {
|
||||
|
||||
private static final int CONNECTION_TIMEOUT = 30 * 1000;
|
||||
|
||||
private final StanzaIdSourceFactory stanzaIdSourceFactory;
|
||||
|
||||
@Inject
|
||||
public XmppTcpConnectionFactory(StanzaIdSourceFactory stanzaIdSourceFactory) {
|
||||
this.stanzaIdSourceFactory = stanzaIdSourceFactory;
|
||||
}
|
||||
|
||||
public AbstractXMPPConnection createConnection(Account account) {
|
||||
try {
|
||||
XMPPTCPConnectionConfiguration.Builder configBuilder =
|
||||
XMPPTCPConnectionConfiguration.builder()
|
||||
.setStanzaIdSourceFactory(stanzaIdSourceFactory)
|
||||
.setConnectTimeout(CONNECTION_TIMEOUT)
|
||||
.setXmppAddressAndPassword(account.getAddress(), account.getPassword());
|
||||
if (account.getHost() != null) {
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package org.mercury_im.messenger.core.connection.message;
|
||||
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
|
||||
import org.mercury_im.messenger.core.data.repository.MessageRepository;
|
||||
import org.mercury_im.messenger.entity.chat.Chat;
|
||||
|
||||
public abstract class AbstractMessageConsignor implements MessageConsignor {
|
||||
|
||||
protected final MessageComposer messageComposer;
|
||||
|
||||
protected final MercuryConnectionManager connectionManager;
|
||||
protected final MessageRepository messageRepository;
|
||||
protected final Chat chat;
|
||||
|
||||
public AbstractMessageConsignor(MessageComposer composer,
|
||||
MercuryConnectionManager connectionManager,
|
||||
MessageRepository messageRepository,
|
||||
Chat chat) {
|
||||
this.messageComposer = composer;
|
||||
this.connectionManager = connectionManager;
|
||||
this.messageRepository = messageRepository;
|
||||
this.chat = chat;
|
||||
}
|
||||
}
|
|
@ -1,27 +1,33 @@
|
|||
package org.mercury_im.messenger.core.connection;
|
||||
package org.mercury_im.messenger.core.connection.message;
|
||||
|
||||
import org.jivesoftware.smack.packet.id.StandardStanzaIdSource;
|
||||
import org.mercury_im.messenger.entity.chat.Chat;
|
||||
import org.mercury_im.messenger.entity.message.Message;
|
||||
import org.mercury_im.messenger.entity.message.MessageDeliveryState;
|
||||
import org.mercury_im.messenger.entity.message.MessageDirection;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MercuryMessageComposer implements MessageCenter.Composer {
|
||||
public class MessageComposer {
|
||||
|
||||
@Override
|
||||
public Message createChatMessage(Chat chat, String body) {
|
||||
UUID messageId = UUID.randomUUID();
|
||||
Message message = new Message();
|
||||
message.setId(messageId);
|
||||
message.setChatId(chat.getId());
|
||||
|
||||
message.setLegacyStanzaId(new StandardStanzaIdSource().getNewStanzaId());
|
||||
message.setOriginId(messageId.toString());
|
||||
|
||||
message.setBody(body);
|
||||
message.setSender(chat.getAccount().getJid());
|
||||
message.setRecipient(chat.getAddress());
|
||||
message.setRecipient(chat.getJid());
|
||||
message.setDeliveryState(MessageDeliveryState.pending_delivery);
|
||||
message.setDirection(MessageDirection.outgoing);
|
||||
message.setRead(false);
|
||||
message.setTimestamp(new Date());
|
||||
|
||||
UUID messageId = UUID.randomUUID();
|
||||
message.setId(messageId);
|
||||
message.setOriginId(messageId.toString());
|
||||
return message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package org.mercury_im.messenger.core.connection.message;
|
||||
|
||||
public interface MessageConsignee {
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package org.mercury_im.messenger.core.connection.message;
|
||||
|
||||
import org.mercury_im.messenger.entity.chat.Chat;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import io.reactivex.Single;
|
||||
|
||||
public interface MessageConsignor {
|
||||
|
||||
Single<UUID> sendTextMessage(Chat chat, String body);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package org.mercury_im.messenger.core.connection.message;
|
||||
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
|
||||
import org.mercury_im.messenger.core.data.repository.MessageRepository;
|
||||
import org.mercury_im.messenger.entity.chat.Chat;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import io.reactivex.Single;
|
||||
|
||||
public class OxMessageConsignor extends AbstractMessageConsignor {
|
||||
|
||||
public OxMessageConsignor(MercuryConnectionManager connectionManager, MessageRepository messageRepository, Chat chat) {
|
||||
this(new MessageComposer(), connectionManager, messageRepository, chat);
|
||||
}
|
||||
|
||||
public OxMessageConsignor(MessageComposer composer, MercuryConnectionManager connectionManager, MessageRepository messageRepository, Chat chat) {
|
||||
super(composer, connectionManager, messageRepository, chat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Single<UUID> sendTextMessage(Chat chat, String body) {
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package org.mercury_im.messenger.core.connection.message;
|
||||
|
||||
import org.jivesoftware.smack.chat2.ChatManager;
|
||||
import org.jivesoftware.smack.packet.MessageBuilder;
|
||||
import org.jivesoftware.smackx.muc.MultiUserChat;
|
||||
import org.jivesoftware.smackx.muc.MultiUserChatManager;
|
||||
import org.jivesoftware.smackx.sid.element.OriginIdElement;
|
||||
import org.jxmpp.jid.parts.Resourcepart;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnection;
|
||||
import org.mercury_im.messenger.core.connection.MercuryConnectionManager;
|
||||
import org.mercury_im.messenger.core.data.repository.MessageRepository;
|
||||
import org.mercury_im.messenger.core.util.AppendCompletableToSingle;
|
||||
import org.mercury_im.messenger.entity.chat.Chat;
|
||||
import org.mercury_im.messenger.entity.chat.DirectChat;
|
||||
import org.mercury_im.messenger.entity.chat.GroupChat;
|
||||
import org.mercury_im.messenger.entity.message.Message;
|
||||
import org.mercury_im.messenger.entity.message.MessageDeliveryState;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Single;
|
||||
|
||||
public class PlaintextMessageConsignor extends AbstractMessageConsignor {
|
||||
|
||||
public PlaintextMessageConsignor(MercuryConnectionManager connectionManager, MessageRepository messageRepository, Chat chat) {
|
||||
this(new MessageComposer(), connectionManager, messageRepository, chat);
|
||||
}
|
||||
|
||||
public PlaintextMessageConsignor(MessageComposer composer,
|
||||
MercuryConnectionManager connectionManager,
|
||||
MessageRepository messageRepository,
|
||||
Chat chat) {
|
||||
super(composer, connectionManager, messageRepository, chat);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Single<UUID> sendTextMessage(Chat chat, String body) {
|
||||
Message message = messageComposer.createChatMessage(chat, body);
|
||||
MessageBuilder messageBuilder = commonMessageBuilder(message);
|
||||
|
||||
Completable deliverMessage;
|
||||
if (chat instanceof DirectChat) {
|
||||
deliverMessage = sendDirectChatMessage((DirectChat) chat, messageBuilder);
|
||||
} else if (chat instanceof GroupChat) {
|
||||
deliverMessage = sendGroupChatMessage((GroupChat) chat, messageBuilder);
|
||||
} else {
|
||||
throw new AssertionError("Unknown chat type.");
|
||||
}
|
||||
|
||||
Single<UUID> deliverAndStore = messageRepository.insertMessage(message)
|
||||
.map(Message::getId)
|
||||
.compose(new AppendCompletableToSingle<>(deliverMessage))
|
||||
.flatMap(messageId -> messageRepository.updateDeliveryState(messageId, MessageDeliveryState.delivered_to_server)
|
||||
.toSingle(() -> messageId));
|
||||
|
||||
return deliverAndStore;
|
||||
}
|
||||
|
||||
private MessageBuilder commonMessageBuilder(Message message) {
|
||||
return MessageBuilder.buildMessage(message.getLegacyStanzaId())
|
||||
.ofType(org.jivesoftware.smack.packet.Message.Type.chat)
|
||||
.addExtension(new OriginIdElement(message.getOriginId()))
|
||||
.to(chat.getJid())
|
||||
.from(chat.getAccount().getJid())
|
||||
.setBody(message.getBody());
|
||||
}
|
||||
|
||||
private Completable sendDirectChatMessage(DirectChat chat, MessageBuilder messageBuilder) {
|
||||
return Completable.fromAction(() -> {
|
||||
MercuryConnection connection = connectionManager.getConnection(chat.getAccount());
|
||||
ChatManager chatManager = ChatManager.getInstanceFor(connection.getConnection());
|
||||
org.jivesoftware.smack.chat2.Chat smackChat = chatManager.chatWith(chat.getJid().asEntityBareJid());
|
||||
|
||||
smackChat.send(messageBuilder.build());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private Completable sendGroupChatMessage(GroupChat chat, MessageBuilder messageBuilder) {
|
||||
return Completable.fromAction(() -> {
|
||||
MercuryConnection connection = connectionManager.getConnection(chat.getAccount());
|
||||
MultiUserChatManager multiUserChatManager = MultiUserChatManager.getInstanceFor(connection.getConnection());
|
||||
MultiUserChat muc = multiUserChatManager.getMultiUserChat(chat.getJid().asEntityBareJid());
|
||||
if (!muc.isJoined()) {
|
||||
muc.join(Resourcepart.from(chat.getNickname()));
|
||||
}
|
||||
muc.sendMessage(messageBuilder);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -1,10 +1,14 @@
|
|||
package org.mercury_im.messenger.core.data.repository;
|
||||
|
||||
import org.jxmpp.jid.EntityBareJid;
|
||||
import org.mercury_im.messenger.entity.chat.DirectChat;
|
||||
import org.mercury_im.messenger.entity.chat.GroupChat;
|
||||
import org.mercury_im.messenger.entity.message.ChatMarkerState;
|
||||
import org.mercury_im.messenger.entity.message.Message;
|
||||
import org.mercury_im.messenger.entity.message.MessageDeliveryState;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Observable;
|
||||
|
@ -29,4 +33,8 @@ public interface MessageRepository {
|
|||
Single<Message> updateMessage(Message message);
|
||||
|
||||
Completable deleteMessage(Message message);
|
||||
|
||||
Completable markMessage(String stanzaId, EntityBareJid xmppAddressOfChatPartner, ChatMarkerState received);
|
||||
|
||||
Completable updateDeliveryState(UUID messageId, MessageDeliveryState deliveryState);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package org.mercury_im.messenger.core.di.module;
|
||||
|
||||
import org.jivesoftware.smack.packet.id.StandardStanzaIdSource;
|
||||
import org.jivesoftware.smack.packet.id.StanzaIdSourceFactory;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
@Module
|
||||
public class StanzaIdSourceFactoryModule {
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
static StanzaIdSourceFactory provideStanzaIdSourceFactory() {
|
||||
return new StandardStanzaIdSource.Factory();
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package org.mercury_im.messenger.core.di.module;
|
||||
|
||||
import org.jivesoftware.smack.packet.id.StanzaIdSourceFactory;
|
||||
import org.mercury_im.messenger.core.connection.XmppConnectionFactory;
|
||||
import org.mercury_im.messenger.core.connection.XmppTcpConnectionFactory;
|
||||
|
||||
|
@ -13,7 +14,7 @@ public class XmppTcpConnectionFactoryModule {
|
|||
|
||||
@Provides
|
||||
@Singleton
|
||||
static XmppConnectionFactory provideConnectionFactory() {
|
||||
return new XmppTcpConnectionFactory();
|
||||
static XmppConnectionFactory provideConnectionFactory(StanzaIdSourceFactory stanzaIdSourceFactory) {
|
||||
return new XmppTcpConnectionFactory(stanzaIdSourceFactory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ import io.reactivex.disposables.CompositeDisposable;
|
|||
import io.reactivex.disposables.Disposable;
|
||||
|
||||
@Singleton
|
||||
public class MercuryMessageStore implements IncomingChatMessageListener, OutgoingChatMessageListener, OxMessageListener {
|
||||
public class MercuryMessageStore implements IncomingChatMessageListener, OxMessageListener {
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(MercuryMessageStore.class.getName());
|
||||
|
||||
|
@ -66,8 +66,8 @@ public class MercuryMessageStore implements IncomingChatMessageListener, Outgoin
|
|||
message.setDirection(MessageDirection.incoming);
|
||||
DelayInformation delayInformation = DelayInformation.from(smackMessage);
|
||||
message.setTimestamp(delayInformation != null ? delayInformation.getStamp() : new Date());
|
||||
message.setSender(from.asEntityBareJidString());
|
||||
message.setRecipient(smackMessage.getTo().asBareJid().toString());
|
||||
message.setSender(from);
|
||||
message.setRecipient(smackMessage.getTo().asEntityJidOrThrow());
|
||||
message.setXml(smackMessage.toXML().toString());
|
||||
if (smackMessage.getBody() != null) {
|
||||
message.setBody(smackMessage.getBody());
|
||||
|
@ -75,25 +75,6 @@ public class MercuryMessageStore implements IncomingChatMessageListener, Outgoin
|
|||
disposable.add(writeMessageToStore(from, message));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newOutgoingMessage(EntityBareJid to,
|
||||
MessageBuilder smackMessage,
|
||||
org.jivesoftware.smack.chat2.Chat smackChat) {
|
||||
if (smackMessage.hasExtension(ExplicitMessageEncryptionElement.QNAME)) {
|
||||
return;
|
||||
}
|
||||
Message message = new Message();
|
||||
message.setDirection(MessageDirection.outgoing);
|
||||
message.setTimestamp(new Date());
|
||||
message.setSender(account.getAddress());
|
||||
message.setRecipient(to.asBareJid().toString());
|
||||
message.setXml(smackMessage.build().toXML().toString());
|
||||
if (smackMessage.getBody() != null) {
|
||||
message.setBody(smackMessage.getBody());
|
||||
}
|
||||
disposable.add(writeMessageToStore(to, message));
|
||||
}
|
||||
|
||||
private Disposable writeMessageToStore(EntityBareJid peer, Message message) {
|
||||
return peerRepository.getOrCreatePeer(account, peer)
|
||||
.flatMap(directChatRepository::getOrCreateChatWithPeer)
|
||||
|
@ -115,8 +96,8 @@ public class MercuryMessageStore implements IncomingChatMessageListener, Outgoin
|
|||
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());
|
||||
message.setSender(contact.getJid().asEntityJidOrThrow());
|
||||
message.setRecipient(smackMessage.getTo().asEntityJidOrThrow());
|
||||
message.setXml(smackMessage.toXML().toString());
|
||||
org.jivesoftware.smack.packet.Message.Body body = decryptedPayload.getExtension(org.jivesoftware.smack.packet.Message.Body.ELEMENT,
|
||||
org.jivesoftware.smack.packet.Message.Body.NAMESPACE);
|
||||
|
|
|
@ -117,11 +117,11 @@ public class LoginViewModel implements MercuryViewModel {
|
|||
|
||||
Account account = createAccountEntity();
|
||||
|
||||
MercuryConnection connection = connectionManager.createConnection(account);
|
||||
//MercuryConnection connection = connectionManager.createConnection(account);
|
||||
addDisposable(accountRepository.upsertAccount(account).ignoreElement()
|
||||
.andThen(connection.connect())
|
||||
.andThen(connection.login())
|
||||
.andThen(connectionManager.registerConnection(connection))
|
||||
//.andThen(connection.connect())
|
||||
//.andThen(connection.login())
|
||||
//.andThen(connectionManager.registerConnection(connection))
|
||||
.subscribeOn(schedulers.getNewThread())
|
||||
.observeOn(schedulers.getUiScheduler())
|
||||
.subscribe(
|
||||
|
|
|
@ -19,6 +19,7 @@ import java.util.logging.Logger;
|
|||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
import io.reactivex.functions.Function;
|
||||
import io.reactivex.subjects.BehaviorSubject;
|
||||
import lombok.Getter;
|
||||
|
||||
|
@ -35,8 +36,6 @@ public class ChatViewModel implements MercuryViewModel {
|
|||
@Getter
|
||||
private BehaviorSubject<Optional<Peer>> peer = BehaviorSubject.create();
|
||||
|
||||
private Single<DirectChat> directChat;
|
||||
|
||||
@Getter
|
||||
private BehaviorSubject<DirectChat> chat = BehaviorSubject.create();
|
||||
|
||||
|
@ -62,13 +61,20 @@ public class ChatViewModel implements MercuryViewModel {
|
|||
}
|
||||
|
||||
public void init(UUID accountId, EntityBareJid contactJid) {
|
||||
Single<Peer> peerSingle = contactRepository.getOrCreatePeer(accountId, contactJid);
|
||||
peerSingle.flatMapObservable(contactRepository::observePeer).subscribe(peer);
|
||||
directChat = peerSingle.flatMap(directChatRepository::getOrCreateChatWithPeer);
|
||||
contactRepository.getOrCreatePeer(accountId, contactJid)
|
||||
.flatMapObservable(contactRepository::observePeer)
|
||||
.subscribe(peer);
|
||||
|
||||
directChat.toObservable().compose(schedulers.executeUiSafeObservable()).subscribe(chat);
|
||||
peer.compose(schedulers.executeUiSafeObservable())
|
||||
.subscribe();
|
||||
|
||||
Observable<List<Message>> allMessagesObservable = directChat.flatMapObservable(messageRepository::observeMessages);
|
||||
peer.filter(Optional::isPresent).map(Optional::getItem)
|
||||
.flatMap(p -> directChatRepository.getOrCreateChatWithPeer(p).toObservable())
|
||||
.subscribe(chat);
|
||||
|
||||
chat.compose(schedulers.executeUiSafeObservable()).subscribe();
|
||||
|
||||
Observable<List<Message>> allMessagesObservable = chat.flatMap(messageRepository::observeMessages);
|
||||
messageQueryObservable.onNext(allMessagesObservable);
|
||||
messages = Observable.switchOnNext(messageQueryObservable);
|
||||
contactDisplayName = peer.filter(Optional::isPresent).map(Optional::getItem)
|
||||
|
@ -77,9 +83,9 @@ public class ChatViewModel implements MercuryViewModel {
|
|||
|
||||
public void onQueryTextChanged(String query) {
|
||||
if (query.trim().isEmpty()) {
|
||||
messageQueryObservable.onNext(directChat.flatMapObservable(messageRepository::observeMessages));
|
||||
messageQueryObservable.onNext(chat.flatMap(messageRepository::observeMessages));
|
||||
} else {
|
||||
messageQueryObservable.onNext(directChat.flatMapObservable(c -> messageRepository.findMessagesWithBody(c, query)));
|
||||
messageQueryObservable.onNext(chat.flatMap(c -> messageRepository.findMessagesWithBody(c, query)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -95,9 +101,10 @@ public class ChatViewModel implements MercuryViewModel {
|
|||
}
|
||||
|
||||
public void sendMessage(String body) {
|
||||
addDisposable(messenger.sendEncryptedMessage(peer.getValue().getItem(), body)
|
||||
.compose(schedulers.executeUiSafeCompletable())
|
||||
.subscribe(() -> LOGGER.log(Level.INFO, "Successfully sent encrypted message."),
|
||||
e -> LOGGER.log(Level.SEVERE, "Error sending encrypted message.", e)));
|
||||
addDisposable(messenger.getMessageConsignor(chat.getValue())
|
||||
.sendTextMessage(chat.getValue(), body)
|
||||
.compose(schedulers.executeUiSafeSingle())
|
||||
.subscribe(messageId -> LOGGER.log(Level.INFO, "Successfully sent message."),
|
||||
e -> LOGGER.log(Level.WARNING, "Error sending message.", e)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
package org.mercury_im.messenger.learning_tests.dagger;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
|
||||
public class DaggerTest {
|
||||
|
||||
@dagger.Component(modules = {SingletonModule.class})
|
||||
@Singleton
|
||||
public interface Component {
|
||||
|
||||
void inject(Consumer consumer);
|
||||
}
|
||||
|
||||
@Module
|
||||
public class NewInstanceModule {
|
||||
|
||||
private int DEPENDENCY_INDEX = 0;
|
||||
private final String MODULE_NAME;
|
||||
|
||||
public NewInstanceModule(String moduleName) {
|
||||
this.MODULE_NAME = moduleName;
|
||||
}
|
||||
|
||||
@Provides
|
||||
Dependency provideDependency() {
|
||||
return new Dependency(DEPENDENCY_INDEX++, MODULE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
@Module
|
||||
public class SingletonModule {
|
||||
private int DEPENDENCY_INDEX = 0;
|
||||
private final String MODULE_NAME;
|
||||
|
||||
public SingletonModule(String moduleName) {
|
||||
this.MODULE_NAME = moduleName;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
Dependency provideDependency() {
|
||||
return new Dependency(DEPENDENCY_INDEX++, MODULE_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Dependency {
|
||||
|
||||
final int index;
|
||||
final String moduleName;
|
||||
|
||||
@Inject
|
||||
public Dependency(int index, String moduleName) {
|
||||
this.index = index;
|
||||
this.moduleName = moduleName;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public String getModuleName() {
|
||||
return moduleName;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Consumer {
|
||||
|
||||
@Inject
|
||||
Dependency dependency;
|
||||
|
||||
public Consumer() {
|
||||
|
||||
}
|
||||
|
||||
public Dependency getDependency() {
|
||||
return dependency;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
Component component0 = DaggerDaggerTest_Component.builder().singletonModule(new SingletonModule("First")).build();
|
||||
|
||||
Consumer consumer0 = new Consumer();
|
||||
Consumer consumer1 = new Consumer();
|
||||
|
||||
component0.inject(consumer0);
|
||||
component0.inject(consumer1);
|
||||
|
||||
Component component1 = DaggerDaggerTest_Component.builder().singletonModule(new SingletonModule("Second")).build();
|
||||
|
||||
Consumer consumer2 = new Consumer();
|
||||
Consumer consumer3 = new Consumer();
|
||||
component1.inject(consumer2);
|
||||
component1.inject(consumer3);
|
||||
|
||||
assertEquals(0, consumer0.getDependency().getIndex());
|
||||
assertEquals(1, consumer1.getDependency().getIndex());
|
||||
assertEquals(0, consumer2.getDependency().getIndex());
|
||||
assertEquals(1, consumer3.getDependency().getIndex());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package org.mercury_im.messenger.learning_tests.rx;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.subjects.BehaviorSubject;
|
||||
import io.reactivex.subjects.Subject;
|
||||
|
||||
import static junit.framework.TestCase.assertNotNull;
|
||||
|
||||
public class BehaviourSubjectSubscriptionTest {
|
||||
|
||||
@Test
|
||||
public void test() throws InterruptedException {
|
||||
Observable<String> observable = Observable.just("One", "Two", "Three");
|
||||
BehaviorSubject<String> behaviorSubject = BehaviorSubject.create();
|
||||
|
||||
observable.subscribe(behaviorSubject);
|
||||
behaviorSubject.subscribe(System.out::println);
|
||||
|
||||
Thread.sleep(100);
|
||||
|
||||
String s = behaviorSubject.getValue();
|
||||
assertNotNull(s);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package org.mercury_im.messenger.entity.chat;
|
||||
|
||||
import org.jxmpp.jid.EntityJid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.mercury_im.messenger.entity.Account;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -15,11 +17,15 @@ import lombok.Data;
|
|||
public abstract class Chat {
|
||||
UUID id;
|
||||
Account account;
|
||||
ChatPreferences chatPreferences;
|
||||
ChatPreferences chatPreferences = new ChatPreferences();
|
||||
|
||||
public Chat() {
|
||||
this.id = UUID.randomUUID();
|
||||
}
|
||||
|
||||
public abstract String getAddress();
|
||||
|
||||
public EntityJid getJid() {
|
||||
return JidCreate.entityFromOrThrowUnchecked(getAddress());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.mercury_im.messenger.entity.chat;
|
||||
|
||||
import org.mercury_im.messenger.entity.Encryption;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
|
@ -12,6 +14,7 @@ public class ChatPreferences {
|
|||
boolean sendTypingNotificationsEnabled;
|
||||
boolean readNotificationsSupported;
|
||||
boolean sendReadNotificationsEnabled;
|
||||
Encryption encryption = Encryption.plain; // TODO: Fix
|
||||
|
||||
@Data
|
||||
public static class NotificationPreferences {
|
||||
|
|
|
@ -16,6 +16,7 @@ public class GroupChat extends Chat {
|
|||
Set<Peer> participants;
|
||||
String roomAddress;
|
||||
String roomName;
|
||||
String nickname = "NICK"; // TODO: Fix
|
||||
|
||||
@Override
|
||||
public String getAddress() {
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
package org.mercury_im.messenger.entity.message;
|
||||
|
||||
public enum ChatMarkerState {
|
||||
markable,
|
||||
received,
|
||||
displayed,
|
||||
acknowledged
|
||||
}
|
|
@ -1,10 +1,9 @@
|
|||
package org.mercury_im.messenger.entity.message;
|
||||
|
||||
import org.jxmpp.jid.EntityFullJid;
|
||||
import org.jxmpp.jid.EntityJid;
|
||||
import org.mercury_im.messenger.entity.Encryption;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import lombok.Data;
|
||||
|
@ -13,8 +12,8 @@ import lombok.Data;
|
|||
public class Message {
|
||||
UUID id;
|
||||
UUID chatId;
|
||||
EntityFullJid sender;
|
||||
EntityFullJid recipient;
|
||||
EntityJid sender;
|
||||
EntityJid recipient;
|
||||
|
||||
String body;
|
||||
|
||||
|
@ -34,6 +33,7 @@ public class Message {
|
|||
Encryption encryption;
|
||||
boolean received;
|
||||
boolean read;
|
||||
boolean pending;
|
||||
|
||||
public boolean isIncoming() {
|
||||
return getDirection() == MessageDirection.incoming;
|
||||
|
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
#Sun Sep 01 01:05:38 CEST 2019
|
||||
#Mon Jul 27 15:17:47 CEST 2020
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1267729430f2c53f966b98febf16ef7f262b94d7
|
||||
Subproject commit 30030941307262173ac7347e11235a8cadf68787
|
|
@ -86,7 +86,7 @@ ext {
|
|||
rxAndroidVersion = "2.1.1"
|
||||
|
||||
// Dagger 2
|
||||
daggerVersion = '2.25.4'
|
||||
daggerVersion = '2.28.3'
|
||||
|
||||
// Lombok
|
||||
lombokVersion = '1.18.12'
|
||||
|
|
Loading…
Reference in a new issue