Add notification permission flow in settings
This commit is contained in:
@@ -7,6 +7,9 @@ abstract class ReminderScheduler {
|
||||
|
||||
/// Clears all platform-scheduled reminder jobs.
|
||||
Future<void> clearAll();
|
||||
|
||||
/// Requests notification permissions where the platform requires them.
|
||||
Future<bool> requestPermissions();
|
||||
}
|
||||
|
||||
/// Default scheduler used until platform notifications are integrated.
|
||||
@@ -18,4 +21,7 @@ class NoopReminderScheduler implements ReminderScheduler {
|
||||
|
||||
@override
|
||||
Future<void> reconcile(List<ReminderRule> reminders) async {}
|
||||
|
||||
@override
|
||||
Future<bool> requestPermissions() async => true;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,15 @@ class LocalNotificationsReminderScheduler implements ReminderScheduler {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> requestPermissions() async {
|
||||
if (!_supportsSchedulingPlatform()) {
|
||||
return false;
|
||||
}
|
||||
await _driver.ensureInitialized();
|
||||
return _driver.requestPermissions();
|
||||
}
|
||||
|
||||
DateTimeComponents? _repeatComponents(ReminderCadence cadence) {
|
||||
return switch (cadence) {
|
||||
ReminderCadence.daily => DateTimeComponents.time,
|
||||
@@ -107,6 +116,8 @@ abstract class ReminderNotificationsDriver {
|
||||
required DateTimeComponents? repeatComponents,
|
||||
required String payload,
|
||||
});
|
||||
|
||||
Future<bool> requestPermissions();
|
||||
}
|
||||
|
||||
class FlutterReminderNotificationsDriver
|
||||
@@ -148,6 +159,38 @@ class FlutterReminderNotificationsDriver
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> requestPermissions() async {
|
||||
if (defaultTargetPlatform == TargetPlatform.android) {
|
||||
return await _plugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
AndroidFlutterLocalNotificationsPlugin
|
||||
>()
|
||||
?.requestNotificationsPermission() ??
|
||||
false;
|
||||
}
|
||||
|
||||
if (defaultTargetPlatform == TargetPlatform.iOS) {
|
||||
return await _plugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
IOSFlutterLocalNotificationsPlugin
|
||||
>()
|
||||
?.requestPermissions(alert: true, badge: true, sound: true) ??
|
||||
false;
|
||||
}
|
||||
|
||||
if (defaultTargetPlatform == TargetPlatform.macOS) {
|
||||
return await _plugin
|
||||
.resolvePlatformSpecificImplementation<
|
||||
MacOSFlutterLocalNotificationsPlugin
|
||||
>()
|
||||
?.requestPermissions(alert: true, badge: true, sound: true) ??
|
||||
false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<void> _initialize() async {
|
||||
await _plugin.initialize(
|
||||
settings: const InitializationSettings(
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:relationship_saver/core/config/app_config.dart';
|
||||
import 'package:relationship_saver/core/config/app_theme.dart';
|
||||
import 'package:relationship_saver/features/auth/session_controller.dart';
|
||||
import 'package:relationship_saver/features/reminders/scheduling/reminder_scheduler_provider.dart';
|
||||
import 'package:relationship_saver/features/shared/frosted_card.dart';
|
||||
import 'package:relationship_saver/integrations/backend/models/backend_models.dart';
|
||||
|
||||
@@ -74,6 +75,14 @@ class SettingsView extends ConsumerWidget {
|
||||
label: 'Realtime',
|
||||
value: 'Planned later (SSE/WebSocket)',
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
_SettingRow(
|
||||
compact: compact,
|
||||
label: 'Local notifications',
|
||||
value: AppConfig.enableLocalNotifications
|
||||
? 'Enabled'
|
||||
: 'Disabled',
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
@@ -99,6 +108,18 @@ class SettingsView extends ConsumerWidget {
|
||||
icon: const Icon(Icons.refresh_rounded),
|
||||
label: const Text('Refresh Profile'),
|
||||
),
|
||||
OutlinedButton.icon(
|
||||
onPressed: AppConfig.enableLocalNotifications
|
||||
? () => _requestNotificationPermissions(
|
||||
context,
|
||||
ref,
|
||||
)
|
||||
: null,
|
||||
icon: const Icon(
|
||||
Icons.notifications_active_rounded,
|
||||
),
|
||||
label: const Text('Request Notification Access'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -127,6 +148,27 @@ class SettingsView extends ConsumerWidget {
|
||||
).showSnackBar(const SnackBar(content: Text('Signed out.')));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _requestNotificationPermissions(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
) async {
|
||||
final bool granted = await ref
|
||||
.read(reminderSchedulerProvider)
|
||||
.requestPermissions();
|
||||
if (!context.mounted) {
|
||||
return;
|
||||
}
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
granted
|
||||
? 'Notification access granted.'
|
||||
: 'Notification access not granted.',
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SettingRow extends StatelessWidget {
|
||||
|
||||
Reference in New Issue
Block a user