diff --git a/lib/common/push/notification_permission.dart b/lib/common/push/notification_permission.dart index a3933da..ceda7ae 100644 --- a/lib/common/push/notification_permission.dart +++ b/lib/common/push/notification_permission.dart @@ -23,9 +23,15 @@ abstract final class NotificationPermission { return isGranted(); } if (await isGranted() || !context.mounted) return true; - await showNotificationPermissionTip(context); + final tip = showNotificationPermissionTip(context); await StorageService.to.setBool(storagePushPermissionPrompted, true); - return (await Permission.notification.request()).isGranted; + try { + // Match the legacy app's persistent top snackbar: keep the in-app + // explanation on screen until the system authorization dialog closes. + return (await Permission.notification.request()).isGranted; + } finally { + tip.remove(); + } } /// 设置页不使用顶部说明;iOS/Android 都直接请求系统授权。 diff --git a/lib/common/widgets/notification_permission_tip.dart b/lib/common/widgets/notification_permission_tip.dart index ca292d7..dd824e9 100644 --- a/lib/common/widgets/notification_permission_tip.dart +++ b/lib/common/widgets/notification_permission_tip.dart @@ -73,10 +73,26 @@ class NotificationPermissionTip extends StatelessWidget { } } -Future showNotificationPermissionTip(BuildContext context) async { +/// Keeps the explanation visible while Android's system permission dialog is +/// presented. Call [remove] after the permission request completes. +NotificationPermissionTipHandle showNotificationPermissionTip( + BuildContext context, +) { final overlay = Overlay.of(context, rootOverlay: true); final entry = OverlayEntry(builder: (_) => const NotificationPermissionTip()); overlay.insert(entry); - await Future.delayed(const Duration(milliseconds: 500)); - entry.remove(); + return NotificationPermissionTipHandle._(entry); +} + +class NotificationPermissionTipHandle { + NotificationPermissionTipHandle._(this._entry); + + final OverlayEntry _entry; + bool _isRemoved = false; + + void remove() { + if (_isRemoved) return; + _isRemoved = true; + _entry.remove(); + } }