Mercury-IM/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/contact/ContactDetailViewModel.java

180 lines
7.3 KiB
Java

package org.mercury_im.messenger.core.viewmodel.contact;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.roster.PresenceEventListener;
import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smack.roster.RosterEntry;
import org.jivesoftware.smack.roster.RosterGroup;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.core.Messenger;
import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.crypto.ikey.IkeyRepository;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.util.CombinedPresenceListener;
import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.MercuryViewModel;
import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.mercury_im.messenger.entity.chat.Chat;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import javax.inject.Inject;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.subjects.BehaviorSubject;
public class ContactDetailViewModel implements MercuryViewModel {
@Inject
SchedulersFacade schedulers;
@Inject
Messenger messenger;
@Inject
PeerRepository peerRepository;
@Inject
IkeyRepository ikeyRepository;
@Inject
DirectChatRepository directChatRepository;
@Inject
OpenPgpRepository openPgpRepository;
private final BehaviorSubject<Presence.Mode> contactPresenceMode = BehaviorSubject.create();
private final BehaviorSubject<String> contactPresenceStatus = BehaviorSubject.create();
private final BehaviorSubject<List<FingerprintViewItem>> contactFingerprints = BehaviorSubject.createDefault(Collections.emptyList());
private final BehaviorSubject<EntityBareJid> contactAddress = BehaviorSubject.create();
private final BehaviorSubject<UUID> contactAccountId = BehaviorSubject.create();
private final BehaviorSubject<EntityBareJid> contactAccountAddress = BehaviorSubject.create();
private final BehaviorSubject<String> contactName = BehaviorSubject.create();
private final BehaviorSubject<List<String>> contactGroups = BehaviorSubject.createDefault(Collections.emptyList());
private UUID peerId;
private Roster roster;
public void init(UUID peerId) {
this.peerId = peerId;
addDisposable(peerRepository.getPeer(peerId)
.subscribe(p -> {
roster = Roster.getInstanceFor(messenger.getConnectionManager().getConnection(p.getAccount()).getConnection());
roster.addPresenceEventListener(presenceEventListener);
Presence presence = roster.getPresence(p.getJid());
if (presence != null) {
contactPresenceMode.onNext(presence.getMode());
contactPresenceStatus.onNext(presence.getStatus());
}
addDisposable(openPgpRepository.observeFingerprints(p.getAccount().getId(), p.getJid())
.subscribeOn(schedulers.getIoScheduler())
.observeOn(schedulers.getUiScheduler())
.subscribe(contactFingerprints::onNext));
addDisposable(ikeyRepository.ob);
}));
addDisposable(peerRepository.observePeer(peerId)
.filter(Optional::isPresent)
.map(Optional::getItem)
.compose(schedulers.executeUiSafeObservable())
.subscribe(peer -> {
contactAddress.onNext(peer.getJid());
contactAccountId.onNext(peer.getAccount().getId());
contactAccountAddress.onNext(peer.getAccount().getJid());
contactName.onNext(peer.getDisplayName());
RosterEntry entry = roster.getEntry(peer.getJid());
if (entry != null) {
List<RosterGroup> groups = entry.getGroups();
List<String> groupNames = new ArrayList<>(groups.size());
for (RosterGroup g : groups) {
groupNames.add(g.getName());
}
contactGroups.onNext(groupNames);
}
}));
}
public Single<UUID> getOrCreateChat() {
return peerRepository.getPeer(peerId)
.flatMapSingle(directChatRepository::getOrCreateChatWithPeer)
.map(Chat::getId);
}
public Observable<EntityBareJid> getContactAddress() {
return contactAddress;
}
private final PresenceEventListener presenceEventListener = new CombinedPresenceListener() {
@Override
public void presenceReceived(Jid address, Presence presence) {
if (presence.getFrom().asBareJid().equals(getContactAddress().blo)) {
contactPresenceMode.postValue(presence.getMode());
contactPresenceStatus.postValue(presence.getStatus());
}
}
};
public void changeContactName(String newName)
throws XMPPException.XMPPErrorException, SmackException.NotConnectedException,
InterruptedException, SmackException.NoResponseException {
if (!newName.trim().isEmpty()) {
RosterEntry entry = roster.getEntry(JidCreate.entityBareFromOrThrowUnchecked(getContactAddress().getValue()));
entry.setName(newName);
}
}
public Completable addContactToRosterGroup() {
return Completable.fromAction(() -> doAddContactToRosterGroup());
}
private void doAddContactToRosterGroup() throws XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, SmackException.NoResponseException {
String groupName = "Mercury Seven";
RosterGroup group = roster.getGroup(groupName);
if (group == null) {
group = roster.createGroup(groupName);
}
BareJid jid = JidCreate.entityBareFromOrThrowUnchecked(getContactAddress().getValue());
if (group.contains(jid)) {
return;
}
RosterEntry entry = roster.getEntry(jid);
group.addEntry(entry);
}
public Completable removeContactFromRosterGroup(String group) {
return Completable.fromAction(() -> roster.getGroup(group).removeEntry(roster.getEntry(JidCreate.entityBareFromOrThrowUnchecked(getContactAddress().getValue()))));
}
public void markFingerprintTrusted(OpenPgpV4Fingerprint fingerprint, boolean checked) {
openPgpRepository.storeTrust(contactAccountId.getValue(),
JidCreate.entityBareFromOrThrowUnchecked(contactAddress.getValue()),
fingerprint,
checked ? OpenPgpTrustStore.Trust.trusted : OpenPgpTrustStore.Trust.untrusted)
.subscribe();
}
}