diff --git a/data/src/main/java/com/moez/QKSMS/extensions/CollectionExtensions.kt b/data/src/main/java/com/moez/QKSMS/extensions/CollectionExtensions.kt new file mode 100644 index 00000000..e22d70dd --- /dev/null +++ b/data/src/main/java/com/moez/QKSMS/extensions/CollectionExtensions.kt @@ -0,0 +1,13 @@ +package com.moez.QKSMS.extensions + +inline fun Iterable.associateByNotNull(keySelector: (T) -> K?): Map { + val map = hashMapOf() + forEach { value -> + val key = keySelector(value) + if (key != null) { + map[key] = value + } + } + + return map +} diff --git a/data/src/main/java/com/moez/QKSMS/repository/ConversationRepositoryImpl.kt b/data/src/main/java/com/moez/QKSMS/repository/ConversationRepositoryImpl.kt index 24935ee6..02ac38f7 100644 --- a/data/src/main/java/com/moez/QKSMS/repository/ConversationRepositoryImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/repository/ConversationRepositoryImpl.kt @@ -206,6 +206,17 @@ class ConversationRepositoryImpl @Inject constructor( .observeOn(Schedulers.io()) } + override fun getUnmanagedRecipients(): Observable> { + val realm = Realm.getDefaultInstance() + return realm.where(Recipient::class.java) + .isNotNull("contact") + .findAllAsync() + .asObservable() + .filter { it.isLoaded && it.isValid } + .map { realm.copyFromRealm(it) } + .subscribeOn(AndroidSchedulers.mainThread()) + } + override fun getRecipient(recipientId: Long): Recipient? { return Realm.getDefaultInstance() .where(Recipient::class.java) diff --git a/domain/src/main/java/com/moez/QKSMS/repository/ConversationRepository.kt b/domain/src/main/java/com/moez/QKSMS/repository/ConversationRepository.kt index a6f1a071..0377c677 100644 --- a/domain/src/main/java/com/moez/QKSMS/repository/ConversationRepository.kt +++ b/domain/src/main/java/com/moez/QKSMS/repository/ConversationRepository.kt @@ -54,6 +54,8 @@ interface ConversationRepository { fun getUnmanagedConversations(): Observable> + fun getUnmanagedRecipients(): Observable> + fun getRecipient(recipientId: Long): Recipient? fun getThreadId(recipient: String): Long? diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ComposeItemAdapter.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ComposeItemAdapter.kt index 101e7ba5..718edcc1 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ComposeItemAdapter.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/editing/ComposeItemAdapter.kt @@ -29,21 +29,35 @@ import com.moez.QKSMS.common.base.QkViewHolder import com.moez.QKSMS.common.util.Colors import com.moez.QKSMS.common.util.extensions.forwardTouches import com.moez.QKSMS.common.util.extensions.setTint +import com.moez.QKSMS.extensions.associateByNotNull import com.moez.QKSMS.model.Contact import com.moez.QKSMS.model.ContactGroup import com.moez.QKSMS.model.Conversation import com.moez.QKSMS.model.Recipient +import com.moez.QKSMS.repository.ConversationRepository +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.rxkotlin.plusAssign import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.Subject import kotlinx.android.synthetic.main.contact_list_item.view.* import javax.inject.Inject -class ComposeItemAdapter @Inject constructor(private val colors: Colors) : QkAdapter() { +class ComposeItemAdapter @Inject constructor( + private val colors: Colors, + private val conversationRepo: ConversationRepository +) : QkAdapter() { val clicks: Subject = PublishSubject.create() val longClicks: Subject = PublishSubject.create() private val numbersViewPool = RecyclerView.RecycledViewPool() + private val disposables = CompositeDisposable() + + var recipients: Map = mapOf() + set(value) { + field = value + notifyDataSetChanged() + } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): QkViewHolder { val layoutInflater = LayoutInflater.from(parent.context) @@ -87,7 +101,7 @@ class ComposeItemAdapter @Inject constructor(private val colors: Colors) : QkAda view.icon.isVisible = false - view.avatar.recipients = listOf(Recipient(contact = contact)) + view.avatar.recipients = listOf(createRecipient(contact)) view.title.text = contact.numbers.joinToString { it.address } @@ -123,7 +137,7 @@ class ComposeItemAdapter @Inject constructor(private val colors: Colors) : QkAda view.icon.isVisible = prev !is ComposeItem.Starred view.icon.setImageResource(R.drawable.ic_star_black_24dp) - view.avatar.recipients = listOf(Recipient(contact = contact)) + view.avatar.recipients = listOf(createRecipient(contact)) view.title.text = contact.name @@ -139,7 +153,7 @@ class ComposeItemAdapter @Inject constructor(private val colors: Colors) : QkAda view.icon.isVisible = prev !is ComposeItem.Group view.icon.setImageResource(R.drawable.ic_people_black_24dp) - view.avatar.recipients = group.contacts.map { contact -> Recipient(contact = contact) } + view.avatar.recipients = group.contacts.map(::createRecipient) view.title.text = group.title @@ -158,7 +172,7 @@ class ComposeItemAdapter @Inject constructor(private val colors: Colors) : QkAda view.icon.isVisible = false - view.avatar.recipients = listOf(Recipient(contact = contact)) + view.avatar.recipients = listOf(createRecipient(contact)) view.title.text = contact.name @@ -168,6 +182,22 @@ class ComposeItemAdapter @Inject constructor(private val colors: Colors) : QkAda (view.numbers.adapter as PhoneNumberAdapter).data = contact.numbers } + private fun createRecipient(contact: Contact): Recipient { + return recipients[contact.lookupKey] ?: Recipient( + address = contact.numbers.firstOrNull()?.address ?: "", + contact = contact) + } + + override fun onAttachedToRecyclerView(recyclerView: RecyclerView) { + disposables += conversationRepo.getUnmanagedRecipients() + .map { recipients -> recipients.associateByNotNull { recipient -> recipient.contact?.lookupKey } } + .subscribe { recipients -> this@ComposeItemAdapter.recipients = recipients } + } + + override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) { + disposables.clear() + } + override fun areItemsTheSame(old: ComposeItem, new: ComposeItem): Boolean { val oldIds = old.getContacts().map { contact -> contact.lookupKey } val newIds = new.getContacts().map { contact -> contact.lookupKey }