diff --git a/data/src/main/java/com/moez/QKSMS/blocking/CallControlBlockingClient.kt b/data/src/main/java/com/moez/QKSMS/blocking/CallControlBlockingClient.kt index 601ccc0a..42618930 100644 --- a/data/src/main/java/com/moez/QKSMS/blocking/CallControlBlockingClient.kt +++ b/data/src/main/java/com/moez/QKSMS/blocking/CallControlBlockingClient.kt @@ -25,6 +25,7 @@ import androidx.core.database.getStringOrNull import com.callcontrol.datashare.CallControl import com.moez.QKSMS.extensions.map import com.moez.QKSMS.util.tryOrNull +import io.reactivex.Completable import io.reactivex.Single import javax.inject.Inject @@ -41,7 +42,7 @@ class CallControlBlockingClient @Inject constructor( val blockReason: String? = cursor.getStringOrNull(0) } - override fun shouldBlock(address: String): Single { + override fun isBlocked(address: String): Single { val uri = Uri.withAppendedPath(CallControl.LOOKUP_TEXT_URI, address) return Single.fromCallable { tryOrNull { @@ -52,4 +53,14 @@ class CallControlBlockingClient @Inject constructor( } } + override fun canBlock(): Boolean = true + + override fun block(address: String): Completable = Completable.fromCallable { + CallControl.report(context, CallControl.Report(address)) + } + + override fun unblock(address: String): Completable = Completable.fromCallable { + CallControl.openBlockedList(context, address) + } + } diff --git a/data/src/main/java/com/moez/QKSMS/blocking/QkBlockingClient.kt b/data/src/main/java/com/moez/QKSMS/blocking/QkBlockingClient.kt index 15f53f3a..7fbde8f9 100644 --- a/data/src/main/java/com/moez/QKSMS/blocking/QkBlockingClient.kt +++ b/data/src/main/java/com/moez/QKSMS/blocking/QkBlockingClient.kt @@ -18,13 +18,72 @@ */ package com.moez.QKSMS.blocking +import android.content.Context +import android.os.Build +import android.provider.BlockedNumberContract +import android.telecom.TelecomManager +import android.telephony.PhoneNumberUtils +import com.moez.QKSMS.extensions.anyOf +import com.moez.QKSMS.model.BlockedNumber +import io.reactivex.Completable import io.reactivex.Single +import io.realm.Realm import javax.inject.Inject -class QkBlockingClient @Inject constructor() : BlockingClient { +class QkBlockingClient @Inject constructor(private val context: Context) : BlockingClient { - override fun shouldBlock(address: String): Single { - return Single.just(false) // TODO: This will be implemented once we're able to reject these messages entirely + override fun isBlocked(address: String): Single = Single.fromCallable { + when { + Build.VERSION.SDK_INT >= 24 -> BlockedNumberContract.isBlocked(context, address) + + else -> Realm.getDefaultInstance() + .where(BlockedNumber::class.java) + .findAll() + .any { number -> PhoneNumberUtils.compare(number.address, address) } + } + } + + override fun canBlock(): Boolean = Build.VERSION.SDK_INT < 24 + + override fun block(address: String): Completable = Completable.fromCallable { + when { + Build.VERSION.SDK_INT >= 24 -> { + val telecomManager = context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager + val intent = telecomManager.createManageBlockedNumbersIntent() + context.startActivity(intent) + } + + else -> Realm.getDefaultInstance().use { realm -> + val maxId = realm.where(BlockedNumber::class.java) + .max("id")?.toLong() ?: -1 + + realm.executeTransaction { + realm.insert(BlockedNumber(maxId + 1, address)) + } + } + } + } + + override fun canUnblock(): Boolean = true + + override fun unblock(address: String): Completable = Completable.fromCallable { + when { + Build.VERSION.SDK_INT >= 24 -> BlockedNumberContract.unblock(context, address) + + else -> Realm.getDefaultInstance().use { realm -> + val ids = realm + .where(BlockedNumber::class.java) + .findAll() + .filter { number -> PhoneNumberUtils.compare(number.address, address) } + .map { number -> number.id } + .toLongArray() + + realm.executeTransaction { + realm.where(BlockedNumber::class.java) + .anyOf("id", ids) + } + } + } } } diff --git a/data/src/main/java/com/moez/QKSMS/blocking/ShouldIAnswerBlockingClient.kt b/data/src/main/java/com/moez/QKSMS/blocking/ShouldIAnswerBlockingClient.kt index 9f62715d..e5f4624b 100644 --- a/data/src/main/java/com/moez/QKSMS/blocking/ShouldIAnswerBlockingClient.kt +++ b/data/src/main/java/com/moez/QKSMS/blocking/ShouldIAnswerBlockingClient.kt @@ -30,6 +30,7 @@ import android.os.Messenger import androidx.core.os.bundleOf import com.moez.QKSMS.util.Preferences import com.moez.QKSMS.util.tryOrNull +import io.reactivex.Completable import io.reactivex.Single import io.reactivex.subjects.SingleSubject import javax.inject.Inject @@ -51,8 +52,16 @@ class ShouldIAnswerBlockingClient @Inject constructor( /** * Return a Single which emits whether or not the given [address] should be blocked */ - override fun shouldBlock(address: String): Single { - return Binder(context, prefs, address).shouldBlock() + override fun isBlocked(address: String): Single { + return Binder(context, prefs, address).isBlocked() + } + + override fun block(address: String): Completable = Completable.fromCallable { showSia() } + + override fun unblock(address: String): Completable = Completable.fromCallable { showSia() } + + private fun showSia() { + // TODO } private class Binder( @@ -65,8 +74,7 @@ class ShouldIAnswerBlockingClient @Inject constructor( private var serviceMessenger: Messenger? = null private var isBound: Boolean = false - fun shouldBlock(): Single { - + fun isBlocked(): Single { var intent: Intent? = null // If either version of Should I Answer? is installed and SIA is enabled, build the 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 0828d2e6..52b1d117 100644 --- a/data/src/main/java/com/moez/QKSMS/repository/ConversationRepositoryImpl.kt +++ b/data/src/main/java/com/moez/QKSMS/repository/ConversationRepositoryImpl.kt @@ -341,7 +341,7 @@ class ConversationRepositoryImpl @Inject constructor( } conversation.blocked = recipients.any { recipient -> - blockingClient.shouldBlock(recipient.address).blockingGet() + blockingClient.isBlocked(recipient.address).blockingGet() } conversation.recipients.clear() diff --git a/domain/src/main/java/com/moez/QKSMS/blocking/BlockingClient.kt b/domain/src/main/java/com/moez/QKSMS/blocking/BlockingClient.kt index fc29e0a8..57741da5 100644 --- a/domain/src/main/java/com/moez/QKSMS/blocking/BlockingClient.kt +++ b/domain/src/main/java/com/moez/QKSMS/blocking/BlockingClient.kt @@ -18,6 +18,7 @@ */ package com.moez.QKSMS.blocking +import io.reactivex.Completable import io.reactivex.Single interface BlockingClient { @@ -25,6 +26,28 @@ interface BlockingClient { /** * Return a Single which emits whether or not the given [address] should be blocked */ - fun shouldBlock(address: String): Single + fun isBlocked(address: String): Single + + /** + * Returns true if the client is capable of blocking the address in the manager without any + * further user input + */ + fun canBlock(): Boolean = false + + /** + * Blocks the number or opens the manager + */ + fun block(address: String): Completable + + /** + * Returns true if the client is capable of unblocking the address in the manager without any + * further user input + */ + fun canUnblock(): Boolean = false + + /** + * Unblocks the number or opens the manager + */ + fun unblock(address: String): Completable } \ No newline at end of file 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 1e2a5f3a..dee539bf 100644 --- a/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveMms.kt +++ b/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveMms.kt @@ -57,7 +57,7 @@ class ReceiveMms @Inject constructor( // to check if it should be blocked after we've pulled it into realm. If it // turns out that it should be dropped, then delete it // TODO Don't store blocked messages in the first place - val shouldBlock = blockingClient.shouldBlock(message.address).blockingGet() + val shouldBlock = blockingClient.isBlocked(message.address).blockingGet() val shouldDrop = prefs.drop.get() Timber.v("block=$shouldBlock, drop=$shouldDrop") 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 283a4320..891c032e 100644 --- a/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveSms.kt +++ b/domain/src/main/java/com/moez/QKSMS/interactor/ReceiveSms.kt @@ -49,7 +49,7 @@ class ReceiveSms @Inject constructor( // Don't continue if the sender is blocked val messages = it.messages val address = messages[0].displayOriginatingAddress - val shouldBlock = blockingClient.shouldBlock(address).blockingGet() + val shouldBlock = blockingClient.isBlocked(address).blockingGet() val shouldDrop = prefs.drop.get() Timber.v("block=$shouldBlock, drop=$shouldDrop") diff --git a/domain/src/main/java/com/moez/QKSMS/model/BlockedNumber.kt b/domain/src/main/java/com/moez/QKSMS/model/BlockedNumber.kt new file mode 100644 index 00000000..f2bf54a1 --- /dev/null +++ b/domain/src/main/java/com/moez/QKSMS/model/BlockedNumber.kt @@ -0,0 +1,10 @@ +package com.moez.QKSMS.model + +import io.realm.RealmObject +import io.realm.annotations.PrimaryKey + +open class BlockedNumber( + @PrimaryKey var id: Long = 0, + + var address: String = "" +) : RealmObject() diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 93bbefc1..3957e831 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -223,6 +223,8 @@ Blocking Blocking Manager Built-in blocking functionality in QKSMS + Would you also like to block this number in %s? + Would you also like to block this number in %s? Call Control Automatically filter your calls and messages in one convenient place! Community IQ™ allows you to prevent unwanted messages from community known spammers