From da28edc7829f0a27581cdb0ba7ff667b3001b43e Mon Sep 17 00:00:00 2001 From: moezbhatti Date: Sat, 27 Jul 2019 14:04:22 -0400 Subject: [PATCH] #1351 - Fix new conversation not being created on Huawei devices --- .../QKSMS/mapper/CursorToConversationImpl.kt | 4 +- .../com/moez/QKSMS/interactor/SendMessage.kt | 26 ++++--- .../moez/QKSMS/mapper/CursorToConversation.kt | 2 +- .../QKSMS/feature/compose/ComposeViewModel.kt | 68 ++++++++++--------- 4 files changed, 57 insertions(+), 43 deletions(-) diff --git a/data/src/main/java/com/moez/QKSMS/mapper/CursorToConversationImpl.kt b/data/src/main/java/com/moez/QKSMS/mapper/CursorToConversationImpl.kt index 9ee32c36..304a4517 100644 --- a/data/src/main/java/com/moez/QKSMS/mapper/CursorToConversationImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/mapper/CursorToConversationImpl.kt @@ -66,9 +66,9 @@ class CursorToConversationImpl @Inject constructor( } } - override fun getConversationsCursor(lastSync: Long): Cursor? { + override fun getConversationsCursor(): Cursor? { return when (permissionManager.hasReadSms()) { - true -> context.contentResolver.query(URI, PROJECTION, "date > $lastSync", null, "date desc") + true -> context.contentResolver.query(URI, PROJECTION, null, null, "date desc") false -> null } } diff --git a/domain/src/main/java/com/moez/QKSMS/interactor/SendMessage.kt b/domain/src/main/java/com/moez/QKSMS/interactor/SendMessage.kt index 687a5f81..5a5b727d 100644 --- a/domain/src/main/java/com/moez/QKSMS/interactor/SendMessage.kt +++ b/domain/src/main/java/com/moez/QKSMS/interactor/SendMessage.kt @@ -18,6 +18,9 @@ */ package com.moez.QKSMS.interactor +import android.content.Context +import com.moez.QKSMS.compat.TelephonyCompat +import com.moez.QKSMS.extensions.mapNotNull import com.moez.QKSMS.model.Attachment import com.moez.QKSMS.repository.ConversationRepository import com.moez.QKSMS.repository.MessageRepository @@ -25,6 +28,7 @@ import io.reactivex.Flowable import javax.inject.Inject class SendMessage @Inject constructor( + private val context: Context, private val conversationRepo: ConversationRepository, private val messageRepo: MessageRepository ) : Interactor() { @@ -41,16 +45,20 @@ class SendMessage @Inject constructor( override fun buildObservable(params: Params): Flowable<*> = Flowable.just(Unit) .filter { params.addresses.isNotEmpty() } .doOnNext { - messageRepo.sendMessage(params.subId, params.threadId, params.addresses, params.body, - params.attachments, params.delay) + // If a threadId isn't provided, try to obtain one + val threadId = when (params.threadId) { + 0L -> TelephonyCompat.getOrCreateThreadId(context, params.addresses.toSet()) + else -> params.threadId + } + messageRepo.sendMessage(params.subId, threadId, params.addresses, params.body, params.attachments, + params.delay) } - .map { - // On some manufacturers, we can't obtain a threadId for a new conversation. In - // this case, find the threadId manually now that it contains a message - if (params.threadId == 0L) { - conversationRepo.getOrCreateConversation(params.addresses)?.id ?: 0 - } else { - params.threadId + .mapNotNull { + // If the threadId wasn't provided, then it's probably because it doesn't exist in Realm. + // Sync it now and get the id + when (params.threadId) { + 0L -> conversationRepo.getOrCreateConversation(params.addresses)?.id + else -> params.threadId } } .doOnNext { threadId -> conversationRepo.updateConversations(threadId) } diff --git a/domain/src/main/java/com/moez/QKSMS/mapper/CursorToConversation.kt b/domain/src/main/java/com/moez/QKSMS/mapper/CursorToConversation.kt index fcbdeaa3..56f15e3e 100644 --- a/domain/src/main/java/com/moez/QKSMS/mapper/CursorToConversation.kt +++ b/domain/src/main/java/com/moez/QKSMS/mapper/CursorToConversation.kt @@ -23,6 +23,6 @@ import com.moez.QKSMS.model.Conversation interface CursorToConversation : Mapper { - fun getConversationsCursor(lastSync: Long = 0): Cursor? + fun getConversationsCursor(): Cursor? } \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt index bbef29b5..fb34d22a 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/compose/ComposeViewModel.kt @@ -132,8 +132,7 @@ class ComposeViewModel @Inject constructor( .observeOn(AndroidSchedulers.mainThread()) .doOnNext { newState { copy(loading = false) } } .switchMap { (threadId, addresses) -> - - // If we already have this thread in realm, or were able to obtain it from the + // If we already have this thread in realm, or we're able to obtain it from the // system, just return that. threadId.takeIf { it > 0 }?.let { return@switchMap conversationRepo.getConversationAsync(threadId).asObservable() @@ -249,7 +248,8 @@ class ComposeViewModel @Inject constructor( // Update the list of contact suggestions based on the query input, while also filtering out any contacts // that have already been selected Observables - .combineLatest(view.queryChangedIntent, contacts, selectedContacts) { query, contacts, selectedContacts -> + .combineLatest(view.queryChangedIntent, contacts, selectedContacts) { query, contacts, + selectedContacts -> // Strip the accents from the query. This can be an expensive operation, so // cache the result instead of doing it for each contact @@ -375,7 +375,6 @@ class ComposeViewModel @Inject constructor( .autoDisposable(view.scope()) .subscribe { view.clearSelection() } - // Show the previous search result view.optionsItemIntent .filter { it == R.id.previous } @@ -388,7 +387,6 @@ class ComposeViewModel @Inject constructor( .autoDisposable(view.scope()) .subscribe(searchSelection) - // Show the next search result view.optionsItemIntent .filter { it == R.id.next } @@ -401,20 +399,17 @@ class ComposeViewModel @Inject constructor( .autoDisposable(view.scope()) .subscribe(searchSelection) - // Clear the search view.optionsItemIntent .filter { it == R.id.clear } .autoDisposable(view.scope()) .subscribe { newState { copy(query = "", searchSelectionId = -1) } } - // Toggle the group sending mode view.sendAsGroupIntent .autoDisposable(view.scope()) .subscribe { newState { copy(sendAsGroup = !sendAsGroup) } } - // Scroll to search position searchSelection .filter { id -> id != -1L } @@ -422,7 +417,6 @@ class ComposeViewModel @Inject constructor( .autoDisposable(view.scope()) .subscribe(view::scrollToMessage) - // Retry sending view.messageClickIntent .filter { message -> message.isFailedMessage() } @@ -443,20 +437,21 @@ class ComposeViewModel @Inject constructor( .subscribe { message -> cancelMessage.execute(message.id) } // Set the current conversation - Observables - .combineLatest( - view.activityVisibleIntent.distinctUntilChanged(), - conversation.mapNotNull { conversation -> conversation.takeIf { it.isValid }?.id }.distinctUntilChanged()) - { visible, threadId -> - when (visible) { - true -> { - activeConversationManager.setActiveConversation(threadId) - markRead.execute(listOf(threadId)) - } - - false -> activeConversationManager.setActiveConversation(null) - } + Observables.combineLatest( + view.activityVisibleIntent.distinctUntilChanged(), + conversation.mapNotNull { conversation -> + conversation.takeIf { it.isValid }?.id + }.distinctUntilChanged()) + { visible, threadId -> + when (visible) { + true -> { + activeConversationManager.setActiveConversation(threadId) + markRead.execute(listOf(threadId)) } + + false -> activeConversationManager.setActiveConversation(null) + } + } .autoDisposable(view.scope()) .subscribe() @@ -533,7 +528,7 @@ class ComposeViewModel @Inject constructor( // Contact was selected for attachment view.contactSelectedIntent .map { uri -> Attachment.Contact(getVCard(uri)!!) } - .withLatestFrom(attachments) { attachment, attachments -> attachments + attachment} + .withLatestFrom(attachments) { attachment, attachments -> attachments + attachment } .subscribeOn(Schedulers.io()) .autoDisposable(view.scope()) .subscribe(attachments::onNext) { error -> @@ -617,7 +612,8 @@ class ComposeViewModel @Inject constructor( .filter { permissionManager.hasSendSms().also { if (!it) view.requestSmsPermission() } } .withLatestFrom(view.textChangedIntent) { _, body -> body } .map { body -> body.toString() } - .withLatestFrom(state, attachments, conversation, selectedContacts) { body, state, attachments, conversation, contacts -> + .withLatestFrom(state, attachments, conversation, selectedContacts) { body, state, attachments, + conversation, contacts -> val subId = state.subscription?.subscriptionId ?: -1 val addresses = when (conversation.recipients.isNotEmpty()) { true -> conversation.recipients.map { it.address } @@ -634,15 +630,20 @@ class ComposeViewModel @Inject constructor( // Scheduling a message state.scheduled != 0L -> { newState { copy(scheduled = 0) } - val uris = attachments.mapNotNull { it as? Attachment.Image }.map { it.getUri() }.map { it.toString() } - val params = AddScheduledMessage.Params(state.scheduled, subId, addresses, state.sendAsGroup, body, uris) + val uris = attachments + .mapNotNull { it as? Attachment.Image } + .map { it.getUri() } + .map { it.toString() } + val params = AddScheduledMessage + .Params(state.scheduled, subId, addresses, state.sendAsGroup, body, uris) addScheduledMessage.execute(params) context.makeToast(R.string.compose_scheduled_toast) } // Sending a group message state.sendAsGroup -> { - sendMessage.execute(SendMessage.Params(subId, conversation.id, addresses, body, attachments, delay)) + sendMessage.execute(SendMessage + .Params(subId, conversation.id, addresses, body, attachments, delay)) } // Sending a message to an existing conversation with one recipient @@ -653,15 +654,20 @@ class ComposeViewModel @Inject constructor( // Create a new conversation with one address addresses.size == 1 -> { - sendMessage.execute(SendMessage.Params(subId, threadId, addresses, body, attachments, delay)) + sendMessage.execute(SendMessage + .Params(subId, threadId, addresses, body, attachments, delay)) } // Send a message to multiple addresses else -> { addresses.forEach { addr -> - val threadId = tryOrNull(false) { TelephonyCompat.getOrCreateThreadId(context, addr) } ?: 0 - val address = listOf(conversationRepo.getConversation(threadId)?.recipients?.firstOrNull()?.address ?: addr) - sendMessage.execute(SendMessage.Params(subId, threadId, address, body, attachments, delay)) + val threadId = tryOrNull(false) { + TelephonyCompat.getOrCreateThreadId(context, addr) + } ?: 0 + val address = listOf(conversationRepo + .getConversation(threadId)?.recipients?.firstOrNull()?.address ?: addr) + sendMessage.execute(SendMessage + .Params(subId, threadId, address, body, attachments, delay)) } } }