import 'package:didvan/main.dart'; import 'package:didvan/models/didvan_plus_model.dart'; import 'package:didvan/models/didvan_voice_model.dart'; import 'package:didvan/models/top_banner_model.dart'; import 'package:didvan/models/enums.dart'; import 'package:didvan/models/home_page_content/content.dart'; import 'package:didvan/models/home_page_content/home_page_content.dart'; import 'package:didvan/models/home_page_content/swot.dart'; import 'package:didvan/models/requests/infography.dart'; import 'package:didvan/models/requests/news.dart'; import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/models/story_model.dart'; import 'package:didvan/providers/core.dart'; import 'package:didvan/routes/routes.dart'; import 'package:didvan/services/app_initalizer.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/network/request_helper.dart'; import 'package:didvan/services/story_service.dart'; import 'package:didvan/services/swot_service.dart'; import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher_string.dart'; class MainPageState extends CoreProvier { MainPageContent? content; int unread = 0; List stories = []; List swotItems = []; List didvanPlusList = []; DidvanPlusModel? didvanPlus; DidvanVoiceModel? didvanVoice; List didvanVoiceList = []; TopBannerModel? topBanner; // ... (سایر متدها بدون تغییر) ... DidvanVoiceModel? _pickLatestVoice(List items) { if (items.isEmpty) return null; items.sort((a, b) { try { return DateTime.parse(b.publishedAt) .compareTo(DateTime.parse(a.publishedAt)); } catch (_) { return b.id.compareTo(a.id); } }); return items.first; } Future _getMainPageContent() async { final service = RequestService(RequestHelper.mainPageContent); await service.httpGet(); if (service.isSuccess) { content = MainPageContent.fromJson(service.result); unread = service.result['unread']; notifyListeners(); } else { notifyListeners(); throw Exception('Failed to load main page content'); } } // ... (سایر متدهای دریافت اطلاعات بدون تغییر) ... Future _getSwotItems() async { try { swotItems = await SwotService.fetchSwotItems(); } catch (e) { print(e); } } Future _getDidvanPlus() async { try { final service = RequestService(RequestHelper.didvanPlus); await service.httpGet(); if (service.statusCode == 200) { final rawData = service.data('result'); if (rawData is List && rawData.isNotEmpty) { didvanPlusList = rawData .map((item) => DidvanPlusModel.fromJson(Map.from(item))) .toList(); didvanPlus = didvanPlusList.first; notifyListeners(); } else if (rawData is Map) { didvanPlus = DidvanPlusModel.fromJson(Map.from(rawData)); didvanPlusList = [didvanPlus!]; notifyListeners(); } } } catch (e) { debugPrint('❌ Failed to load Didvan Plus: $e'); } } Future _getDidvanVoice() async { try { final service = RequestService(RequestHelper.didvanVoice); await service.httpGet(); if (service.statusCode == 200) { final rawData = service.data('result'); if (rawData is List && rawData.isNotEmpty) { didvanVoiceList = rawData .map((e) => DidvanVoiceModel.fromJson( Map.from(e as Map))) .toList(); didvanVoice = _pickLatestVoice(List.from(didvanVoiceList)); notifyListeners(); } else if (rawData is Map) { didvanVoice = DidvanVoiceModel.fromJson(Map.from(rawData)); didvanVoiceList = [didvanVoice!]; notifyListeners(); } } } catch (e) { debugPrint('❌ Failed to load Didvan Voice: $e'); } } Future _getTopBanner() async { try { final service = RequestService(RequestHelper.topBanner); await service.httpGet(); if (service.statusCode == 200) { final data = service.result['result'] ?? service.result; topBanner = TopBannerModel.fromJson(data); notifyListeners(); } } catch (e) { debugPrint('❌ Failed to load Top Banner: $e'); } } Future _fetchStories() async { try { stories = await StoryService.getStories(); } catch (e) { stories = []; debugPrint("Could not fetch stories: $e"); } } void init() { debugPrint("🏠 MainPageState init called"); Future.delayed(Duration.zero, () async { appState = AppState.busy; try { await Future.wait([ _getMainPageContent(), _fetchStories(), _getSwotItems(), _getDidvanPlus(), _getDidvanVoice(), _getTopBanner(), ]); appState = AppState.idle; } catch (e) { debugPrint("❌ Main page init failed: $e"); appState = AppState.failed; } }); _getMainPageContent(); } void markChangeHandler(String type, int id, bool value) { content?.lists .firstWhere((element) => element.type == type) .contents .firstWhere((element) => element.id == id) .marked = value; notifyListeners(); } /// متد جدید: دریافت جزئیات ماهنامه برای پیدا کردن فایل PDF Future _fetchMonthlyDetailsAndNavigate(int id, String? title) async { final context = navigatorKey.currentContext!; debugPrint('🔄 Fetching monthly details for ID: $id'); // می‌توانید اینجا یک لودینگ نمایش دهید // showDialog(context: context, builder: (_) => const Center(child: CircularProgressIndicator())); try { final url = '${RequestHelper.baseUrl}/monthly/$id'; final service = RequestService(url); await service.httpGet(); if (service.isSuccess) { // بسته به ساختار جیسون، ممکن است دیتا داخل result باشد یا مستقیم final data = service.result.containsKey('result') ? service.result['result'] : service.result; debugPrint('📥 Monthly details fetched: $data'); // استخراج فایل final fetchedFile = data['file']; final fetchedLink = data['link']; // اولویت ۱: لینک if (fetchedLink != null && fetchedLink.toString().isNotEmpty) { Navigator.of(context).pushNamed( Routes.web, arguments: fetchedLink.toString(), ); return; } // اولویت ۲: فایل if (fetchedFile != null && fetchedFile.toString().isNotEmpty) { debugPrint('✅ Found file in details: $fetchedFile'); Navigator.of(context).pushNamed( Routes.pdfViewer, arguments: { 'pdfUrl': fetchedFile.toString(), 'title': title ?? '', }, ); return; } } } catch (e) { debugPrint('❌ Error fetching monthly details: $e'); } // اولویت ۳: اگر هیچکدام پیدا نشد، برو به لیست debugPrint('⚠️ No file/link found even after fetch, going to list'); Navigator.of(context).pushNamed(Routes.monthlyList); } void navigationHandler( String type, int id, String? link, { String? description, String? file, }) { link = link ?? ''; dynamic args; switch (type) { case 'infography': { link = Routes.infography; args = { 'onMarkChanged': (id, value) => markChangeHandler(type, id, value), 'id': id, 'args': const InfographyRequestArgs(page: 0), 'hasUnmarkConfirmation': false, }; break; } case 'news': { link = Routes.newsDetails; args = { 'onMarkChanged': (id, value) => markChangeHandler(type, id, value), 'id': id, 'args': const NewsRequestArgs(page: 0), 'hasUnmarkConfirmation': false, 'description': description, }; break; } case 'radar': { link = Routes.radarDetails; args = { 'onMarkChanged': (id, value) => markChangeHandler(type, id, value), 'id': id, 'args': const RadarRequestArgs(page: 0), 'hasUnmarkConfirmation': false, 'description': description, }; break; } case 'video': { link = Routes.studioDetails; args = { 'type': 'podcast', 'id': id, }; break; } case 'monthly': { debugPrint('=== Monthly Navigation Logic ==='); debugPrint('ID: $id'); debugPrint('Link: "$link"'); debugPrint('File provided initially: "$file"'); // ۱. بررسی لینک if (link!.isNotEmpty) { debugPrint('Opening WebView for Monthly'); Navigator.of(navigatorKey.currentContext!).pushNamed( Routes.web, arguments: link, ); return; } // ۲. بررسی فایل موجود // چک میکنیم فایل نال نباشد، رشته "null" نباشد و خالی نباشد if (file != null && file.isNotEmpty && file != 'null') { debugPrint('Opening PDF Viewer for Monthly: $file'); Navigator.of(navigatorKey.currentContext!).pushNamed( Routes.pdfViewer, arguments: { 'pdfUrl': file, 'title': description ?? '', }, ); return; } // ۳. اگر فایل نبود، اطلاعات را فچ کن (راهکار جدید) debugPrint('File missing, trying to fetch details...'); _fetchMonthlyDetailsAndNavigate(id, description); return; } } // هندل کردن سایر لینک‌های عمومی if (link == '') { return; } if (link!.startsWith('http')) { AppInitializer.openWebLink( navigatorKey.currentContext!, '$link?accessToken=${RequestService.token}', mode: LaunchMode.inAppWebView, ); return; } Navigator.of(navigatorKey.currentContext!).pushNamed(link!, arguments: args); } }