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 97ede681..0828d2e6 100644 --- a/data/src/main/java/com/moez/QKSMS/repository/ConversationRepositoryImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/repository/ConversationRepositoryImpl.kt @@ -22,6 +22,7 @@ import android.content.ContentUris import android.content.Context import android.provider.Telephony import android.telephony.PhoneNumberUtils +import com.moez.QKSMS.blocking.BlockingClient import com.moez.QKSMS.compat.TelephonyCompat import com.moez.QKSMS.extensions.anyOf import com.moez.QKSMS.extensions.map @@ -41,6 +42,7 @@ import java.util.concurrent.TimeUnit import javax.inject.Inject class ConversationRepositoryImpl @Inject constructor( + private val blockingClient: BlockingClient, private val context: Context, private val conversationFilter: ConversationFilter, private val cursorToConversation: CursorToConversation, @@ -338,6 +340,10 @@ class ConversationRepositoryImpl @Inject constructor( } } + conversation.blocked = recipients.any { recipient -> + blockingClient.shouldBlock(recipient.address).blockingGet() + } + conversation.recipients.clear() conversation.recipients.addAll(recipients) realm.executeTransaction { it.insertOrUpdate(conversation) } diff --git a/domain/build.gradle b/domain/build.gradle index 9c037815..3f56c3ba 100644 --- a/domain/build.gradle +++ b/domain/build.gradle @@ -52,6 +52,7 @@ dependencies { implementation "io.reactivex.rxjava2:rxkotlin:$rxkotlin_version" implementation "androidx.core:core-ktx:$androidx_core_version" + implementation "com.f2prateek.rx.preferences2:rx-preferences:$rx_preferences_version" implementation "com.jakewharton.timber:timber:$timber_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation project(":common") diff --git a/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveMms.kt b/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveMms.kt index c13f0e00..1e2a5f3a 100644 --- a/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveMms.kt +++ b/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveMms.kt @@ -26,6 +26,7 @@ import com.moez.QKSMS.manager.NotificationManager import com.moez.QKSMS.repository.ConversationRepository import com.moez.QKSMS.repository.MessageRepository import com.moez.QKSMS.repository.SyncRepository +import com.moez.QKSMS.util.Preferences import io.reactivex.Flowable import timber.log.Timber import javax.inject.Inject @@ -34,6 +35,7 @@ class ReceiveMms @Inject constructor( private val activeConversationManager: ActiveConversationManager, private val conversationRepo: ConversationRepository, private val blockingClient: BlockingClient, + private val prefs: Preferences, private val syncManager: SyncRepository, private val messageRepo: MessageRepository, private val notificationManager: NotificationManager, @@ -50,15 +52,25 @@ class ReceiveMms @Inject constructor( messageRepo.markRead(message.threadId) } } - .filter { message -> + .mapNotNull { message -> // Because we use the smsmms library for receiving and storing MMS, we'll need // to check if it should be blocked after we've pulled it into realm. If it - // turns out that it should be blocked, then delete it + // turns out that it should be dropped, then delete it // TODO Don't store blocked messages in the first place - !blockingClient.shouldBlock(message.address).blockingGet().also { blocked -> - Timber.v("Should block: $blocked") - if (blocked) messageRepo.deleteMessages(message.id) + val shouldBlock = blockingClient.shouldBlock(message.address).blockingGet() + val shouldDrop = prefs.drop.get() + Timber.v("block=$shouldBlock, drop=$shouldDrop") + + if (shouldBlock && shouldDrop) { + messageRepo.deleteMessages(message.id) + return@mapNotNull null } + + if (shouldBlock) { + conversationRepo.markBlocked(message.threadId) + } + + message } .doOnNext { message -> conversationRepo.updateConversations(message.threadId) // Update the conversation diff --git a/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveSms.kt b/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveSms.kt index 675ff9e1..283a4320 100644 --- a/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveSms.kt +++ b/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveSms.kt @@ -25,6 +25,7 @@ import com.moez.QKSMS.manager.NotificationManager import com.moez.QKSMS.manager.ShortcutManager import com.moez.QKSMS.repository.ConversationRepository import com.moez.QKSMS.repository.MessageRepository +import com.moez.QKSMS.util.Preferences import io.reactivex.Flowable import timber.log.Timber import javax.inject.Inject @@ -32,6 +33,7 @@ import javax.inject.Inject class ReceiveSms @Inject constructor( private val conversationRepo: ConversationRepository, private val blockingClient: BlockingClient, + private val prefs: Preferences, private val messageRepo: MessageRepository, private val notificationManager: NotificationManager, private val updateBadge: UpdateBadge, @@ -43,22 +45,32 @@ class ReceiveSms @Inject constructor( override fun buildObservable(params: Params): Flowable<*> { return Flowable.just(params) .filter { it.messages.isNotEmpty() } - .filter { + .mapNotNull { // Don't continue if the sender is blocked - val address = it.messages[0].displayOriginatingAddress - val shouldBlock = blockingClient.shouldBlock(address).blockingGet() - Timber.v("Should block: $shouldBlock") - !shouldBlock - } - .map { val messages = it.messages val address = messages[0].displayOriginatingAddress + val shouldBlock = blockingClient.shouldBlock(address).blockingGet() + val shouldDrop = prefs.drop.get() + Timber.v("block=$shouldBlock, drop=$shouldDrop") + + // If we should drop the message, don't even save it + if (shouldBlock && shouldDrop) { + return@mapNotNull null + } + val time = messages[0].timestampMillis val body: String = messages .mapNotNull { message -> message.displayMessageBody } .reduce { body, new -> body + new } - messageRepo.insertReceivedSms(it.subId, address, body, time) // Add the message to the db + // Add the message to the db + val message = messageRepo.insertReceivedSms(it.subId, address, body, time) + + if (shouldBlock) { + conversationRepo.markBlocked(message.threadId) + } + + message } .doOnNext { message -> conversationRepo.updateConversations(message.threadId) // Update the conversation diff --git a/data/src/main/java/com/moez/QKSMS/util/Preferences.kt b/domain/src/main/java/com/moez/QKSMS/util/Preferences.kt similarity index 99% rename from data/src/main/java/com/moez/QKSMS/util/Preferences.kt rename to domain/src/main/java/com/moez/QKSMS/util/Preferences.kt index aac8ca8b..e2295120 100644 --- a/data/src/main/java/com/moez/QKSMS/util/Preferences.kt +++ b/domain/src/main/java/com/moez/QKSMS/util/Preferences.kt @@ -78,6 +78,7 @@ class Preferences @Inject constructor(private val rxPrefs: RxSharedPreferences) val textSize = rxPrefs.getInteger("textSize", TEXT_SIZE_NORMAL) val callControl = rxPrefs.getBoolean("callControl", false) val sia = rxPrefs.getBoolean("sia", false) + val drop = rxPrefs.getBoolean("drop", false) val notifAction1 = rxPrefs.getInteger("notifAction1", NOTIFICATION_ACTION_READ) val notifAction2 = rxPrefs.getInteger("notifAction2", NOTIFICATION_ACTION_REPLY) val notifAction3 = rxPrefs.getInteger("notifAction3", NOTIFICATION_ACTION_NONE) diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedActivity.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedActivity.kt index 1e75d0ae..1619b8ca 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedActivity.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedActivity.kt @@ -39,6 +39,7 @@ class BlockedActivity : QkThemedActivity(), BlockedView { override val ccClickedIntent by lazy { callControl.clicks() } override val siaClickedIntent by lazy { shouldIAnswer.clicks() } + override val dropClickedIntent by lazy { drop.clicks() } override val unblockIntent by lazy { blockedAdapter.unblock } override val confirmUnblockIntent: Subject = PublishSubject.create() @@ -59,6 +60,7 @@ class BlockedActivity : QkThemedActivity(), BlockedView { override fun render(state: BlockedState) { callControl.checkbox.isChecked = state.ccEnabled shouldIAnswer.checkbox.isChecked = state.siaEnabled + drop.checkbox.isChecked = state.dropEnabled blockedAdapter.updateData(state.data) } diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedState.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedState.kt index 3456005b..be854a15 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedState.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedState.kt @@ -24,5 +24,6 @@ import io.realm.RealmResults data class BlockedState( val ccEnabled: Boolean = false, val siaEnabled: Boolean = false, + val dropEnabled: Boolean = false, val data: RealmResults? = null ) \ No newline at end of file diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedView.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedView.kt index 49d38b77..33a74faf 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedView.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedView.kt @@ -25,6 +25,7 @@ interface BlockedView : QkView { val ccClickedIntent: Observable<*> val siaClickedIntent: Observable<*> + val dropClickedIntent: Observable<*> val unblockIntent: Observable val confirmUnblockIntent: Observable diff --git a/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedViewModel.kt b/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedViewModel.kt index fc22e1c2..e2559710 100644 --- a/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedViewModel.kt +++ b/presentation/src/main/java/com/moez/QKSMS/feature/blocked/BlockedViewModel.kt @@ -48,6 +48,9 @@ class BlockedViewModel @Inject constructor( disposables += prefs.sia.asObservable() .subscribe { enabled -> newState { copy(siaEnabled = enabled) } } + + disposables += prefs.drop.asObservable() + .subscribe { enabled -> newState { copy(dropEnabled = enabled) } } } override fun bindView(view: BlockedView) { @@ -86,6 +89,10 @@ class BlockedViewModel @Inject constructor( .autoDisposable(view.scope()) .subscribe(prefs.sia::set) + view.dropClickedIntent + .autoDisposable(view.scope()) + .subscribe { prefs.drop.set(!prefs.drop.get()) } + // Show confirm unblock conversation dialog view.unblockIntent .autoDisposable(view.scope()) diff --git a/presentation/src/main/res/layout/blocked_activity.xml b/presentation/src/main/res/layout/blocked_activity.xml index f3f79ef9..d1ec419d 100644 --- a/presentation/src/main/res/layout/blocked_activity.xml +++ b/presentation/src/main/res/layout/blocked_activity.xml @@ -76,6 +76,17 @@ app:title="@string/settings_should_i_answer_title" app:widget="@layout/settings_switch_widget" /> + +