From 292f6ec769bb0f8c10a0ee286e4e446d67af890e Mon Sep 17 00:00:00 2001 From: mohamadmahdi jebeli Date: Sat, 27 Sep 2025 11:57:02 +0330 Subject: [PATCH] fixed navigat for notif --- .../home_widget_repository.dart | 119 +++++++++++++++--- lib/services/notification/firebase_api.dart | 64 +++++++++- .../notification/notification_service.dart | 44 +++++-- 3 files changed, 197 insertions(+), 30 deletions(-) diff --git a/lib/services/app_home_widget/home_widget_repository.dart b/lib/services/app_home_widget/home_widget_repository.dart index 262837e..1c69c4f 100644 --- a/lib/services/app_home_widget/home_widget_repository.dart +++ b/lib/services/app_home_widget/home_widget_repository.dart @@ -1,10 +1,10 @@ import 'package:didvan/models/notification_message.dart'; import 'package:didvan/services/app_initalizer.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; import 'package:home_widget/home_widget.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 '../../main.dart'; import '../../models/requests/infography.dart'; @@ -100,8 +100,6 @@ class HomeWidgetRepository { case "infography": route = Routes.infography; args = { - // 'onMarkChanged': (id, value) => - // markChangeHandler(data.type, id, value), 'id': data.id, 'args': const InfographyRequestArgs(page: 0), 'hasUnmarkConfirmation': false, @@ -110,8 +108,6 @@ class HomeWidgetRepository { case "news": route = Routes.newsDetails; args = { - // 'onMarkChanged': (id, value) => - // markChangeHandler(data.type, id, value), 'id': data.id, 'args': const NewsRequestArgs(page: 0), 'hasUnmarkConfirmation': false, @@ -120,8 +116,6 @@ class HomeWidgetRepository { case "radar": route = Routes.radarDetails; args = { - // 'onMarkChanged': (id, value) => - // markChangeHandler(data.type, id, value), 'id': data.id, 'args': const RadarRequestArgs(page: 0), 'hasUnmarkConfirmation': false, @@ -161,18 +155,25 @@ class HomeWidgetRepository { static NotificationMessage? data; static Future decideWhereToGoNotif() async { 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 = ""; dynamic args; bool openComments = data!.notificationType.toString() == "2"; - if (data.link.toString().isEmpty) { + if (data.link.toString().isEmpty || data.link.toString() == "null") { switch (data.type!) { case "infography": route = Routes.infography; args = { - // 'onMarkChanged': (id, value) => - // markChangeHandler(data.type, id, value), 'id': int.parse(data.id.toString()), 'args': const InfographyRequestArgs(page: 0), 'hasUnmarkConfirmation': false, @@ -182,25 +183,32 @@ class HomeWidgetRepository { case "news": route = Routes.newsDetails; args = { - // 'onMarkChanged': (id, value) => - // markChangeHandler(data.type, id, value), 'id': int.parse(data.id.toString()), 'args': const NewsRequestArgs(page: 0), 'hasUnmarkConfirmation': false, 'goToComment': openComments }; + if (kDebugMode) { + print("News navigation - ID: ${data.id}"); + } break; case "radar": route = Routes.radarDetails; args = { - // 'onMarkChanged': (id, value) => - // markChangeHandler(data.type, id, value), 'id': int.parse(data.id.toString()), 'args': const RadarRequestArgs(page: 0), 'hasUnmarkConfirmation': false, 'goToComment': openComments }; break; + case "studio": + route = Routes.studioDetails; + args = { + 'type': 'podcast', + 'id': int.parse(data.id.toString()), + 'goToComment': openComments + }; + break; case "video": route = Routes.studioDetails; args = { @@ -217,20 +225,97 @@ class HomeWidgetRepository { 'goToComment': openComments }; 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 { + if (kDebugMode) { + print("External link detected: ${data.link}"); + } 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( navigatorKey.currentContext!, - '${data.link}', + linkWithToken, mode: LaunchMode.inAppWebView, ); } } + + if (kDebugMode) { + print("Final navigation decision:"); + print("Route: $route"); + print("Args: $args"); + print("==========================="); + } + if (route.isNotEmpty) { navigatorKey.currentState!.pushNamed(route, arguments: args); } return; } -} +} \ No newline at end of file diff --git a/lib/services/notification/firebase_api.dart b/lib/services/notification/firebase_api.dart index 33f7907..4221cbb 100644 --- a/lib/services/notification/firebase_api.dart +++ b/lib/services/notification/firebase_api.dart @@ -35,31 +35,59 @@ class FirebaseApi { final initMsg = await FirebaseMessaging.instance.getInitialMessage(); 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 { NotificationMessage data = NotificationMessage.fromJson(initMsg.data); HomeWidgetRepository.data = data; if (kDebugMode) { - print("data: ${HomeWidgetRepository.data}"); + print("Parsed NotificationMessage: ${data.toJson()}"); } await HomeWidgetRepository.decideWhereToGoNotif(); await StorageService.delete( key: 'notification${AppInitializer.createNotificationId(data)}'); } catch (e) { + if (kDebugMode) { + print("Error handling initial message: $e"); + } e.printError(); } } 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 { NotificationMessage data = NotificationMessage.fromJson(initMsg.data); HomeWidgetRepository.data = data; if (kDebugMode) { - print("data: ${HomeWidgetRepository.data}"); + print("Parsed NotificationMessage: ${data.toJson()}"); } await HomeWidgetRepository.decideWhereToGoNotif(); await StorageService.delete( key: 'notification${AppInitializer.createNotificationId(data)}'); } catch (e) { + if (kDebugMode) { + print("Error handling background message: $e"); + } e.printError(); } }); @@ -69,12 +97,36 @@ class FirebaseApi { void handleMessage(RemoteMessage? message) async { if (message == null) return; - //do ever you want with message - // 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 { await NotificationService.showFirebaseNotification(message); } catch (e) { diff --git a/lib/services/notification/notification_service.dart b/lib/services/notification/notification_service.dart index 96437ec..83f3e32 100644 --- a/lib/services/notification/notification_service.dart +++ b/lib/services/notification/notification_service.dart @@ -25,9 +25,9 @@ class NotificationService { ); const AndroidNotificationChannel channel = AndroidNotificationChannel( - 'content', // id - 'Content Notification', // name - description: 'Notification channel', // description + 'content', + 'Content Notification', + description: 'Notification channel', importance: Importance.max, playSound: true, ); @@ -40,6 +40,16 @@ class NotificationService { static Future _onNotificationResponse( 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 { final payload = response.payload; if (payload != null) { @@ -47,26 +57,46 @@ class NotificationService { NotificationMessage.fromJson(jsonDecode(payload)); HomeWidgetRepository.data = data; if (kDebugMode) { - print("data: ${HomeWidgetRepository.data}"); + print("Parsed payload data: ${data.toJson()}"); } await HomeWidgetRepository.decideWhereToGoNotif(); await StorageService.delete( key: 'notification${AppInitializer.createNotificationId(data)}'); } } catch (e) { + if (kDebugMode) { + print("Error in _onNotificationResponse: $e"); + } e.printError(); } } static Future showFirebaseNotification(RemoteMessage message) async { + if (kDebugMode) { + print("=== SHOWING FIREBASE NOTIFICATION ==="); + print("Message Data: ${message.data}"); + print("Notification: ${message.notification?.title} - ${message.notification?.body}"); + } + try { final data = NotificationMessage.fromJson(message.data); + if (kDebugMode) { + print("Parsed NotificationMessage: ${data.toJson()}"); + print("Notification Type: ${data.notificationType}"); + } + if (data.notificationType!.contains('3')) { + if (kDebugMode) { + print("Widget notification - calling fetchWidget()"); + } HomeWidgetRepository.fetchWidget(); return; } NotificationService.showNotification(data); } catch (e) { + if (kDebugMode) { + print("Error in showFirebaseNotification: $e"); + } e.printError(); } } @@ -84,9 +114,9 @@ class NotificationService { final AndroidNotificationDetails androidPlatformChannelSpecifics = AndroidNotificationDetails( - 'content', // channel id - 'Content Notification', // channel name - channelDescription: 'Notification channel', // channel description + 'content', + 'Content Notification', + channelDescription: 'Notification channel', importance: Importance.max, priority: Priority.high, playSound: true,