feat: Improve permission request

This commit is contained in:
Myzel394 2023-08-08 10:11:29 +02:00
parent 3f124a24e9
commit 1c49ac35b8
No known key found for this signature in database
GPG Key ID: 79CC92F37B3E1A2B
5 changed files with 121 additions and 46 deletions

View File

@ -69,13 +69,8 @@ fun StartRecording(
) {
Spacer(modifier = Modifier.weight(1f))
PermissionRequester(
permission = arrayOf(Manifest.permission.RECORD_AUDIO),
icon = {
Icon(
Icons.Default.Mic,
contentDescription = null,
)
},
permission = Manifest.permission.RECORD_AUDIO,
icon = Icons.Default.Mic,
onPermissionAvailable = {
RecorderService.startService(context, connection)
},

View File

@ -37,7 +37,7 @@ fun MessageBox(
}
val onContainerColor = when(type) {
MessageType.ERROR -> MaterialTheme.colorScheme.onError
MessageType.INFO -> MaterialTheme.colorScheme.onTertiary
MessageType.INFO -> MaterialTheme.colorScheme.onTertiaryContainer
MessageType.SUCCESS -> Color.Green
MessageType.WARNING -> Color.Yellow
}

View File

@ -1,10 +1,17 @@
package app.myzel394.alibi.ui.components.atoms
import android.app.Activity
import android.content.pm.PackageManager
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Cancel
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.OpenInNew
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
@ -12,55 +19,136 @@ import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.app.ActivityCompat
import app.myzel394.alibi.R
import app.myzel394.alibi.ui.utils.PermissionHelper
import app.myzel394.alibi.ui.utils.openAppSystemSettings
@Composable
fun PermissionRequester(
permission: Array<String>,
icon: (@Composable () -> Unit)? = null,
permission: String,
icon: ImageVector,
onPermissionAvailable: () -> Unit,
content: @Composable (trigger: () -> Unit) -> Unit
) {
val context = LocalContext.current
var showExplanationDialog by remember { mutableStateOf(false) }
var isGranted by remember { mutableStateOf(PermissionHelper.hasGranted(context, permission)) }
var visibleDialog by remember { mutableStateOf<VisibleDialog?>(null) }
val requestPermission = rememberLauncherForActivityResult(
contract = ActivityResultContracts.RequestPermission(),
onResult = { isPermissionGranted: Boolean ->
isGranted = isPermissionGranted
if (isGranted) {
onPermissionAvailable()
} else {
if (ActivityCompat.shouldShowRequestPermissionRationale(context as Activity, permission)) {
visibleDialog = VisibleDialog.REQUEST
} else {
visibleDialog = VisibleDialog.PERMANENTLY_DENIED
}
}
}
)
fun callback() {
if (PermissionHelper.hasPermanentlyDenied(context, permission)) {
showExplanationDialog = true
return
}
if (PermissionHelper.checkPermissions(context, permission)) {
if (isGranted) {
onPermissionAvailable()
} else {
requestPermission.launch(permission)
}
}
if (showExplanationDialog) {
if (visibleDialog == VisibleDialog.REQUEST) {
AlertDialog(
onDismissRequest = {
showExplanationDialog = false
visibleDialog = null
},
icon = {
Icon(
icon,
contentDescription = null,
)
},
icon = icon,
title = {
Text(stringResource(R.string.ui_permissions_request_title))
},
text = {
Text(stringResource(R.string.ui_permissions_request_message))
Text(stringResource(R.string.ui_permissions_request))
},
confirmButton = {
Button(
onClick = {
showExplanationDialog = false
visibleDialog = null
callback()
}
) {
Icon(
Icons.Default.Check,
contentDescription = null,
modifier = Modifier.size(ButtonDefaults.IconSize),
)
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
Text(stringResource(R.string.dialog_close_neutral_label))
}
},
dismissButton = {
Button(
onClick = {
visibleDialog = null
},
colors = ButtonDefaults.textButtonColors(),
) {
Icon(
Icons.Default.Cancel,
contentDescription = null,
modifier = Modifier.size(ButtonDefaults.IconSize),
)
Spacer(modifier = Modifier.width(ButtonDefaults.IconSpacing))
Text(stringResource(R.string.dialog_close_cancel_label))
}
}
)
}
if (visibleDialog == VisibleDialog.PERMANENTLY_DENIED) {
AlertDialog(
onDismissRequest = {
visibleDialog = null
},
icon = {
Icon(
icon,
contentDescription = null,
)
},
title = {
Text(stringResource(R.string.ui_permissions_request_title))
},
text = {
Column {
Text(stringResource(R.string.ui_permissions_request))
Spacer(modifier = Modifier.height(32.dp))
MessageBox(
type = MessageType.INFO,
message = stringResource(R.string.ui_permissions_permanentlyDenied_message)
)
}
},
confirmButton = {
Button(
onClick = {
visibleDialog = null
context.openAppSystemSettings()
}
) {
@ -76,7 +164,7 @@ fun PermissionRequester(
dismissButton = {
Button(
onClick = {
showExplanationDialog = false
visibleDialog = null
},
colors = ButtonDefaults.textButtonColors(),
) {
@ -92,4 +180,9 @@ fun PermissionRequester(
)
}
content(::callback)
}
enum class VisibleDialog {
REQUEST,
PERMANENTLY_DENIED
}

View File

@ -10,34 +10,20 @@ import androidx.core.app.ActivityCompat
// From @Bnyro
object PermissionHelper {
fun checkPermissions(context: Context, permissions: Array<String>): Boolean {
permissions.forEach {
if (!hasGranted(context, it)) {
ActivityCompat.requestPermissions(
context as Activity,
arrayOf(it),
1
)
return false
}
fun checkPermission(context: Context, permission: String): Boolean {
if (!hasGranted(context, permission)) {
ActivityCompat.requestPermissions(
context as Activity,
arrayOf(permission),
1
)
return false
}
return true
}
fun hasGranted(context: Context, permission: String): Boolean =
ActivityCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED
fun hasPermanentlyDenied(context: Context, permission: String): Boolean =
!hasGranted(context, permission) &&
!ActivityCompat.shouldShowRequestPermissionRationale(context as Activity, permission)
fun hasPermanentlyDenied(context: Context, permission: Array<String>): Boolean {
permission.forEach {
if (hasPermanentlyDenied(context, it))
return true
}
return false
}
}
fun Context.openAppSystemSettings() {

View File

@ -15,7 +15,8 @@
<string name="notificationChannels_recorder_description">Shows the current recording status</string>
<string name="ui_permissions_request_title">Permission denied</string>
<string name="ui_permissions_request_message">Please grant the permission to continue. You will be redirected to the app settings to grant the permission there.</string>
<string name="ui_permissions_request">Please grant the permission to continue</string>
<string name="ui_permissions_permanentlyDenied_message">You will be redirected to the app settings to grant the permission there.</string>
<string name="ui_audioRecorder_action_start_label">Start Recording</string>
<string name="ui_audioRecorder_action_saveOldRecording_label">Save Recording from <xliff:g name="date">%s</xliff:g></string>