fixed navigat for notif

This commit is contained in:
mohamadmahdi jebeli 2025-09-27 11:57:02 +03:30
parent 18f67d6a17
commit 292f6ec769
3 changed files with 197 additions and 30 deletions

View File

@ -1,10 +1,10 @@
import 'package:didvan/models/notification_message.dart'; import 'package:didvan/models/notification_message.dart';
import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/services/app_initalizer.dart';
import 'package:flutter/cupertino.dart'; import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:home_widget/home_widget.dart'; import 'package:home_widget/home_widget.dart';
import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:persian_number_utility/persian_number_utility.dart';
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
// import 'package:url_launcher/url_launcher_string.dart';
import '../../main.dart'; import '../../main.dart';
import '../../models/requests/infography.dart'; import '../../models/requests/infography.dart';
@ -100,8 +100,6 @@ class HomeWidgetRepository {
case "infography": case "infography":
route = Routes.infography; route = Routes.infography;
args = { args = {
// 'onMarkChanged': (id, value) =>
// markChangeHandler(data.type, id, value),
'id': data.id, 'id': data.id,
'args': const InfographyRequestArgs(page: 0), 'args': const InfographyRequestArgs(page: 0),
'hasUnmarkConfirmation': false, 'hasUnmarkConfirmation': false,
@ -110,8 +108,6 @@ class HomeWidgetRepository {
case "news": case "news":
route = Routes.newsDetails; route = Routes.newsDetails;
args = { args = {
// 'onMarkChanged': (id, value) =>
// markChangeHandler(data.type, id, value),
'id': data.id, 'id': data.id,
'args': const NewsRequestArgs(page: 0), 'args': const NewsRequestArgs(page: 0),
'hasUnmarkConfirmation': false, 'hasUnmarkConfirmation': false,
@ -120,8 +116,6 @@ class HomeWidgetRepository {
case "radar": case "radar":
route = Routes.radarDetails; route = Routes.radarDetails;
args = { args = {
// 'onMarkChanged': (id, value) =>
// markChangeHandler(data.type, id, value),
'id': data.id, 'id': data.id,
'args': const RadarRequestArgs(page: 0), 'args': const RadarRequestArgs(page: 0),
'hasUnmarkConfirmation': false, 'hasUnmarkConfirmation': false,
@ -161,18 +155,25 @@ class HomeWidgetRepository {
static NotificationMessage? data; static NotificationMessage? data;
static Future<void> decideWhereToGoNotif() async { static Future<void> decideWhereToGoNotif() async {
NotificationMessage? data = HomeWidgetRepository.data; NotificationMessage? data = HomeWidgetRepository.data;
// Navigate into pages, avoiding to open the notification details page over another details page already opened
if (kDebugMode) {
print("=== NAVIGATION DECISION ===");
print("Notification Data: ${data?.toJson()}");
print("Type: ${data?.type}");
print("ID: ${data?.id}");
print("Link: ${data?.link}");
print("Notification Type: ${data?.notificationType}");
}
String route = ""; String route = "";
dynamic args; dynamic args;
bool openComments = data!.notificationType.toString() == "2"; bool openComments = data!.notificationType.toString() == "2";
if (data.link.toString().isEmpty) { if (data.link.toString().isEmpty || data.link.toString() == "null") {
switch (data.type!) { switch (data.type!) {
case "infography": case "infography":
route = Routes.infography; route = Routes.infography;
args = { args = {
// 'onMarkChanged': (id, value) =>
// markChangeHandler(data.type, id, value),
'id': int.parse(data.id.toString()), 'id': int.parse(data.id.toString()),
'args': const InfographyRequestArgs(page: 0), 'args': const InfographyRequestArgs(page: 0),
'hasUnmarkConfirmation': false, 'hasUnmarkConfirmation': false,
@ -182,25 +183,32 @@ class HomeWidgetRepository {
case "news": case "news":
route = Routes.newsDetails; route = Routes.newsDetails;
args = { args = {
// 'onMarkChanged': (id, value) =>
// markChangeHandler(data.type, id, value),
'id': int.parse(data.id.toString()), 'id': int.parse(data.id.toString()),
'args': const NewsRequestArgs(page: 0), 'args': const NewsRequestArgs(page: 0),
'hasUnmarkConfirmation': false, 'hasUnmarkConfirmation': false,
'goToComment': openComments 'goToComment': openComments
}; };
if (kDebugMode) {
print("News navigation - ID: ${data.id}");
}
break; break;
case "radar": case "radar":
route = Routes.radarDetails; route = Routes.radarDetails;
args = { args = {
// 'onMarkChanged': (id, value) =>
// markChangeHandler(data.type, id, value),
'id': int.parse(data.id.toString()), 'id': int.parse(data.id.toString()),
'args': const RadarRequestArgs(page: 0), 'args': const RadarRequestArgs(page: 0),
'hasUnmarkConfirmation': false, 'hasUnmarkConfirmation': false,
'goToComment': openComments 'goToComment': openComments
}; };
break; break;
case "studio":
route = Routes.studioDetails;
args = {
'type': 'podcast',
'id': int.parse(data.id.toString()),
'goToComment': openComments
};
break;
case "video": case "video":
route = Routes.studioDetails; route = Routes.studioDetails;
args = { args = {
@ -217,16 +225,93 @@ class HomeWidgetRepository {
'goToComment': openComments 'goToComment': openComments
}; };
break; break;
case "startup":
case "technology":
case "trend":
if (data.link != null && data.link!.isNotEmpty && data.link! != "null") {
if (kDebugMode) {
print("Opening external link for ${data.type}: ${data.link}");
}
AppInitializer.openWebLink(
navigatorKey.currentContext!,
data.link!,
mode: LaunchMode.inAppWebView,
);
} else if (data.id != null && data.id.toString().isNotEmpty) {
String url = "";
String title = data.title?.split(" ").join("-") ?? "";
switch (data.type) {
case "startup":
url = "https://startup.didvan.app/startup/${data.id}/${RequestService.token}";
break;
case "technology":
url = "https://tech.didvan.app/technology/${data.id}/$title/${RequestService.token}";
break;
case "trend":
url = "https://trend.didvan.app/trend/${data.id}/$title/${RequestService.token}";
break;
}
if (url.isNotEmpty) {
if (kDebugMode) {
print("Opening constructed URL for ${data.type}: $url");
}
AppInitializer.openWebLink(
navigatorKey.currentContext!,
url,
mode: LaunchMode.inAppWebView,
);
} else {
route = Routes.home;
if (kDebugMode) {
print("Unable to construct URL for ${data.type} - navigating to home");
}
}
} else {
route = Routes.home;
if (kDebugMode) {
print("No ID or link available for ${data.type} - navigating to home");
}
}
break;
default:
route = Routes.home;
if (kDebugMode) {
print("Unknown notification type: ${data.type} - navigating to home");
}
break;
} }
} else { } else {
if (kDebugMode) {
print("External link detected: ${data.link}");
}
if (data.link!.startsWith('http')) { if (data.link!.startsWith('http')) {
String linkWithToken = data.link!;
if (RequestService.token != null && RequestService.token!.isNotEmpty) {
String separator = data.link!.contains('?') ? '&' : '?';
linkWithToken = "${data.link}${separator}accessToken=${RequestService.token}";
}
if (kDebugMode) {
print("Opening external link with token: $linkWithToken");
}
AppInitializer.openWebLink( AppInitializer.openWebLink(
navigatorKey.currentContext!, navigatorKey.currentContext!,
'${data.link}', linkWithToken,
mode: LaunchMode.inAppWebView, mode: LaunchMode.inAppWebView,
); );
} }
} }
if (kDebugMode) {
print("Final navigation decision:");
print("Route: $route");
print("Args: $args");
print("===========================");
}
if (route.isNotEmpty) { if (route.isNotEmpty) {
navigatorKey.currentState!.pushNamed(route, arguments: args); navigatorKey.currentState!.pushNamed(route, arguments: args);
} }

View File

@ -35,31 +35,59 @@ class FirebaseApi {
final initMsg = await FirebaseMessaging.instance.getInitialMessage(); final initMsg = await FirebaseMessaging.instance.getInitialMessage();
if (initMsg != null) { if (initMsg != null) {
if (kDebugMode) {
print("=== APP OPENED FROM NOTIFICATION (TERMINATED) ===");
print("Message ID: ${initMsg.messageId}");
print("Raw Data: ${initMsg.data}");
if (initMsg.notification != null) {
print("Title: ${initMsg.notification!.title}");
print("Body: ${initMsg.notification!.body}");
}
print("================================================");
}
try { try {
NotificationMessage data = NotificationMessage.fromJson(initMsg.data); NotificationMessage data = NotificationMessage.fromJson(initMsg.data);
HomeWidgetRepository.data = data; HomeWidgetRepository.data = data;
if (kDebugMode) { if (kDebugMode) {
print("data: ${HomeWidgetRepository.data}"); print("Parsed NotificationMessage: ${data.toJson()}");
} }
await HomeWidgetRepository.decideWhereToGoNotif(); await HomeWidgetRepository.decideWhereToGoNotif();
await StorageService.delete( await StorageService.delete(
key: 'notification${AppInitializer.createNotificationId(data)}'); key: 'notification${AppInitializer.createNotificationId(data)}');
} catch (e) { } catch (e) {
if (kDebugMode) {
print("Error handling initial message: $e");
}
e.printError(); e.printError();
} }
} }
FirebaseMessaging.onMessageOpenedApp.listen((initMsg) async { FirebaseMessaging.onMessageOpenedApp.listen((initMsg) async {
if (kDebugMode) {
print("=== APP OPENED FROM NOTIFICATION (BACKGROUND) ===");
print("Message ID: ${initMsg.messageId}");
print("Raw Data: ${initMsg.data}");
if (initMsg.notification != null) {
print("Title: ${initMsg.notification!.title}");
print("Body: ${initMsg.notification!.body}");
}
print("================================================");
}
try { try {
NotificationMessage data = NotificationMessage.fromJson(initMsg.data); NotificationMessage data = NotificationMessage.fromJson(initMsg.data);
HomeWidgetRepository.data = data; HomeWidgetRepository.data = data;
if (kDebugMode) { if (kDebugMode) {
print("data: ${HomeWidgetRepository.data}"); print("Parsed NotificationMessage: ${data.toJson()}");
} }
await HomeWidgetRepository.decideWhereToGoNotif(); await HomeWidgetRepository.decideWhereToGoNotif();
await StorageService.delete( await StorageService.delete(
key: 'notification${AppInitializer.createNotificationId(data)}'); key: 'notification${AppInitializer.createNotificationId(data)}');
} catch (e) { } catch (e) {
if (kDebugMode) {
print("Error handling background message: $e");
}
e.printError(); e.printError();
} }
}); });
@ -69,12 +97,36 @@ class FirebaseApi {
void handleMessage(RemoteMessage? message) async { void handleMessage(RemoteMessage? message) async {
if (message == null) return; if (message == null) return;
//do ever you want with message
// if (kDebugMode) {
if (kDebugMode) { if (kDebugMode) {
print("forground: ${NotificationData.fromJson(message.data).toJson()}"); print("=== NOTIFICATION RECEIVED (FOREGROUND) ===");
print("Message ID: ${message.messageId}");
print("From: ${message.from}");
print("Sent Time: ${message.sentTime}");
print("TTL: ${message.ttl}");
print("Message Type: ${message.messageType}");
print("Category: ${message.category}");
if (message.notification != null) {
print("--- NOTIFICATION PAYLOAD ---");
print("Title: ${message.notification!.title}");
print("Body: ${message.notification!.body}");
print("Android Image: ${message.notification!.android?.imageUrl}");
print("Apple Image: ${message.notification!.apple?.imageUrl}");
}
print("--- DATA PAYLOAD ---");
print("Raw Data: ${message.data}");
try {
NotificationData notifData = NotificationData.fromJson(message.data);
print("Parsed Data: ${notifData.toJson()}");
} catch (e) {
print("Error parsing NotificationData: $e");
}
print("==========================================");
} }
// }
try { try {
await NotificationService.showFirebaseNotification(message); await NotificationService.showFirebaseNotification(message);
} catch (e) { } catch (e) {

View File

@ -25,9 +25,9 @@ class NotificationService {
); );
const AndroidNotificationChannel channel = AndroidNotificationChannel( const AndroidNotificationChannel channel = AndroidNotificationChannel(
'content', // id 'content',
'Content Notification', // name 'Content Notification',
description: 'Notification channel', // description description: 'Notification channel',
importance: Importance.max, importance: Importance.max,
playSound: true, playSound: true,
); );
@ -40,6 +40,16 @@ class NotificationService {
static Future<void> _onNotificationResponse( static Future<void> _onNotificationResponse(
NotificationResponse response) async { NotificationResponse response) async {
if (kDebugMode) {
print("=== LOCAL NOTIFICATION CLICKED ===");
print("Notification ID: ${response.id}");
print("Action ID: ${response.actionId}");
print("Input: ${response.input}");
print("Response Type: ${response.notificationResponseType}");
print("Payload: ${response.payload}");
print("===================================");
}
try { try {
final payload = response.payload; final payload = response.payload;
if (payload != null) { if (payload != null) {
@ -47,26 +57,46 @@ class NotificationService {
NotificationMessage.fromJson(jsonDecode(payload)); NotificationMessage.fromJson(jsonDecode(payload));
HomeWidgetRepository.data = data; HomeWidgetRepository.data = data;
if (kDebugMode) { if (kDebugMode) {
print("data: ${HomeWidgetRepository.data}"); print("Parsed payload data: ${data.toJson()}");
} }
await HomeWidgetRepository.decideWhereToGoNotif(); await HomeWidgetRepository.decideWhereToGoNotif();
await StorageService.delete( await StorageService.delete(
key: 'notification${AppInitializer.createNotificationId(data)}'); key: 'notification${AppInitializer.createNotificationId(data)}');
} }
} catch (e) { } catch (e) {
if (kDebugMode) {
print("Error in _onNotificationResponse: $e");
}
e.printError(); e.printError();
} }
} }
static Future<void> showFirebaseNotification(RemoteMessage message) async { static Future<void> showFirebaseNotification(RemoteMessage message) async {
if (kDebugMode) {
print("=== SHOWING FIREBASE NOTIFICATION ===");
print("Message Data: ${message.data}");
print("Notification: ${message.notification?.title} - ${message.notification?.body}");
}
try { try {
final data = NotificationMessage.fromJson(message.data); final data = NotificationMessage.fromJson(message.data);
if (kDebugMode) {
print("Parsed NotificationMessage: ${data.toJson()}");
print("Notification Type: ${data.notificationType}");
}
if (data.notificationType!.contains('3')) { if (data.notificationType!.contains('3')) {
if (kDebugMode) {
print("Widget notification - calling fetchWidget()");
}
HomeWidgetRepository.fetchWidget(); HomeWidgetRepository.fetchWidget();
return; return;
} }
NotificationService.showNotification(data); NotificationService.showNotification(data);
} catch (e) { } catch (e) {
if (kDebugMode) {
print("Error in showFirebaseNotification: $e");
}
e.printError(); e.printError();
} }
} }
@ -84,9 +114,9 @@ class NotificationService {
final AndroidNotificationDetails androidPlatformChannelSpecifics = final AndroidNotificationDetails androidPlatformChannelSpecifics =
AndroidNotificationDetails( AndroidNotificationDetails(
'content', // channel id 'content',
'Content Notification', // channel name 'Content Notification',
channelDescription: 'Notification channel', // channel description channelDescription: 'Notification channel',
importance: Importance.max, importance: Importance.max,
priority: Priority.high, priority: Priority.high,
playSound: true, playSound: true,