import 'dart:async'; import 'dart:math'; import 'package:didvan/models/enums.dart'; import 'package:didvan/models/news_details_data.dart'; import 'package:didvan/models/overview_data.dart'; import 'package:didvan/models/requests/news.dart'; import 'package:didvan/providers/core.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/network/request_helper.dart'; class NewsDetailsState extends CoreProvier { final List news = []; late final int initialIndex; late final NewsRequestArgs args; late Timer _trackingTimer; int _trackingTimerCounter = 0; bool isFetchingNewItem = false; final List relatedQueue = []; int _currentIndex = 0; int get currentIndex => _currentIndex; NewsDetailsData get currentNews => news[_currentIndex]!; Future getNewsDetails(int id, {bool? isForward}) async { if (isForward == null) { appState = AppState.busy; } else { isFetchingNewItem = true; notifyListeners(); } final service = RequestService(RequestHelper.newsDetails(id, args)); await service.httpGet(); _handleTracking(sendRequest: isForward != null); if (service.isSuccess) { final result = service.result; final newsItem = NewsDetailsData.fromJson(result['news']); if (args.page == 0) { news.add(newsItem); initialIndex = 0; appState = AppState.idle; return; } NewsDetailsData? prevNews; if (result['prevNews'].isNotEmpty) { prevNews = NewsDetailsData.fromJson(result['prevNews']); } NewsDetailsData? nextNews; if (result['nextNews'].isNotEmpty) { nextNews = NewsDetailsData.fromJson(result['nextNews']); } if (isForward == null) { news.addAll(List.generate(max(newsItem.order - 2, 0), (index) => null)); if (prevNews != null) { news.add(prevNews); } news.add(newsItem); if (nextNews != null) { news.add(nextNews); } _currentIndex = initialIndex = newsItem.order - 1; } else if (isForward) { if (!exists(nextNews) && nextNews != null) { news.add(nextNews); } _currentIndex++; } else if (!isForward) { if (!exists(prevNews) && prevNews != null) { news[_currentIndex - 2] = prevNews; } _currentIndex--; } isFetchingNewItem = false; appState = AppState.idle; return; } if (isForward == null) { appState = AppState.failed; } } bool exists(NewsDetailsData? newsItem) => news.any((n) => newsItem != null && n != null && n.id == newsItem.id); void onCommentsChanged(int count) { news.firstWhere((item) => item?.id == currentNews.id)!.comments = count; notifyListeners(); } Future _handleTracking({bool sendRequest = true}) async { if (!sendRequest) { _trackingTimerCounter = 0; _trackingTimer = Timer.periodic(const Duration(seconds: 1), (timer) { _trackingTimerCounter++; }); return; } final service = RequestService( RequestHelper.tracking(currentNews.id, 'news'), body: { 'sec': _trackingTimerCounter, }, ); service.put(); _trackingTimerCounter = 0; _trackingTimer.cancel(); } Future getRelatedContents() async { if (currentNews.relatedContents.isNotEmpty) return; relatedQueue.add(currentNews.id); final service = RequestService(RequestHelper.tag( ids: currentNews.tags.map((tag) => tag.id).toList(), itemId: currentNews.id, type: 'news', )); await service.httpGet(); if (service.isSuccess) { final relateds = service.result['contents']; for (var i = 0; i < relateds.length; i++) { news .where((element) => element != null) .firstWhere((element) => element!.id == currentNews.id)! .relatedContents .add(OverviewData.fromJson(relateds[i])); } notifyListeners(); } } @override void dispose() { _handleTracking(sendRequest: true); _trackingTimer.cancel(); super.dispose(); } }