336 lines
11 KiB
Dart
336 lines
11 KiB
Dart
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<UserStories> stories = [];
|
||
List<SwotItem> swotItems = [];
|
||
List<DidvanPlusModel> didvanPlusList = [];
|
||
DidvanPlusModel? didvanPlus;
|
||
DidvanVoiceModel? didvanVoice;
|
||
List<DidvanVoiceModel> didvanVoiceList = [];
|
||
TopBannerModel? topBanner;
|
||
|
||
// ... (سایر متدها بدون تغییر) ...
|
||
|
||
DidvanVoiceModel? _pickLatestVoice(List<DidvanVoiceModel> 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<void> _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<void> _getSwotItems() async {
|
||
try {
|
||
swotItems = await SwotService.fetchSwotItems();
|
||
} catch (e) {
|
||
print(e);
|
||
}
|
||
}
|
||
|
||
Future<void> _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<String, dynamic>.from(item)))
|
||
.toList();
|
||
didvanPlus = didvanPlusList.first;
|
||
notifyListeners();
|
||
} else if (rawData is Map) {
|
||
didvanPlus =
|
||
DidvanPlusModel.fromJson(Map<String, dynamic>.from(rawData));
|
||
didvanPlusList = [didvanPlus!];
|
||
notifyListeners();
|
||
}
|
||
}
|
||
} catch (e) {
|
||
debugPrint('❌ Failed to load Didvan Plus: $e');
|
||
}
|
||
}
|
||
|
||
Future<void> _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<String, dynamic>.from(e as Map)))
|
||
.toList();
|
||
didvanVoice = _pickLatestVoice(List.from(didvanVoiceList));
|
||
notifyListeners();
|
||
} else if (rawData is Map) {
|
||
didvanVoice =
|
||
DidvanVoiceModel.fromJson(Map<String, dynamic>.from(rawData));
|
||
didvanVoiceList = [didvanVoice!];
|
||
notifyListeners();
|
||
}
|
||
}
|
||
} catch (e) {
|
||
debugPrint('❌ Failed to load Didvan Voice: $e');
|
||
}
|
||
}
|
||
|
||
Future<void> _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<void> _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<void> _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);
|
||
}
|
||
} |