package org.mercury_im.messenger.core.viewmodel.chat; import org.jxmpp.jid.EntityBareJid; import org.mercury_im.messenger.core.Messenger; import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.data.repository.DirectChatRepository; import org.mercury_im.messenger.core.data.repository.MessageRepository; import org.mercury_im.messenger.core.data.repository.PeerRepository; import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.viewmodel.MercuryViewModel; import org.mercury_im.messenger.entity.chat.DirectChat; import org.mercury_im.messenger.entity.contact.Peer; import org.mercury_im.messenger.entity.message.Message; import java.util.List; import java.util.UUID; import java.util.logging.Level; 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; public class ChatViewModel implements MercuryViewModel { private static final Logger LOGGER = Logger.getLogger(ChatViewModel.class.getName()); private final Messenger messenger; private final PeerRepository contactRepository; private final DirectChatRepository directChatRepository; private final MessageRepository messageRepository; private final SchedulersFacade schedulers; @Getter private BehaviorSubject> peer = BehaviorSubject.create(); @Getter private BehaviorSubject chat = BehaviorSubject.create(); @Getter private Observable> messages; @Getter private Observable contactDisplayName; private final BehaviorSubject>> messageQueryObservable = BehaviorSubject.create(); public ChatViewModel(Messenger messenger, PeerRepository peerRepository, DirectChatRepository directChatRepository, MessageRepository messageRepository, SchedulersFacade schedulers) { this.messenger = messenger; this.contactRepository = peerRepository; this.directChatRepository = directChatRepository; this.messageRepository = messageRepository; this.schedulers = schedulers; } public void init(UUID accountId, EntityBareJid contactJid) { contactRepository.getOrCreatePeer(accountId, contactJid) .flatMapObservable(contactRepository::observePeer) .subscribe(peer); peer.compose(schedulers.executeUiSafeObservable()) .subscribe(); peer.filter(Optional::isPresent).map(Optional::getItem) .flatMap(p -> directChatRepository.getOrCreateChatWithPeer(p).toObservable()) .subscribe(chat); chat.compose(schedulers.executeUiSafeObservable()).subscribe(); Observable> allMessagesObservable = chat.flatMap(messageRepository::observeMessages); messageQueryObservable.onNext(allMessagesObservable); messages = Observable.switchOnNext(messageQueryObservable); contactDisplayName = peer.filter(Optional::isPresent).map(Optional::getItem) .map(Peer::getDisplayName); } public void onQueryTextChanged(String query) { if (query.trim().isEmpty()) { messageQueryObservable.onNext(chat.flatMap(messageRepository::observeMessages)); } else { messageQueryObservable.onNext(chat.flatMap(c -> messageRepository.findMessagesWithBody(c, query))); } } public void deleteContact() { addDisposable(peer.single(new Optional<>()) .filter(Optional::isPresent) .map(Optional::getItem) .flatMapCompletable(messenger::deleteContact) .compose(schedulers.executeUiSafeCompletable()) .subscribe( () -> LOGGER.log(Level.INFO, "Contact deleted."), e -> LOGGER.log(Level.SEVERE, "Error deleting contact.", e))); } public void sendMessage(String body) { 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))); } }