diff --git a/data/src/main/java/mapper/CursorToPartImpl.kt b/data/src/main/java/mapper/CursorToPartImpl.kt index 67398b00..07da3497 100644 --- a/data/src/main/java/mapper/CursorToPartImpl.kt +++ b/data/src/main/java/mapper/CursorToPartImpl.kt @@ -40,7 +40,6 @@ class CursorToPartImpl @Inject constructor(private val context: Context) : Curso override fun map(from: Cursor) = MmsPart().apply { id = from.getLong(from.getColumnIndexOrThrow(Telephony.Mms.Part._ID)) - messageId = from.getLong(from.getColumnIndexOrThrow(Telephony.Mms.Part.MSG_ID)) // Type will sometimes return null, resulting in a crash if we don't default to an empty string type = from.getString(from.getColumnIndexOrThrow(Telephony.Mms.Part.CONTENT_TYPE)) ?: "" diff --git a/data/src/main/java/repository/MessageRepositoryImpl.kt b/data/src/main/java/repository/MessageRepositoryImpl.kt index a57737cb..85b38f4d 100644 --- a/data/src/main/java/repository/MessageRepositoryImpl.kt +++ b/data/src/main/java/repository/MessageRepositoryImpl.kt @@ -32,7 +32,6 @@ import com.klinker.android.send_message.BroadcastUtils import com.klinker.android.send_message.StripAccents import io.reactivex.Flowable import io.reactivex.Maybe -import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import io.realm.Realm @@ -50,7 +49,6 @@ import util.MessageUtils import util.Preferences import util.extensions.asFlowable import util.extensions.asMaybe -import util.extensions.asObservable import util.extensions.insertOrUpdate import util.extensions.map import javax.inject.Inject @@ -207,15 +205,14 @@ class MessageRepositoryImpl @Inject constructor( .findFirst() } - override fun getPartsForConversation(threadId: Long): Observable> { + override fun getPartsForConversation(threadId: Long): RealmResults { return Realm.getDefaultInstance() - .where(Message::class.java) - .equalTo("threadId", threadId) - .isNotEmpty("parts") - .sort("date") - .findAll() - .asObservable() - .map { messages -> messages.flatMap { it.parts } } + .where(MmsPart::class.java) + .equalTo("messages.threadId", threadId) + .contains("type", "image/") + .isNotEmpty("image") + .sort("id", Sort.DESCENDING) + .findAllAsync() } /** diff --git a/domain/src/main/java/model/MmsPart.kt b/domain/src/main/java/model/MmsPart.kt index 7b9bbd7c..ac8b6eee 100644 --- a/domain/src/main/java/model/MmsPart.kt +++ b/domain/src/main/java/model/MmsPart.kt @@ -19,15 +19,19 @@ package model import io.realm.RealmObject +import io.realm.RealmResults +import io.realm.annotations.LinkingObjects import io.realm.annotations.PrimaryKey open class MmsPart : RealmObject() { @PrimaryKey var id: Long = 0 - var messageId: Long = 0 var type: String = "" var text: String? = null var image: String? = null + @LinkingObjects("parts") + val messages: RealmResults? = null + } \ No newline at end of file diff --git a/domain/src/main/java/repository/MessageRepository.kt b/domain/src/main/java/repository/MessageRepository.kt index d0fcac7f..928f95ef 100644 --- a/domain/src/main/java/repository/MessageRepository.kt +++ b/domain/src/main/java/repository/MessageRepository.kt @@ -20,7 +20,6 @@ package repository import io.reactivex.Flowable import io.reactivex.Maybe -import io.reactivex.Observable import io.realm.RealmResults import model.Conversation import model.Message @@ -56,7 +55,7 @@ interface MessageRepository { fun getPart(id: Long): MmsPart? - fun getPartsForConversation(threadId: Long): Observable> + fun getPartsForConversation(threadId: Long): RealmResults /** * Retrieves the list of messages which should be shown in the notification diff --git a/presentation/src/main/java/feature/conversationinfo/ConversationInfoActivity.kt b/presentation/src/main/java/feature/conversationinfo/ConversationInfoActivity.kt index a65bef75..6e021de9 100644 --- a/presentation/src/main/java/feature/conversationinfo/ConversationInfoActivity.kt +++ b/presentation/src/main/java/feature/conversationinfo/ConversationInfoActivity.kt @@ -94,7 +94,7 @@ class ConversationInfoActivity : QkThemedActivity(), false -> R.string.info_block }) - mediaAdapter.data = state.media + mediaAdapter.updateData(state.media) } override fun showDeleteDialog() { diff --git a/presentation/src/main/java/feature/conversationinfo/ConversationInfoState.kt b/presentation/src/main/java/feature/conversationinfo/ConversationInfoState.kt index edf1b210..6cbacc28 100644 --- a/presentation/src/main/java/feature/conversationinfo/ConversationInfoState.kt +++ b/presentation/src/main/java/feature/conversationinfo/ConversationInfoState.kt @@ -19,6 +19,7 @@ package feature.conversationinfo import io.realm.RealmList +import io.realm.RealmResults import model.MmsPart import model.Recipient @@ -27,6 +28,6 @@ data class ConversationInfoState( val threadId: Long = 0, val archived: Boolean = false, val blocked: Boolean = false, - val media: List = ArrayList(), + val media: RealmResults? = null, val hasError: Boolean = false ) \ No newline at end of file diff --git a/presentation/src/main/java/feature/conversationinfo/ConversationInfoViewModel.kt b/presentation/src/main/java/feature/conversationinfo/ConversationInfoViewModel.kt index a2b989f5..437c56d2 100644 --- a/presentation/src/main/java/feature/conversationinfo/ConversationInfoViewModel.kt +++ b/presentation/src/main/java/feature/conversationinfo/ConversationInfoViewModel.kt @@ -22,6 +22,8 @@ import android.content.Context import android.content.Intent import com.uber.autodispose.android.lifecycle.scope import com.uber.autodispose.kotlin.autoDisposable +import common.Navigator +import common.base.QkViewModel import injection.appComponent import interactor.DeleteConversation import interactor.MarkArchived @@ -32,11 +34,8 @@ import io.reactivex.Observable import io.reactivex.rxkotlin.plusAssign import io.reactivex.rxkotlin.withLatestFrom import model.Conversation -import common.Navigator -import common.base.QkViewModel import repository.MessageRepository import util.extensions.asObservable -import util.extensions.isImage import javax.inject.Inject class ConversationInfoViewModel(intent: Intent) : QkViewModel() .filter { conversation -> conversation.isLoaded } @@ -93,12 +95,6 @@ class ConversationInfoViewModel(intent: Intent) : QkViewModel conversation.blocked } .distinctUntilChanged() .subscribe { blocked -> newState { it.copy(blocked = blocked) } } - - // Load the attachments from the conversation - disposables += messageRepo.getPartsForConversation(threadId) - .map { parts -> parts.filter { part -> part.isImage() } } - .map { parts -> parts.reversed() } - .subscribe { media -> newState { it.copy(media = media) } } } override fun bindView(view: ConversationInfoView) { diff --git a/presentation/src/main/java/feature/conversationinfo/ConversationMediaAdapter.kt b/presentation/src/main/java/feature/conversationinfo/ConversationMediaAdapter.kt index c092c642..a1a0cc5d 100644 --- a/presentation/src/main/java/feature/conversationinfo/ConversationMediaAdapter.kt +++ b/presentation/src/main/java/feature/conversationinfo/ConversationMediaAdapter.kt @@ -24,6 +24,8 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import com.moez.QKSMS.R +import common.base.QkRealmAdapter +import common.base.QkViewHolder import common.util.Colors import common.util.GlideApp import io.reactivex.disposables.CompositeDisposable @@ -31,14 +33,12 @@ import io.reactivex.rxkotlin.plusAssign import io.reactivex.subjects.PublishSubject import kotlinx.android.synthetic.main.conversation_media_list_item.view.* import model.MmsPart -import common.base.QkAdapter -import common.base.QkViewHolder import javax.inject.Inject class ConversationMediaAdapter @Inject constructor( private val context: Context, private val colors: Colors -) : QkAdapter() { +) : QkRealmAdapter() { val thumbnailClicks: PublishSubject = PublishSubject.create() @@ -53,7 +53,7 @@ class ConversationMediaAdapter @Inject constructor( } override fun onBindViewHolder(holder: QkViewHolder, position: Int) { - val part = getItem(position) + val part = getItem(position)!! val view = holder.itemView GlideApp.with(context)