diff --git a/lib/models/home_page_content/result.dart b/lib/models/home_page_content/result.dart new file mode 100644 index 0000000..6d2846a --- /dev/null +++ b/lib/models/home_page_content/result.dart @@ -0,0 +1,27 @@ +class MainPageResultType { + final int id; + final String title; + final String image; + final String link; + final String createdAt; + final String type; + + MainPageResultType({ + required this.id, + required this.title, + required this.image, + required this.link, + required this.createdAt, + required this.type, + }); + + factory MainPageResultType.fromJson(Map json) => + MainPageResultType( + id: json['id'], + title: json['title'], + image: json['image'] ?? 'https://wallpapercave.com/fwp/wp12977378.jpg', + link: json['link'], + createdAt: json['createdAt'], + type: json['type'], + ); +} diff --git a/lib/models/view/app_bar_data.dart b/lib/models/view/app_bar_data.dart index 85b6e91..5e3ff55 100644 --- a/lib/models/view/app_bar_data.dart +++ b/lib/models/view/app_bar_data.dart @@ -6,6 +6,7 @@ class AppBarData { final bool hasBack; final Widget? trailing; final bool isSmall; + final bool? hasElevation; AppBarData({ this.title, @@ -13,5 +14,6 @@ class AppBarData { this.hasBack = false, this.trailing, this.isSmall = false, + this.hasElevation = true, }); } diff --git a/lib/providers/user.dart b/lib/providers/user.dart index 335c7fc..a253a3b 100644 --- a/lib/providers/user.dart +++ b/lib/providers/user.dart @@ -161,21 +161,28 @@ class UserProvider extends CoreProvier { ); } - static Future changeItemMark(String type, int id, bool value) async { + static Future changeItemMark(String type, int id, bool? value, + {String? description}) async { _itemMarkQueue.add({ 'type': type, 'id': id, 'value': value, + 'description': description, }); Future.delayed(const Duration(milliseconds: 500), () async { final lastChange = _itemMarkQueue.lastWhereOrNull((item) => item['id'] == id); if (lastChange == null) return; - final service = RequestService(RequestHelper.editItemBookmark(type, id)); - if (lastChange['value']) { + final service = RequestService( + RequestHelper.editItemBookmark(type, id), + body: {'description': lastChange['description']}, + ); + if (lastChange['value'] == true) { await service.post(); - } else { + } else if (lastChange['value'] == false) { await service.delete(); + } else { + service.put(); } _itemMarkQueue.removeWhere((element) => element['id'] == id); }); diff --git a/lib/services/network/request_helper.dart b/lib/services/network/request_helper.dart index d0ab7aa..2214268 100644 --- a/lib/services/network/request_helper.dart +++ b/lib/services/network/request_helper.dart @@ -18,7 +18,7 @@ class RequestHelper { String? startDate, String? endDate, String? search, - List? types, + List? types, }) => '$_baseHomeUrl/search${_urlConcatGenerator([ MapEntry('page', page), @@ -27,6 +27,16 @@ class RequestHelper { MapEntry('q', search), MapEntry('type', _urlListConcatGenerator(types)), ])}'; + static String searchMarks({ + required int page, + String? search, + List? types, + }) => + '$_baseHomeUrl/mark${_urlConcatGenerator([ + MapEntry('page', page), + MapEntry('q', search), + MapEntry('type', _urlListConcatGenerator(types)), + ])}'; static const String confirmUsername = '$_baseUserUrl/confirmUsername'; static const String changePassword = '$_baseUserUrl/changePassword'; diff --git a/lib/views/home/bookmarks/filtered_bookmark/filtered_bookmark.dart b/lib/views/home/bookmarks/filtered_bookmark/filtered_bookmark.dart index 2609b28..e07da8f 100644 --- a/lib/views/home/bookmarks/filtered_bookmark/filtered_bookmark.dart +++ b/lib/views/home/bookmarks/filtered_bookmark/filtered_bookmark.dart @@ -1,10 +1,7 @@ -import 'package:didvan/models/requests/studio.dart'; import 'package:didvan/models/view/app_bar_data.dart'; import 'package:didvan/views/home/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart'; -import 'package:didvan/views/widgets/overview/news.dart'; -import 'package:didvan/views/widgets/overview/podcast.dart'; +import 'package:didvan/views/widgets/overview/multitype.dart'; import 'package:didvan/views/widgets/overview/radar.dart'; -import 'package:didvan/views/widgets/overview/video.dart'; import 'package:didvan/views/widgets/didvan/scaffold.dart'; import 'package:didvan/views/widgets/state_handlers/empty_list.dart'; import 'package:didvan/views/widgets/state_handlers/sliver_state_handler.dart'; @@ -32,13 +29,15 @@ class _FilteredBookmarksState extends State { String get _appBarTitle { switch (context.read().type) { case 'radar': - return 'تحلیل‌های رادار'; + return 'پویش افق'; case 'news': - return 'اخبار'; + return 'دنیای فولاد'; case 'video': - return 'ویدئو‌ها'; + return 'ویدئوکست‌ها'; case 'podcast': return 'پادکست‌ها'; + case 'new-radar': + return 'تحلیل‌های رادار'; default: return 'پادکست‌ها'; } @@ -63,37 +62,46 @@ class _FilteredBookmarksState extends State { state.getBookmarks(page: state.page + 1); } index--; - if (state.type == 'radar') { - return RadarOverview( - radar: state.bookmarks[index], - onMarkChanged: _onBookmarkChanged, - onCommentsChanged: state.onCommentsChanged, - hasUnmarkConfirmation: true, - ); - } - if (state.type == 'news') { - return NewsOverview( - news: state.bookmarks[index], - onMarkChanged: _onBookmarkChanged, - hasUnmarkConfirmation: true, - ); - } - if (state.type == 'podcast') { - return PodcastOverview( - studioRequestArgs: - const StudioRequestArgs(page: 0, type: 'podcast'), - podcast: state.bookmarks[index], - onMarkChanged: _onBookmarkChanged, - hasUnmarkConfirmation: true, - ); - } - return VideoOverview( - studioRequestArgs: - const StudioRequestArgs(page: 0, type: 'video'), - video: state.bookmarks[index], - onMarkChanged: _onBookmarkChanged, - hasUnmarkConfirmation: true, + return MultitypeOverview( + item: state.bookmarks[index], + enableCaption: true, + onMarkChanged: (id, value) => _onBookmarkChanged( + id, + value, + true, + ), ); + // if (state.type == 'radar') { + // return RadarOverview( + // radar: state.bookmarks[index], + // onMarkChanged: _onBookmarkChanged, + // onCommentsChanged: state.onCommentsChanged, + // hasUnmarkConfirmation: true, + // ); + // } + // if (state.type == 'news') { + // return NewsOverview( + // news: state.bookmarks[index], + // onMarkChanged: _onBookmarkChanged, + // hasUnmarkConfirmation: true, + // ); + // } + // if (state.type == 'podcast') { + // return PodcastOverview( + // studioRequestArgs: + // const StudioRequestArgs(page: 0, type: 'podcast'), + // podcast: state.bookmarks[index], + // onMarkChanged: _onBookmarkChanged, + // hasUnmarkConfirmation: true, + // ); + // } + // return VideoOverview( + // studioRequestArgs: + // const StudioRequestArgs(page: 0, type: 'video'), + // video: state.bookmarks[index], + // onMarkChanged: _onBookmarkChanged, + // hasUnmarkConfirmation: true, + // ); }, childCount: state.bookmarks.length, onRetry: () => state.getBookmarks(page: state.page), diff --git a/lib/views/home/home.dart b/lib/views/home/home.dart index 8fe6d96..e1bfe68 100644 --- a/lib/views/home/home.dart +++ b/lib/views/home/home.dart @@ -27,6 +27,7 @@ class _HomeState extends State with SingleTickerProviderStateMixin { final state = context.read(); DesignConfig.updateSystemUiOverlayStyle(); _tabController = TabController(length: 4, vsync: this, initialIndex: 0); + state.tabController = _tabController; _tabController.addListener(() { state.currentPageIndex = _tabController.index; }); @@ -43,22 +44,26 @@ class _HomeState extends State with SingleTickerProviderStateMixin { @override Widget build(BuildContext context) { return Scaffold( - appBar: const LogoAppBar(), + appBar: LogoAppBar(), body: Consumer( builder: (context, state, child) => AnimatedCrossFade( duration: DesignConfig.lowAnimationDuration, - crossFadeState: state.showSearchPage + crossFadeState: state.filtering ? CrossFadeState.showSecond : CrossFadeState.showFirst, - firstChild: TabBarView( - physics: const NeverScrollableScrollPhysics(), - controller: _tabController, - children: const [ - MainPage(), - Statistic(), - CategoriesPage(), - Bookmarks(), - ], + firstChild: SizedBox( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: TabBarView( + physics: const NeverScrollableScrollPhysics(), + controller: _tabController, + children: const [ + MainPage(), + Statistic(), + CategoriesPage(), + Bookmarks(), + ], + ), ), secondChild: const SearchPage(), ), diff --git a/lib/views/home/home_state.dart b/lib/views/home/home_state.dart index a835725..422127d 100644 --- a/lib/views/home/home_state.dart +++ b/lib/views/home/home_state.dart @@ -2,10 +2,13 @@ import 'dart:async'; import 'package:didvan/constants/assets.dart'; import 'package:didvan/models/category.dart'; +import 'package:didvan/models/enums.dart'; +import 'package:didvan/models/overview_data.dart'; import 'package:didvan/providers/core.dart'; import 'package:didvan/routes/routes.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/network/request_helper.dart'; +import 'package:flutter/material.dart'; class MenuItemType { final String label; @@ -25,6 +28,24 @@ class HomeState extends CoreProvier { String lastSearch = ''; bool _showSearchPage = false; Timer? timer; + String? startDate; + String? endDate; + int page = 1; + int lastPage = 1; + final List selectedCats = []; + final List results = []; + late TabController tabController; + + void resetFilters(bool isInit) { + startDate = null; + endDate = null; + selectedCats.clear(); + search = ''; + lastSearch = ''; + if (!isInit) { + searchAll(page: 1); + } + } set showSearchPage(bool value) { _showSearchPage = value; @@ -43,12 +64,76 @@ class HomeState extends CoreProvier { List menuItems = []; List categories = []; - Future searchAll({required int page}) async { + bool get filtering => + selectedCats.isNotEmpty || + startDate != null || + endDate != null || + search.isNotEmpty; + + Future searchMarks({required int page}) async { + this.page = page; + if (page == 1) { + results.clear(); + appState = AppState.busy; + } lastSearch = search; final service = RequestService( - RequestHelper.searchAll(page: page, search: search), + RequestHelper.searchAll( + page: page, + search: search, + endDate: endDate, + types: selectedCats.map((e) => e.id).toList(), + startDate: startDate, + ), ); await service.httpGet(); + if (service.isSuccess) { + lastPage = service.result['lastPage']; + results.addAll( + List.from( + service.result['contents'].map( + (e) => OverviewData.fromJson(e), + ), + ), + ); + lastPage = service.result['lastPage']; + appState = AppState.idle; + return; + } + appState = AppState.failed; + } + + Future searchAll({required int page}) async { + this.page = page; + if (page == 1) { + results.clear(); + appState = AppState.busy; + } + lastSearch = search; + final service = RequestService( + RequestHelper.searchAll( + page: page, + search: search, + endDate: endDate, + types: selectedCats.map((e) => e.id).toList(), + startDate: startDate, + ), + ); + await service.httpGet(); + if (service.isSuccess) { + lastPage = service.result['lastPage']; + results.addAll( + List.from( + service.result['contents'].map( + (e) => OverviewData.fromJson(e), + ), + ), + ); + lastPage = service.result['lastPage']; + appState = AppState.idle; + return; + } + appState = AppState.failed; } void refresh() { @@ -62,7 +147,7 @@ class HomeState extends CoreProvier { ), MenuItemType( label: 'پویش افق', - asset: Assets.fooladWorld, + asset: Assets.ofogh, link: Routes.radars, ), MenuItemType( diff --git a/lib/views/home/main/main_page.dart b/lib/views/home/main/main_page.dart index fb8eb86..4d545e2 100644 --- a/lib/views/home/main/main_page.dart +++ b/lib/views/home/main/main_page.dart @@ -134,18 +134,19 @@ class _MainPageSection extends StatelessWidget { ], ), ), - DidvanSlider( - height: 260, - itemCount: list.contents.length, - viewportFraction: 0.65, - itemBuilder: (context, index, realIndex) => Padding( - padding: const EdgeInsets.symmetric(horizontal: 4), - child: MainPageGeneralItem( - content: list.contents[index], - type: list.type, + if (list.type != 'podcast') + DidvanSlider( + height: 260, + itemCount: list.contents.length, + viewportFraction: 0.65, + itemBuilder: (context, index, realIndex) => Padding( + padding: const EdgeInsets.symmetric(horizontal: 4), + child: MainPageGeneralItem( + content: list.contents[index], + type: list.type, + ), ), ), - ), // if (list.type == 'radar') // DidvanSlider( // height: 260, @@ -171,21 +172,24 @@ class _MainPageSection extends StatelessWidget { // ), // ), if (list.type == 'podcast') - Column( - children: list.contents - .map( - (e) => Padding( - padding: const EdgeInsets.only( - bottom: 12, - left: 28, - right: 28, + Padding( + padding: const EdgeInsets.only(top: 28), + child: Column( + children: list.contents + .map( + (e) => Padding( + padding: const EdgeInsets.only( + bottom: 12, + left: 28, + right: 28, + ), + child: MainPagePodcastItem( + content: e, + ), ), - child: MainPagePodcastItem( - content: e, - ), - ), - ) - .toList(), + ) + .toList(), + ), ), // if (list.type != 'news' && // list.type != 'radar' && diff --git a/lib/views/home/main/main_page_state.dart b/lib/views/home/main/main_page_state.dart index c4890ee..2853db0 100644 --- a/lib/views/home/main/main_page_state.dart +++ b/lib/views/home/main/main_page_state.dart @@ -1,8 +1,14 @@ import 'package:didvan/models/enums.dart'; import 'package:didvan/models/home_page_content/home_page_content.dart'; +import 'package:didvan/models/requests/news.dart'; +import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/providers/core.dart'; +import 'package:didvan/routes/routes.dart'; import 'package:didvan/services/network/request.dart'; import 'package:didvan/services/network/request_helper.dart'; +import 'package:didvan/utils/action_sheet.dart'; +import 'package:flutter/material.dart'; +import 'package:url_launcher/url_launcher_string.dart'; class MainPageState extends CoreProvier { late MainPageContent content; @@ -22,4 +28,63 @@ class MainPageState extends CoreProvier { _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(); + } + + void navigationHandler( + String type, + int id, + String? link, + ) { + link = link ?? ''; + dynamic args; + switch (type) { + case 'news': + { + link = Routes.newsDetails; + args = { + 'onMarkChanged': (id, value) => markChangeHandler(type, id, value), + 'id': id, + 'args': const NewsRequestArgs(page: 0), + 'hasUnmarkConfirmation': false, + }; + break; + } + case 'radar': + { + link = Routes.radarDetails; + args = { + 'onMarkChanged': (id, value) => markChangeHandler(type, id, value), + 'id': id, + 'args': const RadarRequestArgs(page: 0), + 'hasUnmarkConfirmation': false, + }; + break; + } + case 'video': + { + link = Routes.studioDetails; + args = { + type: 'podcast', + id: 'id', + }; + break; + } + } + if (link == '') { + return; + } + if (link.startsWith('http')) { + launchUrlString('$link?accessToken=${RequestService.token}'); + return; + } + Navigator.of(ActionSheetUtils.context).pushNamed(link, arguments: args); + } } diff --git a/lib/views/home/main/widgets/general_item.dart b/lib/views/home/main/widgets/general_item.dart index 1136516..79990a5 100644 --- a/lib/views/home/main/widgets/general_item.dart +++ b/lib/views/home/main/widgets/general_item.dart @@ -3,11 +3,15 @@ import 'package:didvan/constants/app_icons.dart'; import 'package:didvan/models/home_page_content/content.dart'; import 'package:didvan/providers/user.dart'; import 'package:didvan/utils/date_time.dart'; +import 'package:didvan/views/home/home_state.dart'; +import 'package:didvan/views/home/main/main_page_state.dart'; import 'package:didvan/views/widgets/didvan/card.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/skeleton_image.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:persian_number_utility/persian_number_utility.dart'; +import 'package:provider/provider.dart'; class MainPageGeneralItem extends StatefulWidget { final MainPageContentType content; @@ -74,79 +78,140 @@ class _MainPageGeneralItemState extends State { @override Widget build(BuildContext context) { - return DidvanCard( - padding: EdgeInsets.zero, - child: Column( - children: [ - SkeletonImage( - imageUrl: widget.content.image, - height: 140, - width: double.infinity, - borderRadius: const BorderRadius.vertical(top: Radius.circular(10)), + return GestureDetector( + onTap: () => context.read().navigationHandler( + widget.type, + widget.content.id, + widget.content.link, ), - Expanded( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: DidvanText( - widget.content.title, - style: Theme.of(context).textTheme.bodyLarge, - maxLines: 2, - overflow: TextOverflow.ellipsis, + child: DidvanCard( + padding: EdgeInsets.zero, + child: Column( + children: [ + Stack( + children: [ + SkeletonImage( + imageUrl: widget.content.image, + height: 140, + width: double.infinity, + borderRadius: + const BorderRadius.vertical(top: Radius.circular(10)), + ), + if (widget.type == 'video') + Positioned.fill( + child: Center( + child: Container( + height: 36, + width: 36, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: Theme.of(context) + .colorScheme + .secondary + .withOpacity(0.7), + ), + child: Icon( + DidvanIcons.play_solid, + color: Theme.of(context).colorScheme.white, + ), + ), ), ), - if (widget.type == 'radar' || widget.type == 'video') - Row( - children: [ - for (int i = 0; - i < widget.content.subtitles.length; - i++) - Expanded(child: _subtitleItem(i, context)) - ], - ) - else - Column( - children: [ - for (int i = 0; - i < widget.content.subtitles.length; - i++) - _subtitleItem(i, context) - ], - ) - ], + if (widget.type == 'radar') + Positioned( + left: 0, + bottom: 0, + child: Container( + width: 36, + height: 36, + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + borderRadius: const BorderRadius.only( + topRight: Radius.circular(10), + ), + color: Theme.of(context).colorScheme.surface, + ), + child: SvgPicture.asset( + context + .read() + .categories + .firstWhere( + (element) => + element.id.toString() == + widget.content.subtitles[2], + ) + .asset ?? + '', + ), + ), + ), + ], + ), + Expanded( + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: DidvanText( + widget.content.title, + style: Theme.of(context).textTheme.bodyLarge, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + if (widget.type == 'radar' || widget.type == 'video') + Row( + children: [ + for (int i = 0; + i < widget.content.subtitles.length; + i++) + Expanded(child: _subtitleItem(i, context)) + ], + ) + else + Column( + children: [ + for (int i = 0; + i < widget.content.subtitles.length; + i++) + _subtitleItem(i, context) + ], + ) + ], + ), ), ), - ), - GestureDetector( - onTap: _onMarkChange, - child: Padding( - padding: const EdgeInsets.only(left: 12, right: 12, bottom: 8), - child: Row( - children: [ - Icon( - widget.content.marked - ? DidvanIcons.bookmark_solid - : DidvanIcons.bookmark_regular, - color: widget.content.marked - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.caption, - ), - DidvanText( - widget.content.marked - ? 'به رصدهای من افزوده شد!' - : 'افزودن به رصدهای من', - color: widget.content.marked - ? Theme.of(context).colorScheme.secondary - : Theme.of(context).colorScheme.caption, - ), - ], + GestureDetector( + onTap: _onMarkChange, + child: Padding( + padding: const EdgeInsets.only(left: 12, right: 12, bottom: 8), + child: Row( + children: [ + Icon( + widget.content.marked + ? DidvanIcons.bookmark_solid + : DidvanIcons.bookmark_regular, + color: widget.content.marked + ? Theme.of(context).colorScheme.secondary + : Theme.of(context).colorScheme.caption, + ), + DidvanText( + widget.content.marked + ? 'به رصدهای من افزوده شد!' + : 'افزودن به رصدهای من', + color: widget.content.marked + ? Theme.of(context).colorScheme.secondary + : Theme.of(context).colorScheme.caption, + ), + ], + ), ), - ), - ) - ], + ) + ], + ), ), ); } diff --git a/lib/views/home/search/search.dart b/lib/views/home/search/search.dart index 51acfc4..0a0591b 100644 --- a/lib/views/home/search/search.dart +++ b/lib/views/home/search/search.dart @@ -1,10 +1,37 @@ +import 'package:didvan/models/enums.dart'; +import 'package:didvan/views/home/home_state.dart'; +import 'package:didvan/views/home/search/widgets/search_result_item.dart'; +import 'package:didvan/views/widgets/state_handlers/empty_list.dart'; +import 'package:didvan/views/widgets/state_handlers/state_handler.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class SearchPage extends StatelessWidget { const SearchPage({super.key}); @override Widget build(BuildContext context) { - return const Placeholder(); + final state = context.watch(); + return SizedBox( + height: MediaQuery.of(context).size.height, + width: MediaQuery.of(context).size.width, + child: StateHandler( + state: state, + enableEmptyState: + state.appState == AppState.idle && state.results.isEmpty, + emptyState: const EmptyList(), + onRetry: () => state.searchAll(page: state.page), + builder: (context, state) => ListView.builder( + padding: const EdgeInsets.all(16), + itemBuilder: (context, index) => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: SearchResultItem( + item: state.results[index], + ), + ), + itemCount: state.results.length, + ), + ), + ); } } diff --git a/lib/views/home/search/widgets/search_result_item.dart b/lib/views/home/search/widgets/search_result_item.dart new file mode 100644 index 0000000..8aec79a --- /dev/null +++ b/lib/views/home/search/widgets/search_result_item.dart @@ -0,0 +1,171 @@ +import 'package:didvan/config/theme_data.dart'; +import 'package:didvan/constants/app_icons.dart'; +import 'package:didvan/models/overview_data.dart'; +import 'package:didvan/models/requests/news.dart'; +import 'package:didvan/models/requests/radar.dart'; +import 'package:didvan/models/requests/studio.dart'; +import 'package:didvan/routes/routes.dart'; +import 'package:didvan/services/media/media.dart'; +import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart'; +import 'package:didvan/views/widgets/didvan/card.dart'; +import 'package:didvan/views/widgets/didvan/text.dart'; +import 'package:didvan/views/widgets/shimmer_placeholder.dart'; +import 'package:didvan/views/widgets/skeleton_image.dart'; +import 'package:flutter/material.dart'; +import 'package:persian_number_utility/persian_number_utility.dart'; +import 'package:provider/provider.dart'; + +class SearchResultItem extends StatelessWidget { + final OverviewData item; + + const SearchResultItem({ + Key? key, + required this.item, + }) : super(key: key); + + get _targetPageArgs { + if (item.type == 'radar') { + return const RadarRequestArgs(page: 0); + } + if (item.type == 'news') { + return const NewsRequestArgs(page: 0); + } + return StudioRequestArgs(page: 0, type: item.type); + } + + String get _targetPageRouteName { + if (item.type == 'radar') { + return Routes.radarDetails; + } + if (item.type == 'news') { + return Routes.newsDetails; + } + return Routes.studioDetails; + } + + IconData get _icon { + if (item.type == 'radar') { + return DidvanIcons.radar_light; + } + if (item.type == 'news') { + return DidvanIcons.news_light; + } + if (item.type == 'video') { + return DidvanIcons.video_light; + } + return DidvanIcons.podcast_light; + } + + @override + Widget build(BuildContext context) { + return DidvanCard( + onTap: () async { + if (item.type == 'podcast') { + final state = context.read(); + await state.getStudioDetails( + item.id, + args: const StudioRequestArgs(page: 0, type: 'podcast'), + ); + MediaService.handleAudioPlayback( + audioSource: item.link, + id: item.id, + isNetworkAudio: true, + isVoiceMessage: false, + ); + return; + } + Navigator.of(context).pushNamed( + _targetPageRouteName, + arguments: { + 'id': item.id, + 'args': _targetPageArgs, + }, + ); + }, + child: Column( + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Stack( + children: [ + SkeletonImage(imageUrl: item.image, height: 80, width: 80), + Container( + padding: + const EdgeInsets.symmetric(vertical: 4, horizontal: 8), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.secondary, + borderRadius: const BorderRadius.horizontal( + left: Radius.circular(10), + ), + ), + child: Icon( + _icon, + color: Theme.of(context).colorScheme.white, + size: 18, + ), + ), + ], + ), + const SizedBox(width: 8), + Expanded( + child: SizedBox( + height: 80, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + DidvanText( + item.title, + style: Theme.of(context).textTheme.bodyLarge, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + Row( + children: [ + const Icon( + DidvanIcons.calendar_day_light, + size: 18, + ), + const SizedBox(width: 4), + DidvanText( + DateTime.parse(item.createdAt).toPersianDateStr(), + style: Theme.of(context).textTheme.labelSmall, + ), + const Spacer(), + ], + ), + ], + ), + ), + ), + ], + ), + ], + ), + ); + } + + static Widget get placeholder => const DidvanCard( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ShimmerPlaceholder(height: 80, width: 80), + SizedBox(width: 8), + SizedBox( + height: 80, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ShimmerPlaceholder(height: 18, width: 150), + SizedBox(height: 8), + ShimmerPlaceholder(height: 18, width: 100), + Spacer(), + ShimmerPlaceholder(height: 14, width: 80), + ], + ), + ), + ], + ), + ); +} diff --git a/lib/views/home/statistic/statistic.dart b/lib/views/home/statistic/statistic.dart index 141534a..5b2370b 100644 --- a/lib/views/home/statistic/statistic.dart +++ b/lib/views/home/statistic/statistic.dart @@ -138,6 +138,7 @@ class _StatisticState extends State { ), if (state.appState != AppState.failed) CategoriesList( + top: 0, categories: state.categories, isColapsed: state.isColapsed, onSelected: (id) { diff --git a/lib/views/home/statistic/statistic_details/statistic_details.dart b/lib/views/home/statistic/statistic_details/statistic_details.dart index e86d279..a76be99 100644 --- a/lib/views/home/statistic/statistic_details/statistic_details.dart +++ b/lib/views/home/statistic/statistic_details/statistic_details.dart @@ -159,6 +159,7 @@ class _StatisticDetailsState extends State { ), const SizedBox(height: 20), CategoriesList( + top: 0, isColapsed: false, isAppBar: false, selectedCats: [state.currentDateRange], diff --git a/lib/views/home/widgets/categories.dart b/lib/views/home/widgets/categories.dart index d151062..1200c81 100644 --- a/lib/views/home/widgets/categories.dart +++ b/lib/views/home/widgets/categories.dart @@ -14,7 +14,9 @@ class MainCategories extends StatelessWidget { if (link.startsWith('http')) { launchUrlString(link); } else if (link.startsWith('tab-')) { - context.read().currentPageIndex = 1; + final state = context.read(); + state.currentPageIndex = 1; + state.tabController.animateTo(1); } else { Navigator.of(context).pushNamed( link.contains('audio') ? link.replaceAll('/audio', '') : link, diff --git a/lib/views/news/news.dart b/lib/views/news/news.dart index c188e57..ea3c1b5 100644 --- a/lib/views/news/news.dart +++ b/lib/views/news/news.dart @@ -41,10 +41,12 @@ class _NewsState extends State { appBarData: AppBarData( title: 'دنیای فولاد', hasBack: true, + hasElevation: false, ), slivers: [ if (state.appState != AppState.failed) SliverAppBar( + backgroundColor: Theme.of(context).colorScheme.surface, scrolledUnderElevation: 0, automaticallyImplyLeading: false, pinned: true, diff --git a/lib/views/podcasts/podcasts_state.dart b/lib/views/podcasts/podcasts_state.dart index 87e4436..3cba203 100644 --- a/lib/views/podcasts/podcasts_state.dart +++ b/lib/views/podcasts/podcasts_state.dart @@ -8,6 +8,7 @@ import 'package:didvan/providers/core.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:collection/collection.dart'; class PodcastsState extends CoreProvier { final List studios = []; @@ -129,7 +130,7 @@ class PodcastsState extends CoreProvier { } Future changeMark(int id, bool value, bool shouldUpdate) async { - studios.firstWhere((element) => element.id == id).marked = value; + studios.firstWhereOrNull((element) => element.id == id)?.marked = value; if (shouldUpdate) { notifyListeners(); } diff --git a/lib/views/radar/radar.dart b/lib/views/radar/radar.dart index f48fcf5..8e3e9f7 100644 --- a/lib/views/radar/radar.dart +++ b/lib/views/radar/radar.dart @@ -8,11 +8,12 @@ import 'package:didvan/models/category.dart'; import 'package:didvan/models/enums.dart'; import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/models/view/action_sheet_data.dart'; +import 'package:didvan/models/view/app_bar_data.dart'; import 'package:didvan/views/radar/radar_state.dart'; import 'package:didvan/views/widgets/categories_gird.dart'; import 'package:didvan/views/widgets/categories_list.dart'; import 'package:didvan/views/widgets/date_picker_button.dart'; -import 'package:didvan/views/widgets/logo_app_bar.dart'; +import 'package:didvan/views/widgets/didvan/scaffold.dart'; import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/views/widgets/overview/radar.dart'; import 'package:didvan/views/widgets/search_field.dart'; @@ -59,23 +60,136 @@ class _RadarState extends State { @override Widget build(BuildContext context) { return Consumer( - builder: (context, state, child) => Stack( + builder: (context, state, child) => DidvanScaffold( + padding: EdgeInsets.zero, + appBarData: AppBarData( + hasBack: true, + hasElevation: false, + title: 'پویش‌های افق', + ), children: [ - CustomScrollView( - physics: _isAnimating - ? const NeverScrollableScrollPhysics() - : const ClampingScrollPhysics(), - controller: _scrollController, - slivers: [ - const SliverToBoxAdapter(child: LogoAppBar()), - if (state.appState != AppState.failed) - SliverPadding( - padding: const EdgeInsets.only( - left: 16, - right: 16, - bottom: 16, + SizedBox( + height: MediaQuery.of(context).size.height, + child: Stack( + children: [ + CustomScrollView( + physics: _isAnimating + ? const NeverScrollableScrollPhysics() + : const ClampingScrollPhysics(), + controller: _scrollController, + slivers: [ + if (!state.filtering && + !state.searching && + state.appState != AppState.failed) + const SliverToBoxAdapter( + child: SizedBox(height: 320), + ), + if (state.appState != AppState.failed) + SliverPadding( + padding: const EdgeInsets.only(right: 16, bottom: 20), + sliver: SliverToBoxAdapter( + child: Align( + alignment: Alignment.centerRight, + child: AnimatedVisibility( + isVisible: !state.isColapsed && + !state.searching && + !state.filtering, + duration: DesignConfig.lowAnimationDuration, + child: DidvanText( + 'آخرین رصد', + style: Theme.of(context).textTheme.titleMedium, + color: Theme.of(context).colorScheme.title, + ), + ), + ), + ), + ), + SliverStateHandler( + onRetry: () => state.getRadars(page: state.page), + state: state, + itemPadding: const EdgeInsets.only( + bottom: 20, + left: 16, + right: 16, + ), + enableEmptyState: state.radars.isEmpty, + emptyState: Padding( + padding: const EdgeInsets.only(bottom: 120), + child: EmptyResult( + onNewSearch: () => _focusNode.requestFocus()), + ), + placeholder: RadarOverview.placeholder, + builder: (context, state, index) { + index += 2; + if (index % 15 == 0 && state.lastPage != state.page) { + state.getRadars(page: state.page + 1); + } + index -= 2; + if (index >= state.radars.length) { + return RadarOverview.placeholder; + } + final radar = state.radars[index]; + return RadarOverview( + radar: radar, + onMarkChanged: state.changeMark, + onCommentsChanged: (id, count) => + state.onCommentsChanged(id, count), + radarRequestArgs: RadarRequestArgs( + page: state.page, + categories: List.from( + state.selectedCats.map((cat) => cat.id)), + endDate: state.endDate, + isSingleItem: false, + search: state.search, + startDate: state.startDate, + ), + ); + }, + childCount: state.radars.length + + (state.lastPage == state.page ? 0 : 3), + ), + if (state.radars.length == 1) + const SliverToBoxAdapter( + child: SizedBox(height: 320), + ), + ], + ), + if (state.appState != AppState.failed) + CategoriesRow1( + topPadding: 212, + rightPadding: 124, + onSelected: _onCategorySelected, + categories: state.categories, + isColapsed: + state.isColapsed || state.searching || state.filtering, ), - sliver: SliverToBoxAdapter( + if (state.appState != AppState.failed) + CategoriesRow2( + categories: state.categories, + isColapsed: + state.isColapsed || state.searching || state.filtering, + onSelected: _onCategorySelected, + ), + if (state.appState != AppState.failed && + !state.searching && + !state.filtering) + CategoriesList( + top: 60, + categories: state.categories, + isColapsed: + state.isColapsed || state.searching || state.filtering, + onSelected: (_) => state.getRadars(page: 1), + selectedCats: state.selectedCats, + ), + if (state.appState != AppState.failed) + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.surface, + borderRadius: const BorderRadius.vertical( + bottom: Radius.circular(12), + ), + ), child: SearchField( focusNode: _focusNode, isFiltered: state.filtering, @@ -84,109 +198,9 @@ class _RadarState extends State { onFilterButtonPressed: _showFilterBottomSheet, ), ), - ), - if (!state.filtering && - !state.searching && - state.appState != AppState.failed) - const SliverToBoxAdapter( - child: SizedBox(height: 276), - ), - if (state.appState != AppState.failed) - SliverPadding( - padding: const EdgeInsets.only(right: 16, bottom: 20), - sliver: SliverToBoxAdapter( - child: Align( - alignment: Alignment.centerRight, - child: AnimatedVisibility( - isVisible: !state.isColapsed && - !state.searching && - !state.filtering, - duration: DesignConfig.lowAnimationDuration, - child: DidvanText( - 'آخرین رصد', - style: Theme.of(context).textTheme.titleMedium, - color: Theme.of(context).colorScheme.title, - ), - ), - ), - ), - ), - SliverStateHandler( - onRetry: () => state.getRadars(page: state.page), - state: state, - itemPadding: const EdgeInsets.only( - bottom: 20, - left: 16, - right: 16, - ), - enableEmptyState: state.radars.isEmpty, - emptyState: Padding( - padding: const EdgeInsets.only(bottom: 120), - child: - EmptyResult(onNewSearch: () => _focusNode.requestFocus()), - ), - placeholder: RadarOverview.placeholder, - builder: (context, state, index) { - index += 2; - if (index % 15 == 0 && state.lastPage != state.page) { - state.getRadars(page: state.page + 1); - } - index -= 2; - if (index >= state.radars.length) { - return RadarOverview.placeholder; - } - final radar = state.radars[index]; - return RadarOverview( - radar: radar, - onMarkChanged: state.changeMark, - onCommentsChanged: (id, count) => - state.onCommentsChanged(id, count), - radarRequestArgs: RadarRequestArgs( - page: state.page, - categories: - List.from(state.selectedCats.map((cat) => cat.id)), - endDate: state.endDate, - isSingleItem: false, - search: state.search, - startDate: state.startDate, - ), - ); - }, - childCount: state.radars.length + - (state.lastPage == state.page ? 0 : 3), - ), - if (state.radars.length == 1) - const SliverToBoxAdapter( - child: SizedBox(height: 320), - ), - ], + ], + ), ), - if (state.appState != AppState.failed) - CategoriesRow1( - topPadding: 300, - rightPadding: 124, - onSelected: _onCategorySelected, - categories: state.categories, - isColapsed: - state.isColapsed || state.searching || state.filtering, - ), - if (state.appState != AppState.failed) - CategoriesRow2( - categories: state.categories, - isColapsed: - state.isColapsed || state.searching || state.filtering, - onSelected: _onCategorySelected, - ), - if (state.appState != AppState.failed && - !state.searching && - !state.filtering) - CategoriesList( - categories: state.categories, - isColapsed: - state.isColapsed || state.searching || state.filtering, - onSelected: (_) => state.getRadars(page: 1), - selectedCats: state.selectedCats, - ), ], ), ); diff --git a/lib/views/widgets/categories_gird.dart b/lib/views/widgets/categories_gird.dart index 4ff4519..7f9b225 100644 --- a/lib/views/widgets/categories_gird.dart +++ b/lib/views/widgets/categories_gird.dart @@ -66,7 +66,7 @@ class CategoriesRow2 extends StatelessWidget { return AnimatedPositioned( curve: Curves.easeIn, duration: DesignConfig.mediumAnimationDuration, - top: isColapsed ? 12 : 176 + d.padding.top, + top: isColapsed ? 12 : 92 + d.padding.top, left: isColapsed ? -d.size.width : 0, right: isColapsed ? d.size.width : 0, child: Row( diff --git a/lib/views/widgets/categories_list.dart b/lib/views/widgets/categories_list.dart index df6e8db..c23fce4 100644 --- a/lib/views/widgets/categories_list.dart +++ b/lib/views/widgets/categories_list.dart @@ -11,6 +11,7 @@ class CategoriesList extends StatefulWidget { final List selectedCats; final List categories; final void Function(int id) onSelected; + final double top; const CategoriesList({ Key? key, required this.isColapsed, @@ -18,6 +19,7 @@ class CategoriesList extends StatefulWidget { required this.categories, required this.onSelected, this.isAppBar = true, + required this.top, }) : super(key: key); @override @@ -73,7 +75,7 @@ class _CategoriesListState extends State { ); if (widget.isAppBar) { return Positioned( - top: 0, + top: widget.top, left: 0, right: 0, child: AnimatedCrossFade( diff --git a/lib/views/widgets/didvan/scaffold.dart b/lib/views/widgets/didvan/scaffold.dart index 83e6c42..7e8ec28 100644 --- a/lib/views/widgets/didvan/scaffold.dart +++ b/lib/views/widgets/didvan/scaffold.dart @@ -89,6 +89,8 @@ class _DidvanScaffoldState extends State { pinned: true, backgroundColor: widget.backgroundColor ?? Theme.of(context).colorScheme.surface, + elevation: + widget.appBarData?.hasElevation == false ? 0 : null, flexibleSpace: DidvanAppBar( appBarData: widget.appBarData!, backgroundColor: widget.backgroundColor ?? diff --git a/lib/views/widgets/logo_app_bar.dart b/lib/views/widgets/logo_app_bar.dart index 19b5821..6203b91 100644 --- a/lib/views/widgets/logo_app_bar.dart +++ b/lib/views/widgets/logo_app_bar.dart @@ -2,11 +2,14 @@ import 'dart:async'; import 'package:didvan/config/theme_data.dart'; import 'package:didvan/constants/app_icons.dart'; -import 'package:didvan/constants/assets.dart'; +import 'package:didvan/models/category.dart'; import 'package:didvan/models/view/action_sheet_data.dart'; import 'package:didvan/routes/routes.dart'; import 'package:didvan/utils/action_sheet.dart'; import 'package:didvan/views/home/home_state.dart'; +import 'package:didvan/views/widgets/date_picker_button.dart'; +import 'package:didvan/views/widgets/didvan/checkbox.dart'; +import 'package:didvan/views/widgets/item_title.dart'; import 'package:didvan/views/widgets/search_field.dart'; import 'package:didvan/views/widgets/didvan/icon_button.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; @@ -14,10 +17,9 @@ import 'package:didvan/views/widgets/logos/didvan_vertical_logo.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:provider/provider.dart'; -import 'package:url_launcher/url_launcher_string.dart'; class LogoAppBar extends StatelessWidget implements PreferredSizeWidget { - const LogoAppBar({Key? key}) : super(key: key); + LogoAppBar({Key? key}) : super(key: key); @override Size get preferredSize => const Size(double.infinity, 144); @@ -64,19 +66,21 @@ class LogoAppBar extends StatelessWidget implements PreferredSizeWidget { DidvanIconButton( icon: DidvanIcons.notification_light, size: 32, - onPressed: () => _handleMenuOpen(context), + onPressed: () => {}, ), ], ), ], ), const SizedBox(height: 16), - SearchField( - title: 'دیدوان', - onChanged: (value) => _onChanged(value, context), - focusNode: FocusNode(), - onFilterButtonPressed: () => _handleMenuOpen(context), - isFiltered: false, + Consumer( + builder: (context, state, child) => SearchField( + title: state.currentPageIndex == 3 ? 'رصدهای من' : 'دیدوان', + onChanged: (value) => _onChanged(value, context), + focusNode: FocusNode(), + onFilterButtonPressed: () => _showFilterBottomSheet(context), + isFiltered: state.filtering && state.search == '', + ), ), ], ), @@ -85,82 +89,167 @@ class LogoAppBar extends StatelessWidget implements PreferredSizeWidget { void _onChanged(String value, BuildContext context) { final state = context.read(); - if (state.currentPageIndex == 3) { - //search bookmarks - } + if (value.length < 3 && value.isNotEmpty || state.lastSearch == value) { return; } state.timer?.cancel(); state.timer = Timer(const Duration(seconds: 1), () { state.search = value; - state.searchAll(page: 1); + if (state.currentPageIndex == 3) { + state.searchMarks(page: 1); + } else { + state.searchAll(page: 1); + } }); } - void _handleMenuOpen(BuildContext context) { - ActionSheetUtils.showBottomSheet( + final categoryFilters = [ + CategoryData(id: 1, label: 'پویش افق'), + CategoryData(id: 2, label: 'دنیای فولاد'), + CategoryData(id: 3, label: 'ویدئوکست'), + CategoryData(id: 4, label: 'پادکست'), + CategoryData(id: 1, label: 'تحلیل‌های راداری'), + CategoryData(id: 1, label: 'سها'), + ]; + + Future _showFilterBottomSheet(BuildContext context) async { + final state = context.read(); + await ActionSheetUtils.showBottomSheet( data: ActionSheetData( + title: 'فیلتر جستجو', + smallDismissButton: true, + titleIcon: DidvanIcons.filter_regular, + dismissTitle: 'حذف فیلتر', + confrimTitle: 'نمایش نتایج', + onDismissed: () => state.resetFilters(false), + onConfirmed: () => state.searchAll(page: 1), content: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, + if (state.currentPageIndex != 3) ...[ + ItemTitle( + title: 'تاریخ ایجاد', + style: Theme.of(context).textTheme.bodyMedium, + icon: DidvanIcons.calendar_range_regular, + ), + const SizedBox(height: 8), + StatefulBuilder( + builder: (context, setState) => Row( + children: [ + DatePickerButton( + initialValue: state.startDate, + emptyText: 'از تاریخ', + onPicked: (date) => + setState(() => state.startDate = date), + lastDate: state.endDate, + ), + const SizedBox(width: 8), + DatePickerButton( + initialValue: state.endDate, + emptyText: 'تا تاریخ', + onPicked: (date) => setState(() => state.endDate = date), + firstDate: state.startDate, + ), + ], + ), + ), + const SizedBox(height: 28), + ], + ItemTitle( + title: 'دسته بندی', + icon: DidvanIcons.radar_regular, + style: Theme.of(context).textTheme.bodyMedium, + ), + const SizedBox(height: 12), + Wrap( children: [ - SvgPicture.asset( - Assets.strategicRadarIcon, - width: 48, - height: 48, - ), - const SizedBox(width: 4), - DidvanText( - 'سامانه رادارهای استراتژیک', - style: Theme.of(context).textTheme.titleMedium, - ), + for (var i = 0; i < categoryFilters.length; i++) + SizedBox( + width: (MediaQuery.of(context).size.width - 40) / 2, + child: DidvanCheckbox( + title: categoryFilters[i].label, + value: state.selectedCats.contains(state.categories[i]), + onChanged: (value) { + if (value) { + state.selectedCats.add(state.categories[i]); + return; + } + state.selectedCats.remove(state.categories[i]); + }, + ), + ), ], ), - const SizedBox(height: 16), - _BottomSheetItem( - icon: Assets.progressRadarIcon, - title: 'رادار روند', - enabled: true, - onTap: () { - launchUrlString( - 'https://trend.didvan.app/', - mode: LaunchMode.inAppWebView, - ); - }, - ), - const SizedBox(height: 16), - _BottomSheetItem( - icon: Assets.techRadarIcon, - title: 'رادار تکنولوژی', - onTap: () {}, - ), - const SizedBox(height: 16), - _BottomSheetItem( - icon: Assets.riskRadarIcon, - title: 'رادار ریسک', - enabled: true, - onTap: () { - launchUrlString( - 'https://risk.didvan.app/', - mode: LaunchMode.inAppWebView, - ); - }, - ), - const SizedBox(height: 16), - _BottomSheetItem( - icon: Assets.startupRadarIcon, - title: 'رادار استارت‌آپ', - onTap: () {}, - ), ], ), - hasConfirmButton: false, - hasDismissButton: false, ), ); } + + // void _handleMenuOpen(BuildContext context) { + // ActionSheetUtils.showBottomSheet( + // data: ActionSheetData( + // content: Column( + // children: [ + // Row( + // crossAxisAlignment: CrossAxisAlignment.center, + // children: [ + // SvgPicture.asset( + // Assets.strategicRadarIcon, + // width: 48, + // height: 48, + // ), + // const SizedBox(width: 4), + // DidvanText( + // 'سامانه رادارهای استراتژیک', + // style: Theme.of(context).textTheme.titleMedium, + // ), + // ], + // ), + // const SizedBox(height: 16), + // _BottomSheetItem( + // icon: Assets.progressRadarIcon, + // title: 'رادار روند', + // enabled: true, + // onTap: () { + // launchUrlString( + // 'https://trend.didvan.app/', + // mode: LaunchMode.inAppWebView, + // ); + // }, + // ), + // const SizedBox(height: 16), + // _BottomSheetItem( + // icon: Assets.techRadarIcon, + // title: 'رادار تکنولوژی', + // onTap: () {}, + // ), + // const SizedBox(height: 16), + // _BottomSheetItem( + // icon: Assets.riskRadarIcon, + // title: 'رادار ریسک', + // enabled: true, + // onTap: () { + // launchUrlString( + // 'https://risk.didvan.app/', + // mode: LaunchMode.inAppWebView, + // ); + // }, + // ), + // const SizedBox(height: 16), + // _BottomSheetItem( + // icon: Assets.startupRadarIcon, + // title: 'رادار استارت‌آپ', + // onTap: () {}, + // ), + // ], + // ), + // hasConfirmButton: false, + // hasDismissButton: false, + // ), + // ); + // } } class _BottomSheetItem extends StatelessWidget { diff --git a/lib/views/widgets/overview/multitype.dart b/lib/views/widgets/overview/multitype.dart index 6a0916b..4610b4c 100644 --- a/lib/views/widgets/overview/multitype.dart +++ b/lib/views/widgets/overview/multitype.dart @@ -4,7 +4,9 @@ import 'package:didvan/models/overview_data.dart'; import 'package:didvan/models/requests/news.dart'; import 'package:didvan/models/requests/radar.dart'; import 'package:didvan/models/requests/studio.dart'; +import 'package:didvan/providers/user.dart'; import 'package:didvan/routes/routes.dart'; +import 'package:didvan/services/media/media.dart'; import 'package:didvan/utils/date_time.dart'; import 'package:didvan/views/podcasts/studio_details/studio_details_state.dart'; import 'package:didvan/views/widgets/didvan/card.dart'; @@ -66,12 +68,19 @@ class MultitypeOverview extends StatelessWidget { @override Widget build(BuildContext context) { return DidvanCard( - onTap: () { + onTap: () async { if (item.type == 'podcast') { - context.read().getStudioDetails( - item.id, - args: StudioRequestArgs(page: 0, type: item.type), - ); + final state = context.read(); + await state.getStudioDetails( + item.id, + args: const StudioRequestArgs(page: 0, type: 'podcast'), + ); + MediaService.handleAudioPlayback( + audioSource: item.link, + id: item.id, + isNetworkAudio: true, + isVoiceMessage: false, + ); return; } Navigator.of(context).pushNamed( @@ -196,8 +205,14 @@ class MultitypeOverview extends StatelessWidget { ), DidvanTextField( disableBorders: true, + initialValue: item.description, hintText: 'برای اضافه کردن یادداشت لمس کنید.', - onChanged: (value) {}, + onChanged: (value) => UserProvider.changeItemMark( + item.type, + item.id, + null, + description: value, + ), isSmall: true, ), ], diff --git a/pubspec.lock b/pubspec.lock index 5bd1bfc..c0dc14f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -131,7 +131,7 @@ packages: source: hosted version: "1.1.1" collection: - dependency: transitive + dependency: "direct main" description: name: collection sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 diff --git a/pubspec.yaml b/pubspec.yaml index 8b8d714..cf76f67 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -68,6 +68,7 @@ dependencies: url: https://github.com/tintran-dev/betterplayer.git assets_audio_player: ^3.1.1 fl_chart: ^0.63.0 + collection: ^1.17.2 dev_dependencies: flutter_test: