Skip to content

Commit d155c43

Browse files
committed
Added generic component to handle permission requests to the user
To double check if the Android11Dialog is still shown correctly
1 parent 81c78ef commit d155c43

File tree

5 files changed

+145
-39
lines changed

5 files changed

+145
-39
lines changed

app/src/main/java/app/revanced/manager/ui/screen/DashboardScreen.kt

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ import app.revanced.manager.ui.component.bundle.ImportPatchBundleDialog
6969
import app.revanced.manager.ui.component.haptics.HapticFloatingActionButton
7070
import app.revanced.manager.ui.component.haptics.HapticTab
7171
import app.revanced.manager.ui.viewmodel.DashboardViewModel
72+
import app.revanced.manager.util.PermissionRequestHandler
7273
import app.revanced.manager.util.RequestInstallAppsContract
7374
import app.revanced.manager.util.toast
7475
import kotlinx.coroutines.launch
@@ -142,19 +143,19 @@ fun DashboardScreen(
142143
}
143144

144145
var showAndroid11Dialog by rememberSaveable { mutableStateOf(false) }
145-
val installAppsPermissionLauncher =
146-
rememberLauncherForActivityResult(RequestInstallAppsContract) { granted ->
147-
showAndroid11Dialog = false
148-
if (granted) onAppSelectorClick()
149-
}
150-
if (showAndroid11Dialog) Android11Dialog(
151-
onDismissRequest = {
152-
showAndroid11Dialog = false
153-
},
154-
onContinue = {
155-
installAppsPermissionLauncher.launch(androidContext.packageName)
156-
}
157-
)
146+
147+
if(showAndroid11Dialog)
148+
PermissionRequestHandler(
149+
contract = RequestInstallAppsContract,
150+
input = androidContext.packageName,
151+
title = stringResource(R.string.android_11_bug_dialog_title),
152+
description = stringResource(R.string.android_11_bug_dialog_description),
153+
icon = Icons.Outlined.BugReport,
154+
onDismissRequest = { showAndroid11Dialog = false },
155+
onResult = { granted ->
156+
if (granted) onAppSelectorClick()
157+
}
158+
)
158159

159160
var showDeleteConfirmationDialog by rememberSaveable { mutableStateOf(false) }
160161
if (showDeleteConfirmationDialog) {
@@ -386,25 +387,4 @@ fun Notifications(
386387
}
387388
}
388389
}
389-
}
390-
391-
@Composable
392-
fun Android11Dialog(onDismissRequest: () -> Unit, onContinue: () -> Unit) {
393-
AlertDialogExtended(
394-
onDismissRequest = onDismissRequest,
395-
confirmButton = {
396-
TextButton(onClick = onContinue) {
397-
Text(stringResource(R.string.continue_))
398-
}
399-
},
400-
title = {
401-
Text(stringResource(R.string.android_11_bug_dialog_title))
402-
},
403-
icon = {
404-
Icon(Icons.Outlined.BugReport, null)
405-
},
406-
text = {
407-
Text(stringResource(R.string.android_11_bug_dialog_description))
408-
}
409-
)
410390
}

app/src/main/java/app/revanced/manager/ui/screen/settings/update/UpdatesSettingsScreen.kt

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
package app.revanced.manager.ui.screen.settings.update
22

