Skip to content

Commit

Permalink
#1274 feat: show error when Key Mapper is not selected as the device …
Browse files Browse the repository at this point in the history
…assistant
  • Loading branch information
sds100 committed Nov 14, 2024
1 parent a4723b6 commit 3cc1549
Show file tree
Hide file tree
Showing 12 changed files with 36 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ class KeyMapperApp : MultiDexApplication() {
suAdapter,
notificationReceiverAdapter,
ServiceLocator.settingsRepository(this),
packageManagerAdapter,
)
}

Expand Down
1 change: 0 additions & 1 deletion app/src/main/java/io/github/sds100/keymapper/UseCases.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ object UseCases {
ServiceLocator.inputMethodAdapter(ctx),
displaySimpleMapping(ctx),
ServiceLocator.settingsRepository(ctx),
ServiceLocator.packageManagerAdapter(ctx),
ServiceLocator.purchasingManager(ctx),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package io.github.sds100.keymapper.mappings.keymaps

import android.os.Build
import android.view.KeyEvent
import io.github.sds100.keymapper.Constants
import io.github.sds100.keymapper.data.Keys
import io.github.sds100.keymapper.data.repositories.PreferenceRepository
import io.github.sds100.keymapper.mappings.DisplaySimpleMappingUseCase
Expand All @@ -11,13 +10,10 @@ import io.github.sds100.keymapper.mappings.keymaps.trigger.KeyCodeTriggerKey
import io.github.sds100.keymapper.mappings.keymaps.trigger.TriggerError
import io.github.sds100.keymapper.purchasing.ProductId
import io.github.sds100.keymapper.purchasing.PurchasingManager
import io.github.sds100.keymapper.system.apps.PackageManagerAdapter
import io.github.sds100.keymapper.system.inputmethod.InputMethodAdapter
import io.github.sds100.keymapper.system.inputmethod.KeyMapperImeHelper
import io.github.sds100.keymapper.system.permissions.Permission
import io.github.sds100.keymapper.system.permissions.PermissionAdapter
import io.github.sds100.keymapper.util.Success
import io.github.sds100.keymapper.util.then
import io.github.sds100.keymapper.util.valueIfFailure
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.drop
Expand All @@ -33,7 +29,6 @@ class DisplayKeyMapUseCaseImpl(
private val inputMethodAdapter: InputMethodAdapter,
displaySimpleMappingUseCase: DisplaySimpleMappingUseCase,
private val preferenceRepository: PreferenceRepository,
private val packageManagerAdapter: PackageManagerAdapter,
private val purchasingManager: PurchasingManager,
) : DisplayKeyMapUseCase,
DisplaySimpleMappingUseCase by displaySimpleMappingUseCase {
Expand All @@ -46,9 +41,10 @@ class DisplayKeyMapUseCaseImpl(

private val keyMapperImeHelper: KeyMapperImeHelper = KeyMapperImeHelper(inputMethodAdapter)

override val invalidateTriggerErrors = merge(
override val invalidateTriggerErrors: Flow<Unit> = merge(
permissionAdapter.onPermissionsUpdate,
preferenceRepository.get(Keys.neverShowDndError).map { }.drop(1),
purchasingManager.onCompleteProductPurchase.map { },
)

override suspend fun getTriggerErrors(keyMap: KeyMap): List<TriggerError> {
Expand Down Expand Up @@ -89,10 +85,7 @@ class DisplayKeyMapUseCaseImpl(
errors.add(TriggerError.ASSISTANT_TRIGGER_NOT_PURCHASED)
}

val isKeyMapperDeviceAssistant =
packageManagerAdapter.getDeviceAssistantPackage()
.then { Success(it == Constants.PACKAGE_NAME) }
.valueIfFailure { false }
val isKeyMapperDeviceAssistant = permissionAdapter.isGranted(Permission.DEVICE_ASSISTANT)

// Show an error if Key Mapper isn't selected as the device assistant
// and an assistant trigger is used. The error shouldn't be shown
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class KeyMapListItemCreator(
TriggerError.ASSISTANT_NOT_SELECTED -> ChipUi.Error(
id = error.toString(),
text = getString(R.string.trigger_error_assistant_activity_not_chosen),
error = Error.DeviceAssistantNotSet,
error = Error.PermissionDenied(Permission.DEVICE_ASSISTANT),
)

TriggerError.ASSISTANT_TRIGGER_NOT_PURCHASED -> ChipUi.Error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -436,11 +436,11 @@ abstract class BaseConfigTriggerViewModel(
}

TriggerError.ASSISTANT_NOT_SELECTED -> {
TODO()
displayKeyMap.fixError(Error.PermissionDenied(Permission.DEVICE_ASSISTANT))
}

TriggerError.ASSISTANT_TRIGGER_NOT_PURCHASED -> {
TODO()
showAdvancedTriggersBottomSheet = true
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package io.github.sds100.keymapper.purchasing

import io.github.sds100.keymapper.util.Result
import kotlinx.coroutines.flow.MutableSharedFlow

interface PurchasingManager {
val onCompleteProductPurchase: MutableSharedFlow<ProductId>
suspend fun launchPurchasingFlow(product: ProductId): Result<Unit>
suspend fun getProductPrice(product: ProductId): Result<String>
suspend fun isPurchased(product: ProductId): Result<Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,15 +137,14 @@ class AndroidPackageManagerAdapter(
}

override fun getDeviceAssistantPackage(): Result<String> {
try {
val intent = Intent(Intent.ACTION_ASSIST)
val activity =
packageManager.resolveActivity(intent, 0) ?: return Error.NoDeviceAssistant
val settingValue = Settings.Secure.getString(ctx.contentResolver, "assistant")

return Success(activity.activityInfo!!.packageName)
} catch (e: ActivityNotFoundException) {
if (settingValue.isNullOrEmpty()) {
return Error.NoDeviceAssistant
}

val packageName = settingValue.split("/").first()
return Success(packageName)
}

override fun enableApp(packageName: String) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@ import io.github.sds100.keymapper.data.repositories.PreferenceRepository
import io.github.sds100.keymapper.shizuku.ShizukuUtils
import io.github.sds100.keymapper.system.DeviceAdmin
import io.github.sds100.keymapper.system.accessibility.ServiceAdapter
import io.github.sds100.keymapper.system.apps.PackageManagerAdapter
import io.github.sds100.keymapper.system.root.SuAdapter
import io.github.sds100.keymapper.util.Error
import io.github.sds100.keymapper.util.Result
import io.github.sds100.keymapper.util.Success
import io.github.sds100.keymapper.util.getIdentifier
import io.github.sds100.keymapper.util.onFailure
import io.github.sds100.keymapper.util.onSuccess
import io.github.sds100.keymapper.util.success
import io.github.sds100.keymapper.util.then
import io.github.sds100.keymapper.util.valueIfFailure
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
Expand Down Expand Up @@ -56,6 +60,7 @@ class AndroidPermissionAdapter(
private val suAdapter: SuAdapter,
private val notificationReceiverAdapter: ServiceAdapter,
private val preferenceRepository: PreferenceRepository,
private val packageManagerAdapter: PackageManagerAdapter,
) : PermissionAdapter {
companion object {
const val REQUEST_CODE_SHIZUKU_PERMISSION = 1
Expand Down Expand Up @@ -333,6 +338,11 @@ class AndroidPermissionAdapter(
} else {
true
}

Permission.DEVICE_ASSISTANT ->
packageManagerAdapter.getDeviceAssistantPackage()
.then { Success(it == Constants.PACKAGE_NAME) }
.valueIfFailure { false }
}

override fun isGrantedFlow(permission: Permission): Flow<Boolean> = callbackFlow {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ enum class Permission {
ANSWER_PHONE_CALL,
FIND_NEARBY_DEVICES,
POST_NOTIFICATIONS,
DEVICE_ASSISTANT,
}
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,16 @@ class RequestPermissionDelegate(
Permission.POST_NOTIFICATIONS -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
requestPermissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
}

Permission.DEVICE_ASSISTANT -> {
try {
Intent(Settings.ACTION_VOICE_INPUT_SETTINGS).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK
startActivityForResultLauncher.launch(this)
}
} catch (e: ActivityNotFoundException) {
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,6 @@ fun Error.getFullMessage(resourceProvider: ResourceProvider): String = when (thi
Error.PurchasingError.StoreProblem -> resourceProvider.getString(R.string.purchasing_error_store_problem)
is Error.PurchasingError.Unexpected -> this.message

Error.DeviceAssistantNotSet -> resourceProvider.getString(R.string.trigger_error_assistant_activity_not_chosen_short)

is Error.ProductNotPurchased -> when (this.product) {
ProductId.ASSISTANT_TRIGGER -> resourceProvider.getString(R.string.purchasing_error_assistant_not_purchased_home_screen)
}
Expand Down
5 changes: 1 addition & 4 deletions app/src/main/java/io/github/sds100/keymapper/util/Result.kt
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ sealed class Error : Result<Nothing>() {
Permission.ANSWER_PHONE_CALL -> R.string.error_answer_end_phone_call_permission_denied
Permission.FIND_NEARBY_DEVICES -> R.string.error_find_nearby_devices_permission_denied
Permission.POST_NOTIFICATIONS -> R.string.error_notifications_permission_denied
Permission.DEVICE_ASSISTANT -> R.string.trigger_error_assistant_activity_not_chosen_short
}

return resourceProvider.getString(resId)
Expand Down Expand Up @@ -126,10 +127,6 @@ sealed class Error : Result<Nothing>() {
// have the pro features implemented.
data object PurchasingNotImplemented : Error()

/**
* Key Mapper isn't set as the device assistant.
*/
data object DeviceAssistantNotSet : Error()
data class ProductNotPurchased(val product: ProductId) : Error()

sealed class PurchasingError : Error() {
Expand Down

0 comments on commit 3cc1549

Please sign in to comment.