No notification permission enforcement on web
This commit is contained in:
parent
0173e91d94
commit
aef88de54b
|
|
@ -1,5 +1,6 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
import 'package:audioplayers/audioplayers.dart';
|
import 'package:audioplayers/audioplayers.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:supabase_flutter/supabase_flutter.dart';
|
import 'package:supabase_flutter/supabase_flutter.dart';
|
||||||
|
|
@ -56,17 +57,37 @@ Future<void> main() async {
|
||||||
|
|
||||||
// ensure token saved right away if already signed in
|
// ensure token saved right away if already signed in
|
||||||
final supaClient = Supabase.instance.client;
|
final supaClient = Supabase.instance.client;
|
||||||
final initialToken = await FirebaseMessaging.instance.getToken();
|
String? initialToken;
|
||||||
|
if (!kIsWeb) {
|
||||||
|
try {
|
||||||
|
initialToken = await FirebaseMessaging.instance.getToken();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('FCM getToken failed: $e');
|
||||||
|
initialToken = null;
|
||||||
|
}
|
||||||
if (initialToken != null && supaClient.auth.currentUser != null) {
|
if (initialToken != null && supaClient.auth.currentUser != null) {
|
||||||
debugPrint('initial FCM token for signed-in user: $initialToken');
|
debugPrint('initial FCM token for signed-in user: $initialToken');
|
||||||
final ctrl = NotificationsController(supaClient);
|
final ctrl = NotificationsController(supaClient);
|
||||||
await ctrl.registerFcmToken(initialToken);
|
await ctrl.registerFcmToken(initialToken);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// listen for auth changes to register/unregister token accordingly
|
// listen for auth changes to register/unregister token accordingly
|
||||||
supaClient.auth.onAuthStateChange.listen((data) async {
|
supaClient.auth.onAuthStateChange.listen((data) async {
|
||||||
final event = data.event;
|
final event = data.event;
|
||||||
final token = await FirebaseMessaging.instance.getToken();
|
if (kIsWeb) {
|
||||||
|
debugPrint(
|
||||||
|
'auth state change $event on web: skipping FCM token handling',
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String? token;
|
||||||
|
try {
|
||||||
|
token = await FirebaseMessaging.instance.getToken();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('FCM getToken failed during auth change: $e');
|
||||||
|
token = null;
|
||||||
|
}
|
||||||
debugPrint('auth state change $event, token=$token');
|
debugPrint('auth state change $event, token=$token');
|
||||||
if (token == null) return;
|
if (token == null) return;
|
||||||
final ctrl = NotificationsController(supaClient);
|
final ctrl = NotificationsController(supaClient);
|
||||||
|
|
@ -77,18 +98,20 @@ Future<void> main() async {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!kIsWeb) {
|
||||||
// on Android 13+ we must request POST_NOTIFICATIONS at runtime; without it
|
// on Android 13+ we must request POST_NOTIFICATIONS at runtime; without it
|
||||||
// notifications are automatically denied and cannot be re‑enabled from the
|
// notifications are automatically denied and cannot be re‑enabled from the
|
||||||
// system settings. The helper uses `permission_handler`.
|
// system settings. The helper uses `permission_handler`.
|
||||||
final granted = await ensureNotificationPermission();
|
final granted = await ensureNotificationPermission();
|
||||||
if (!granted) {
|
if (!granted) {
|
||||||
// we don’t block startup, but it’s worth logging so developers notice. A
|
// we don’t block startup, but it’s worth logging so developers notice.
|
||||||
// real app might show a dialog pointing the user to settings.
|
// A real app might show a dialog pointing the user to settings.
|
||||||
// debugPrint('notification permission not granted');
|
// debugPrint('notification permission not granted');
|
||||||
}
|
}
|
||||||
|
|
||||||
// request FCM permission (iOS/Android13+) and handle foreground messages
|
// request FCM permission (iOS/Android13+) and handle foreground messages
|
||||||
await FirebaseMessaging.instance.requestPermission();
|
await FirebaseMessaging.instance.requestPermission();
|
||||||
|
}
|
||||||
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
|
||||||
final notification = message.notification;
|
final notification = message.notification;
|
||||||
if (notification != null) {
|
if (notification != null) {
|
||||||
|
|
@ -160,25 +183,35 @@ class NotificationSoundObserver extends ProviderObserver {
|
||||||
|
|
||||||
if (profile != null) {
|
if (profile != null) {
|
||||||
// signed in: save current token and keep listening for refreshes
|
// signed in: save current token and keep listening for refreshes
|
||||||
FirebaseMessaging.instance.getToken().then((token) {
|
if (!kIsWeb) {
|
||||||
|
FirebaseMessaging.instance
|
||||||
|
.getToken()
|
||||||
|
.then((token) {
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
debugPrint('profile observer registering token: $token');
|
debugPrint('profile observer registering token: $token');
|
||||||
controller.registerFcmToken(token);
|
controller.registerFcmToken(token);
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.catchError((e) => debugPrint('getToken error: $e'));
|
||||||
_tokenSub = FirebaseMessaging.instance.onTokenRefresh.listen((token) {
|
_tokenSub = FirebaseMessaging.instance.onTokenRefresh.listen((token) {
|
||||||
debugPrint('token refreshed: $token');
|
debugPrint('token refreshed: $token');
|
||||||
controller.registerFcmToken(token);
|
controller.registerFcmToken(token);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// signed out: unregister whatever token we currently have
|
// signed out: unregister whatever token we currently have
|
||||||
_tokenSub?.cancel();
|
_tokenSub?.cancel();
|
||||||
FirebaseMessaging.instance.getToken().then((token) {
|
if (!kIsWeb) {
|
||||||
|
FirebaseMessaging.instance
|
||||||
|
.getToken()
|
||||||
|
.then((token) {
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
debugPrint('profile observer unregistering token: $token');
|
debugPrint('profile observer unregistering token: $token');
|
||||||
controller.unregisterFcmToken(token);
|
controller.unregisterFcmToken(token);
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.catchError((e) => debugPrint('getToken error: $e'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
|
|
||||||
/// Information about a permission that the application cares about.
|
/// Information about a permission that the application cares about.
|
||||||
///
|
///
|
||||||
|
|
@ -24,7 +25,21 @@ class PermissionInfo {
|
||||||
/// it should be expanded as new features are added. Declaring a permission
|
/// it should be expanded as new features are added. Declaring a permission
|
||||||
/// here ensures it appears on the permissions screen and is considered when
|
/// here ensures it appears on the permissions screen and is considered when
|
||||||
/// performing bulk checks/requests.
|
/// performing bulk checks/requests.
|
||||||
const List<PermissionInfo> appPermissions = [
|
List<PermissionInfo> get appPermissions {
|
||||||
|
// On web, browser notifications are handled separately; avoid including
|
||||||
|
// the notification runtime permission in the app permissions list so the
|
||||||
|
// permissions screen and bulk request flow do not attempt to enforce it.
|
||||||
|
if (kIsWeb) {
|
||||||
|
return [
|
||||||
|
PermissionInfo(
|
||||||
|
permission: Permission.location,
|
||||||
|
label: 'Location',
|
||||||
|
description: 'Access your location for geofencing',
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
PermissionInfo(
|
PermissionInfo(
|
||||||
permission: Permission.notification,
|
permission: Permission.notification,
|
||||||
label: 'Notifications',
|
label: 'Notifications',
|
||||||
|
|
@ -37,6 +52,7 @@ const List<PermissionInfo> appPermissions = [
|
||||||
),
|
),
|
||||||
// add new permissions here as necessary
|
// add new permissions here as necessary
|
||||||
];
|
];
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the current status for every permission in [appPermissions].
|
/// Returns the current status for every permission in [appPermissions].
|
||||||
Future<Map<Permission, PermissionStatus>> getAllStatuses() async {
|
Future<Map<Permission, PermissionStatus>> getAllStatuses() async {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
||||||
|
|
||||||
import '../services/permission_service.dart';
|
import '../services/permission_service.dart';
|
||||||
|
|
||||||
|
|
@ -8,10 +9,14 @@ import '../services/permission_service.dart';
|
||||||
/// [permission_service].
|
/// [permission_service].
|
||||||
|
|
||||||
Future<PermissionStatus> requestNotificationPermission() async {
|
Future<PermissionStatus> requestNotificationPermission() async {
|
||||||
|
if (kIsWeb) {
|
||||||
|
return PermissionStatus.granted;
|
||||||
|
}
|
||||||
return requestPermission(Permission.notification);
|
return requestPermission(Permission.notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> ensureNotificationPermission() async {
|
Future<bool> ensureNotificationPermission() async {
|
||||||
|
if (kIsWeb) return true;
|
||||||
final status = await Permission.notification.status;
|
final status = await Permission.notification.status;
|
||||||
if (status.isGranted) return true;
|
if (status.isGranted) return true;
|
||||||
if (status.isDenied || status.isRestricted || status.isLimited) {
|
if (status.isDenied || status.isRestricted || status.isLimited) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user