3+
import android.Manifest
4+
import androidx.activity.result.contract.ActivityResultContracts
35
import androidx.compose.foundation.clickable
46
import androidx.compose.foundation.layout.Column
57
import androidx.compose.foundation.layout.Row
68
import androidx.compose.foundation.layout.fillMaxSize
79
import androidx.compose.foundation.layout.fillMaxWidth
810
import androidx.compose.foundation.layout.padding
11+
import androidx.compose.material.icons.Icons
12+
import androidx.compose.material.icons.outlined.Notifications
913
import androidx.compose.material3.AlertDialog
1014
import androidx.compose.material3.ExperimentalMaterial3Api
1115
import androidx.compose.material3.Scaffold
@@ -33,6 +37,8 @@ import app.revanced.manager.ui.component.haptics.HapticRadioButton
3337
import app.revanced.manager.ui.component.settings.BooleanItem
3438
import app.revanced.manager.ui.component.settings.SettingsListItem
3539
import app.revanced.manager.ui.viewmodel.UpdatesSettingsViewModel
40+
import app.revanced.manager.util.PermissionRequestHandler
41+
import app.revanced.manager.util.hasNotificationPermission
3642
import app.revanced.manager.util.toast
3743
import kotlinx.coroutines.launch
3844
import org.koin.androidx.compose.koinViewModel
@@ -129,11 +135,34 @@ private fun BackgroundBundleUpdateTimeDialog(
129135
onConfirm: (BackgroundBundleUpdateTime) -> Unit,
130136
prefs: PreferencesManager = koinInject()
131137
) {
138+
var context = LocalContext.current
132139
var selected by rememberSaveable { mutableStateOf(prefs.backgroundBundleUpdateTime.getBlocking()) }
133140

141+
var askNotificationPermission by rememberSaveable { mutableStateOf(false) }
142+
143+
fun onApply() {
144+
onConfirm(selected)
145+
onDismiss()
146+
}
147+
148+
if (askNotificationPermission) {
149+
PermissionRequestHandler(
150+
contract = ActivityResultContracts.RequestPermission(),
151+
input = Manifest.permission.POST_NOTIFICATIONS,
152+
title = stringResource(R.string.background_bundle_ask_notification),
153+
description = stringResource(R.string.background_bundle_ask_notification_description),
154+
icon = Icons.Outlined.Notifications,
155+
onDismissRequest = { askNotificationPermission = false },
156+
onResult = { granted ->
157+
askNotificationPermission = false
158+
onApply()
159+
}
160+
)
161+
}
162+
134163
AlertDialog(
135164
onDismissRequest = onDismiss,
136-
title = { Text(stringResource(R.string.theme)) },
165+
title = { Text(stringResource(R.string.background_radio_menu_title)) },
137166
text = {
138167
Column {
139168
BackgroundBundleUpdateTime.entries.forEach {
@@ -154,8 +183,11 @@ private fun BackgroundBundleUpdateTimeDialog(
154183
confirmButton = {
155184
TextButton(
156185
onClick = {
157-
onConfirm(selected)
158-
onDismiss()
186+
if (selected != BackgroundBundleUpdateTime.NEVER &&
187+
!hasNotificationPermission(context)
188+
) askNotificationPermission = true
189+
else
190+
onApply()
159191
}
160192
) {
161193
Text(stringResource(R.string.apply))
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package app.revanced.manager.util
2+
3+
import android.app.Activity
4+
import androidx.activity.compose.rememberLauncherForActivityResult
5+
import androidx.activity.result.contract.ActivityResultContract
6+
import androidx.compose.material3.Icon
7+
import androidx.compose.material3.Text
8+
import androidx.compose.material3.TextButton
9+
import androidx.compose.runtime.Composable
10+
import androidx.compose.ui.graphics.vector.ImageVector
11+
import androidx.compose.ui.platform.LocalContext
12+
import androidx.compose.ui.res.stringResource
13+
import androidx.core.app.ActivityCompat
14+
import app.revanced.manager.R
15+
import app.revanced.manager.ui.component.AlertDialogExtended
16+
17+
@Composable
18+
fun PermissionRequestHandler(
19+
contract: ActivityResultContract<String, Boolean>,
20+
input: String,
21+
onDismissRequest: () -> Unit,
22+
onResult: (Boolean) -> Unit,
23+
onContinue: () -> Unit = {},
24+
title: String,
25+
description: String,
26+
icon: ImageVector
27+
) {
28+
val context = LocalContext.current
29+
val showDialog = ActivityCompat.shouldShowRequestPermissionRationale(
30+
context as Activity,
31+
input
32+
)
33+
34+
val launcher = rememberLauncherForActivityResult(contract) { result ->
35+
onResult(result)
36+
}
37+
38+
if(showDialog)
39+
PermissionDialog(
40+
title,
41+
description,
42+
icon,
43+
onDismissRequest = onDismissRequest,
44+
onContinue = {
45+
onContinue()
46+
launcher.launch(input)
47+
}
48+
)
49+
else
50+
onResult(false)
51+
}
52+
53+
@Composable
54+
private fun PermissionDialog(
55+
title: String,
56+
description: String,
57+
icon: ImageVector,
58+
onDismissRequest: () -> Unit,
59+
onContinue: () -> Unit
60+
) {
61+
AlertDialogExtended(
62+
onDismissRequest = onDismissRequest,
63+
title = { Text(title) },
64+
text = { Text(description) },
65+
icon = { Icon(icon, null) },
66+
confirmButton = {
67+
TextButton(onClick = onContinue) {
68+
Text(stringResource(R.string.ok))
69+
}
70+
},
71+
dismissButton = {
72+
TextButton(onClick = onDismissRequest) {
73+
Text(stringResource(R.string.cancel))
74+
}
75+
}
76+
)
77+
}

app/src/main/java/app/revanced/manager/util/Util.kt

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package app.revanced.manager.util
22

3+
import android.Manifest
34
import android.content.Context
45
import android.content.Intent
56
import android.content.pm.ApplicationInfo
7+
import android.content.pm.PackageManager
8+
import android.os.Build
69
import android.util.Log
710
import android.widget.Toast
811
import androidx.annotation.MainThread
@@ -25,6 +28,7 @@ import androidx.compose.ui.Modifier
2528
import androidx.compose.ui.draw.alpha
2629
import androidx.compose.ui.graphics.Color
2730
import androidx.compose.ui.platform.LocalView
31+
import androidx.core.content.ContextCompat
2832
import androidx.core.net.toUri
2933
import androidx.lifecycle.Lifecycle
3034
import androidx.lifecycle.LifecycleOwner
@@ -288,4 +292,14 @@ fun <T : Any> SavedStateHandle.saveableVar(): ReadWriteProperty<Any?, T?> =
288292
override fun getValue(thisRef: Any?, property: KProperty<*>): T? = get(property.name)
289293
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) =
290294
set(property.name, value)
291-
}
295+
}
296+
297+
fun hasNotificationPermission(context: Context): Boolean {
298+
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
299+
ContextCompat.checkSelfPermission(
300+
context,
301+
Manifest.permission.POST_NOTIFICATIONS
302+
) == PackageManager.PERMISSION_GRANTED
303+
} else
304+
true
305+
}

app/src/main/res/values/strings.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@
184184
<string name="process_runtime_memory_limit">Patcher process memory limit</string>
185185
<string name="process_runtime_memory_limit_description">The max amount of memory that the Patcher process can use (in megabytes)</string>
186186
<string name="background_bundle_update">Enable bundles auto update in background</string>
187-
<string name="background_bundle_update_description">TODO</string>
187+
<string name="background_bundle_update_description">Automatically checks for bundles updates and update them in the background</string>
188+
<string name="background_radio_menu_title">Check for bundles updates</string>
189+
<string name="background_bundle_ask_notification">Stay updated</string>
190+
<string name="background_bundle_ask_notification_description">ReVanced will send you a notification when a bundle was updated. Press "OK" if you wish to be notified.</string>
188191
<string name="never">Never</string>
189192
<string name="minutes_15">Every 15 minutes</string>
190193
<string name="hourly">Hourly</string>

0 commit comments

Comments
 (0)