commit 2b0e4ad09ae0d954f781ba0e00ad5e658f638560
parent b92589fa07c6a6fc496433d0e090bc2375ce8277
Author: rhunk <101876869+rhunk@users.noreply.github.com>
Date:   Sat, 14 Oct 2023 15:07:01 +0200

feat(setup/permissions): display over other apps

Diffstat:
Mapp/proguard-rules.pro | 2+-
Mapp/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PermissionsScreen.kt | 147+++++++++++++++++++++++++++++++++++++++++++++++--------------------------------
Mcommon/src/main/assets/lang/en_US.json | 1+
3 files changed, 89 insertions(+), 61 deletions(-)

diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro @@ -6,5 +6,5 @@ -keep class org.jf.dexlib2.** { *; } -keep class org.mozilla.javascript.** { *; } -keep class androidx.compose.material.icons.** { *; } --keep class androidx.navigation.compose.** { *; } +-keep class androidx.navigation.** { *; } -keep class me.rhunk.snapenhance.** { *; } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PermissionsScreen.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ui/setup/screens/impl/PermissionsScreen.kt @@ -17,7 +17,11 @@ import androidx.compose.material3.Button import androidx.compose.material3.Icon import androidx.compose.material3.OutlinedCard import androidx.compose.material3.Text -import androidx.compose.runtime.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.mutableStateMapOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -25,6 +29,12 @@ import kotlinx.coroutines.launch import me.rhunk.snapenhance.ui.setup.screens.SetupScreen import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper +data class PermissionData( + val translationKey: String, + val isPermissionGranted: () -> Boolean, + val requestPermission: (PermissionData) -> Unit, +) + class PermissionsScreen : SetupScreen() { private lateinit var activityLauncherHelper: ActivityLauncherHelper @@ -53,27 +63,73 @@ class PermissionsScreen : SetupScreen() { @SuppressLint("BatteryLife") @Composable override fun Content() { - var notificationPermissionGranted by remember { mutableStateOf(true) } - var isBatteryOptimisationIgnored by remember { mutableStateOf(false) } val coroutineScope = rememberCoroutineScope() - - if (isBatteryOptimisationIgnored && notificationPermissionGranted) { - allowNext(true) - } else { - allowNext(false) + val grantedPermissions = remember { + mutableStateMapOf<String, Boolean>() + } + val permissions = remember { + listOf( + PermissionData( + translationKey = "notification_access", + isPermissionGranted = { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + context.androidContext.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED + } else { + true + } + }, + requestPermission = { perm -> + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + activityLauncherHelper.requestPermission(Manifest.permission.POST_NOTIFICATIONS) { resultCode, _ -> + coroutineScope.launch { + grantedPermissions[perm.translationKey] = resultCode == ComponentActivity.RESULT_OK + } + } + } + } + ), + PermissionData( + translationKey = "battery_optimization", + isPermissionGranted = { + val powerManager = + context.androidContext.getSystemService(Context.POWER_SERVICE) as PowerManager + powerManager.isIgnoringBatteryOptimizations(context.androidContext.packageName) + }, + requestPermission = { perm -> + activityLauncherHelper.launch(Intent().apply { + action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS + data = Uri.parse("package:${context.androidContext.packageName}") + }) { resultCode, _ -> + coroutineScope.launch { + grantedPermissions[perm.translationKey] = resultCode == 0 + } + } + } + ), + PermissionData( + translationKey = "display_over_other_apps", + isPermissionGranted = { + Settings.canDrawOverlays(context.androidContext) + }, + requestPermission = { perm -> + activityLauncherHelper.launch(Intent().apply { + action = Settings.ACTION_MANAGE_OVERLAY_PERMISSION + data = Uri.parse("package:${context.androidContext.packageName}") + }) { resultCode, _ -> + coroutineScope.launch { + grantedPermissions[perm.translationKey] = resultCode == 0 + } + } + } + ) + ) } + allowNext(permissions.all { perm -> grantedPermissions[perm.translationKey] == true }) + LaunchedEffect(Unit) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - notificationPermissionGranted = - context.androidContext.checkSelfPermission(Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED - } - val powerManager = - context.androidContext.getSystemService(Context.POWER_SERVICE) as PowerManager - isBatteryOptimisationIgnored = - powerManager.isIgnoringBatteryOptimizations(context.androidContext.packageName) - if (isBatteryOptimisationIgnored && notificationPermissionGranted) { - goNext() + permissions.forEach { perm -> + grantedPermissions[perm.translationKey] = perm.isPermissionGranted() } } @@ -88,52 +144,23 @@ class PermissionsScreen : SetupScreen() { modifier = Modifier .padding(all = 16.dp), ) { - Row( - verticalAlignment = Alignment.CenterVertically, - ) { - DialogText( - text = context.translation["setup.permissions.notification_access"], - modifier = Modifier.weight(1f) - ) - if (notificationPermissionGranted) { - GrantedIcon() - } else { - RequestButton { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - activityLauncherHelper.requestPermission(Manifest.permission.POST_NOTIFICATIONS) { resultCode, _ -> - coroutineScope.launch { - notificationPermissionGranted = - resultCode == ComponentActivity.RESULT_OK - } - } + permissions.forEach { perm -> + Row( + verticalAlignment = Alignment.CenterVertically, + ) { + DialogText( + text = context.translation["setup.permissions.${perm.translationKey}"], + modifier = Modifier.weight(1f) + ) + if (grantedPermissions[perm.translationKey] == true) { + GrantedIcon() + } else { + RequestButton { + perm.requestPermission(perm) } } } } - - Row( - verticalAlignment = Alignment.CenterVertically, - ) { - DialogText( - text = context.translation["setup.permissions.battery_optimization"], - modifier = Modifier.weight(1f) - ) - if (isBatteryOptimisationIgnored) { - GrantedIcon() - } else { - RequestButton { - activityLauncherHelper.launch(Intent().apply { - action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS - data = Uri.parse("package:${context.androidContext.packageName}") - }) { resultCode, _ -> - coroutineScope.launch { - isBatteryOptimisationIgnored = resultCode == 0 - } - } - } - } - - } } } } diff --git a/common/src/main/assets/lang/en_US.json b/common/src/main/assets/lang/en_US.json @@ -16,6 +16,7 @@ "dialog": "To continue you need to fit the following requirements:", "notification_access": "Notification Access", "battery_optimization": "Battery Optimization", + "display_over_other_apps": "Display Over Other Apps", "request_button": "Request" } },