feat: Add map navigation, enhance FCM deep linking, localize Google Places API, and refine activity display.
This commit is contained in:
@@ -4,6 +4,12 @@ import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
import 'package:travel_mate/services/logger_service.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:travel_mate/services/error_service.dart';
|
||||
import 'package:travel_mate/repositories/group_repository.dart';
|
||||
import 'package:travel_mate/repositories/account_repository.dart';
|
||||
import 'package:travel_mate/components/group/chat_group_content.dart';
|
||||
import 'package:travel_mate/components/account/group_expenses_page.dart';
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||
@@ -43,6 +49,7 @@ class NotificationService {
|
||||
onDidReceiveNotificationResponse: (details) {
|
||||
// Handle notification tap
|
||||
LoggerService.info('Notification tapped: ${details.payload}');
|
||||
// TODO: Handle local notification tap if needed, usually we rely on FCM callbacks
|
||||
},
|
||||
);
|
||||
|
||||
@@ -52,6 +59,10 @@ class NotificationService {
|
||||
// Handle token refresh
|
||||
FirebaseMessaging.instance.onTokenRefresh.listen(_onTokenRefresh);
|
||||
|
||||
// Setup interacted message (Deep Linking)
|
||||
// We don't call this here anymore, it will be called from HomePage
|
||||
// await setupInteractedMessage();
|
||||
|
||||
_isInitialized = true;
|
||||
LoggerService.info('NotificationService initialized');
|
||||
|
||||
@@ -60,6 +71,87 @@ class NotificationService {
|
||||
LoggerService.info('Current FCM Token: $token');
|
||||
}
|
||||
|
||||
/// Sets up the background message listener.
|
||||
/// Should be called when the app is ready to handle navigation.
|
||||
void startListening() {
|
||||
// Handle any interaction when the app is in the background via a
|
||||
// Stream listener
|
||||
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
|
||||
_handleNotificationTap(message.data);
|
||||
});
|
||||
}
|
||||
|
||||
/// Checks for an initial message (app opened from terminated state)
|
||||
/// and handles it if present.
|
||||
Future<void> handleInitialMessage() async {
|
||||
// Get any messages which caused the application to open from
|
||||
// a terminated state.
|
||||
RemoteMessage? initialMessage = await _firebaseMessaging
|
||||
.getInitialMessage();
|
||||
|
||||
if (initialMessage != null) {
|
||||
LoggerService.info('Found initial message: ${initialMessage.data}');
|
||||
_handleNotificationTap(initialMessage.data);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _handleNotificationTap(Map<String, dynamic> data) async {
|
||||
LoggerService.info('Handling notification tap with data: $data');
|
||||
// DEBUG: Show snackbar to verify payload
|
||||
// ErrorService().showSnackbar(message: 'Debug: Payload $data', isError: false);
|
||||
|
||||
final type = data['type'];
|
||||
|
||||
try {
|
||||
if (type == 'message') {
|
||||
final groupId = data['groupId'];
|
||||
if (groupId != null) {
|
||||
final groupRepository = GroupRepository();
|
||||
final group = await groupRepository.getGroupById(groupId);
|
||||
if (group != null) {
|
||||
ErrorService.navigatorKey.currentState?.push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => ChatGroupContent(group: group),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
LoggerService.error('Group not found: $groupId');
|
||||
// ErrorService().showError(message: 'Groupe introuvable: $groupId');
|
||||
}
|
||||
} else {
|
||||
LoggerService.error('Missing groupId in payload');
|
||||
// ErrorService().showError(message: 'Payload invalide: groupId manquant');
|
||||
}
|
||||
} else if (type == 'expense') {
|
||||
final tripId = data['tripId'];
|
||||
if (tripId != null) {
|
||||
final accountRepository = AccountRepository();
|
||||
final groupRepository = GroupRepository();
|
||||
|
||||
final account = await accountRepository.getAccountByTripId(tripId);
|
||||
final group = await groupRepository.getGroupByTripId(tripId);
|
||||
|
||||
if (account != null && group != null) {
|
||||
ErrorService.navigatorKey.currentState?.push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
GroupExpensesPage(account: account, group: group),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
LoggerService.error('Account or Group not found for trip: $tripId');
|
||||
// ErrorService().showError(message: 'Compte ou Groupe introuvable');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LoggerService.info('Unknown notification type: $type');
|
||||
}
|
||||
} catch (e) {
|
||||
LoggerService.error('Error handling notification tap: $e');
|
||||
ErrorService().showError(message: 'Erreur navigation: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onTokenRefresh(String newToken) async {
|
||||
LoggerService.info('FCM Token refreshed: $newToken');
|
||||
// We need the user ID to save the token.
|
||||
|
||||
Reference in New Issue
Block a user