diff --git a/lib/models/news_details_data.dart b/lib/models/news_details_data.dart index 1b603bd..75430e6 100644 --- a/lib/models/news_details_data.dart +++ b/lib/models/news_details_data.dart @@ -1,4 +1,5 @@ import 'package:didvan/models/content.dart'; +import 'package:didvan/models/item_overview.dart'; import 'package:didvan/models/tag.dart'; class NewsDetailsData { @@ -12,6 +13,7 @@ class NewsDetailsData { final int order; final List tags; final List contents; + final List relatedContents = []; NewsDetailsData({ required this.id, diff --git a/lib/models/radar_details_data.dart b/lib/models/radar_details_data.dart index fb493e3..70be8d0 100644 --- a/lib/models/radar_details_data.dart +++ b/lib/models/radar_details_data.dart @@ -1,4 +1,5 @@ import 'package:didvan/models/category.dart'; +import 'package:didvan/models/item_overview.dart'; import 'content.dart'; import 'tag.dart'; @@ -17,6 +18,7 @@ class RadarDetailsData { final List contents; final List categories; final int order; + final List relatedContents = []; RadarDetailsData({ required this.id, diff --git a/lib/pages/home/news/news_details/news_details.dart b/lib/pages/home/news/news_details/news_details.dart index 9b55a2d..ddff4cd 100644 --- a/lib/pages/home/news/news_details/news_details.dart +++ b/lib/pages/home/news/news_details/news_details.dart @@ -20,6 +20,13 @@ class _NewsDetailsState extends State { @override void initState() { final state = context.read(); + _scrollController.addListener(() { + if (_scrollController.position.pixels > + _scrollController.position.maxScrollExtent - 200 && + !state.relatedQueue.contains(state.currentNews.id)) { + state.getRelatedContents(); + } + }); state.args = widget.pageData['args'] ?? const NewsRequestArgs(page: 0); Future.delayed(Duration.zero, () { state.getNewsDetails(widget.pageData['id']); diff --git a/lib/pages/home/news/news_details/news_details_state.dart b/lib/pages/home/news/news_details/news_details_state.dart index ba97db3..ece6105 100644 --- a/lib/pages/home/news/news_details/news_details_state.dart +++ b/lib/pages/home/news/news_details/news_details_state.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:math'; import 'package:didvan/models/enums.dart'; +import 'package:didvan/models/item_overview.dart'; import 'package:didvan/models/news_details_data.dart'; import 'package:didvan/models/requests/news.dart'; import 'package:didvan/providers/core_provider.dart'; @@ -14,6 +15,7 @@ class NewsDetailsState extends CoreProvier { late final NewsRequestArgs args; late Timer _trackingTimer; int _trackingTimerCounter = 0; + final List relatedQueue = []; int _currentIndex = 0; int get currentIndex => _currentIndex; @@ -92,6 +94,25 @@ class NewsDetailsState extends CoreProvier { _trackingTimerCounter = 0; } + Future getRelatedContents() async { + if (currentNews.relatedContents.isNotEmpty) return; + relatedQueue.add(currentNews.id); + final service = RequestService( + RequestHelper.tag(currentNews.tags.map((tag) => tag.id).toList())); + 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() { _trackingTimer.cancel(); diff --git a/lib/pages/home/radar/radar_details/radar_details.dart b/lib/pages/home/radar/radar_details/radar_details.dart index 6b27000..010cabe 100644 --- a/lib/pages/home/radar/radar_details/radar_details.dart +++ b/lib/pages/home/radar/radar_details/radar_details.dart @@ -20,6 +20,13 @@ class _RadarDetailsState extends State { @override void initState() { final state = context.read(); + _scrollController.addListener(() { + if (_scrollController.position.pixels > + _scrollController.position.maxScrollExtent - 200 && + !state.relatedQueue.contains(state.currentRadar.id)) { + state.getRelatedContents(); + } + }); state.args = widget.pageData['args'] ?? const RadarRequestArgs(page: 0); Future.delayed(Duration.zero, () { state.getRadarDetails(widget.pageData['id']); diff --git a/lib/pages/home/radar/radar_details/radar_details_state.dart b/lib/pages/home/radar/radar_details/radar_details_state.dart index 61f9ccf..5d9a439 100644 --- a/lib/pages/home/radar/radar_details/radar_details_state.dart +++ b/lib/pages/home/radar/radar_details/radar_details_state.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:math'; import 'package:didvan/models/enums.dart'; +import 'package:didvan/models/item_overview.dart'; import 'package:didvan/models/radar_details_data.dart'; import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/providers/core_provider.dart'; @@ -14,6 +15,7 @@ class RadarDetailsState extends CoreProvier { int _trackingTimerCounter = 0; late final int initialIndex; late final RadarRequestArgs args; + final List relatedQueue = []; int _currentIndex = 0; int get currentIndex => _currentIndex; @@ -83,6 +85,25 @@ class RadarDetailsState extends CoreProvier { } } + Future getRelatedContents() async { + if (currentRadar.relatedContents.isNotEmpty) return; + relatedQueue.add(currentRadar.id); + final service = RequestService( + RequestHelper.tag(currentRadar.tags.map((tag) => tag.id).toList())); + await service.httpGet(); + if (service.isSuccess) { + final relateds = service.result['contents']; + for (var i = 0; i < relateds.length; i++) { + radars + .where((element) => element != null) + .firstWhere((element) => element!.id == currentRadar.id)! + .relatedContents + .add(OverviewData.fromJson(relateds[i])); + } + notifyListeners(); + } + } + bool exists(RadarDetailsData? radar) => radars.any((r) => radar != null && r != null && r.id == radar.id); diff --git a/lib/pages/home/widgets/multitype_overview.dart b/lib/pages/home/widgets/multitype_overview.dart index ef0a944..4cd5f54 100644 --- a/lib/pages/home/widgets/multitype_overview.dart +++ b/lib/pages/home/widgets/multitype_overview.dart @@ -72,6 +72,8 @@ class MultitypeOverview extends StatelessWidget { DidvanText( item.title, style: Theme.of(context).textTheme.bodyText1, + maxLines: 2, + overflow: TextOverflow.ellipsis, ), Row( children: [ diff --git a/lib/services/network/request_helper.dart b/lib/services/network/request_helper.dart index b9f2876..5baf2fb 100644 --- a/lib/services/network/request_helper.dart +++ b/lib/services/network/request_helper.dart @@ -19,6 +19,13 @@ class RequestHelper { static const String directTypes = baseUrl + '/direct/types'; static String direct(int id) => _baseUserUrl + '/direct/$id'; + static String tag(List ids) => + baseUrl + + '/tag' + + _urlConcatGenerator([ + const MapEntry('limit', '3'), + MapEntry('tags', _urlListConcatGenerator(ids)) + ]); static String markRadar(int id) => _baseRadarUrl + '/$id/mark'; static String radarComments(int id) => _baseRadarUrl + '/$id/comments'; diff --git a/lib/widgets/didvan/page_view.dart b/lib/widgets/didvan/page_view.dart index efbe19b..77f91ad 100644 --- a/lib/widgets/didvan/page_view.dart +++ b/lib/widgets/didvan/page_view.dart @@ -1,8 +1,10 @@ import 'package:carousel_slider/carousel_slider.dart'; +import 'package:didvan/pages/home/widgets/multitype_overview.dart'; import 'package:didvan/utils/date_time.dart'; import 'package:didvan/widgets/didvan/card.dart'; import 'package:didvan/widgets/didvan/divider.dart'; import 'package:didvan/widgets/didvan/text.dart'; +import 'package:didvan/widgets/item_title.dart'; import 'package:didvan/widgets/skeleton_image.dart'; import 'package:didvan/pages/home/widgets/tag_item.dart'; import 'package:flutter/material.dart'; @@ -109,9 +111,40 @@ class _DidvanPageViewState extends State { ), ), const Padding( - padding: EdgeInsets.symmetric(horizontal: 16), - child: DidvanDivider(), + padding: EdgeInsets.only( + left: 16, + right: 16, + top: 16, + ), + child: DidvanDivider(verticalPadding: 0), ), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 16.0), + child: ItemTitle(title: 'مطالب مشابه'), + ), + if (item.relatedContents.isEmpty) + for (var i = 0; i < 3; i++) + Padding( + padding: const EdgeInsets.only( + bottom: 8, + left: 16, + right: 16, + ), + child: MultitypeOverview.placeholder, + ), + for (var i = 0; i < item.relatedContents.length; i++) + Padding( + padding: const EdgeInsets.only( + bottom: 8, + left: 16, + right: 16, + ), + child: MultitypeOverview( + item: item.relatedContents[i], + onMarkChanged: (id, value) {}, + ), + ), + const SizedBox(height: 8), ], ); },