Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.unit.dp
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.shouldShowRationale
import com.hedvig.android.design.system.hedvig.HedvigBottomSheet
import com.hedvig.android.design.system.hedvig.HedvigButton
import com.hedvig.android.design.system.hedvig.HedvigText
Expand All @@ -29,7 +27,9 @@ import com.hedvig.android.design.system.hedvig.api.HedvigBottomSheetState
import com.hedvig.android.design.system.hedvig.rememberHedvigBottomSheetState
import com.hedvig.android.design.system.hedvig.show
import com.hedvig.android.notification.permission.NotificationPermissionState
import com.hedvig.android.notification.permission.isGranted
import com.hedvig.android.notification.permission.rememberNotificationPermissionState
import com.hedvig.android.notification.permission.shouldShowRationale
import hedvig.resources.CLAIMS_ACTIVATE_NOTIFICATIONS_BODY
import hedvig.resources.CLAIMS_ACTIVATE_NOTIFICATIONS_CTA
import hedvig.resources.CLAIM_CHAT_GET_NOTIFIED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ import arrow.core.nonEmptyListOf
import arrow.core.toNonEmptyListOrNull
import coil3.ImageLoader
import coil3.compose.AsyncImage
import com.google.accompanist.permissions.isGranted
import com.hedvig.android.compose.pager.indicator.CardCarousel
import com.hedvig.android.compose.ui.LocalClock
import com.hedvig.android.compose.ui.dropUnlessResumed
Expand Down Expand Up @@ -209,6 +208,7 @@ import com.hedvig.android.memberreminders.ui.homeInformationalReminders
import com.hedvig.android.memberreminders.ui.missingPayinMethodReminder
import com.hedvig.android.notification.permission.NotificationPermissionDialog
import com.hedvig.android.notification.permission.NotificationPermissionState
import com.hedvig.android.notification.permission.isGranted
import com.hedvig.android.notification.permission.rememberNotificationPermissionState
import com.hedvig.android.notification.permission.rememberPreviewNotificationPermissionState
import com.hedvig.android.pullrefresh.PullRefreshDefaults
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.google.accompanist.permissions.PermissionStatus
import com.google.accompanist.permissions.PermissionStatus.Granted
import com.google.accompanist.permissions.isGranted
import com.hedvig.android.data.settings.datastore.AnalyticsConsent
import com.hedvig.android.design.system.hedvig.DialogDefaults.ButtonSize.BIG
import com.hedvig.android.design.system.hedvig.HedvigAlertDialog
Expand All @@ -52,6 +49,9 @@ import com.hedvig.android.language.label
import com.hedvig.android.memberreminders.ui.ReminderCardEnableNotifications
import com.hedvig.android.notification.permission.NotificationPermissionDialog
import com.hedvig.android.notification.permission.NotificationPermissionState
import com.hedvig.android.notification.permission.PermissionStatus
import com.hedvig.android.notification.permission.PermissionStatus.Granted
import com.hedvig.android.notification.permission.isGranted
import com.hedvig.android.notification.permission.rememberNotificationPermissionState
import com.hedvig.android.theme.Theme
import hedvig.resources.GENERAL_DISABLED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameter
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.compose.dropUnlessResumed
import com.google.accompanist.permissions.isGranted
import com.hedvig.android.compose.ui.plus
import com.hedvig.android.compose.ui.preview.PreviewContentWithProvidedParametersAnimatedOnClick
import com.hedvig.android.data.coinsured.CoInsuredFlowType
Expand Down Expand Up @@ -77,6 +76,7 @@ import com.hedvig.android.memberreminders.ui.MissingPayinMethodCard
import com.hedvig.android.memberreminders.ui.cardReminders
import com.hedvig.android.memberreminders.ui.missingPayinMethodReminder
import com.hedvig.android.notification.permission.NotificationPermissionDialog
import com.hedvig.android.notification.permission.isGranted
import com.hedvig.android.notification.permission.rememberNotificationPermissionState
import com.hedvig.android.placeholder.PlaceholderHighlight
import com.hedvig.android.pullrefresh.PullRefreshDefaults
Expand Down
22 changes: 15 additions & 7 deletions app/notification-permission/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
plugins {
id("hedvig.android.library")
id("hedvig.multiplatform.library")
id("hedvig.multiplatform.library.android")
id("hedvig.gradle.plugin")
}

