Pass IDs instead of value pairs to initialize fragments/view models

This commit is contained in:
Paul Schaub 2020-08-09 13:14:49 +02:00
parent 3a7b17649a
commit 4f04a29798
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
9 changed files with 93 additions and 88 deletions

View File

@ -31,7 +31,6 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
/** /**
* Started, Bound Service, which is responsible keeping the application alive when the app is not open. * Started, Bound Service, which is responsible keeping the application alive when the app is not open.

View File

@ -51,11 +51,13 @@ public class AndroidChatViewModel extends ViewModel implements MercuryAndroidVie
MercuryImApplication.getApplication().getAppComponent().inject(this); MercuryImApplication.getApplication().getAppComponent().inject(this);
} }
public void init(UUID accountId, EntityBareJid jid) { public void init(UUID chatId) {
commonViewModel.init(accountId, jid); commonViewModel.init(chatId);
bindObservablesToLiveData();
}
private void bindObservablesToLiveData() {
addDisposable(commonViewModel.getPeer() addDisposable(commonViewModel.getPeer()
.filter(Optional::isPresent).map(Optional::getItem)
.compose(schedulers.executeUiSafeObservable()) .compose(schedulers.executeUiSafeObservable())
.subscribe(contact::setValue)); .subscribe(contact::setValue));

View File

@ -32,6 +32,7 @@ import io.reactivex.disposables.CompositeDisposable;
public class ChatActivity extends AppCompatActivity public class ChatActivity extends AppCompatActivity
implements ChatInputFragment.OnChatInputActionListener, SearchView.OnQueryTextListener { implements ChatInputFragment.OnChatInputActionListener, SearchView.OnQueryTextListener {
public static final String EXTRA_CHAT_ID = "CHAT_ID";
public static final String EXTRA_JID = "JID"; public static final String EXTRA_JID = "JID";
public static final String EXTRA_ACCOUNT = "ACCOUNT"; public static final String EXTRA_ACCOUNT = "ACCOUNT";
@ -47,17 +48,20 @@ public class ChatActivity extends AppCompatActivity
private final CompositeDisposable disposable = new CompositeDisposable(); private final CompositeDisposable disposable = new CompositeDisposable();
private EntityBareJid jid; private UUID chatId;
private UUID accountId;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
Log.d("Mercury", "onCreate");
setContentView(R.layout.activity_chat); setContentView(R.layout.activity_chat);
ButterKnife.bind(this); ButterKnife.bind(this);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
recyclerView.setAdapter(recyclerViewAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
MercuryImApplication.getApplication().getAppComponent().inject(this); MercuryImApplication.getApplication().getAppComponent().inject(this);
if (savedInstanceState == null) { if (savedInstanceState == null) {
@ -65,32 +69,22 @@ public class ChatActivity extends AppCompatActivity
if (savedInstanceState == null) return; if (savedInstanceState == null) return;
} }
setSupportActionBar(toolbar); String chatIdString = savedInstanceState.getString(EXTRA_CHAT_ID);
// Show back arrow if (chatIdString == null) {
getSupportActionBar().setDisplayHomeAsUpEnabled(true); return;
recyclerView.setAdapter(recyclerViewAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
String jidString = savedInstanceState.getString(EXTRA_JID);
if (jidString != null) {
jid = JidCreate.entityBareFromOrThrowUnchecked(jidString);
// JID will never change, so just set it once
getSupportActionBar().setSubtitle(jid.asUnescapedString());
accountId = UUID.fromString(savedInstanceState.getString(EXTRA_ACCOUNT));
androidChatViewModel = new ViewModelProvider(this).get(AndroidChatViewModel.class);
androidChatViewModel.init(accountId, jid);
// Listen for updates to contact information and messages
observeViewModel(androidChatViewModel);
} }
chatId = UUID.fromString(chatIdString);
androidChatViewModel = new ViewModelProvider(this).get(AndroidChatViewModel.class);
androidChatViewModel.init(chatId);
// Listen for updates to contact information and messages
observeViewModel(androidChatViewModel);
toolbar.setOnClickListener(new View.OnClickListener() { toolbar.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
Intent intent = new Intent(ChatActivity.this, ContactDetailActivity.class); Intent intent = new Intent(ChatActivity.this, ContactDetailActivity.class);
intent.putExtra(ContactDetailActivity.EXTRA_JID, jidString); intent.putExtra(ContactDetailActivity.EXTRA_PEER_ID, androidChatViewModel.getContact().getValue().getId().toString());
intent.putExtra(ContactDetailActivity.EXTRA_ACCOUNT, accountId.toString());
ChatActivity.this.startActivity(intent); ChatActivity.this.startActivity(intent);
} }
@ -100,6 +94,8 @@ public class ChatActivity extends AppCompatActivity
public void observeViewModel(AndroidChatViewModel viewModel) { public void observeViewModel(AndroidChatViewModel viewModel) {
viewModel.getContactDisplayName().observe(this, viewModel.getContactDisplayName().observe(this,
name -> getSupportActionBar().setTitle(name)); name -> getSupportActionBar().setTitle(name));
viewModel.getContact().observe(this,
contact -> getSupportActionBar().setSubtitle(contact.getJid()));
viewModel.getMessages().observe(this, messageModels -> { viewModel.getMessages().observe(this, messageModels -> {
recyclerViewAdapter.updateMessages(messageModels); recyclerViewAdapter.updateMessages(messageModels);
@ -161,8 +157,7 @@ public class ChatActivity extends AppCompatActivity
@Override @Override
protected void onSaveInstanceState(@NonNull Bundle outState) { protected void onSaveInstanceState(@NonNull Bundle outState) {
outState.putString(EXTRA_JID, jid.toString()); outState.putString(EXTRA_CHAT_ID, chatId.toString());
outState.putString(EXTRA_ACCOUNT, accountId.toString());
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
} }

View File

@ -53,8 +53,7 @@ public class ChatListRecyclerViewAdapter
holder.itemView.setOnClickListener(view -> { holder.itemView.setOnClickListener(view -> {
Intent intent = new Intent(holder.context, ChatActivity.class); Intent intent = new Intent(holder.context, ChatActivity.class);
intent.putExtra(ChatActivity.EXTRA_JID, model.getPeer().getAddress()); intent.putExtra(ChatActivity.EXTRA_CHAT_ID, model.getId().toString());
intent.putExtra(ChatActivity.EXTRA_ACCOUNT, model.getPeer().getAccount().getId().toString());
holder.context.startActivity(intent); holder.context.startActivity(intent);
}); });

View File

@ -73,8 +73,7 @@ public class ContactListRecyclerViewAdapter
view.setOnClickListener(view -> { view.setOnClickListener(view -> {
Intent intent = new Intent(context, ContactDetailActivity.class); Intent intent = new Intent(context, ContactDetailActivity.class);
intent.putExtra(ContactDetailActivity.EXTRA_JID, address); intent.putExtra(ContactDetailActivity.EXTRA_PEER_ID, contact.getId().toString());
intent.putExtra(ContactDetailActivity.EXTRA_ACCOUNT, contact.getAccount().getId().toString());
context.startActivity(intent); context.startActivity(intent);
}); });

View File

@ -18,6 +18,7 @@ import butterknife.ButterKnife;
public class ContactDetailActivity extends AppCompatActivity { public class ContactDetailActivity extends AppCompatActivity {
public static final String EXTRA_JID = "JID"; public static final String EXTRA_JID = "JID";
public static final String EXTRA_ACCOUNT = "ACCOUNT"; public static final String EXTRA_ACCOUNT = "ACCOUNT";
public static final String EXTRA_PEER_ID = "PEER_ID";
@BindView(R.id.fragment) @BindView(R.id.fragment)
FrameLayout container; FrameLayout container;
@ -35,13 +36,11 @@ public class ContactDetailActivity extends AppCompatActivity {
if (savedInstanceState == null) return; if (savedInstanceState == null) return;
} }
String jidString = savedInstanceState.getString(EXTRA_JID); String peerIdString = savedInstanceState.getString(EXTRA_PEER_ID);
if (jidString != null) { UUID peerId = UUID.fromString(peerIdString);
UUID accountId = UUID.fromString(savedInstanceState.getString(EXTRA_ACCOUNT));
ContactDetailViewModel viewModel = new ViewModelProvider(this).get(ContactDetailViewModel.class); ContactDetailViewModel viewModel = new ViewModelProvider(this).get(ContactDetailViewModel.class);
viewModel.bind(accountId, jidString); viewModel.bind(peerId);
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment, new ContactDetailFragment(), "contact_details").commit(); getSupportFragmentManager().beginTransaction().replace(R.id.fragment, new ContactDetailFragment(), "contact_details").commit();
} }

View File

@ -31,6 +31,7 @@ import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.ui.chat.ChatActivity; import org.mercury_im.messenger.android.ui.chat.ChatActivity;
import org.mercury_im.messenger.android.util.ColorUtil; import org.mercury_im.messenger.android.util.ColorUtil;
import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.mercury_im.messenger.entity.chat.DirectChat;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -92,8 +93,7 @@ public class ContactDetailFragment extends Fragment {
if (fab != null) { if (fab != null) {
fab.setOnClickListener(v -> { fab.setOnClickListener(v -> {
Intent intent = new Intent(getContext(), ChatActivity.class); Intent intent = new Intent(getContext(), ChatActivity.class);
intent.putExtra(ChatActivity.EXTRA_JID, viewModel.getContactAddress().getValue()); intent.putExtra(ChatActivity.EXTRA_CHAT_ID, viewModel.getOrCreateChat().blockingGet().toString());
intent.putExtra(ChatActivity.EXTRA_ACCOUNT, viewModel.getAccountId().getValue().toString());
startActivity(intent); startActivity(intent);
}); });
} }

View File

@ -22,9 +22,12 @@ import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.android.MercuryImApplication; import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.core.Messenger; import org.mercury_im.messenger.core.Messenger;
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.OpenPgpRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository; import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.mercury_im.messenger.entity.chat.Chat;
import org.mercury_im.messenger.entity.contact.Peer; import org.mercury_im.messenger.entity.contact.Peer;
import org.mercury_im.messenger.android.ui.avatar.AvatarDrawable; import org.mercury_im.messenger.android.ui.avatar.AvatarDrawable;
import org.mercury_im.messenger.core.util.CombinedPresenceListener; import org.mercury_im.messenger.core.util.CombinedPresenceListener;
@ -38,6 +41,7 @@ import java.util.UUID;
import javax.inject.Inject; import javax.inject.Inject;
import io.reactivex.Completable; import io.reactivex.Completable;
import io.reactivex.Single;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
public class ContactDetailViewModel extends ViewModel { public class ContactDetailViewModel extends ViewModel {
@ -45,6 +49,9 @@ public class ContactDetailViewModel extends ViewModel {
@Inject @Inject
PeerRepository peerRepository; PeerRepository peerRepository;
@Inject
DirectChatRepository directChatRepository;
@Inject @Inject
OpenPgpRepository openPgpRepository; OpenPgpRepository openPgpRepository;
@ -65,6 +72,7 @@ public class ContactDetailViewModel extends ViewModel {
private MutableLiveData<List<FingerprintViewItem>> contactFingerprints = new MutableLiveData<>(Collections.emptyList()); private MutableLiveData<List<FingerprintViewItem>> contactFingerprints = new MutableLiveData<>(Collections.emptyList());
private Roster roster; private Roster roster;
private UUID peerId;
private CompositeDisposable disposable = new CompositeDisposable(); private CompositeDisposable disposable = new CompositeDisposable();
@ -73,26 +81,40 @@ public class ContactDetailViewModel extends ViewModel {
MercuryImApplication.getApplication().getAppComponent().inject(this); MercuryImApplication.getApplication().getAppComponent().inject(this);
} }
public void bind(UUID accountId, String peerAddress) { public void bind(UUID peerId) {
Log.d("MMMMMM", "Bind!"); this.peerId = peerId;
EntityBareJid peerJid = JidCreate.entityBareFromOrThrowUnchecked(peerAddress);
roster = Roster.getInstanceFor(messenger.getConnectionManager().getConnection(accountId).getConnection()); disposable.add(peerRepository.getPeer(peerId)
roster.addPresenceEventListener(presenceEventListener); .subscribe(p -> {
contactAddress.setValue(peerAddress); roster = Roster.getInstanceFor(messenger.getConnectionManager().getConnection(p.getAccount()).getConnection());
contactAccountId.setValue(accountId); roster.addPresenceEventListener(presenceEventListener);
disposable.add(peerRepository.observePeerByAddress(accountId, peerJid)
.subscribeOn(schedulers.getIoScheduler()) Presence presence = roster.getPresence(p.getJid());
.observeOn(schedulers.getUiScheduler()) if (presence != null) {
.subscribe(peerOptional -> { contactPresenceMode.postValue(presence.getMode());
if (!peerOptional.isPresent()) { contactPresenceStatus.postValue(presence.getStatus());
return;
} }
Peer peer = peerOptional.getItem();
disposable.add(openPgpRepository.observeFingerprints(p.getAccount().getId(), p.getJid())
.subscribeOn(schedulers.getIoScheduler())
.observeOn(schedulers.getUiScheduler())
.subscribe(list -> contactFingerprints.setValue(list)));
}));
disposable.add(peerRepository.observePeer(peerId)
.filter(Optional::isPresent)
.map(Optional::getItem)
.compose(schedulers.executeUiSafeObservable())
.subscribe(peer -> {
contactAddress.setValue(peer.getAddress());
contactAccountId.setValue(peer.getAccount().getId());
contactAccountAddress.setValue(peer.getAccount().getAddress()); contactAccountAddress.setValue(peer.getAccount().getAddress());
contactAvatar.setValue(new AvatarDrawable(peer.getDisplayName(), peer.getAddress())); contactAvatar.setValue(new AvatarDrawable(peer.getDisplayName(), peer.getAddress()));
contactName.setValue(peer.getDisplayName()); contactName.setValue(peer.getDisplayName());
RosterEntry entry = roster.getEntry(JidCreate.entityBareFromOrThrowUnchecked(peerAddress)); RosterEntry entry = roster.getEntry(peer.getJid());
if (entry != null) { if (entry != null) {
List<RosterGroup> groups = entry.getGroups(); List<RosterGroup> groups = entry.getGroups();
List<String> groupNames = new ArrayList<>(groups.size()); List<String> groupNames = new ArrayList<>(groups.size());
@ -102,17 +124,6 @@ public class ContactDetailViewModel extends ViewModel {
contactGroups.postValue(groupNames); contactGroups.postValue(groupNames);
} }
})); }));
Presence presence = roster.getPresence(peerJid);
if (presence != null) {
contactPresenceMode.postValue(presence.getMode());
contactPresenceStatus.postValue(presence.getStatus());
}
disposable.add(openPgpRepository.observeFingerprints(accountId, peerJid)
.subscribeOn(schedulers.getIoScheduler())
.observeOn(schedulers.getUiScheduler())
.subscribe(list -> contactFingerprints.setValue(list)));
} }
public LiveData<String> getContactAddress() { public LiveData<String> getContactAddress() {
@ -156,6 +167,12 @@ public class ContactDetailViewModel extends ViewModel {
return contactGroups; return contactGroups;
} }
public Single<UUID> getOrCreateChat() {
return peerRepository.getPeer(peerId)
.flatMapSingle(directChatRepository::getOrCreateChatWithPeer)
.map(Chat::getId);
}
private final PresenceEventListener presenceEventListener = new CombinedPresenceListener() { private final PresenceEventListener presenceEventListener = new CombinedPresenceListener() {
@Override @Override
public void presenceReceived(Jid address, Presence presence) { public void presenceReceived(Jid address, Presence presence) {

View File

@ -1,6 +1,5 @@
package org.mercury_im.messenger.core.viewmodel.chat; 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.Messenger;
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;
@ -18,8 +17,6 @@ import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.functions.Function;
import io.reactivex.subjects.BehaviorSubject; import io.reactivex.subjects.BehaviorSubject;
import lombok.Getter; import lombok.Getter;
@ -34,7 +31,7 @@ public class ChatViewModel implements MercuryViewModel {
private final SchedulersFacade schedulers; private final SchedulersFacade schedulers;
@Getter @Getter
private BehaviorSubject<Optional<Peer>> peer = BehaviorSubject.create(); private BehaviorSubject<Peer> peer = BehaviorSubject.create();
@Getter @Getter
private BehaviorSubject<DirectChat> chat = BehaviorSubject.create(); private BehaviorSubject<DirectChat> chat = BehaviorSubject.create();
@ -60,25 +57,25 @@ public class ChatViewModel implements MercuryViewModel {
this.schedulers = schedulers; this.schedulers = schedulers;
} }
public void init(UUID accountId, EntityBareJid contactJid) { public void init(UUID chatId) {
contactRepository.getOrCreatePeer(accountId, contactJid) directChatRepository.observeDirectChat(chatId)
.flatMapObservable(contactRepository::observePeer) .filter(Optional::isPresent)
.subscribe(peer); .map(Optional::getItem)
.compose(schedulers.executeUiSafeObservable())
peer.compose(schedulers.executeUiSafeObservable())
.subscribe();
peer.filter(Optional::isPresent).map(Optional::getItem)
.flatMap(p -> directChatRepository.getOrCreateChatWithPeer(p).toObservable())
.subscribe(chat); .subscribe(chat);
chat.compose(schedulers.executeUiSafeObservable()).subscribe(); chat.map(DirectChat::getPeer)
.flatMap(contactRepository::observePeer)
.compose(schedulers.executeUiSafeObservable())
.filter(Optional::isPresent)
.map(Optional::getItem)
.subscribe(peer);
Observable<List<Message>> allMessagesObservable = chat.flatMap(messageRepository::observeMessages); Observable<List<Message>> allMessagesObservable = chat.flatMap(messageRepository::observeMessages);
messageQueryObservable.onNext(allMessagesObservable); messageQueryObservable.onNext(allMessagesObservable);
messages = Observable.switchOnNext(messageQueryObservable); messages = Observable.switchOnNext(messageQueryObservable);
contactDisplayName = peer.filter(Optional::isPresent).map(Optional::getItem)
.map(Peer::getDisplayName); contactDisplayName = peer.map(Peer::getDisplayName);
} }
public void onQueryTextChanged(String query) { public void onQueryTextChanged(String query) {
@ -90,9 +87,7 @@ public class ChatViewModel implements MercuryViewModel {
} }
public void deleteContact() { public void deleteContact() {
addDisposable(peer.single(new Optional<>()) addDisposable(peer.singleOrError()
.filter(Optional::isPresent)
.map(Optional::getItem)
.flatMapCompletable(messenger::deleteContact) .flatMapCompletable(messenger::deleteContact)
.compose(schedulers.executeUiSafeCompletable()) .compose(schedulers.executeUiSafeCompletable())
.subscribe( .subscribe(