feat(setup/permissions): display over other apps

This commit is contained in:
rhunk
2023-10-14 15:07:01 +02:00
parent b92589fa07
commit 2b0e4ad09a
3 changed files with 89 additions and 61 deletions

View File

@ -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.** { *; }

View File

@ -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>()
}
LaunchedEffect(Unit) {
val permissions = remember {
listOf(
PermissionData(
translationKey = "notification_access",
isPermissionGranted = {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
notificationPermissionGranted =
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
isBatteryOptimisationIgnored =
powerManager.isIgnoringBatteryOptimizations(context.androidContext.packageName)
if (isBatteryOptimisationIgnored && notificationPermissionGranted) {
goNext()
},
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) {
permissions.forEach { perm ->
grantedPermissions[perm.translationKey] = perm.isPermissionGranted()
}
}
@ -88,53 +144,24 @@ class PermissionsScreen : SetupScreen() {
modifier = Modifier
.padding(all = 16.dp),
) {
permissions.forEach { perm ->
Row(
verticalAlignment = Alignment.CenterVertically,
) {
DialogText(
text = context.translation["setup.permissions.notification_access"],
text = context.translation["setup.permissions.${perm.translationKey}"],
modifier = Modifier.weight(1f)
)
if (notificationPermissionGranted) {
if (grantedPermissions[perm.translationKey] == true) {
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
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
}
}
}
}
}
}
}
}
}

View File

@ -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"
}
},