-
Notifications
You must be signed in to change notification settings - Fork 0
[PC-1627] 알람 권한 티라미수 이하 버전 로직 수정 #203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
📝 WalkthroughWalkthroughNotification permission handling was refactored in sign-up and settings: lifecycle-aware state collection added, notification enablement now considers NotificationManagerCompat for pre-TIRAMISU and POST_NOTIFICATIONS for TIRAMISU+, and toggle actions either request permission or open system app notification settings. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI as App UI (Toggle)
participant PermAPI as Permission API (POST_NOTIFICATIONS)
participant SysSettings as System Settings / NotificationManager
User->>UI: Toggle Push Notifications
UI->>SysSettings: check areNotificationsEnabled()
alt Android >= TIRAMISU
UI->>PermAPI: check POST_NOTIFICATIONS state
PermAPI-->>UI: Granted / Denied
alt Granted
UI-->>User: Enable toggle (persist)
else Denied
UI->>PermAPI: requestPermission()
PermAPI-->>User: system permission dialog
PermAPI-->>UI: result (Granted/Denied)
UI-->>User: Update toggle / show settings prompt
end
else Android < TIRAMISU
SysSettings-->>UI: areNotificationsEnabled() result
alt Enabled
UI-->>User: Enable toggle (persist)
else Disabled
UI->>SysSettings: open ACTION_APP_NOTIFICATION_SETTINGS
SysSettings-->>User: show app notification settings
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
feature/auth/src/main/java/com/puzzle/auth/graph/signup/page/AccessRightsPage.kt (2)
101-107: Consider optimizing lifecycle state dependency.The current implementation recomputes
isNotificationGrantedon every lifecycle state change. WhileareNotificationsEnabled()is lightweight, you could optimize by filtering for specific states or usingderivedStateOfto reduce unnecessary recompositions.♻️ Optional optimization
- val isNotificationGranted = remember(lifecycleState, notificationPermission?.status) { + val isNotificationGranted = remember( + key1 = if (lifecycleState.isAtLeast(Lifecycle.State.RESUMED)) lifecycleState else null, + key2 = notificationPermission?.status + ) { if (SDK_INT >= TIRAMISU) { notificationPermission?.status == PermissionStatus.Granted } else { NotificationManagerCompat.from(context).areNotificationsEnabled() } }This limits recomputation to when the screen becomes visible (RESUMED state), which is when the user might return from settings.
255-266: Extract duplicatedhandlePermissionto shared utility.The
handlePermissionfunction is duplicated in bothAccessRightsPage.ktandSettingScreen.ktwith identical logic. Consider extracting it to a common utility module to improve maintainability.♻️ Suggested refactor
Create a shared utility file (e.g.,
core/common/src/main/java/com/puzzle/common/permission/PermissionUtils.kt):package com.puzzle.common.permission import android.content.Context import android.content.Intent import android.net.Uri import android.provider.Settings import com.google.accompanist.permissions.ExperimentalPermissionsApi import com.google.accompanist.permissions.PermissionState import com.google.accompanist.permissions.PermissionStatus import com.google.accompanist.permissions.shouldShowRationale @OptIn(ExperimentalPermissionsApi::class) fun handlePermission(context: Context, permission: PermissionState?) { permission?.let { if (it.status == PermissionStatus.Granted || !it.status.shouldShowRationale) { val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { data = Uri.fromParts("package", context.packageName, null) } context.startActivity(intent) } else { it.launchPermissionRequest() } } }Then import and use it in both files.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
feature/auth/src/main/java/com/puzzle/auth/graph/signup/page/AccessRightsPage.kt
🧰 Additional context used
🧬 Code graph analysis (1)
feature/auth/src/main/java/com/puzzle/auth/graph/signup/page/AccessRightsPage.kt (2)
feature/auth/src/main/java/com/puzzle/auth/graph/signup/SignUpViewModel.kt (1)
onBackClick(112-121)feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt (1)
handlePermission(401-413)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (5)
feature/auth/src/main/java/com/puzzle/auth/graph/signup/page/AccessRightsPage.kt (5)
32-33: LGTM! Imports support lifecycle-aware permission handling.The added imports are necessary for the new implementation: lifecycle state tracking, notification status checking on older APIs, and state management.
Also applies to: 44-46
67-70: LGTM! Lifecycle tracking enables state refresh on resume.Collecting lifecycle state allows the notification permission status to be rechecked when the user returns from system settings, which is essential for pre-Tiramisu devices.
92-94: LGTM! Correct API-level handling for notification permission.The conditional retrieval correctly reflects that
POST_NOTIFICATIONSruntime permission only exists on API 33+.
109-114: LGTM! Conditional permission request prevents unnecessary prompts.The change to
LaunchedEffect(Unit)with ahasDeniedcheck correctly implements the requirement to show already-granted permissions without immediately launching a permission request. This improves UX by respecting previously granted permissions.
155-165: LGTM! Correct API-level branching for notification settings.The implementation correctly handles both API levels:
- API 33+: Uses runtime permission flow via
handlePermission- Below API 33: Opens notification settings directly, since no runtime permission exists
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In
@feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt:
- Around line 230-237: The pre-TIRAMISU notification permission check in
NotificationBody is computed on every recomposition and isn’t lifecycle-aware,
so the UI won’t refresh when the user toggles notifications in system settings;
change this by hoisting isPermissionGranted into a remembered MutableState
(e.g., remember { mutableStateOf(...) }) and update that state from a
lifecycle-aware coroutine (use lifecycleOwner.repeatOnStarted or a
LaunchedEffect tied to lifecycleOwner) to call
NotificationManagerCompat.from(context).areNotificationsEnabled() on resume;
reference NotificationBody for where to create and read the state, and mirror
the lifecycle pattern used in SettingRoute and AccessRightsPage to trigger a
state refresh when the screen resumes.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (1)
feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt (1)
43-43: LGTM! Necessary additions for pre-TIRAMISU support.The
NotificationManagerCompatimport andLocalContextretrieval are correctly added to support the new notification permission logic for Android versions below TIRAMISU.Also applies to: 224-224
feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt
Outdated
Show resolved
Hide resolved
| if (SDK_INT >= TIRAMISU) { | ||
| handlePermission(context, notificationPermission) | ||
| } else { | ||
| val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { | ||
| putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) | ||
| } | ||
| context.startActivity(intent) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
Settings.ACTION_APP_NOTIFICATION_SETTINGS EXTRA_APP_PACKAGE Android API 21 32 documentation
💡 Result:
Summary — official docs and practical compatibility:
-
Official (Android SDK): Settings.ACTION_APP_NOTIFICATION_SETTINGS and Settings.EXTRA_APP_PACKAGE were added in API level 26 (Android O). Use Intent action Settings.ACTION_APP_NOTIFICATION_SETTINGS with extra Settings.EXTRA_APP_PACKAGE (android.provider.extra.APP_PACKAGE). [1]
-
Pre-O compatibility (API 21–25): many apps use the settings action string "android.settings.APP_NOTIFICATION_SETTINGS" and the undocumented extras "app_package" (String) and "app_uid" (int) to open an app's notification settings on Lollipop—Marshmallow—Nougat devices. This approach is not part of the public SDK and may not work on all devices. Example usages and community guidance are shown on Stack Overflow. [2]
References:
[1] Android Developers — Settings (API reference) (shows ACTION_APP_NOTIFICATION_SETTINGS and EXTRA_APP_PACKAGE added in API 26).
[2] Stack Overflow — “Any way to link to the Android notification settings for my app?” (compatibility examples for API 21–25 using "app_package" / "app_uid").
Fix Intent approach for API 21-25 compatibility.
The code uses Settings.ACTION_APP_NOTIFICATION_SETTINGS and Settings.EXTRA_APP_PACKAGE, which were added in API level 26. These constants are unavailable on API 21-25, causing the pre-TIRAMISU branch (which includes API 21-25) to crash when executed on those devices.
For API 21-25 compatibility, use the undocumented Intent action "android.settings.APP_NOTIFICATION_SETTINGS" with extras "app_package" (String) and "app_uid" (int) instead. Add a version check:
- API 26+: Use
Settings.ACTION_APP_NOTIFICATION_SETTINGSwithSettings.EXTRA_APP_PACKAGE - API 21-25: Use the undocumented action string with
"app_package"and"app_uid"extras
tgyuuAn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 PR은 어떤 맥락에서 등장한 PR일까요?
PR에 Context가 빈약한 것 같아요.
코드가 작성된 이유도 작성되었으면 좋겠어요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In
@feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt:
- Around line 235-246: The permission check in SettingScreen.kt for
isPermissionGranted is inconsistent with AccessRightsPage.kt: update the
remember block used to compute isPermissionGranted so that on SDK_INT >=
TIRAMISU you return true only if notifications are enabled OR the runtime
notificationPermission?.status == PermissionStatus.Granted (i.e., use the same
areNotificationsEnabled() || notificationPermission?.status ==
PermissionStatus.Granted logic used in AccessRightsPage.kt), referencing
NotificationManagerCompat.from(context).areNotificationsEnabled() and the
notificationPermission variable to ensure both system setting and runtime
permission are considered.
🧹 Nitpick comments (1)
feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt (1)
433-444: Extract duplicated function to shared utility.This
handlePermissionfunction is duplicated inAccessRightsPage.kt(lines 257-268). Consider extracting it to a common utility module or package to maintain DRY principles and ensure consistent behavior across the app.♻️ Suggestion: Extract to common module
Create a shared utility file like
feature-common/src/main/java/com/puzzle/common/permission/PermissionUtils.kt:@OptIn(ExperimentalPermissionsApi::class) fun handlePermission(context: Context, permission: PermissionState?) { permission?.let { if (it.status == PermissionStatus.Granted || !it.status.shouldShowRationale) { val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { data = Uri.fromParts("package", context.packageName, null) } context.startActivity(intent) } else { it.launchPermissionRequest() } } }Then import and use it in both files.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
feature/auth/src/main/java/com/puzzle/auth/graph/signup/page/AccessRightsPage.ktfeature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt
🧰 Additional context used
🧬 Code graph analysis (2)
feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt (1)
feature/auth/src/main/java/com/puzzle/auth/graph/signup/page/AccessRightsPage.kt (1)
handlePermission(256-268)
feature/auth/src/main/java/com/puzzle/auth/graph/signup/page/AccessRightsPage.kt (1)
feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt (1)
handlePermission(432-444)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (6)
feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt (2)
248-252: Review auto-enable behavior for UX implications.This effect automatically enables push notifications when permission is granted, even if the user hasn't explicitly toggled it on. While this may be intentional, consider whether users who grant permission from system settings might want to manually control the toggle.
For example: A user grants notification permission but may still want to decide later whether to enable push notifications in the app.
Is this auto-enable behavior the intended UX? If so, consider adding a comment explaining the rationale.
280-287: LGTM! Correct pre-TIRAMISU behavior.The conditional logic correctly handles both API levels:
- TIRAMISU+: Uses runtime permission flow
- Pre-TIRAMISU: Opens system notification settings directly
This aligns with the PR objectives to avoid showing permission popup on older Android versions.
feature/auth/src/main/java/com/puzzle/auth/graph/signup/page/AccessRightsPage.kt (4)
68-69: LGTM! Lifecycle-aware state handling.The lifecycle state collection enables the UI to update when the user returns from the system settings screen, which is essential for reflecting permission changes.
101-109: LGTM! Correct combined permission check.The logic correctly combines both checks for TIRAMISU+:
- Runtime permission status (
POST_NOTIFICATIONS)- System notification settings (
areNotificationsEnabled())This is the proper approach since on Android 13+, both can be controlled independently.
Note: Ensure
SettingScreen.ktuses this same logic (see comment on that file).
111-116: LGTM! Improved permission request logic.Changing to
LaunchedEffect(Unit)ensures permissions are only requested once during initial composition, and thehasDeniedcheck prevents unnecessary requests when all permissions are already granted.
157-167: LGTM! Consistent pre-TIRAMISU handling.The notification row correctly:
- Uses the combined
isNotificationGrantedstate for the toggle- Routes to appropriate handlers based on API level
- Opens system notification settings directly on pre-TIRAMISU devices
This aligns with the PR objectives and matches the approach in
SettingScreen.kt.
| val isPermissionGranted = remember( | ||
| lifecycleState, | ||
| notificationPermission?.status | ||
| ) { | ||
| if (SDK_INT >= TIRAMISU) { | ||
| notificationPermission?.status == PermissionStatus.Granted | ||
| } else { | ||
| NotificationManagerCompat | ||
| .from(context) | ||
| .areNotificationsEnabled() | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent permission check logic for TIRAMISU+ between files.
For Android 13+ (TIRAMISU), this code only checks the runtime permission status, but in AccessRightsPage.kt (lines 104-108), the logic uses:
areNotificationsEnabled || notificationPermission?.status == PermissionStatus.GrantedThis inconsistency could cause issues because:
- On TIRAMISU+, users can grant the runtime permission but still disable notifications in system settings
- The two screens would show different permission states for the same notification status
🔧 Proposed fix to align with AccessRightsPage.kt logic
val isPermissionGranted = remember(
lifecycleState,
notificationPermission?.status
) {
+ val areNotificationsEnabled = NotificationManagerCompat
+ .from(context)
+ .areNotificationsEnabled()
+
if (SDK_INT >= TIRAMISU) {
- notificationPermission?.status == PermissionStatus.Granted
+ areNotificationsEnabled || notificationPermission?.status == PermissionStatus.Granted
} else {
- NotificationManagerCompat
- .from(context)
- .areNotificationsEnabled()
+ areNotificationsEnabled
}
}🤖 Prompt for AI Agents
In @feature/setting/src/main/java/com/puzzle/setting/graph/main/SettingScreen.kt
around lines 235 - 246, The permission check in SettingScreen.kt for
isPermissionGranted is inconsistent with AccessRightsPage.kt: update the
remember block used to compute isPermissionGranted so that on SDK_INT >=
TIRAMISU you return true only if notifications are enabled OR the runtime
notificationPermission?.status == PermissionStatus.Granted (i.e., use the same
areNotificationsEnabled() || notificationPermission?.status ==
PermissionStatus.Granted logic used in AccessRightsPage.kt), referencing
NotificationManagerCompat.from(context).areNotificationsEnabled() and the
notificationPermission variable to ensure both system setting and runtime
permission are considered.
1. ⭐️ 변경된 내용
2. 🖼️ 스크린샷(선택)
3. 💡 알게된 부분
4. 📌 이 부분은 꼭 봐주세요!
문제:
기존 코드에서는 Android 13(Tiramisu) 미만일 경우 permissionList.permissions.find { ... } 내부 조건이 항상 true를 반환하도록 되어 있어, 권한 리스트의 첫 번째 상태를 참조하는 문제가 생기고 그로 인해 UI에 알람 권한 허용 여부가 부정확한 경우가 생김
@tgyuuAn @kkh725
Summary by CodeRabbit
Bug Fixes
New Features
✏️ Tip: You can customize this high-level summary in your review settings.