Add notification
This commit is contained in:
@@ -53,13 +53,6 @@ class SettingsContent extends StatelessWidget {
|
||||
onTap: () {},
|
||||
),
|
||||
|
||||
ListTile(
|
||||
leading: const Icon(Icons.language),
|
||||
title: const Text('Langue'),
|
||||
trailing: const Icon(Icons.arrow_forward_ios),
|
||||
onTap: () {},
|
||||
),
|
||||
|
||||
ListTile(
|
||||
leading: const Icon(Icons.privacy_tip),
|
||||
title: const Text('Confidentialité'),
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:cloud_firestore/cloud_firestore.dart';
|
||||
import '../models/user.dart';
|
||||
import '../services/auth_service.dart';
|
||||
import '../services/error_service.dart';
|
||||
import '../services/notification_service.dart';
|
||||
|
||||
/// Repository for authentication operations and user data management.
|
||||
///
|
||||
@@ -57,6 +58,7 @@ class AuthRepository {
|
||||
email: email,
|
||||
password: password,
|
||||
);
|
||||
await _saveFCMToken(firebaseUser.user!.uid);
|
||||
return await getUserFromFirestore(firebaseUser.user!.uid);
|
||||
} catch (e) {
|
||||
_errorService.showError(message: 'Utilisateur ou mot de passe incorrect');
|
||||
@@ -102,6 +104,9 @@ class AuthRepository {
|
||||
);
|
||||
|
||||
await _firestore.collection('users').doc(user.id).set(user.toMap());
|
||||
if (user.id != null) {
|
||||
await _saveFCMToken(user.id!);
|
||||
}
|
||||
return user;
|
||||
} catch (e) {
|
||||
_errorService.showError(message: 'Erreur lors de la création du compte');
|
||||
@@ -149,6 +154,9 @@ class AuthRepository {
|
||||
);
|
||||
|
||||
await _firestore.collection('users').doc(user.id).set(user.toMap());
|
||||
if (user.id != null) {
|
||||
await _saveFCMToken(user.id!);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
return null;
|
||||
@@ -163,6 +171,9 @@ class AuthRepository {
|
||||
final firebaseUser = await _authService.signInWithGoogle();
|
||||
final user = await getUserFromFirestore(firebaseUser.user!.uid);
|
||||
if (user != null) {
|
||||
if (user.id != null) {
|
||||
await _saveFCMToken(user.id!);
|
||||
}
|
||||
return user;
|
||||
} else {
|
||||
throw Exception('Utilisateur non trouvé');
|
||||
@@ -211,6 +222,9 @@ class AuthRepository {
|
||||
);
|
||||
|
||||
await _firestore.collection('users').doc(user.id).set(user.toMap());
|
||||
if (user.id != null) {
|
||||
await _saveFCMToken(user.id!);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
return null;
|
||||
@@ -225,6 +239,9 @@ class AuthRepository {
|
||||
final firebaseUser = await _authService.signInWithApple();
|
||||
final user = await getUserFromFirestore(firebaseUser.user!.uid);
|
||||
if (user != null) {
|
||||
if (user.id != null) {
|
||||
await _saveFCMToken(user.id!);
|
||||
}
|
||||
return user;
|
||||
} else {
|
||||
throw Exception('Utilisateur non trouvé');
|
||||
@@ -258,7 +275,7 @@ class AuthRepository {
|
||||
///
|
||||
/// [uid] - The Firebase user ID to look up
|
||||
///
|
||||
/// Returns the [User] model if found, null otherwise.
|
||||
/// Returns the [User] model if successful, null otherwise.
|
||||
Future<User?> getUserFromFirestore(String uid) async {
|
||||
try {
|
||||
final doc = await _firestore.collection('users').doc(uid).get();
|
||||
@@ -271,4 +288,19 @@ class AuthRepository {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper method to save the FCM token for the authenticated user.
|
||||
Future<void> _saveFCMToken(String userId) async {
|
||||
try {
|
||||
final token = await NotificationService().getFCMToken();
|
||||
if (token != null) {
|
||||
await _firestore.collection('users').doc(userId).set({
|
||||
'fcmToken': token,
|
||||
}, SetOptions(merge: true));
|
||||
}
|
||||
} catch (e) {
|
||||
// Non-blocking error
|
||||
print('Error saving FCM token: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
98
lib/services/notification_service.dart
Normal file
98
lib/services/notification_service.dart
Normal file
@@ -0,0 +1,98 @@
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:travel_mate/services/logger_service.dart';
|
||||
|
||||
class NotificationService {
|
||||
static final NotificationService _instance = NotificationService._internal();
|
||||
factory NotificationService() => _instance;
|
||||
NotificationService._internal();
|
||||
|
||||
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;
|
||||
final FlutterLocalNotificationsPlugin _localNotifications =
|
||||
FlutterLocalNotificationsPlugin();
|
||||
|
||||
bool _isInitialized = false;
|
||||
|
||||
Future<void> initialize() async {
|
||||
if (_isInitialized) return;
|
||||
|
||||
// Request permissions
|
||||
await _requestPermissions();
|
||||
|
||||
// Initialize local notifications
|
||||
const androidSettings = AndroidInitializationSettings(
|
||||
'@mipmap/ic_launcher',
|
||||
);
|
||||
const iosSettings = DarwinInitializationSettings();
|
||||
const initSettings = InitializationSettings(
|
||||
android: androidSettings,
|
||||
iOS: iosSettings,
|
||||
);
|
||||
|
||||
await _localNotifications.initialize(
|
||||
initSettings,
|
||||
onDidReceiveNotificationResponse: (details) {
|
||||
// Handle notification tap
|
||||
LoggerService.info('Notification tapped: ${details.payload}');
|
||||
},
|
||||
);
|
||||
|
||||
// Handle foreground messages
|
||||
FirebaseMessaging.onMessage.listen(_handleForegroundMessage);
|
||||
|
||||
_isInitialized = true;
|
||||
LoggerService.info('NotificationService initialized');
|
||||
}
|
||||
|
||||
Future<void> _requestPermissions() async {
|
||||
NotificationSettings settings = await _firebaseMessaging.requestPermission(
|
||||
alert: true,
|
||||
badge: true,
|
||||
sound: true,
|
||||
);
|
||||
|
||||
LoggerService.info(
|
||||
'User granted permission: ${settings.authorizationStatus}',
|
||||
);
|
||||
}
|
||||
|
||||
Future<String?> getFCMToken() async {
|
||||
try {
|
||||
return await _firebaseMessaging.getToken();
|
||||
} catch (e) {
|
||||
LoggerService.error('Error getting FCM token: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _handleForegroundMessage(RemoteMessage message) async {
|
||||
LoggerService.info('Got a message whilst in the foreground!');
|
||||
LoggerService.info('Message data: ${message.data}');
|
||||
|
||||
if (message.notification != null) {
|
||||
LoggerService.info(
|
||||
'Message also contained a notification: ${message.notification}',
|
||||
);
|
||||
|
||||
// Show local notification
|
||||
const androidDetails = AndroidNotificationDetails(
|
||||
'high_importance_channel',
|
||||
'High Importance Notifications',
|
||||
importance: Importance.max,
|
||||
priority: Priority.high,
|
||||
);
|
||||
const iosDetails = DarwinNotificationDetails();
|
||||
const details = NotificationDetails(
|
||||
android: androidDetails,
|
||||
iOS: iosDetails,
|
||||
);
|
||||
|
||||
await _localNotifications.show(
|
||||
message.hashCode,
|
||||
message.notification?.title,
|
||||
message.notification?.body,
|
||||
details,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user