From 4f04a297984bedb94bd9e0cdaf55c077b8cb0547 Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Sun, 9 Aug 2020 13:14:49 +0200 Subject: [PATCH] Pass IDs instead of value pairs to initialize fragments/view models --- .../service/MercuryForegroundService.java | 1 - .../android/ui/chat/AndroidChatViewModel.java | 8 ++- .../android/ui/chat/ChatActivity.java | 47 ++++++------- .../chatlist/ChatListRecyclerViewAdapter.java | 3 +- .../ContactListRecyclerViewAdapter.java | 3 +- .../detail/ContactDetailActivity.java | 11 ++- .../detail/ContactDetailFragment.java | 4 +- .../detail/ContactDetailViewModel.java | 69 ++++++++++++------- .../core/viewmodel/chat/ChatViewModel.java | 35 ++++------ 9 files changed, 93 insertions(+), 88 deletions(-) diff --git a/app/src/main/java/org/mercury_im/messenger/android/service/MercuryForegroundService.java b/app/src/main/java/org/mercury_im/messenger/android/service/MercuryForegroundService.java index 09de074..dc0c2f3 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/service/MercuryForegroundService.java +++ b/app/src/main/java/org/mercury_im/messenger/android/service/MercuryForegroundService.java @@ -31,7 +31,6 @@ import java.util.logging.Logger; import javax.inject.Inject; 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. diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/chat/AndroidChatViewModel.java b/app/src/main/java/org/mercury_im/messenger/android/ui/chat/AndroidChatViewModel.java index f8ea782..aee1318 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/chat/AndroidChatViewModel.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/chat/AndroidChatViewModel.java @@ -51,11 +51,13 @@ public class AndroidChatViewModel extends ViewModel implements MercuryAndroidVie MercuryImApplication.getApplication().getAppComponent().inject(this); } - public void init(UUID accountId, EntityBareJid jid) { - commonViewModel.init(accountId, jid); + public void init(UUID chatId) { + commonViewModel.init(chatId); + bindObservablesToLiveData(); + } + private void bindObservablesToLiveData() { addDisposable(commonViewModel.getPeer() - .filter(Optional::isPresent).map(Optional::getItem) .compose(schedulers.executeUiSafeObservable()) .subscribe(contact::setValue)); diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/chat/ChatActivity.java b/app/src/main/java/org/mercury_im/messenger/android/ui/chat/ChatActivity.java index 04b8332..eaaf601 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/chat/ChatActivity.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/chat/ChatActivity.java @@ -32,6 +32,7 @@ import io.reactivex.disposables.CompositeDisposable; public class ChatActivity extends AppCompatActivity 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_ACCOUNT = "ACCOUNT"; @@ -47,17 +48,20 @@ public class ChatActivity extends AppCompatActivity private final CompositeDisposable disposable = new CompositeDisposable(); - private EntityBareJid jid; - - private UUID accountId; + private UUID chatId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Log.d("Mercury", "onCreate"); + setContentView(R.layout.activity_chat); ButterKnife.bind(this); + setSupportActionBar(toolbar); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + recyclerView.setAdapter(recyclerViewAdapter); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + MercuryImApplication.getApplication().getAppComponent().inject(this); if (savedInstanceState == null) { @@ -65,32 +69,22 @@ public class ChatActivity extends AppCompatActivity if (savedInstanceState == null) return; } - setSupportActionBar(toolbar); - // Show back arrow - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - - 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); + String chatIdString = savedInstanceState.getString(EXTRA_CHAT_ID); + if (chatIdString == null) { + return; } + 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() { @Override public void onClick(View v) { Intent intent = new Intent(ChatActivity.this, ContactDetailActivity.class); - intent.putExtra(ContactDetailActivity.EXTRA_JID, jidString); - intent.putExtra(ContactDetailActivity.EXTRA_ACCOUNT, accountId.toString()); + intent.putExtra(ContactDetailActivity.EXTRA_PEER_ID, androidChatViewModel.getContact().getValue().getId().toString()); ChatActivity.this.startActivity(intent); } @@ -100,6 +94,8 @@ public class ChatActivity extends AppCompatActivity public void observeViewModel(AndroidChatViewModel viewModel) { viewModel.getContactDisplayName().observe(this, name -> getSupportActionBar().setTitle(name)); + viewModel.getContact().observe(this, + contact -> getSupportActionBar().setSubtitle(contact.getJid())); viewModel.getMessages().observe(this, messageModels -> { recyclerViewAdapter.updateMessages(messageModels); @@ -161,8 +157,7 @@ public class ChatActivity extends AppCompatActivity @Override protected void onSaveInstanceState(@NonNull Bundle outState) { - outState.putString(EXTRA_JID, jid.toString()); - outState.putString(EXTRA_ACCOUNT, accountId.toString()); + outState.putString(EXTRA_CHAT_ID, chatId.toString()); super.onSaveInstanceState(outState); } diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/chatlist/ChatListRecyclerViewAdapter.java b/app/src/main/java/org/mercury_im/messenger/android/ui/chatlist/ChatListRecyclerViewAdapter.java index 8897df6..51d6055 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/chatlist/ChatListRecyclerViewAdapter.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/chatlist/ChatListRecyclerViewAdapter.java @@ -53,8 +53,7 @@ public class ChatListRecyclerViewAdapter holder.itemView.setOnClickListener(view -> { Intent intent = new Intent(holder.context, ChatActivity.class); - intent.putExtra(ChatActivity.EXTRA_JID, model.getPeer().getAddress()); - intent.putExtra(ChatActivity.EXTRA_ACCOUNT, model.getPeer().getAccount().getId().toString()); + intent.putExtra(ChatActivity.EXTRA_CHAT_ID, model.getId().toString()); holder.context.startActivity(intent); }); diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/ContactListRecyclerViewAdapter.java b/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/ContactListRecyclerViewAdapter.java index 9e9a642..5e39b1f 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/ContactListRecyclerViewAdapter.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/ContactListRecyclerViewAdapter.java @@ -73,8 +73,7 @@ public class ContactListRecyclerViewAdapter view.setOnClickListener(view -> { Intent intent = new Intent(context, ContactDetailActivity.class); - intent.putExtra(ContactDetailActivity.EXTRA_JID, address); - intent.putExtra(ContactDetailActivity.EXTRA_ACCOUNT, contact.getAccount().getId().toString()); + intent.putExtra(ContactDetailActivity.EXTRA_PEER_ID, contact.getId().toString()); context.startActivity(intent); }); diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailActivity.java b/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailActivity.java index b2e3ce9..df48a34 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailActivity.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailActivity.java @@ -18,6 +18,7 @@ import butterknife.ButterKnife; public class ContactDetailActivity extends AppCompatActivity { public static final String EXTRA_JID = "JID"; public static final String EXTRA_ACCOUNT = "ACCOUNT"; + public static final String EXTRA_PEER_ID = "PEER_ID"; @BindView(R.id.fragment) FrameLayout container; @@ -35,13 +36,11 @@ public class ContactDetailActivity extends AppCompatActivity { if (savedInstanceState == null) return; } - String jidString = savedInstanceState.getString(EXTRA_JID); - if (jidString != null) { - UUID accountId = UUID.fromString(savedInstanceState.getString(EXTRA_ACCOUNT)); + String peerIdString = savedInstanceState.getString(EXTRA_PEER_ID); + UUID peerId = UUID.fromString(peerIdString); - ContactDetailViewModel viewModel = new ViewModelProvider(this).get(ContactDetailViewModel.class); - viewModel.bind(accountId, jidString); - } + ContactDetailViewModel viewModel = new ViewModelProvider(this).get(ContactDetailViewModel.class); + viewModel.bind(peerId); getSupportFragmentManager().beginTransaction().replace(R.id.fragment, new ContactDetailFragment(), "contact_details").commit(); } diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailFragment.java b/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailFragment.java index 75f4c5a..f86c1f2 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailFragment.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailFragment.java @@ -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.util.ColorUtil; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem; +import org.mercury_im.messenger.entity.chat.DirectChat; import java.util.Arrays; import java.util.List; @@ -92,8 +93,7 @@ public class ContactDetailFragment extends Fragment { if (fab != null) { fab.setOnClickListener(v -> { Intent intent = new Intent(getContext(), ChatActivity.class); - intent.putExtra(ChatActivity.EXTRA_JID, viewModel.getContactAddress().getValue()); - intent.putExtra(ChatActivity.EXTRA_ACCOUNT, viewModel.getAccountId().getValue().toString()); + intent.putExtra(ChatActivity.EXTRA_CHAT_ID, viewModel.getOrCreateChat().blockingGet().toString()); startActivity(intent); }); } diff --git a/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailViewModel.java b/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailViewModel.java index 0870917..352c186 100644 --- a/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailViewModel.java +++ b/app/src/main/java/org/mercury_im/messenger/android/ui/roster/contacts/detail/ContactDetailViewModel.java @@ -22,9 +22,12 @@ import org.jxmpp.jid.impl.JidCreate; import org.mercury_im.messenger.android.MercuryImApplication; 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.OpenPgpRepository; 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.entity.chat.Chat; import org.mercury_im.messenger.entity.contact.Peer; import org.mercury_im.messenger.android.ui.avatar.AvatarDrawable; import org.mercury_im.messenger.core.util.CombinedPresenceListener; @@ -38,6 +41,7 @@ import java.util.UUID; import javax.inject.Inject; import io.reactivex.Completable; +import io.reactivex.Single; import io.reactivex.disposables.CompositeDisposable; public class ContactDetailViewModel extends ViewModel { @@ -45,6 +49,9 @@ public class ContactDetailViewModel extends ViewModel { @Inject PeerRepository peerRepository; + @Inject + DirectChatRepository directChatRepository; + @Inject OpenPgpRepository openPgpRepository; @@ -65,6 +72,7 @@ public class ContactDetailViewModel extends ViewModel { private MutableLiveData> contactFingerprints = new MutableLiveData<>(Collections.emptyList()); private Roster roster; + private UUID peerId; private CompositeDisposable disposable = new CompositeDisposable(); @@ -73,26 +81,40 @@ public class ContactDetailViewModel extends ViewModel { MercuryImApplication.getApplication().getAppComponent().inject(this); } - public void bind(UUID accountId, String peerAddress) { - Log.d("MMMMMM", "Bind!"); - EntityBareJid peerJid = JidCreate.entityBareFromOrThrowUnchecked(peerAddress); - roster = Roster.getInstanceFor(messenger.getConnectionManager().getConnection(accountId).getConnection()); - roster.addPresenceEventListener(presenceEventListener); - contactAddress.setValue(peerAddress); - contactAccountId.setValue(accountId); - disposable.add(peerRepository.observePeerByAddress(accountId, peerJid) - .subscribeOn(schedulers.getIoScheduler()) - .observeOn(schedulers.getUiScheduler()) - .subscribe(peerOptional -> { - if (!peerOptional.isPresent()) { - return; + public void bind(UUID peerId) { + this.peerId = peerId; + + disposable.add(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.postValue(presence.getMode()); + contactPresenceStatus.postValue(presence.getStatus()); } - 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()); contactAvatar.setValue(new AvatarDrawable(peer.getDisplayName(), peer.getAddress())); contactName.setValue(peer.getDisplayName()); - RosterEntry entry = roster.getEntry(JidCreate.entityBareFromOrThrowUnchecked(peerAddress)); + RosterEntry entry = roster.getEntry(peer.getJid()); if (entry != null) { List groups = entry.getGroups(); List groupNames = new ArrayList<>(groups.size()); @@ -102,17 +124,6 @@ public class ContactDetailViewModel extends ViewModel { 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 getContactAddress() { @@ -156,6 +167,12 @@ public class ContactDetailViewModel extends ViewModel { return contactGroups; } + public Single getOrCreateChat() { + return peerRepository.getPeer(peerId) + .flatMapSingle(directChatRepository::getOrCreateChatWithPeer) + .map(Chat::getId); + } + private final PresenceEventListener presenceEventListener = new CombinedPresenceListener() { @Override public void presenceReceived(Jid address, Presence presence) { diff --git a/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/chat/ChatViewModel.java b/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/chat/ChatViewModel.java index caa05c4..89c48ea 100644 --- a/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/chat/ChatViewModel.java +++ b/domain/src/main/java/org/mercury_im/messenger/core/viewmodel/chat/ChatViewModel.java @@ -1,6 +1,5 @@ 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; @@ -18,8 +17,6 @@ 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; @@ -34,7 +31,7 @@ public class ChatViewModel implements MercuryViewModel { private final SchedulersFacade schedulers; @Getter - private BehaviorSubject> peer = BehaviorSubject.create(); + private BehaviorSubject peer = BehaviorSubject.create(); @Getter private BehaviorSubject chat = BehaviorSubject.create(); @@ -60,25 +57,25 @@ public class ChatViewModel implements MercuryViewModel { 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()) + public void init(UUID chatId) { + directChatRepository.observeDirectChat(chatId) + .filter(Optional::isPresent) + .map(Optional::getItem) + .compose(schedulers.executeUiSafeObservable()) .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> allMessagesObservable = chat.flatMap(messageRepository::observeMessages); messageQueryObservable.onNext(allMessagesObservable); 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) { @@ -90,9 +87,7 @@ public class ChatViewModel implements MercuryViewModel { } public void deleteContact() { - addDisposable(peer.single(new Optional<>()) - .filter(Optional::isPresent) - .map(Optional::getItem) + addDisposable(peer.singleOrError() .flatMapCompletable(messenger::deleteContact) .compose(schedulers.executeUiSafeCompletable()) .subscribe(