785 lines
26 KiB
Dart
785 lines
26 KiB
Dart
import 'package:didvan/models/notification_message.dart';
|
|
import 'package:didvan/models/didvan_voice_model.dart';
|
|
import 'package:didvan/models/didvan_plus_model.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 '../../main.dart';
|
|
import '../../models/requests/infography.dart';
|
|
import '../../models/requests/news.dart';
|
|
import '../../models/requests/radar.dart';
|
|
import '../../models/widget_response.dart';
|
|
import '../../routes/routes.dart';
|
|
import '../network/request.dart';
|
|
import '../network/request_helper.dart';
|
|
|
|
class HomeWidgetRepository {
|
|
/// Helper method to safely parse ID from notification data
|
|
static int? _safeParseId(dynamic id) {
|
|
if (id == null) return null;
|
|
|
|
String idStr = id.toString().trim();
|
|
|
|
// Check if string contains "null" or is empty
|
|
if (idStr.isEmpty ||
|
|
idStr == 'null' ||
|
|
idStr.toLowerCase().contains('null')) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
return int.parse(idStr);
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print("Failed to parse ID: $idStr - Error: $e");
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// True when [id] looks like a UUID (e.g. cdaa8830-d03d-420e-9921-4997a44457e9),
|
|
/// which means the notification refers to a content from the new
|
|
/// content-service (UUID-based) rather than a legacy int-id record.
|
|
static bool _isUuid(dynamic id) {
|
|
if (id == null) return false;
|
|
final s = id.toString().trim();
|
|
// Loose check — 8-4-4-4-12 hex with dashes, length 36.
|
|
final re = RegExp(
|
|
r'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$',
|
|
);
|
|
return re.hasMatch(s);
|
|
}
|
|
|
|
static Future<void> fetchWidget() async {
|
|
// RequestService.token = await StorageService.getValue(key: 'token');
|
|
final service = RequestService(
|
|
RequestHelper.widgetNews(),
|
|
);
|
|
await service.httpGet();
|
|
if (service.isSuccess) {
|
|
final favourites = service.data('content');
|
|
HomeWidget.saveWidgetData("token", RequestService.token.toString());
|
|
for (var i = 0; i < favourites.length; i++) {
|
|
HomeWidget.saveWidgetData(
|
|
"id${i + 1}", WidgetResponse.fromJson(favourites[i]).id.toString());
|
|
HomeWidget.saveWidgetData("title${i + 1}",
|
|
WidgetResponse.fromJson(favourites[i]).title.toString());
|
|
HomeWidget.saveWidgetData(
|
|
"createdAt${i + 1}",
|
|
DateTime.parse(
|
|
WidgetResponse.fromJson(favourites[i]).createdAt.toString())
|
|
.toPersianDateStr());
|
|
HomeWidget.saveWidgetData("type${i + 1}",
|
|
WidgetResponse.fromJson(favourites[i]).type.toString());
|
|
HomeWidget.saveWidgetData("link${i + 1}",
|
|
WidgetResponse.fromJson(favourites[i]).link.toString());
|
|
HomeWidget.saveWidgetData("category${i + 1}",
|
|
WidgetResponse.fromJson(favourites[i]).category.toString());
|
|
HomeWidget.saveWidgetData("image${i + 1}",
|
|
WidgetResponse.fromJson(favourites[i]).image.toString());
|
|
}
|
|
|
|
HomeWidget.updateWidget(
|
|
androidName: "FavWidget",
|
|
);
|
|
}
|
|
}
|
|
|
|
static Future<void> decideWhereToGo() async {
|
|
String? uri =
|
|
await HomeWidget.getWidgetData<String>('uri', defaultValue: "");
|
|
if (uri!.isNotEmpty) {
|
|
int row = 0;
|
|
String route = "";
|
|
dynamic args;
|
|
switch (uri) {
|
|
case 'setting':
|
|
route = Routes.favouritesStep;
|
|
args = {"toTimer": false};
|
|
break;
|
|
case 'rowfirst':
|
|
row = 1;
|
|
break;
|
|
case 'rowmiddle':
|
|
row = 2;
|
|
break;
|
|
case 'rowlast':
|
|
row = 3;
|
|
break;
|
|
}
|
|
|
|
if (row != 0) {
|
|
String? id =
|
|
await HomeWidget.getWidgetData<String>("id$row", defaultValue: "");
|
|
|
|
final parsedId = _safeParseId(id);
|
|
if (parsedId == null) {
|
|
if (kDebugMode) {
|
|
print("Invalid widget ID: $id - cannot create WidgetResponse");
|
|
}
|
|
return;
|
|
}
|
|
|
|
WidgetResponse data = WidgetResponse(
|
|
id: parsedId,
|
|
title: await HomeWidget.getWidgetData("title$row", defaultValue: ""),
|
|
createdAt:
|
|
await HomeWidget.getWidgetData("createdAt$row", defaultValue: ""),
|
|
type: await HomeWidget.getWidgetData("type$row", defaultValue: ""),
|
|
link: await HomeWidget.getWidgetData("link$row", defaultValue: ""),
|
|
category:
|
|
await HomeWidget.getWidgetData("category$row", defaultValue: ""),
|
|
image: await HomeWidget.getWidgetData("image$row", defaultValue: ""),
|
|
);
|
|
|
|
if (data.link!.startsWith('http')) {
|
|
AppInitializer.openWebLink(
|
|
navigatorKey.currentContext!,
|
|
'${data.link}',
|
|
mode: LaunchMode.inAppWebView,
|
|
);
|
|
} else {
|
|
switch (data.type!) {
|
|
case "infography":
|
|
route = Routes.infography;
|
|
args = {
|
|
'id': data.id,
|
|
'args': const InfographyRequestArgs(page: 0),
|
|
'hasUnmarkConfirmation': false,
|
|
};
|
|
break;
|
|
case "news":
|
|
route = Routes.newsDetails;
|
|
args = {
|
|
'id': data.id,
|
|
'args': const NewsRequestArgs(page: 0),
|
|
'hasUnmarkConfirmation': false,
|
|
};
|
|
break;
|
|
case "radar":
|
|
route = Routes.radarDetails;
|
|
args = {
|
|
'id': data.id,
|
|
'args': const RadarRequestArgs(page: 0),
|
|
'hasUnmarkConfirmation': false,
|
|
};
|
|
break;
|
|
case "video":
|
|
route = Routes.studioDetails;
|
|
args = {
|
|
'type': 'podcast',
|
|
'id': data.id,
|
|
};
|
|
break;
|
|
case "podcast":
|
|
route = Routes.podcasts;
|
|
args = {
|
|
'type': 'podcast',
|
|
'id': data.id,
|
|
};
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (route.isNotEmpty) {
|
|
Future.delayed(
|
|
const Duration(milliseconds: 500),
|
|
() => Navigator.of(navigatorKey.currentContext!)
|
|
.pushNamed(route.toString(), arguments: args));
|
|
}
|
|
}
|
|
await HomeWidget.saveWidgetData("uri", "");
|
|
|
|
return;
|
|
}
|
|
|
|
static NotificationMessage? data;
|
|
static Future<void> decideWhereToGoNotif() async {
|
|
NotificationMessage? localData = HomeWidgetRepository.data;
|
|
|
|
if (localData == null) {
|
|
if (kDebugMode) {
|
|
print("=== NAVIGATION ABORTED ===");
|
|
print("Reason: Notification data is null");
|
|
print("===========================");
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (RequestService.token == null ||
|
|
RequestService.token.toString().isEmpty) {
|
|
if (kDebugMode) {
|
|
print("⏳ Token not loaded yet. Deferring navigation to Home/MainPage.");
|
|
}
|
|
return;
|
|
}
|
|
|
|
HomeWidgetRepository.data = null;
|
|
|
|
if (kDebugMode) {
|
|
print("=== NAVIGATION DECISION ===");
|
|
print("Notification Data: ${localData.toJson()}");
|
|
print("Type: ${localData.type}");
|
|
print("ID: ${localData.id}");
|
|
print("Link: ${localData.link}");
|
|
print("Notification Type: ${localData.notificationType}");
|
|
}
|
|
|
|
String route = "";
|
|
dynamic args;
|
|
bool openComments = localData.notificationType.toString() == "2";
|
|
|
|
// ---------------- UUID dispatch (FIRST) ----------------
|
|
// Content from the new content-service uses UUIDs. We must decide on
|
|
// the destination BEFORE checking `link`, because some categories
|
|
// (didvanplus / video / monthly) legitimately ship with a `link` (the
|
|
// media URL) and would otherwise get sent to a generic WebView, which
|
|
// breaks Arvan signed URLs.
|
|
//
|
|
// Exception: trend / technology / startup are NOT in-app screens —
|
|
// they live on app.didvan.com and we open them in a WebView, even
|
|
// when the id is a UUID.
|
|
const _webViewTypes = {'trend', 'technology', 'startup'};
|
|
final _isWebViewType = _webViewTypes.contains(localData.type);
|
|
final _isUuidId = _isUuid(localData.id);
|
|
final _hasLink = localData.link != null &&
|
|
localData.link!.isNotEmpty &&
|
|
localData.link!.toString() != 'null';
|
|
|
|
if (_isUuidId && !_isWebViewType) {
|
|
final type = localData.type ?? '';
|
|
switch (type) {
|
|
case 'news':
|
|
case 'story':
|
|
case 'poyesh':
|
|
case 'swot':
|
|
route = Routes.newsDetails;
|
|
args = {
|
|
'contentUuid': localData.id,
|
|
'args': const NewsRequestArgs(page: 0),
|
|
'link': localData.link,
|
|
'goToComment': openComments,
|
|
};
|
|
break;
|
|
|
|
case 'infography':
|
|
case 'banner':
|
|
route = Routes.infographyDetails;
|
|
args = {
|
|
'contentUuid': localData.id,
|
|
'link': localData.link,
|
|
'goToComment': openComments,
|
|
};
|
|
break;
|
|
|
|
case 'podcast':
|
|
route = Routes.studioDetails;
|
|
args = {
|
|
'type': 'podcast',
|
|
'contentUuid': localData.id,
|
|
'goToComment': openComments,
|
|
};
|
|
break;
|
|
|
|
case 'video':
|
|
route = Routes.videoDetails;
|
|
args = {
|
|
'contentUuid': localData.id,
|
|
'goToComment': openComments,
|
|
};
|
|
break;
|
|
|
|
case 'monthly':
|
|
// PDF URL is in `link`; if present, open PdfViewer directly.
|
|
if (_hasLink) {
|
|
route = Routes.pdfViewer;
|
|
args = {
|
|
'pdfUrl': localData.link,
|
|
'title': localData.title ?? 'ماهنامه',
|
|
};
|
|
} else {
|
|
route = Routes.monthlyList;
|
|
}
|
|
break;
|
|
|
|
case 'didvanplus':
|
|
// Open the player directly with a synthesized model.
|
|
if (_hasLink) {
|
|
route = Routes.didvanPlusVideo;
|
|
args = DidvanPlusModel(
|
|
id: 0, // unused for navigation
|
|
title: localData.title ?? '',
|
|
description: localData.body ?? '',
|
|
image: localData.imageUrl ?? '',
|
|
file: localData.link!,
|
|
publishedAt: DateTime.now().toIso8601String(),
|
|
);
|
|
} else {
|
|
route = Routes.didvanPlusList;
|
|
}
|
|
break;
|
|
|
|
case 'didvanvoice':
|
|
case 'media':
|
|
// DidvanVoiceList expects List<DidvanVoiceModel>. The notification
|
|
// doesn't carry the full list, so we fetch it on the fly the same
|
|
// way the legacy int-id branch does.
|
|
try {
|
|
final service = RequestService(RequestHelper.didvanVoice);
|
|
await service.httpGet();
|
|
if (service.statusCode == 200) {
|
|
final rawData = service.data('result');
|
|
List<DidvanVoiceModel> voices = [];
|
|
if (rawData is List && rawData.isNotEmpty) {
|
|
voices = rawData
|
|
.map((e) => DidvanVoiceModel.fromJson(
|
|
Map<String, dynamic>.from(e as Map)))
|
|
.toList();
|
|
} else if (rawData is Map) {
|
|
voices = [
|
|
DidvanVoiceModel.fromJson(
|
|
Map<String, dynamic>.from(rawData)),
|
|
];
|
|
}
|
|
if (voices.isNotEmpty) {
|
|
route = Routes.didvanVoiceList;
|
|
args = voices;
|
|
} else {
|
|
route = Routes.home;
|
|
}
|
|
} else {
|
|
route = Routes.home;
|
|
}
|
|
} catch (e) {
|
|
if (kDebugMode) {
|
|
print("Error fetching didvan voices for notification: $e");
|
|
}
|
|
route = Routes.home;
|
|
}
|
|
break;
|
|
|
|
// Unknown type with a UUID — best effort: generic reader.
|
|
default:
|
|
if (kDebugMode) {
|
|
print("UUID with unmapped type='$type' — defaulting to "
|
|
"InfographyDetails");
|
|
}
|
|
route = Routes.infographyDetails;
|
|
args = {
|
|
'contentUuid': localData.id,
|
|
'link': localData.link,
|
|
'goToComment': openComments,
|
|
};
|
|
}
|
|
if (kDebugMode) {
|
|
print("UUID notification routed: type=$type → route=$route");
|
|
}
|
|
} else if (!_hasLink) {
|
|
// Legacy int-id branch: no link, fall through to per-type detail
|
|
// pages keyed by int id (or home if no type).
|
|
if (localData.type == null || localData.type!.isEmpty) {
|
|
if (kDebugMode) {
|
|
print("=== NAVIGATION ABORTED ===");
|
|
print("Reason: Notification type is null or empty");
|
|
print("Defaulting to home route");
|
|
print("===========================");
|
|
}
|
|
route = Routes.home;
|
|
} else {
|
|
switch (localData.type!) {
|
|
case "infography":
|
|
final infographyId = _safeParseId(localData.id);
|
|
if (infographyId == null) {
|
|
if (kDebugMode) {
|
|
print(
|
|
"WARNING: Infography notification without valid ID - navigating to home");
|
|
}
|
|
route = Routes.home;
|
|
} else {
|
|
route = Routes.infography;
|
|
args = {
|
|
'id': infographyId,
|
|
'args': const InfographyRequestArgs(page: 0),
|
|
'hasUnmarkConfirmation': false,
|
|
'goToComment': openComments
|
|
};
|
|
}
|
|
break;
|
|
case "news":
|
|
final newsId = _safeParseId(localData.id);
|
|
if (newsId == null) {
|
|
if (kDebugMode) {
|
|
print(
|
|
"WARNING: News notification without valid ID - navigating to home");
|
|
}
|
|
route = Routes.home;
|
|
} else {
|
|
route = Routes.newsDetails;
|
|
args = {
|
|
'id': newsId,
|
|
'args': const NewsRequestArgs(page: 0),
|
|
'hasUnmarkConfirmation': false,
|
|
'goToComment': openComments
|
|
};
|
|
if (kDebugMode) {
|
|
print("News navigation - ID: $newsId");
|
|
}
|
|
}
|
|
break;
|
|
case "radar":
|
|
final radarId = _safeParseId(localData.id);
|
|
if (radarId == null) {
|
|
if (kDebugMode) {
|
|
print(
|
|
"WARNING: Radar notification without valid ID - navigating to home");
|
|
}
|
|
route = Routes.home;
|
|
} else {
|
|
route = Routes.radarDetails;
|
|
args = {
|
|
'id': radarId,
|
|
'args': const RadarRequestArgs(page: 0),
|
|
'hasUnmarkConfirmation': false,
|
|
'goToComment': openComments
|
|
};
|
|
}
|
|
break;
|
|
case "studio":
|
|
final studioId = _safeParseId(localData.id);
|
|
if (studioId == null) {
|
|
if (kDebugMode) {
|
|
print(
|
|
"WARNING: Studio notification without valid ID - navigating to home");
|
|
}
|
|
route = Routes.home;
|
|
} else {
|
|
route = Routes.studioDetails;
|
|
args = {
|
|
'type': 'podcast',
|
|
'id': studioId,
|
|
'goToComment': openComments
|
|
};
|
|
}
|
|
break;
|
|
case "video":
|
|
final videoId = _safeParseId(localData.id);
|
|
if (videoId == null) {
|
|
if (kDebugMode) {
|
|
print(
|
|
"WARNING: Video notification without valid ID - navigating to home");
|
|
}
|
|
route = Routes.home;
|
|
} else {
|
|
route = Routes.studioDetails;
|
|
args = {
|
|
'type': 'podcast',
|
|
'id': videoId,
|
|
'goToComment': openComments
|
|
};
|
|
}
|
|
break;
|
|
case "podcast":
|
|
final podcastId = _safeParseId(localData.id);
|
|
if (podcastId == null) {
|
|
if (kDebugMode) {
|
|
print(
|
|
"WARNING: Podcast notification without valid ID - navigating to home");
|
|
}
|
|
route = Routes.home;
|
|
} else {
|
|
route = Routes.podcasts;
|
|
args = {
|
|
'type': 'podcast',
|
|
'id': podcastId,
|
|
'goToComment': openComments
|
|
};
|
|
}
|
|
break;
|
|
|
|
case "monthly":
|
|
route = Routes.monthlyList;
|
|
break;
|
|
|
|
case "didvanplus":
|
|
case "didvan_plus":
|
|
case "didvanPlus":
|
|
if (kDebugMode) {
|
|
print(
|
|
"🎬 Fetching didvan plus list for notification navigation...");
|
|
}
|
|
try {
|
|
final service = RequestService(RequestHelper.didvanPlus);
|
|
await service.httpGet();
|
|
|
|
if (kDebugMode) {
|
|
print("🎬 DidvanPlus API Response - Status: ${service.statusCode}");
|
|
print("🎬 DidvanPlus API Response - Success: ${service.isSuccess}");
|
|
}
|
|
|
|
if (service.statusCode == 200) {
|
|
final rawData = service.data('result');
|
|
|
|
if (kDebugMode) {
|
|
print("🎬 Raw Data Type: ${rawData.runtimeType}");
|
|
print("🎬 Raw Data: $rawData");
|
|
}
|
|
|
|
List<DidvanPlusModel> videos = [];
|
|
|
|
if (rawData is List && rawData.isNotEmpty) {
|
|
videos = rawData
|
|
.map((e) => DidvanPlusModel.fromJson(
|
|
Map<String, dynamic>.from(e as Map)))
|
|
.toList();
|
|
} else if (rawData is Map) {
|
|
videos = [
|
|
DidvanPlusModel.fromJson(
|
|
Map<String, dynamic>.from(rawData))
|
|
];
|
|
}
|
|
|
|
if (kDebugMode) {
|
|
print("🎬 Parsed ${videos.length} didvan plus videos");
|
|
for (var video in videos) {
|
|
print(" - ${video.title} (ID: ${video.id})");
|
|
}
|
|
}
|
|
|
|
if (videos.isNotEmpty) {
|
|
route = Routes.didvanPlusList;
|
|
args = videos;
|
|
if (kDebugMode) {
|
|
print(
|
|
"🎬 ✅ Successfully prepared navigation with ${videos.length} videos");
|
|
print("🎬 Args type: ${args.runtimeType}");
|
|
}
|
|
} else {
|
|
route = Routes.home;
|
|
if (kDebugMode) {
|
|
print("🎬 ⚠️ No didvan plus videos found, navigating to home");
|
|
}
|
|
}
|
|
} else {
|
|
route = Routes.home;
|
|
if (kDebugMode) {
|
|
print(
|
|
"🎬 ❌ Failed to fetch didvan plus (status: ${service.statusCode}), navigating to home");
|
|
}
|
|
}
|
|
} catch (e, stackTrace) {
|
|
route = Routes.home;
|
|
if (kDebugMode) {
|
|
print("🎬 ❌ Error fetching didvan plus: $e");
|
|
print("🎬 Stack trace: $stackTrace");
|
|
}
|
|
}
|
|
break;
|
|
|
|
case "didvanvoice":
|
|
case "didvan_voice":
|
|
case "didvan_Voice":
|
|
case "didvanVoice":
|
|
case "media":
|
|
if (kDebugMode) {
|
|
print(
|
|
"Fetching didvan voice list for notification navigation...");
|
|
}
|
|
try {
|
|
final service = RequestService(RequestHelper.didvanVoice);
|
|
await service.httpGet();
|
|
if (service.statusCode == 200) {
|
|
final rawData = service.data('result');
|
|
List<DidvanVoiceModel> voices = [];
|
|
|
|
if (rawData is List && rawData.isNotEmpty) {
|
|
voices = rawData
|
|
.map((e) => DidvanVoiceModel.fromJson(
|
|
Map<String, dynamic>.from(e as Map)))
|
|
.toList();
|
|
} else if (rawData is Map) {
|
|
voices = [
|
|
DidvanVoiceModel.fromJson(
|
|
Map<String, dynamic>.from(rawData))
|
|
];
|
|
}
|
|
|
|
if (voices.isNotEmpty) {
|
|
route = Routes.didvanVoiceList;
|
|
args = voices;
|
|
if (kDebugMode) {
|
|
print(
|
|
"Successfully fetched ${voices.length} didvan voices");
|
|
}
|
|
} else {
|
|
route = Routes.home;
|
|
if (kDebugMode) {
|
|
print("No didvan voices found, navigating to home");
|
|
}
|
|
}
|
|
} else {
|
|
route = Routes.home;
|
|
if (kDebugMode) {
|
|
print(
|
|
"Failed to fetch didvan voices (status: ${service.statusCode}), navigating to home");
|
|
}
|
|
}
|
|
} catch (e) {
|
|
route = Routes.home;
|
|
if (kDebugMode) {
|
|
print("Error fetching didvan voices: $e, navigating to home");
|
|
}
|
|
}
|
|
break;
|
|
case "startup":
|
|
case "technology":
|
|
case "trend":
|
|
if (localData.link != null &&
|
|
localData.link!.isNotEmpty &&
|
|
localData.link! != "null") {
|
|
if (kDebugMode) {
|
|
print(
|
|
"Opening external link for ${localData.type}: ${localData.link}");
|
|
}
|
|
AppInitializer.openWebLink(
|
|
navigatorKey.currentContext!,
|
|
localData.link!,
|
|
mode: LaunchMode.inAppWebView,
|
|
);
|
|
} else if (localData.id != null &&
|
|
localData.id.toString().isNotEmpty) {
|
|
String url = "";
|
|
// All three apps now live on app.didvan.com (the Next.js
|
|
// frontend). The old subdomain URLs (trend.didvan.app, …)
|
|
// are obsolete. The Next.js routes are a single `[id]`
|
|
// segment — no title slug — so we only append the id.
|
|
|
|
switch (localData.type) {
|
|
case "startup":
|
|
url =
|
|
"https://app.didvan.com/startup/${localData.id}?accessToken=${RequestService.token}";
|
|
break;
|
|
case "technology":
|
|
url =
|
|
"https://app.didvan.com/technology/${localData.id}?accessToken=${RequestService.token}";
|
|
break;
|
|
case "trend":
|
|
url =
|
|
"https://app.didvan.com/trend/${localData.id}?accessToken=${RequestService.token}";
|
|
break;
|
|
}
|
|
|
|
if (url.isNotEmpty) {
|
|
if (kDebugMode) {
|
|
print("Opening constructed URL for ${localData.type}: $url");
|
|
}
|
|
AppInitializer.openWebLink(
|
|
navigatorKey.currentContext!,
|
|
url,
|
|
mode: LaunchMode.inAppWebView,
|
|
);
|
|
} else {
|
|
route = Routes.home;
|
|
if (kDebugMode) {
|
|
print(
|
|
"Unable to construct URL for ${localData.type} - navigating to home");
|
|
}
|
|
}
|
|
} else {
|
|
route = Routes.home;
|
|
if (kDebugMode) {
|
|
print(
|
|
"No ID or link available for ${localData.type} - navigating to home");
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
route = Routes.home;
|
|
if (kDebugMode) {
|
|
print(
|
|
"Unknown notification type: ${localData.type} - navigating to home");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
if (kDebugMode) {
|
|
print("External link detected: ${localData.link}");
|
|
}
|
|
if (localData.type == 'monthly') {
|
|
route = Routes.pdfViewer;
|
|
args = {
|
|
'pdfUrl': localData.link,
|
|
'title': localData.title ?? 'ماهنامه',
|
|
};
|
|
} else if (localData.link!.startsWith('http')) {
|
|
String linkWithToken = localData.link!;
|
|
if (RequestService.token != null && RequestService.token!.isNotEmpty) {
|
|
String separator = localData.link!.contains('?') ? '&' : '?';
|
|
linkWithToken =
|
|
"${localData.link}${separator}accessToken=${RequestService.token}";
|
|
}
|
|
|
|
if (kDebugMode) {
|
|
print("Opening external link with token: $linkWithToken");
|
|
}
|
|
|
|
AppInitializer.openWebLink(
|
|
navigatorKey.currentContext!,
|
|
linkWithToken,
|
|
mode: LaunchMode.inAppWebView,
|
|
);
|
|
}
|
|
}
|
|
|
|
if (kDebugMode) {
|
|
print("Final navigation decision:");
|
|
print("Route: $route");
|
|
print("Args type: ${args.runtimeType}");
|
|
if (args is List) {
|
|
print("Args list length: ${args.length}");
|
|
}
|
|
print("Args: $args");
|
|
print("===========================");
|
|
}
|
|
|
|
if (route.isNotEmpty) {
|
|
await Future.delayed(const Duration(milliseconds: 1000));
|
|
|
|
if (kDebugMode) {
|
|
print("Attempting navigation after delay...");
|
|
print("Navigator ready: ${navigatorKey.currentState != null}");
|
|
}
|
|
|
|
int retryCount = 0;
|
|
while (navigatorKey.currentState == null && retryCount < 10) {
|
|
if (kDebugMode) {
|
|
print(
|
|
"Navigator not ready, waiting... (attempt ${retryCount + 1}/10)");
|
|
}
|
|
await Future.delayed(const Duration(milliseconds: 500));
|
|
retryCount++;
|
|
}
|
|
|
|
if (navigatorKey.currentState != null) {
|
|
if (kDebugMode) {
|
|
print("Navigator is ready, performing navigation to: $route");
|
|
print("With arguments type: ${args.runtimeType}");
|
|
}
|
|
navigatorKey.currentState!.pushNamed(route, arguments: args);
|
|
} else {
|
|
if (kDebugMode) {
|
|
print(
|
|
"ERROR: Navigator still not ready after waiting. Navigation aborted.");
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|