package im.actor.core.modules.messaging.router;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import im.actor.core.api.ApiDialogGroup;
import im.actor.core.api.ApiDialogShort;
import im.actor.core.api.ApiMessageReaction;
import im.actor.core.api.rpc.RequestLoadGroupedDialogs;
import im.actor.core.api.updates.UpdateChatClear;
import im.actor.core.api.updates.UpdateChatDelete;
import im.actor.core.api.updates.UpdateChatDropCache;
import im.actor.core.api.updates.UpdateChatGroupsChanged;
import im.actor.core.api.updates.UpdateMessage;
import im.actor.core.api.updates.UpdateMessageContentChanged;
import im.actor.core.api.updates.UpdateMessageDelete;
import im.actor.core.api.updates.UpdateMessageRead;
import im.actor.core.api.updates.UpdateMessageReadByMe;
import im.actor.core.api.updates.UpdateMessageReceived;
import im.actor.core.api.updates.UpdateMessageSent;
import im.actor.core.api.updates.UpdateReactionsUpdate;
import im.actor.core.entity.Avatar;
import im.actor.core.entity.ContentDescription;
import im.actor.core.entity.ConversationState;
import im.actor.core.entity.Group;
import im.actor.core.entity.Message;
import im.actor.core.entity.MessageState;
import im.actor.core.entity.Peer;
import im.actor.core.entity.PeerType;
import im.actor.core.entity.Reaction;
import im.actor.core.entity.User;
import im.actor.core.entity.content.AbsContent;
import im.actor.core.entity.content.TextContent;
import im.actor.core.modules.AbsModule;
import im.actor.core.modules.ModuleActor;
import im.actor.core.modules.ModuleContext;
import im.actor.core.modules.api.ApiSupportConfiguration;
import im.actor.core.modules.messaging.actions.CursorReaderActor;
import im.actor.core.modules.messaging.actions.CursorReceiverActor;
import im.actor.core.modules.messaging.actions.SenderActor;
import im.actor.core.modules.messaging.dialogs.DialogsInt;
import im.actor.core.modules.messaging.history.entity.DialogHistory;
import im.actor.core.modules.messaging.router.entity.ActiveDialogGroup;
import im.actor.core.modules.messaging.router.entity.ActiveDialogStorage;
import im.actor.core.modules.messaging.router.entity.RouterAppHidden;
import im.actor.core.modules.messaging.router.entity.RouterAppVisible;
import im.actor.core.modules.messaging.router.entity.RouterApplyChatHistory;
import im.actor.core.modules.messaging.router.entity.RouterApplyDialogsHistory;
import im.actor.core.modules.messaging.router.entity.RouterChangedContent;
import im.actor.core.modules.messaging.router.entity.RouterConversationHidden;
import im.actor.core.modules.messaging.router.entity.RouterConversationVisible;
import im.actor.core.modules.messaging.router.entity.RouterDeletedMessages;
import im.actor.core.modules.messaging.router.entity.RouterDifferenceEnd;
import im.actor.core.modules.messaging.router.entity.RouterDifferenceStart;
import im.actor.core.modules.messaging.router.entity.RouterMessageOnlyActive;
import im.actor.core.modules.messaging.router.entity.RouterMessageUpdate;
import im.actor.core.modules.messaging.router.entity.RouterNewMessages;
import im.actor.core.modules.messaging.router.entity.RouterOutgoingError;
import im.actor.core.modules.messaging.router.entity.RouterOutgoingMessage;
import im.actor.core.modules.messaging.router.entity.RouterOutgoingSent;
import im.actor.core.modules.messaging.router.entity.RouterPeersChanged;
import im.actor.core.modules.messaging.router.entity.RouterResetChat;
import im.actor.core.network.parser.Update;
import im.actor.core.util.JavaUtil;
import im.actor.core.viewmodel.DialogGroup;
import im.actor.core.viewmodel.DialogSmall;
import im.actor.core.viewmodel.generics.ArrayListDialogSmall;
import im.actor.runtime.Log;
import im.actor.runtime.actors.messages.Void;
import im.actor.runtime.promise.Promise;
import im.actor.runtime.storage.KeyValueEngine;
import im.actor.runtime.storage.ListEngine;
import static im.actor.core.entity.EntityConverter.convert;
import static im.actor.core.util.AssertUtils.assertTrue;
public class RouterActor extends ModuleActor {
private static final String TAG = "RouterActor";
// j2objc workaround
private static final Void DUMB = null;
// Visibility
private final HashSet<Peer> visiblePeers = new HashSet<>();
private boolean isAppVisible = false;
// Storage
private KeyValueEngine<ConversationState> conversationStates;
// Active Dialogs
private ActiveDialogStorage activeDialogStorage;
public RouterActor(ModuleContext context) {
super(context);
}
@Override
public void preStart() {
super.preStart();
conversationStates = context().getMessagesModule().getConversationStates().getEngine();
//
// Loading Active Dialogs
//
activeDialogStorage = new ActiveDialogStorage();
byte[] data = context().getStorageModule().getBlobStorage().loadItem(AbsModule.BLOB_DIALOGS_ACTIVE);
if (data != null) {
try {
activeDialogStorage = new ActiveDialogStorage(data);
} catch (IOException e) {
e.printStackTrace();
}
}
if (!activeDialogStorage.isLoaded()) {
api(new RequestLoadGroupedDialogs(ApiSupportConfiguration.OPTIMIZATIONS))
.chain(r -> updates().applyRelatedData(r.getUsers(), r.getGroups()))
.chain(r -> updates().loadRequiredPeers(r.getUserPeers(), r.getGroupPeers()))
.then(r -> {
boolean showArchived = false;
boolean showInvite = false;
if (r.showArchived() != null) {
showArchived = r.showArchived();
}
if (r.showInvite() != null) {
showInvite = r.showInvite();
}
onActiveDialogsChanged(r.getDialogs(), showArchived, showInvite);
context().getConductor().getConductor().onDialogsLoaded();
});
} else {
notifyActiveDialogsVM();
context().getConductor().getConductor().onDialogsLoaded();
}
}
//
// Active Dialogs
//
private void onActiveDialogsChanged(List<ApiDialogGroup> dialogs, boolean showArchived, boolean showInvite) {
//
// Updating Counters
//
ArrayList<ConversationState> convStates = new ArrayList<>();
for (ApiDialogGroup g : dialogs) {
for (ApiDialogShort s : g.getDialogs()) {
Peer peer = convert(s.getPeer());
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
boolean isChanged = false;
if (state.getUnreadCount() != s.getCounter() && !isConversationVisible(peer)) {
state = state.changeCounter(s.getCounter());
isChanged = true;
}
if (state.getInMaxMessageDate() < s.getDate()) {
state = state.changeInMaxDate(s.getDate());
isChanged = true;
}
if (isChanged) {
convStates.add(state);
}
}
}
conversationStates.addOrUpdateItems(convStates);
//
// Updating storage
//
activeDialogStorage.setHaveArchived(showArchived);
activeDialogStorage.setShowInvite(showInvite);
activeDialogStorage.setLoaded(true);
activeDialogStorage.getGroups().clear();
for (ApiDialogGroup g : dialogs) {
ArrayList<Peer> peers = new ArrayList<>();
for (ApiDialogShort s : g.getDialogs()) {
Peer peer = convert(s.getPeer());
peers.add(peer);
}
activeDialogStorage.getGroups().add(new ActiveDialogGroup(g.getKey(), g.getTitle(), peers));
}
context().getStorageModule().getBlobStorage()
.addOrUpdateItem(AbsModule.BLOB_DIALOGS_ACTIVE, activeDialogStorage.toByteArray());
//
// Notify VM
//
notifyActiveDialogsVM();
//
// Unstash all messages after initial loading
//
unstashAll();
}
//
// Incoming Messages
//
private Promise<Void> onNewMessages(Peer peer, List<Message> messages) {
assertTrue(messages.size() != 0);
boolean isConversationVisible = isConversationVisible(peer);
//
// Collecting Information
//
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
Message topMessage = null;
int unreadCount = 0;
long maxInReadDate = 0;
long maxInDate = 0;
for (Message m : messages) {
if (topMessage == null || topMessage.getSortDate() < m.getSortDate()) {
topMessage = m;
}
if (m.getSenderId() != myUid()) {
if (m.getSortDate() > state.getInReadDate()) {
unreadCount++;
maxInReadDate = Math.max(maxInReadDate, m.getSortDate());
}
if (m.getSortDate() > state.getInMaxMessageDate()) {
maxInDate = Math.max(maxInDate, m.getSortDate());
}
}
}
//
// Writing to Conversation
//
conversation(peer).addOrUpdateItems(messages);
//
// Update Chat State
//
updateChatState(peer);
//
// Updating Counter
//
boolean isRead = false;
if (unreadCount != 0) {
if (isConversationVisible) {
// Auto Reading message
boolean needUpdateState = false;
if (maxInReadDate > 0) {
if (state.getInReadDate() < maxInReadDate) {
state = state.changeInReadDate(maxInReadDate);
}
state = state.changeCounter(0);
context().getMessagesModule().getPlainReadActor()
.send(new CursorReaderActor.MarkRead(peer, maxInReadDate));
context().getNotificationsModule().onOwnRead(peer, maxInReadDate);
isRead = true;
needUpdateState = true;
}
if (state.getInMaxMessageDate() < maxInDate) {
state.changeInMaxDate(maxInDate);
needUpdateState = true;
}
if (needUpdateState) {
conversationStates.addOrUpdateItem(state);
}
} else {
// Updating counter
state = state.changeCounter(state.getUnreadCount() + unreadCount);
if (state.getInMaxMessageDate() < maxInDate) {
state = state
.changeInMaxDate(maxInDate);
}
conversationStates.addOrUpdateItem(state);
notifyActiveDialogsVM();
}
}
//
// Marking As Received
//
if (maxInReadDate > 0 && !isRead) {
context().getMessagesModule().getPlainReceiverActor()
.send(new CursorReceiverActor.MarkReceived(peer, maxInReadDate));
}
//
// Updating Dialog List
//
Promise<Void> res = getDialogsRouter().onMessage(peer, topMessage, state.getUnreadCount());
//
// Playing notifications
//
if (!isConversationVisible) {
for (Message m : messages) {
if (m.getSenderId() != myUid()) {
boolean hasCurrentMention = false;
if (m.getContent() instanceof TextContent) {
if (((TextContent) m.getContent()).getMentions().contains(myUid())) {
hasCurrentMention = true;
}
}
int messagesCount = 0;
int dialogsCount = 0;
for (Peer activePeer : activeDialogStorage.getAllPeers()) {
int activeDialogueUnreadCount = conversationStates.getValue(activePeer.getUnuqueId()).getUnreadCount();
if (activeDialogueUnreadCount > 0) {
dialogsCount++;
messagesCount += activeDialogueUnreadCount;
}
}
context().getNotificationsModule().onInMessage(
peer,
m.getSenderId(),
m.getSortDate(),
ContentDescription.fromContent(m.getContent()),
hasCurrentMention,
messagesCount,
dialogsCount);
}
}
}
return res;
}
//
// Outgoing Messages
//
private Promise<Void> onOutgoingMessage(Peer peer, Message message) {
conversation(peer).addOrUpdateItem(message);
updateChatState(peer);
return Promise.success(null);
}
private Promise<Void> onOutgoingSent(Peer peer, long rid, long date) {
Message msg = conversation(peer).getValue(rid);
// If we have pending message
if (msg != null && (msg.getMessageState() == MessageState.PENDING)) {
// Updating message
Message updatedMsg = msg
.changeAllDate(date)
.changeState(MessageState.SENT);
conversation(peer).addOrUpdateItem(updatedMsg);
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
conversationStates.addOrUpdateItem(state.changeOutSendDate(date));
updateChatState(peer);
// Notify dialogs
return getDialogsRouter().onMessage(peer, updatedMsg, -1);
} else {
return Promise.success(null);
}
}
private Promise<Void> onOutgoingError(Peer peer, long rid) {
Message msg = conversation(peer).getValue(rid);
// If we have pending message
if (msg != null && (msg.getMessageState() == MessageState.PENDING)) {
// Updating message
Message updatedMsg = msg
.changeState(MessageState.ERROR);
conversation(peer).addOrUpdateItem(updatedMsg);
updateChatState(peer);
}
return Promise.success(null);
}
//
// History Messages
//
private Promise<Void> onDialogHistoryLoaded(List<DialogHistory> dialogs) {
for (DialogHistory d : dialogs) {
ConversationState state = conversationStates.getValue(d.getPeer().getUnuqueId());
if (d.getUnreadCount() > 0) {
state = state
.changeCounter(d.getUnreadCount())
.changeInMaxDate(d.getDate());
}
if (d.isRead()) {
state = state
.changeOutReadDate(d.getDate())
.changeOutReceiveDate(d.getDate());
} else if (d.isReceived()) {
state = state
.changeOutReceiveDate(d.getDate());
}
conversationStates.addOrUpdateItem(state);
}
return getDialogsRouter().onHistoryLoaded(dialogs);
}
private Promise<Void> onChatHistoryLoaded(Peer peer, List<Message> messages, Long maxReadDate,
Long maxReceiveDate, boolean isEnded) {
Log.d(TAG, "History Loaded");
long maxMessageDate = 0;
// Processing all new messages
ArrayList<Message> updated = new ArrayList<>();
for (Message historyMessage : messages) {
// Ignore already present messages
if (conversation(peer).getValue(historyMessage.getEngineId()) != null) {
continue;
}
updated.add(historyMessage);
if (historyMessage.getSenderId() != myUid()) {
maxMessageDate = Math.max(maxMessageDate, historyMessage.getSortDate());
}
}
// Writing messages
conversation(peer).addOrUpdateItems(updated);
// Updating conversation state
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
boolean isChanged = false;
if (state.getInMaxMessageDate() < maxMessageDate) {
state = state.changeInMaxDate(maxMessageDate);
isChanged = true;
}
if (maxReadDate != null && maxReadDate != 0 && state.getOutReadDate() < maxMessageDate) {
state = state.changeOutReadDate(maxReadDate);
isChanged = true;
}
if (maxReceiveDate != null && maxReceiveDate != 0 && state.getOutReceiveDate() < maxReceiveDate) {
state = state.changeOutReceiveDate(maxReceiveDate);
isChanged = true;
}
if (state.isLoaded() != isEnded) {
state = state.changeIsLoaded(isEnded);
isChanged = true;
}
boolean isEmpty = conversation(peer).isEmpty();
if (state.isEmpty() != isEmpty) {
state = state.changeIsEmpty(isEmpty);
isChanged = true;
}
if (isChanged) {
conversationStates.addOrUpdateItem(state);
}
// Reading messages if needed
markAsReadIfNeeded(peer);
return Promise.success(null);
}
//
// Message Updating
//
private Promise<Void> onContentUpdate(Peer peer, long rid, AbsContent content) {
Message message = conversation(peer).getValue(rid);
if (message != null) {
conversation(peer).addOrUpdateItem(message.changeContent(content.incrementUpdatedCounter(message.getContent().getUpdatedCounter())));
return getDialogsRouter().onMessageContentChanged(peer, rid, content);
} else {
return Promise.success(null);
}
}
private Promise<Void> onReactionsUpdate(Peer peer, long rid, List<Reaction> reactions) {
Message message = conversation(peer).getValue(rid);
// Ignore if we already doesn't have this message
if (message != null) {
conversation(peer).addOrUpdateItem(message.changeReactions(reactions));
}
return Promise.success(null);
}
//
// Message Deletions
//
private Promise<Void> onMessageDeleted(Peer peer, List<Long> rids) {
// Delete Messages
conversation(peer).removeItems(JavaUtil.unbox(rids));
updateChatState(peer);
Message head = conversation(peer).getHeadValue();
if (head != null) {
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
state = state
.changeInReadDate(head.getSortDate())
.changeOutSendDate(head.getSortDate());
conversationStates.addOrUpdateItem(state);
if (head.getMessageState() == MessageState.PENDING) {
head = null;
}
}
return getDialogsRouter().onMessageDeleted(peer, head);
}
private Promise<Void> onChatClear(Peer peer) {
conversation(peer).clear();
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
if (!state.isLoaded()) {
state = state.changeIsLoaded(true);
conversationStates.addOrUpdateItem(state);
}
updateChatState(peer);
return getDialogsRouter().onChatClear(peer);
}
private Promise<Void> onChatDropCache(Peer peer) {
return context().getMessagesModule().getHistoryActor(peer).reset();
}
private Promise<Void> onChatReset(Peer peer) {
Log.d(TAG, "onChatReset");
conversation(peer).clear();
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
state = state.changeIsLoaded(false);
conversationStates.addOrUpdateItem(state);
updateChatState(peer);
return Promise.success(null);
}
private Promise<Void> onChatDelete(Peer peer) {
conversation(peer).clear();
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
if (!state.isLoaded()) {
state = state.changeIsLoaded(true);
conversationStates.addOrUpdateItem(state);
}
updateChatState(peer);
return getDialogsRouter().onChatDelete(peer).chain(aVoid -> onChatDropCache(peer));
}
//
// Read States
//
private Promise<Void> onMessageRead(Peer peer, long date) {
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
boolean isChanged = false;
Promise<Void> res;
if (date > state.getOutReadDate()) {
state = state.changeOutReadDate(date);
res = getDialogsRouter().onPeerReadChanged(peer, date);
isChanged = true;
} else {
res = Promise.success(null);
}
if (date > state.getOutReceiveDate()) {
state = state.changeOutReceiveDate(date);
isChanged = true;
}
if (isChanged) {
conversationStates.addOrUpdateItem(state);
}
return res;
}
private Promise<Void> onMessageReceived(Peer peer, long date) {
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
if (date > state.getOutReceiveDate()) {
state = state.changeOutReceiveDate(date);
conversationStates.addOrUpdateItem(state);
return getDialogsRouter().onPeerReceiveChanged(peer, date);
} else {
return Promise.success(null);
}
}
private Promise<Void> onMessageReadByMe(Peer peer, long date, int counter) {
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
if (state.getInReadDate() >= date) {
return Promise.success(null);
}
state = state
.changeCounter(counter)
.changeInReadDate(date);
conversationStates.addOrUpdateItem(state);
Promise<Void> res = getDialogsRouter().onCounterChanged(peer, counter);
notifyActiveDialogsVM();
context().getNotificationsModule().onOwnRead(peer, date);
return res;
}
//
// Peer Changed
//
private Promise<Void> onPeersChanged(List<User> users, List<Group> groups) {
Promise<Void> res = Promise.success(null);
boolean isActiveNeedUpdate = false;
for (User u : users) {
if (!isActiveNeedUpdate) {
for (ActiveDialogGroup g : activeDialogStorage.getGroups()) {
if (g.getPeers().contains(u.peer())) {
isActiveNeedUpdate = true;
break;
}
}
}
res = res.chain(v -> getDialogsRouter().onUserChanged(u));
}
for (Group group : groups) {
if (!isActiveNeedUpdate) {
for (ActiveDialogGroup g : activeDialogStorage.getGroups()) {
if (g.getPeers().contains(group.peer())) {
isActiveNeedUpdate = true;
break;
}
}
}
res = res.chain(v -> getDialogsRouter().onGroupChanged(group));
}
if (isActiveNeedUpdate) {
notifyActiveDialogsVM();
}
return res;
}
//
// Auto Messages Read
//
private void onConversationVisible(Peer peer) {
visiblePeers.add(peer);
markAsReadIfNeeded(peer);
updateChatState(peer);
}
private void onConversationHidden(Peer peer) {
visiblePeers.remove(peer);
}
private void onAppVisible() {
isAppVisible = true;
for (Peer p : visiblePeers) {
markAsReadIfNeeded(p);
}
}
private void onAppHidden() {
isAppVisible = false;
}
private boolean isConversationVisible(Peer peer) {
return visiblePeers.contains(peer) && isAppVisible;
}
private void markAsReadIfNeeded(Peer peer) {
if (isConversationVisible(peer)) {
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
long inMaxMessageDate = state.getInMaxMessageDate();
//check UnreadCount for zero, because it can be loaded from server (after login)
if (state.getUnreadCount() != 0 || state.getInReadDate() < inMaxMessageDate) {
state = state
.changeCounter(0)
.changeInReadDate(inMaxMessageDate);
conversationStates.addOrUpdateItem(state);
context().getMessagesModule().getPlainReadActor()
.send(new CursorReaderActor.MarkRead(peer, inMaxMessageDate));
notifyActiveDialogsVM();
getDialogsRouter().onCounterChanged(peer, 0);
context().getNotificationsModule().onOwnRead(peer, inMaxMessageDate);
}
}
}
private void updateChatState(Peer peer) {
boolean isEmpty = conversation(peer).isEmpty();
ConversationState state = conversationStates.getValue(peer.getUnuqueId());
if (state.isEmpty() != isEmpty) {
state = state.changeIsEmpty(isEmpty);
}
conversationStates.addOrUpdateItem(state);
}
//
// Difference Handling
//
public Promise<Void> onDifferenceStart() {
context().getNotificationsModule().pauseNotifications();
return Promise.success(null);
}
public Promise<Void> onDifferenceEnd() {
context().getNotificationsModule().resumeNotifications();
return Promise.success(null);
}
//
// Tools
//
private DialogsInt getDialogsRouter() {
return context().getMessagesModule().getDialogsInt();
}
private ListEngine<Message> conversation(Peer peer) {
return context().getMessagesModule().getConversationEngine(peer);
}
private void notifyActiveDialogsVM() {
int counter = 0;
ArrayList<DialogGroup> groups = new ArrayList<>();
for (ActiveDialogGroup i : activeDialogStorage.getGroups()) {
ArrayListDialogSmall dialogSmalls = new ArrayListDialogSmall();
for (Peer p : i.getPeers()) {
String title;
Avatar avatar;
if (p.getPeerType() == PeerType.GROUP) {
Group group = getGroup(p.getPeerId());
title = group.getTitle();
avatar = group.getAvatar();
} else if (p.getPeerType() == PeerType.PRIVATE) {
User user = getUser(p.getPeerId());
title = user.getName();
avatar = user.getAvatar();
} else {
continue;
}
int unreadCount = conversationStates.getValue(p.getUnuqueId()).getUnreadCount();
counter += unreadCount;
dialogSmalls.add(new DialogSmall(p, title, avatar, unreadCount));
}
groups.add(new DialogGroup(i.getTitle(), i.getKey(), dialogSmalls));
}
context().getMessagesModule().getDialogGroupsVM().getGroupsValueModel().change(groups);
context().getConductor().getGlobalStateVM().onGlobalCounterChanged(counter);
}
public boolean isValidPeer(Peer peer) {
if (peer.getPeerType() == PeerType.PRIVATE) {
return users().getValue(peer.getPeerId()) != null;
} else if (peer.getPeerType() == PeerType.GROUP) {
return groups().getValue(peer.getPeerId()) != null;
}
return false;
}
//
// Messages
//
public Promise<Void> onUpdate(Update update) {
if (update instanceof UpdateMessage) {
UpdateMessage msg = (UpdateMessage) update;
Peer peer = convert(msg.getPeer());
AbsContent msgContent = AbsContent.fromMessage(msg.getMessage());
Message message = new Message(
msg.getRid(),
msg.getDate(),
msg.getDate(),
msg.getSenderUid(),
myUid() == msg.getSenderUid() ? MessageState.SENT : MessageState.UNKNOWN,
msgContent);
ArrayList<Message> messages = new ArrayList<>();
messages.add(message);
return onNewMessages(peer, messages);
} else if (update instanceof UpdateMessageSent) {
UpdateMessageSent messageSent = (UpdateMessageSent) update;
Peer peer = convert(messageSent.getPeer());
if (isValidPeer(peer)) {
// Notify Sender
context().getMessagesModule()
.getSendMessageActor()
.send(new SenderActor.MessageSent(peer, messageSent.getRid()));
return onOutgoingSent(
peer,
messageSent.getRid(),
messageSent.getDate());
}
return Promise.success(null);
} else if (update instanceof UpdateMessageRead) {
UpdateMessageRead read = (UpdateMessageRead) update;
Peer peer = convert(read.getPeer());
if (isValidPeer(peer)) {
return onMessageRead(peer, read.getStartDate());
}
return Promise.success(null);
} else if (update instanceof UpdateMessageReadByMe) {
UpdateMessageReadByMe readByMe = (UpdateMessageReadByMe) update;
Peer peer = convert(readByMe.getPeer());
if (isValidPeer(peer)) {
int counter = 0;
if (readByMe.getUnreadCounter() != null) {
counter = readByMe.getUnreadCounter();
}
return onMessageReadByMe(peer, readByMe.getStartDate(), counter);
}
return Promise.success(null);
} else if (update instanceof UpdateMessageReceived) {
UpdateMessageReceived received = (UpdateMessageReceived) update;
Peer peer = convert(received.getPeer());
if (isValidPeer(peer)) {
return onMessageReceived(peer, received.getStartDate());
}
return Promise.success(null);
} else if (update instanceof UpdateChatDelete) {
UpdateChatDelete delete = (UpdateChatDelete) update;
Peer peer = convert(delete.getPeer());
if (isValidPeer(peer)) {
return onChatDelete(peer);
}
return Promise.success(null);
} else if (update instanceof UpdateChatClear) {
UpdateChatClear clear = (UpdateChatClear) update;
Peer peer = convert(clear.getPeer());
if (isValidPeer(peer)) {
return onChatClear(peer);
}
return Promise.success(null);
} else if (update instanceof UpdateChatDropCache) {
UpdateChatDropCache dropCache = (UpdateChatDropCache) update;
Peer peer = convert(dropCache.getPeer());
if (isValidPeer(peer)) {
return onChatDropCache(peer);
}
return Promise.success(null);
} else if (update instanceof UpdateChatGroupsChanged) {
UpdateChatGroupsChanged chatGroupsChanged = (UpdateChatGroupsChanged) update;
onActiveDialogsChanged(chatGroupsChanged.getDialogs(), true, true);
return Promise.success(null);
} else if (update instanceof UpdateMessageDelete) {
UpdateMessageDelete delete = (UpdateMessageDelete) update;
Peer peer = convert(delete.getPeer());
if (isValidPeer(peer)) {
return onMessageDeleted(peer, delete.getRids());
}
return Promise.success(null);
} else if (update instanceof UpdateMessageContentChanged) {
UpdateMessageContentChanged contentChanged = (UpdateMessageContentChanged) update;
Peer peer = convert(contentChanged.getPeer());
if (isValidPeer(peer)) {
AbsContent content = AbsContent.fromMessage(contentChanged.getMessage());
return onContentUpdate(peer, contentChanged.getRid(), content);
}
return Promise.success(null);
} else if (update instanceof UpdateReactionsUpdate) {
UpdateReactionsUpdate reactionsUpdate = (UpdateReactionsUpdate) update;
Peer peer = convert(reactionsUpdate.getPeer());
if (isValidPeer(peer)) {
ArrayList<Reaction> reactions = new ArrayList<>();
for (ApiMessageReaction r : reactionsUpdate.getReactions()) {
reactions.add(new Reaction(r.getCode(), r.getUsers()));
}
return onReactionsUpdate(peer, reactionsUpdate.getRid(), reactions);
}
return Promise.success(null);
}
return Promise.success(null);
}
@Override
public void onReceive(Object message) {
if (!activeDialogStorage.isLoaded() && message instanceof RouterMessageOnlyActive) {
stash();
return;
}
if (message instanceof RouterConversationVisible) {
RouterConversationVisible conversationVisible = (RouterConversationVisible) message;
onConversationVisible(conversationVisible.getPeer());
} else if (message instanceof RouterConversationHidden) {
RouterConversationHidden conversationHidden = (RouterConversationHidden) message;
onConversationHidden(conversationHidden.getPeer());
} else if (message instanceof RouterAppVisible) {
onAppVisible();
} else if (message instanceof RouterAppHidden) {
onAppHidden();
} else {
super.onReceive(message);
}
}
@Override
public Promise onAsk(Object message) throws Exception {
if (!activeDialogStorage.isLoaded() && message instanceof RouterMessageOnlyActive) {
stash();
return null;
}
if (message instanceof RouterMessageUpdate) {
return onUpdate(((RouterMessageUpdate) message).getUpdate());
} else if (message instanceof RouterDifferenceStart) {
return onDifferenceStart();
} else if (message instanceof RouterDifferenceEnd) {
return onDifferenceEnd();
} else if (message instanceof RouterPeersChanged) {
RouterPeersChanged peersChanged = (RouterPeersChanged) message;
return onPeersChanged(peersChanged.getUsers(), peersChanged.getGroups());
} else if (message instanceof RouterApplyChatHistory) {
RouterApplyChatHistory chatHistory = (RouterApplyChatHistory) message;
return onChatHistoryLoaded(
chatHistory.getPeer(),
chatHistory.getMessages(),
chatHistory.getMaxReadDate(),
chatHistory.getMaxReceiveDate(),
chatHistory.isEnded());
} else if (message instanceof RouterApplyDialogsHistory) {
RouterApplyDialogsHistory dialogsHistory = (RouterApplyDialogsHistory) message;
return onDialogHistoryLoaded(dialogsHistory.getDialogs());
} else if (message instanceof RouterNewMessages) {
RouterNewMessages routerNewMessages = (RouterNewMessages) message;
return onNewMessages(
routerNewMessages.getPeer(),
routerNewMessages.getMessages());
} else if (message instanceof RouterOutgoingMessage) {
RouterOutgoingMessage routerOutgoingMessage = (RouterOutgoingMessage) message;
return onOutgoingMessage(
routerOutgoingMessage.getPeer(),
routerOutgoingMessage.getMessage());
} else if (message instanceof RouterOutgoingSent) {
RouterOutgoingSent routerOutgoingSent = (RouterOutgoingSent) message;
return onOutgoingSent(
routerOutgoingSent.getPeer(),
routerOutgoingSent.getRid(),
routerOutgoingSent.getDate());
} else if (message instanceof RouterOutgoingError) {
RouterOutgoingError outgoingError = (RouterOutgoingError) message;
return onOutgoingError(
outgoingError.getPeer(),
outgoingError.getRid());
} else if (message instanceof RouterChangedContent) {
RouterChangedContent routerChangedContent = (RouterChangedContent) message;
return onContentUpdate(
routerChangedContent.getPeer(),
routerChangedContent.getRid(),
routerChangedContent.getContent());
} else if (message instanceof RouterDeletedMessages) {
RouterDeletedMessages routerDeletedMessages = (RouterDeletedMessages) message;
return onMessageDeleted(
routerDeletedMessages.getPeer(),
routerDeletedMessages.getRids());
} else if (message instanceof RouterResetChat) {
RouterResetChat resetChat = (RouterResetChat) message;
return onChatReset(resetChat.getPeer());
} else {
return super.onAsk(message);
}
}
}