Add notification

This commit is contained in:
Van Leemput Dayron
2025-11-28 19:16:37 +01:00
parent 0668fcad57
commit 68f546d0e8
9 changed files with 4638 additions and 14 deletions

View File

@@ -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é'),

View File

@@ -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');
}
}
}

View 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,
);
}
}
}