hedvig {
compose()
}

dependencies {
api(libs.accompanist.permissions)

implementation(libs.androidx.activity.compose)
implementation(projects.coreResources)
implementation(projects.designSystemHedvig)
kotlin {
sourceSets {
commonMain.dependencies {
implementation(libs.jetbrains.compose.runtime)
implementation(projects.coreResources)
implementation(projects.designSystemHedvig)
}
androidMain.dependencies {
implementation(libs.accompanist.permissions)
implementation(libs.androidx.activity.compose)
implementation(libs.jetbrains.compose.ui)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,30 +19,32 @@ import androidx.compose.ui.platform.LocalInspectionMode
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.MutablePermissionState
import com.google.accompanist.permissions.PermissionLifecycleCheckerEffect
import com.google.accompanist.permissions.PermissionState
import com.google.accompanist.permissions.PermissionStatus
import com.google.accompanist.permissions.isGranted
import com.google.accompanist.permissions.PermissionState as AccompanistPermissionState
import com.google.accompanist.permissions.PermissionStatus as AccompanistPermissionStatus
import com.google.accompanist.permissions.isGranted as accompanistIsGranted
import com.google.accompanist.permissions.rememberPermissionState
import com.google.accompanist.permissions.shouldShowRationale
import com.hedvig.android.design.system.hedvig.PermissionDialog
import hedvig.resources.CLAIMS_ACTIVATE_NOTIFICATIONS_BODY
import hedvig.resources.Res
import org.jetbrains.compose.resources.stringResource

interface NotificationPermissionState : PermissionState {
val showDialog: Boolean

fun dismissDialog()
}

private class NotificationPermissionStateImpl(
private val permissionState: PermissionState,
) : NotificationPermissionState, PermissionState by permissionState {
private val permissionState: AccompanistPermissionState,
) : NotificationPermissionState {
private var _showDialog by mutableStateOf(false)

override val permission: String
get() = permissionState.permission

override val status: PermissionStatus
get() = when (val status = permissionState.status) {
AccompanistPermissionStatus.Granted -> PermissionStatus.Granted
is AccompanistPermissionStatus.Denied -> PermissionStatus.Denied(status.shouldShowRationale)
}

override val showDialog: Boolean
get() = _showDialog

override fun launchPermissionRequest() {
permissionState.launchPermissionRequest()
}

override fun dismissDialog() {
_showDialog = false
}
Expand All @@ -59,7 +61,7 @@ private class NotificationPermissionStateImpl(
*/
@SuppressLint("InlinedApi")
@Composable
fun rememberNotificationPermissionState(onNotificationGranted: () -> Unit = {}): NotificationPermissionState {
actual fun rememberNotificationPermissionState(onNotificationGranted: () -> Unit): NotificationPermissionState {
val context = LocalContext.current
val activity = LocalActivity.current
val permissionState = remember {
Expand Down Expand Up @@ -87,43 +89,13 @@ fun rememberNotificationPermissionState(onNotificationGranted: () -> Unit = {}):
return notificationPermissionState
}

@Composable
fun NotificationPermissionDialog(
notificationPermissionState: NotificationPermissionState,
openAppSettings: () -> Unit,
) {
if (notificationPermissionState.showDialog) {
PermissionDialog(
permissionDescription = stringResource(Res.string.CLAIMS_ACTIVATE_NOTIFICATIONS_BODY),
isPermanentlyDeclined = !notificationPermissionState.status.shouldShowRationale,
onDismiss = notificationPermissionState::dismissDialog,
okClick = notificationPermissionState::launchPermissionRequest,
openAppSettings = openAppSettings,
)
}
}

@OptIn(ExperimentalPermissionsApi::class)
@Composable
fun rememberNotificationPermissionStatus(): Boolean {
actual fun rememberNotificationPermissionStatus(): Boolean {
val isPreview = LocalInspectionMode.current
return if (!isPreview && Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
rememberPermissionState(Manifest.permission.POST_NOTIFICATIONS).status.isGranted
rememberPermissionState(Manifest.permission.POST_NOTIFICATIONS).status.accompanistIsGranted
} else {
true
}
}

fun rememberPreviewNotificationPermissionState(
permissionStatus: PermissionStatus = PermissionStatus.Granted,
isDialogShowing: Boolean = false,
): NotificationPermissionState = object : NotificationPermissionState {
override val showDialog: Boolean = isDialogShowing

override fun dismissDialog() {}

override val permission: String = ""
override val status: PermissionStatus = permissionStatus

override fun launchPermissionRequest() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.hedvig.android.notification.permission

import androidx.compose.runtime.Composable
import com.hedvig.android.design.system.hedvig.PermissionDialog
import hedvig.resources.CLAIMS_ACTIVATE_NOTIFICATIONS_BODY
import hedvig.resources.Res
import org.jetbrains.compose.resources.stringResource

interface NotificationPermissionState {
val permission: String
val status: PermissionStatus
val showDialog: Boolean

fun launchPermissionRequest()

fun dismissDialog()
}

sealed interface PermissionStatus {
data object Granted : PermissionStatus

data class Denied(val shouldShowRationale: Boolean) : PermissionStatus
}

val PermissionStatus.isGranted: Boolean
get() = this == PermissionStatus.Granted

val PermissionStatus.shouldShowRationale: Boolean
get() = when (this) {
PermissionStatus.Granted -> false
is PermissionStatus.Denied -> shouldShowRationale
}

/**
* Notification permission state for the current screen. [onNotificationGranted] runs when a permission request is
* granted; a denied request makes [NotificationPermissionState.showDialog] true. Use in conjunction with
* [NotificationPermissionDialog].
*/
@Composable
expect fun rememberNotificationPermissionState(onNotificationGranted: () -> Unit = {}): NotificationPermissionState

@Composable
fun NotificationPermissionDialog(
notificationPermissionState: NotificationPermissionState,
openAppSettings: () -> Unit,
) {
if (notificationPermissionState.showDialog) {
PermissionDialog(
permissionDescription = stringResource(Res.string.CLAIMS_ACTIVATE_NOTIFICATIONS_BODY),
isPermanentlyDeclined = !notificationPermissionState.status.shouldShowRationale,
onDismiss = notificationPermissionState::dismissDialog,
okClick = notificationPermissionState::launchPermissionRequest,
openAppSettings = openAppSettings,
)
}
}

@Composable
expect fun rememberNotificationPermissionStatus(): Boolean

fun rememberPreviewNotificationPermissionState(
permissionStatus: PermissionStatus = PermissionStatus.Granted,
isDialogShowing: Boolean = false,
): NotificationPermissionState = object : NotificationPermissionState {
override val showDialog: Boolean = isDialogShowing

override fun dismissDialog() {}

override val permission: String = ""
override val status: PermissionStatus = permissionStatus

override fun launchPermissionRequest() {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.hedvig.android.notification.permission

import androidx.compose.runtime.Composable

/**
* The JVM target has no notification permission to request, so the state always reads as denied and never shows a
* dialog.
*/
private object UnavailableNotificationPermissionState : NotificationPermissionState {
override val permission: String = "android.permission.POST_NOTIFICATIONS"
override val status: PermissionStatus = PermissionStatus.Denied(shouldShowRationale = false)
override val showDialog: Boolean = false

override fun launchPermissionRequest() {}

override fun dismissDialog() {}
}

@Composable
actual fun rememberNotificationPermissionState(onNotificationGranted: () -> Unit): NotificationPermissionState {
return UnavailableNotificationPermissionState
}

@Composable
actual fun rememberNotificationPermissionStatus(): Boolean = false
Loading