diff --git a/lib/pages/home/radar/radar_details/radar_details.dart b/lib/pages/home/radar/radar_details/radar_details.dart index bcdfcae..e2896b1 100644 --- a/lib/pages/home/radar/radar_details/radar_details.dart +++ b/lib/pages/home/radar/radar_details/radar_details.dart @@ -1,76 +1,71 @@ +import 'package:didvan/models/requests/radar.dart'; +import 'package:didvan/pages/home/radar/radar_details/radar_details_state.dart'; import 'package:didvan/widgets/didvan/page_view.dart'; -import 'package:didvan/widgets/didvan/text.dart'; import 'package:didvan/widgets/floating_navigation_bar.dart'; -import 'package:didvan/widgets/skeletun_image.dart'; +import 'package:didvan/widgets/state_handlers/state_handler.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; -class RadarDetails extends StatelessWidget { - const RadarDetails({Key? key}) : super(key: key); +class RadarDetails extends StatefulWidget { + final Map pageData; + const RadarDetails({Key? key, required this.pageData}) : super(key: key); + + @override + State createState() => _RadarDetailsState(); +} + +class _RadarDetailsState extends State { + final ScrollController _scrollController = ScrollController(); + + @override + void initState() { + final state = context.read(); + state.args = widget.pageData['args'] ?? const RadarRequestArgs(page: 0); + Future.delayed(Duration.zero, () { + state.getRadarDetails(widget.pageData['id']); + }); + super.initState(); + } @override Widget build(BuildContext context) { return Scaffold( - body: Stack( - children: [ - DidvanPageView( - pages: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const SkeletonImage( - imageUrl: 'https://wallpapercave.com/wp/wp9373116.jpg', - width: double.infinity, - height: 200, + body: Consumer( + builder: (context, state, child) => StateHandler( + onRetry: () => state.getRadarDetails(state.currentRadar.id), + state: state, + builder: (context, state) => Stack( + children: [ + if (state.radars.isNotEmpty) + DidvanPageView( + isRadar: true, + initialIndex: state.initialIndex, + onPageChanged: _onPageChanged, + scrollController: _scrollController, + items: state.radars, + ), + if (state.radars.isNotEmpty) + Positioned( + bottom: 0, + left: 0, + right: 0, + child: FloatingNavigationBar( + radar: state.currentRadar, + scrollController: _scrollController, ), - const SizedBox(height: 20), - for (var i = 0; i < 10; i++) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Builder( - builder: (context) { - switch (i) { - case 0: - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - DidvanText( - 'تحلیل شکاف فناوری صنعت فولاد ایران', - style: - Theme.of(context).textTheme.bodyText1, - ), - const SizedBox(height: 8), - const DidvanText( - 'پایگاه خبری معدن نیوز - 2 ساعت پیش', - ), - const SizedBox(height: 8), - ], - ); - default: - return const Padding( - padding: EdgeInsets.only(bottom: 8), - child: DidvanText( - 'این سایت امروز (شنبه) تیم منتخب قاره آسیا در سال ۲۰۲۱ میلادی را معرفی کرد که از ایران، سردار آزمون و محمد حسین کنعانی‌زادگان در ترکیب اصلی و مهدی طارمی و سیدمجید حسینی در جمع بازیکنان ذخیره دیده می‌شوند.', - ), - ); - } - }, - ), - ), - const SizedBox(height: 20), - ], - ), + ), ], ), - const Positioned( - bottom: 0, - left: 0, - right: 0, - child: FloatingNavigationBar( - isRadar: true, - ), - ), - ], + ), ), ); } + + void _onPageChanged(int index) { + final state = context.read(); + state.getRadarDetails( + state.radars[index]!.id, + isForward: state.currentIndex < index, + ); + } } 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 c4e2fc5..9ecbf05 100644 --- a/lib/pages/home/radar/radar_details/radar_details_state.dart +++ b/lib/pages/home/radar/radar_details/radar_details_state.dart @@ -1,3 +1,81 @@ -import 'package:didvan/providers/core_provider.dart'; +import 'dart:math'; -class RadarDetailsState extends CoreProvier {} +import 'package:didvan/models/enums.dart'; +import 'package:didvan/models/radar_details_data.dart'; +import 'package:didvan/models/requests/radar.dart'; +import 'package:didvan/providers/core_provider.dart'; +import 'package:didvan/services/network/request.dart'; +import 'package:didvan/services/network/request_helper.dart'; + +class RadarDetailsState extends CoreProvier { + final List radars = []; + late final int initialIndex; + late final RadarRequestArgs args; + + int _currentIndex = 0; + int get currentIndex => _currentIndex; + + RadarDetailsData get currentRadar => radars[_currentIndex]!; + + Future getRadarDetails(int id, {bool? isForward}) async { + if (isForward == null) { + appState = AppState.busy; + } + final service = RequestService(RequestHelper.radarDetails(id, args)); + await service.httpGet(); + if (service.isSuccess) { + final result = service.result; + RadarDetailsData? prevRadar; + final radar = RadarDetailsData.fromJson(result['radar']); + if (args.page == 0) { + radars.add(radar); + initialIndex = 0; + appState = AppState.idle; + return; + } + + if (result['prevRadar'].isNotEmpty) { + prevRadar = RadarDetailsData.fromJson(result['prevRadar']); + } + + RadarDetailsData? nextRadar; + if (result['nextRadar'].isNotEmpty) { + nextRadar = RadarDetailsData.fromJson(result['nextRadar']); + } + if (isForward == null) { + radars.addAll(List.generate(max(radar.order - 2, 0), (index) => null)); + if (prevRadar != null) { + radars.add(prevRadar); + } + radars.add(radar); + if (nextRadar != null) { + radars.add(nextRadar); + } + _currentIndex = initialIndex = radar.order - 1; + } else if (isForward) { + if (!exists(nextRadar) && nextRadar != null) { + radars.add(nextRadar); + } + _currentIndex++; + } else if (!isForward) { + if (!exists(prevRadar) && prevRadar != null) { + radars[_currentIndex - 2] = prevRadar; + } + _currentIndex--; + } + appState = AppState.idle; + return; + } + if (isForward == null) { + appState = AppState.failed; + } + } + + bool exists(RadarDetailsData? radar) => + radars.any((r) => radar != null && r != null && r.id == radar.id); + + void onCommentAdded(int id) { + radars.firstWhere((radar) => radar!.id == id)!.comments++; + notifyListeners(); + } +} diff --git a/lib/pages/home/radar/radar_state.dart b/lib/pages/home/radar/radar_state.dart index f6dcd6f..822d5b9 100644 --- a/lib/pages/home/radar/radar_state.dart +++ b/lib/pages/home/radar/radar_state.dart @@ -78,7 +78,7 @@ class RadarState extends CoreProvier { appState = AppState.failed; } - Future markRadar(int id) async { + Future mark(int id) async { radars.firstWhere((element) => element.id == id).marked = true; notifyListeners(); _markQueue.add(MapEntry(id, true)); @@ -94,7 +94,7 @@ class RadarState extends CoreProvier { }); } - Future unMarkRadar(int id) async { + Future unMark(int id) async { radars.firstWhere((element) => element.id == id).marked = false; notifyListeners(); _markQueue.add(MapEntry(id, false)); @@ -110,6 +110,11 @@ class RadarState extends CoreProvier { }); } + void onCommentAdded(int id) { + radars.firstWhere((radar) => radar.id == id).comments++; + notifyListeners(); + } + void init() { resetFilters(true); Future.delayed(Duration.zero, () { diff --git a/lib/pages/home/radar/widgets/radar_item.dart b/lib/pages/home/radar/widgets/radar_item.dart index ffa6a1e..6af1f4a 100644 --- a/lib/pages/home/radar/widgets/radar_item.dart +++ b/lib/pages/home/radar/widgets/radar_item.dart @@ -1,8 +1,10 @@ import 'package:didvan/config/theme_data.dart'; import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/models/radar_overview.dart'; +import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/pages/home/radar/radar_state.dart'; import 'package:didvan/routes/routes.dart'; +import 'package:didvan/utils/date_time.dart'; import 'package:didvan/widgets/bookmark_button.dart'; import 'package:didvan/widgets/didvan/card.dart'; import 'package:didvan/widgets/didvan/divider.dart'; @@ -10,7 +12,6 @@ import 'package:didvan/widgets/didvan/icon_button.dart'; import 'package:didvan/widgets/didvan/text.dart'; import 'package:didvan/widgets/skeleton_image.dart'; import 'package:flutter/material.dart'; -import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:provider/provider.dart'; class RadarItem extends StatelessWidget { @@ -26,6 +27,13 @@ class RadarItem extends StatelessWidget { arguments: { 'state': state, 'id': radar.id, + 'args': RadarRequestArgs( + page: state.page, + categories: state.selectedCats.map((e) => e.id).toList(), + endDate: state.endDate, + search: state.search, + startDate: state.startDate, + ) }, ), child: Column( @@ -75,7 +83,7 @@ class RadarItem extends StatelessWidget { ), const Spacer(), DidvanText( - '${DateTime.parse(radar.createdAt).toPersianDateStr()} | خواندن ${radar.timeToRead} دقیقه', + '${DateTimeUtils.momentGenerator(radar.createdAt)} | خواندن ${radar.timeToRead} دقیقه', style: Theme.of(context).textTheme.overline, color: Theme.of(context).colorScheme.caption, ), @@ -91,8 +99,8 @@ class RadarItem extends StatelessWidget { children: [ BookmarkButton( value: radar.marked, - onMark: () => state.markRadar(radar.id), - onUnmark: () => state.unMarkRadar(radar.id), + onMark: () => state.mark(radar.id), + onUnmark: () => state.unMark(radar.id), ), const Spacer(), if (radar.comments != 0) DidvanText(radar.comments.toString()), @@ -106,6 +114,7 @@ class RadarItem extends StatelessWidget { 'isRadar': true, 'title': radar.title, 'id': radar.id, + 'onCommentAdded': () => state.onCommentAdded(radar.id) }, ), ),