1package com.peachpasswords.ui.pairing23import android.Manifest4import android.content.Intent5import android.os.Build6import android.provider.Settings7import androidx.activity.compose.rememberLauncherForActivityResult8import androidx.activity.result.contract.ActivityResultContracts9import androidx.activity.compose.BackHandler10import androidx.compose.material3.AlertDialog11import androidx.compose.material3.Text12import androidx.compose.material3.TextButton13import androidx.compose.runtime.Composable14import androidx.compose.runtime.getValue15import androidx.compose.runtime.mutableStateOf16import androidx.compose.runtime.remember17import androidx.compose.runtime.setValue18import androidx.compose.ui.platform.LocalContext19import androidx.compose.ui.text.font.FontWeight20import com.peachpasswords.sync.canShowBackgroundSyncNotification21import com.peachpasswords.ui.theme.LocalPeachAccent22import com.peachpasswords.ui.theme.peachColors23import com.peachpasswords.ui.theme.PeachType2425enum class BackgroundSyncAction { ALLOW, MANUAL_ONLY, DISMISS }2627internal fun shouldPromptForBackgroundSync(pairingSucceeded: Boolean): Boolean = pairingSucceeded2829internal fun backgroundSyncChoice(30 action: BackgroundSyncAction,31 notificationsAvailable: Boolean,32): Boolean = action != BackgroundSyncAction.MANUAL_ONLY && notificationsAvailable3334@Composable35fun BackgroundSyncDialog(36 onChoice: (Boolean) -> Unit,37) {38 val context = LocalContext.current39 var permissionDenied by remember { mutableStateOf(false) }40 val permissionLauncher = rememberLauncherForActivityResult(41 ActivityResultContracts.RequestPermission(),42 ) { granted ->43 if (granted && canShowBackgroundSyncNotification(context)) {44 onChoice(true)45 } else {46 permissionDenied = true47 }48 }49 val settingsLauncher = rememberLauncherForActivityResult(50 ActivityResultContracts.StartActivityForResult(),51 ) {52 if (canShowBackgroundSyncNotification(context)) {53 onChoice(true)54 } else {55 permissionDenied = true56 }57 }58 val dismiss = {59 onChoice(60 backgroundSyncChoice(61 BackgroundSyncAction.DISMISS,62 canShowBackgroundSyncNotification(context),63 ),64 )65 }66 val allow = {67 when {68 canShowBackgroundSyncNotification(context) -> onChoice(true)69 permissionDenied -> settingsLauncher.launch(70 Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)71 .putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName),72 )73 Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU ->74 permissionLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)75 else -> permissionDenied = true76 }77 }7879 80 81 BackHandler(onBack = dismiss)82 AlertDialog(83 onDismissRequest = dismiss,84 title = {85 Text("Sync in the background?", fontFamily = PeachType.Display)86 },87 text = {88 Text(89 if (permissionDenied) {90 "Android notifications are off, so background sync stayed off. " +91 "Open Peach's notification settings and allow notifications to keep this phone reachable."92 } else {93 "Allow Peach to keep your devices in step in the background, even when the app isn't open. " +94 "Android will ask to show the small ongoing notification this requires."95 },96 fontFamily = PeachType.Body,97 color = if (permissionDenied) peachColors.Breach else peachColors.T1,98 )99 },100 confirmButton = {101 TextButton(onClick = allow) {102 Text(103 if (permissionDenied) "Open Android settings" else "Allow background sync",104 color = LocalPeachAccent.current,105 fontWeight = FontWeight.Bold,106 )107 }108 },109 dismissButton = {110 TextButton(onClick = {111 onChoice(112 backgroundSyncChoice(113 BackgroundSyncAction.MANUAL_ONLY,114 canShowBackgroundSyncNotification(context),115 ),116 )117 }) {118 Text("Sync manually only")119 }120 },121 )122}