diff --git a/permissions/api/current.api b/permissions/api/current.api index 9348beb05..27ce97ba5 100644 --- a/permissions/api/current.api +++ b/permissions/api/current.api @@ -18,6 +18,7 @@ package com.google.accompanist.permissions { public final class MultiplePermissionsStateKt { method @androidx.compose.runtime.Composable @com.google.accompanist.permissions.ExperimentalPermissionsApi public static com.google.accompanist.permissions.MultiplePermissionsState rememberMultiplePermissionsState(java.util.List permissions, optional kotlin.jvm.functions.Function1,kotlin.Unit> onPermissionsResult); + method @androidx.compose.runtime.Composable @com.google.accompanist.permissions.ExperimentalPermissionsApi public static com.google.accompanist.permissions.MultiplePermissionsState rememberMultiplePermissionsState(java.util.List permissions, optional kotlin.jvm.functions.Function1,kotlin.Unit> onPermissionsResult, optional java.util.Map previewPermissionStatuses); } public final class MutableMultiplePermissionsStateKt { @@ -36,6 +37,7 @@ package com.google.accompanist.permissions { public final class PermissionStateKt { method @androidx.compose.runtime.Composable @com.google.accompanist.permissions.ExperimentalPermissionsApi public static com.google.accompanist.permissions.PermissionState rememberPermissionState(String permission, optional kotlin.jvm.functions.Function1 onPermissionResult); + method @androidx.compose.runtime.Composable @com.google.accompanist.permissions.ExperimentalPermissionsApi public static com.google.accompanist.permissions.PermissionState rememberPermissionState(String permission, optional kotlin.jvm.functions.Function1 onPermissionResult, optional com.google.accompanist.permissions.PermissionStatus previewPermissionStatus); } @androidx.compose.runtime.Stable @com.google.accompanist.permissions.ExperimentalPermissionsApi public sealed interface PermissionStatus { diff --git a/permissions/src/main/java/com/google/accompanist/permissions/MultiplePermissionsState.kt b/permissions/src/main/java/com/google/accompanist/permissions/MultiplePermissionsState.kt index 14bcbc6d6..8d6cb501f 100644 --- a/permissions/src/main/java/com/google/accompanist/permissions/MultiplePermissionsState.kt +++ b/permissions/src/main/java/com/google/accompanist/permissions/MultiplePermissionsState.kt @@ -17,7 +17,10 @@ package com.google.accompanist.permissions import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable +import androidx.compose.ui.platform.LocalInspectionMode +import androidx.compose.ui.util.fastMap /** * Creates a [MultiplePermissionsState] that is remembered across compositions. @@ -35,7 +38,33 @@ public fun rememberMultiplePermissionsState( permissions: List, onPermissionsResult: (Map) -> Unit = {} ): MultiplePermissionsState { - return rememberMutableMultiplePermissionsState(permissions, onPermissionsResult) + return rememberMultiplePermissionsState(permissions, onPermissionsResult, emptyMap()) +} + +/** + * Creates a [MultiplePermissionsState] that is remembered across compositions. + * + * It's recommended that apps exercise the permissions workflow as described in the + * [documentation](https://developer.android.com/training/permissions/requesting#workflow_for_requesting_permissions). + * + * @param permissions the permissions to control and observe. + * @param onPermissionsResult will be called with whether or not the user granted the permissions + * after [MultiplePermissionsState.launchMultiplePermissionRequest] is called. + * @param previewPermissionStatuses provides a [PermissionStatus] for a given permission when running + * in a preview. + */ +@ExperimentalPermissionsApi +@Composable +public fun rememberMultiplePermissionsState( + permissions: List, + onPermissionsResult: (Map) -> Unit = {}, + previewPermissionStatuses: Map = emptyMap() +): MultiplePermissionsState { + return when { + LocalInspectionMode.current -> + PreviewMultiplePermissionsState(permissions, previewPermissionStatuses) + else -> rememberMutableMultiplePermissionsState(permissions, onPermissionsResult) + } } /** @@ -83,3 +112,23 @@ public interface MultiplePermissionsState { */ public fun launchMultiplePermissionRequest(): Unit } + +@OptIn(ExperimentalPermissionsApi::class) +@Immutable +private class PreviewMultiplePermissionsState( + permissions: List, + permissionStatuses: Map +) : MultiplePermissionsState { + override val permissions: List = permissions.fastMap { permission -> + PreviewPermissionState( + permission = permission, + status = permissionStatuses[permission] ?: PermissionStatus.Granted, + ) + } + + override val revokedPermissions: List = emptyList() + override val allPermissionsGranted: Boolean = false + override val shouldShowRationale: Boolean = false + + override fun launchMultiplePermissionRequest() {} +} diff --git a/permissions/src/main/java/com/google/accompanist/permissions/PermissionState.kt b/permissions/src/main/java/com/google/accompanist/permissions/PermissionState.kt index a97a47f66..3b1840188 100644 --- a/permissions/src/main/java/com/google/accompanist/permissions/PermissionState.kt +++ b/permissions/src/main/java/com/google/accompanist/permissions/PermissionState.kt @@ -17,7 +17,9 @@ package com.google.accompanist.permissions import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable import androidx.compose.runtime.Stable +import androidx.compose.ui.platform.LocalInspectionMode /** * Creates a [PermissionState] that is remembered across compositions. @@ -35,7 +37,31 @@ public fun rememberPermissionState( permission: String, onPermissionResult: (Boolean) -> Unit = {} ): PermissionState { - return rememberMutablePermissionState(permission, onPermissionResult) + return rememberPermissionState(permission, onPermissionResult, PermissionStatus.Granted) +} + +/** + * Creates a [PermissionState] that is remembered across compositions. + * + * It's recommended that apps exercise the permissions workflow as described in the + * [documentation](https://developer.android.com/training/permissions/requesting#workflow_for_requesting_permissions). + * + * @param permission the permission to control and observe. + * @param onPermissionResult will be called with whether or not the user granted the permission + * after [PermissionState.launchPermissionRequest] is called. + * @param previewPermissionStatus provides a [PermissionStatus] when running in a preview. + */ +@ExperimentalPermissionsApi +@Composable +public fun rememberPermissionState( + permission: String, + onPermissionResult: (Boolean) -> Unit = {}, + previewPermissionStatus: PermissionStatus = PermissionStatus.Granted +): PermissionState { + return when { + LocalInspectionMode.current -> PreviewPermissionState(permission, previewPermissionStatus) + else -> rememberMutablePermissionState(permission, onPermissionResult) + } } /** @@ -73,3 +99,12 @@ public interface PermissionState { */ public fun launchPermissionRequest(): Unit } + +@OptIn(ExperimentalPermissionsApi::class) +@Immutable +internal class PreviewPermissionState( + override val permission: String, + override val status: PermissionStatus +) : PermissionState { + override fun launchPermissionRequest() {} +}