didvan-app/lib/views/home/news/news_details/news_details_state.dart

139 lines
4.1 KiB
Dart

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<NewsDetailsData?> news = [];
late final int initialIndex;
late final NewsRequestArgs args;
late Timer _trackingTimer;
int _trackingTimerCounter = 0;
bool isFetchingNewItem = false;
final List<int> relatedQueue = [];
int _currentIndex = 0;
int get currentIndex => _currentIndex;
NewsDetailsData get currentNews => news[_currentIndex]!;
Future<void> 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<void> _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<void> 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();
}
}