mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-06-13 13:47:47 +02:00
feat(setup/permissions): display over other apps
This commit is contained in:
2
app/proguard-rules.pro
vendored
2
app/proguard-rules.pro
vendored
@ -6,5 +6,5 @@
|
|||||||
-keep class org.jf.dexlib2.** { *; }
|
-keep class org.jf.dexlib2.** { *; }
|
||||||
-keep class org.mozilla.javascript.** { *; }
|
-keep class org.mozilla.javascript.** { *; }
|
||||||
-keep class androidx.compose.material.icons.** { *; }
|
-keep class androidx.compose.material.icons.** { *; }
|
||||||
-keep class androidx.navigation.compose.** { *; }
|
-keep class androidx.navigation.** { *; }
|
||||||
-keep class me.rhunk.snapenhance.** { *; }
|
-keep class me.rhunk.snapenhance.** { *; }
|
||||||
|
@ -17,7 +17,11 @@ import androidx.compose.material3.Button
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.OutlinedCard
|
import androidx.compose.material3.OutlinedCard
|
||||||
import androidx.compose.material3.Text
|
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.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
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.setup.screens.SetupScreen
|
||||||
import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper
|
import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper
|
||||||
|
|
||||||
|
data class PermissionData(
|
||||||
|
val translationKey: String,
|
||||||
|
val isPermissionGranted: () -> Boolean,
|
||||||
|
val requestPermission: (PermissionData) -> Unit,
|
||||||
|
)
|
||||||
|
|
||||||
class PermissionsScreen : SetupScreen() {
|
class PermissionsScreen : SetupScreen() {
|
||||||
private lateinit var activityLauncherHelper: ActivityLauncherHelper
|
private lateinit var activityLauncherHelper: ActivityLauncherHelper
|
||||||
|
|
||||||
@ -53,27 +63,73 @@ class PermissionsScreen : SetupScreen() {
|
|||||||
@SuppressLint("BatteryLife")
|
@SuppressLint("BatteryLife")
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
var notificationPermissionGranted by remember { mutableStateOf(true) }
|
|
||||||
var isBatteryOptimisationIgnored by remember { mutableStateOf(false) }
|
|
||||||
val coroutineScope = rememberCoroutineScope()
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
val grantedPermissions = remember {
|
||||||
if (isBatteryOptimisationIgnored && notificationPermissionGranted) {
|
mutableStateMapOf<String, Boolean>()
|
||||||
allowNext(true)
|
}
|
||||||
} else {
|
val permissions = remember {
|
||||||
allowNext(false)
|
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) {
|
LaunchedEffect(Unit) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
permissions.forEach { perm ->
|
||||||
notificationPermissionGranted =
|
grantedPermissions[perm.translationKey] = perm.isPermissionGranted()
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,52 +144,23 @@ class PermissionsScreen : SetupScreen() {
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(all = 16.dp),
|
.padding(all = 16.dp),
|
||||||
) {
|
) {
|
||||||
Row(
|
permissions.forEach { perm ->
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
Row(
|
||||||
) {
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
DialogText(
|
) {
|
||||||
text = context.translation["setup.permissions.notification_access"],
|
DialogText(
|
||||||
modifier = Modifier.weight(1f)
|
text = context.translation["setup.permissions.${perm.translationKey}"],
|
||||||
)
|
modifier = Modifier.weight(1f)
|
||||||
if (notificationPermissionGranted) {
|
)
|
||||||
GrantedIcon()
|
if (grantedPermissions[perm.translationKey] == true) {
|
||||||
} else {
|
GrantedIcon()
|
||||||
RequestButton {
|
} else {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
RequestButton {
|
||||||
activityLauncherHelper.requestPermission(Manifest.permission.POST_NOTIFICATIONS) { resultCode, _ ->
|
perm.requestPermission(perm)
|
||||||
coroutineScope.launch {
|
|
||||||
notificationPermissionGranted =
|
|
||||||
resultCode == ComponentActivity.RESULT_OK
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"dialog": "To continue you need to fit the following requirements:",
|
"dialog": "To continue you need to fit the following requirements:",
|
||||||
"notification_access": "Notification Access",
|
"notification_access": "Notification Access",
|
||||||
"battery_optimization": "Battery Optimization",
|
"battery_optimization": "Battery Optimization",
|
||||||
|
"display_over_other_apps": "Display Over Other Apps",
|
||||||
"request_button": "Request"
|
"request_button": "Request"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user