1
1
package com.anafthdev.remindme.ui.main
2
2
3
+ import android.Manifest
4
+ import android.content.pm.PackageManager
5
+ import android.os.Build
3
6
import androidx.activity.compose.BackHandler
4
7
import androidx.compose.foundation.ExperimentalFoundationApi
5
8
import androidx.compose.foundation.border
@@ -22,30 +25,41 @@ import androidx.compose.foundation.lazy.itemsIndexed
22
25
import androidx.compose.foundation.lazy.rememberLazyListState
23
26
import androidx.compose.material.icons.Icons
24
27
import androidx.compose.material.icons.rounded.Add
28
+ import androidx.compose.material3.ExperimentalMaterial3Api
25
29
import androidx.compose.material3.FilledTonalButton
26
30
import androidx.compose.material3.FloatingActionButton
27
31
import androidx.compose.material3.Icon
28
32
import androidx.compose.material3.MaterialTheme
29
33
import androidx.compose.material3.Switch
30
34
import androidx.compose.material3.Text
31
35
import androidx.compose.runtime.Composable
36
+ import androidx.compose.runtime.DisposableEffect
32
37
import androidx.compose.runtime.LaunchedEffect
38
+ import androidx.compose.runtime.getValue
39
+ import androidx.compose.runtime.mutableStateOf
40
+ import androidx.compose.runtime.remember
41
+ import androidx.compose.runtime.setValue
33
42
import androidx.compose.ui.Alignment
34
43
import androidx.compose.ui.Modifier
35
44
import androidx.compose.ui.platform.LocalContext
36
45
import androidx.compose.ui.platform.LocalFocusManager
46
+ import androidx.compose.ui.platform.LocalLifecycleOwner
37
47
import androidx.compose.ui.res.stringResource
38
48
import androidx.compose.ui.text.style.TextAlign
39
49
import androidx.compose.ui.unit.dp
40
50
import androidx.compose.ui.zIndex
51
+ import androidx.core.content.ContextCompat
41
52
import androidx.hilt.navigation.compose.hiltViewModel
53
+ import androidx.lifecycle.Lifecycle
54
+ import androidx.lifecycle.LifecycleEventObserver
42
55
import androidx.window.layout.DisplayFeature
43
56
import com.anafthdev.remindme.R
44
57
import com.anafthdev.remindme.data.RemindMeRoute
45
58
import com.anafthdev.remindme.data.RemindMeTopLevelDestination
46
59
import com.anafthdev.remindme.data.RemindMeTopLevelDestinations
47
60
import com.anafthdev.remindme.data.ReminderMessageType
48
61
import com.anafthdev.remindme.data.model.Reminder
62
+ import com.anafthdev.remindme.extension.openSettings
49
63
import com.anafthdev.remindme.extension.toast
50
64
import com.anafthdev.remindme.ui.remind_me.RemindMeUiState
51
65
import com.anafthdev.remindme.ui.reminder_detail.ReminderDetailScreen
@@ -57,6 +71,9 @@ import com.anafthdev.remindme.uicomponent.ReminderMessageItem
57
71
import com.anafthdev.remindme.utils.RemindMeContentType
58
72
import com.google.accompanist.adaptive.HorizontalTwoPaneStrategy
59
73
import com.google.accompanist.adaptive.TwoPane
74
+ import com.google.accompanist.permissions.ExperimentalPermissionsApi
75
+ import com.google.accompanist.permissions.isGranted
76
+ import com.google.accompanist.permissions.rememberPermissionState
60
77
61
78
@Composable
62
79
fun MainScreen (
@@ -160,6 +177,7 @@ fun RemindMeSinglePaneContent(
160
177
}
161
178
}
162
179
180
+ @OptIn(ExperimentalMaterial3Api ::class , ExperimentalPermissionsApi ::class )
163
181
@Composable
164
182
fun RemindMeReminderList (
165
183
is24Hour : Boolean ,
@@ -172,6 +190,50 @@ fun RemindMeReminderList(
172
190
updateReminder : (Reminder ) -> Unit
173
191
) {
174
192
193
+ val context = LocalContext .current
194
+ val lifecycleOwner = LocalLifecycleOwner .current
195
+
196
+ var permissionRequested by remember { mutableStateOf(false ) }
197
+
198
+ var postNotificationGranted by remember {
199
+ mutableStateOf(
200
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
201
+ ContextCompat .checkSelfPermission(context, Manifest .permission.POST_NOTIFICATIONS ) == PackageManager .PERMISSION_GRANTED
202
+ } else true
203
+ )
204
+ }
205
+
206
+ val postNotificationPermission = rememberPermissionState(
207
+ permission = Manifest .permission.POST_NOTIFICATIONS ,
208
+ onPermissionResult = { granted ->
209
+ postNotificationGranted = granted
210
+
211
+ if (! granted) {
212
+ permissionRequested = true
213
+ }
214
+ }
215
+ )
216
+
217
+ if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
218
+ DisposableEffect (lifecycleOwner) {
219
+ // Create an observer that triggers our remembered callbacks
220
+ // for sending analytics events
221
+ val observer = LifecycleEventObserver { _, event ->
222
+ if (event == Lifecycle .Event .ON_START ) {
223
+ postNotificationGranted = ContextCompat .checkSelfPermission(context, Manifest .permission.POST_NOTIFICATIONS ) == PackageManager .PERMISSION_GRANTED
224
+ }
225
+ }
226
+
227
+ // Add the observer to the lifecycle
228
+ lifecycleOwner.lifecycle.addObserver(observer)
229
+
230
+ // When the effect leaves the Composition, remove the observer
231
+ onDispose {
232
+ lifecycleOwner.lifecycle.removeObserver(observer)
233
+ }
234
+ }
235
+ }
236
+
175
237
Box (modifier = modifier) {
176
238
if (contentType == RemindMeContentType .SINGLE_PANE ) {
177
239
FloatingActionButton (
@@ -207,21 +269,48 @@ fun RemindMeReminderList(
207
269
)
208
270
}
209
271
272
+ if (! postNotificationGranted) {
273
+ item {
274
+ FilledTonalButton (
275
+ onClick = {
276
+ when {
277
+ ! permissionRequested && ! postNotificationPermission.status.isGranted -> {
278
+ postNotificationPermission.launchPermissionRequest()
279
+ }
280
+ // postNotificationPermission.status.shouldShowRationale -> {}
281
+ else -> {
282
+ context.openSettings()
283
+ }
284
+ }
285
+ },
286
+ modifier = Modifier
287
+ .padding(horizontal = 8 .dp)
288
+ .fillMaxWidth()
289
+ ) {
290
+ Text (
291
+ text = stringResource(id = R .string.grant_post_notification_permission)
292
+ )
293
+ }
294
+ }
295
+ }
296
+
210
297
items(
211
298
items = reminders,
212
299
key = { item: Reminder -> item.id }
213
300
) { reminder ->
214
301
ReminderItem (
215
302
reminder = reminder,
216
303
is24Hour = is24Hour,
304
+ enabled = postNotificationGranted,
217
305
onClick = {
218
306
navigateToReminder(reminder.id, contentType) },
219
307
onCheckedChange = { isActive ->
220
308
updateReminder(
221
309
reminder.copy(
222
310
isActive = isActive
223
311
)
224
- ) },
312
+ )
313
+ },
225
314
modifier = Modifier
226
315
.padding(8 .dp)
227
316
.fillMaxWidth()
0 commit comments