NotificationPermissionEffect() (MainActivity.kt, ~lines 110-123) is invoked unconditionally
at the top of the Compose tree inside onCreate's setContent block (~line 87), as a sibling of AppLockGateHost / LibreMailApp. Its LaunchedEffect(Unit) fires on the very first
composition — before the actual onboarding start screen (OnboardingWelcomeScreen, documented as
"Shown as the onboarding start destination when the app launches with no accounts") has
necessarily rendered or settled. In practice this means the system notification-permission dialog
can appear the instant the app icon is tapped, overlapping the cold-start/splash transition,
before the user has seen any onboarding context explaining why LibreMail wants the permission.
Scope
Move the notification-permission request so it fires once the onboarding flow's first
screen (OnboardingWelcomeScreen, ui/onboarding/OnboardingWelcomeScreen.kt) has actually
appeared, rather than from the MainActivity-root effect that runs on cold start regardless
of destination.
Concretely: remove the top-level NotificationPermissionEffect() call at MainActivity.kt
(~line 87) and add an equivalent effect scoped to OnboardingWelcomeScreen's composition
(or gate the existing effect on a "welcome screen is the current destination" signal from
the NavHost).
Preserve existing behavior for already-onboarded users: the permission-granted check
(MainActivity.kt ~lines 119-121) already no-ops when granted. Confirm the new placement
doesn't introduce a re-prompt on every launch for users who previously denied it (if it
already does today, that's a separate, pre-existing issue — note it rather than silently
fixing/changing it here).
Preserve the API 33+ (Build.VERSION_CODES.TIRAMISU) gate — notifications need no runtime
permission on older versions.
Acceptance criteria
On a fresh install, the notification-permission system dialog appears only once the welcome
screen is visible, not overlapping the app's cold-start transition.
Existing, already-onboarded users see no behavior change.
## Context
`NotificationPermissionEffect()` (`MainActivity.kt`, ~lines 110-123) is invoked unconditionally
at the top of the Compose tree inside `onCreate`'s `setContent` block (~line 87), as a sibling of
`AppLockGateHost` / `LibreMailApp`. Its `LaunchedEffect(Unit)` fires on the very first
composition — before the actual onboarding start screen (`OnboardingWelcomeScreen`, documented as
"Shown as the onboarding start destination when the app launches with no accounts") has
necessarily rendered or settled. In practice this means the system notification-permission dialog
can appear the instant the app icon is tapped, overlapping the cold-start/splash transition,
before the user has seen any onboarding context explaining why LibreMail wants the permission.
## Scope
- [ ] Move the notification-permission request so it fires once the onboarding flow's first
screen (`OnboardingWelcomeScreen`, `ui/onboarding/OnboardingWelcomeScreen.kt`) has actually
appeared, rather than from the `MainActivity`-root effect that runs on cold start regardless
of destination.
- [ ] Concretely: remove the top-level `NotificationPermissionEffect()` call at `MainActivity.kt`
(~line 87) and add an equivalent effect scoped to `OnboardingWelcomeScreen`'s composition
(or gate the existing effect on a "welcome screen is the current destination" signal from
the NavHost).
- [ ] Preserve existing behavior for already-onboarded users: the permission-granted check
(`MainActivity.kt` ~lines 119-121) already no-ops when granted. Confirm the new placement
doesn't introduce a re-prompt on every launch for users who previously denied it (if it
already does today, that's a separate, pre-existing issue — note it rather than silently
fixing/changing it here).
- [ ] Preserve the API 33+ (`Build.VERSION_CODES.TIRAMISU`) gate — notifications need no runtime
permission on older versions.
## Acceptance criteria
- On a fresh install, the notification-permission system dialog appears only once the welcome
screen is visible, not overlapping the app's cold-start transition.
- Existing, already-onboarded users see no behavior change.
## Relevant files
- `MainActivity.kt` (~lines 84-123), `ui/onboarding/OnboardingWelcomeScreen.kt`.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Context
NotificationPermissionEffect()(MainActivity.kt, ~lines 110-123) is invoked unconditionallyat the top of the Compose tree inside
onCreate'ssetContentblock (~line 87), as a sibling ofAppLockGateHost/LibreMailApp. ItsLaunchedEffect(Unit)fires on the very firstcomposition — before the actual onboarding start screen (
OnboardingWelcomeScreen, documented as"Shown as the onboarding start destination when the app launches with no accounts") has
necessarily rendered or settled. In practice this means the system notification-permission dialog
can appear the instant the app icon is tapped, overlapping the cold-start/splash transition,
before the user has seen any onboarding context explaining why LibreMail wants the permission.
Scope
screen (
OnboardingWelcomeScreen,ui/onboarding/OnboardingWelcomeScreen.kt) has actuallyappeared, rather than from the
MainActivity-root effect that runs on cold start regardlessof destination.
NotificationPermissionEffect()call atMainActivity.kt(~line 87) and add an equivalent effect scoped to
OnboardingWelcomeScreen's composition(or gate the existing effect on a "welcome screen is the current destination" signal from
the NavHost).
(
MainActivity.kt~lines 119-121) already no-ops when granted. Confirm the new placementdoesn't introduce a re-prompt on every launch for users who previously denied it (if it
already does today, that's a separate, pre-existing issue — note it rather than silently
fixing/changing it here).
Build.VERSION_CODES.TIRAMISU) gate — notifications need no runtimepermission on older versions.
Acceptance criteria
screen is visible, not overlapping the app's cold-start transition.
Relevant files
MainActivity.kt(~lines 84-123),ui/onboarding/OnboardingWelcomeScreen.kt.