From c282921b2b093b8ff980523c31201a392d771882 Mon Sep 17 00:00:00 2001 From: MohammadTaha Basiri Date: Sat, 29 Jan 2022 14:06:53 +0330 Subject: [PATCH] bookmarks (basic) --- .../settings/bookmarks/bookmark_state.dart | 68 +++++++ .../home/settings/bookmarks/bookmarks.dart | 188 ++++++++++++++++++ .../filtered_bookmark/filtered_bookmark.dart | 138 +++++++++++++ 3 files changed, 394 insertions(+) create mode 100644 lib/pages/home/settings/bookmarks/bookmark_state.dart create mode 100644 lib/pages/home/settings/bookmarks/bookmarks.dart create mode 100644 lib/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart diff --git a/lib/pages/home/settings/bookmarks/bookmark_state.dart b/lib/pages/home/settings/bookmarks/bookmark_state.dart new file mode 100644 index 0000000..edd2310 --- /dev/null +++ b/lib/pages/home/settings/bookmarks/bookmark_state.dart @@ -0,0 +1,68 @@ +import 'package:didvan/models/enums.dart'; +import 'package:didvan/models/item_overview.dart'; +import 'package:didvan/providers/core_provider.dart'; +import 'package:didvan/services/network/request.dart'; +import 'package:didvan/services/network/request_helper.dart'; + +class BookmarksState extends CoreProvier { + final List bookmarks = []; + final List filterdBookmarks = []; + String search = ''; + String lastSearch = ''; + + String? groupName; + + bool get searching => search != ''; + + Future getBookmarks() async { + if (search != '') { + lastSearch = search; + } + appState = AppState.busy; + final service = RequestService(RequestHelper.bookmarks(groupName)); + await service.httpGet(); + String resultKey; + switch (groupName) { + case 'radar': + resultKey = 'radars'; + break; + case 'news': + resultKey = groupName!; + break; + default: + resultKey = 'contents'; + } + if (service.isSuccess) { + final marks = service.result[resultKey]; + if (groupName == null) { + bookmarks.clear(); + for (var i = 0; i < marks.length; i++) { + bookmarks.add(ItemOverview.fromJson(marks[i])); + } + } else { + filterdBookmarks.clear(); + for (var i = 0; i < marks.length; i++) { + filterdBookmarks.add(ItemOverview.fromJson(marks[i])); + } + } + + appState = AppState.idle; + return; + } + appState = AppState.failed; + } + + void unMark(int id) { + bookmarks.removeWhere((element) => element.id == id); + filterdBookmarks.removeWhere((element) => element.id == id); + notifyListeners(); + final service = RequestService(RequestHelper.markRadar(id)); + service.delete(); + } + + void onCommentsChanged(int id, int value) { + bookmarks.firstWhere((radar) => radar.id == id).comments = value; + filterdBookmarks.firstWhere((radar) => radar.id == id).comments = value; + notifyListeners(); + } +} diff --git a/lib/pages/home/settings/bookmarks/bookmarks.dart b/lib/pages/home/settings/bookmarks/bookmarks.dart new file mode 100644 index 0000000..d6526b0 --- /dev/null +++ b/lib/pages/home/settings/bookmarks/bookmarks.dart @@ -0,0 +1,188 @@ +import 'dart:async'; + +import 'package:didvan/models/view/app_bar_data.dart'; +import 'package:didvan/pages/home/settings/bookmarks/bookmark_state.dart'; +import 'package:didvan/widgets/didvan/card.dart'; +import 'package:didvan/widgets/didvan/divider.dart'; +import 'package:didvan/widgets/didvan/scaffold.dart'; +import 'package:didvan/widgets/multitype_item.dart'; +import 'package:didvan/widgets/search_field.dart'; +import 'package:didvan/widgets/shimmer_placeholder.dart'; +import 'package:didvan/widgets/state_handlers/empty_list.dart'; +import 'package:didvan/widgets/state_handlers/empty_result.dart'; +import 'package:didvan/widgets/state_handlers/sliver_state_handler.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class Bookmarks extends StatefulWidget { + const Bookmarks({Key? key}) : super(key: key); + + @override + State createState() => _BookmarksState(); +} + +class _BookmarksState extends State { + final _focuseNode = FocusNode(); + Timer? _timer; + + @override + void initState() { + Future.delayed(Duration.zero, () { + context.read().getBookmarks(); + }); + super.initState(); + } + + @override + Widget build(BuildContext context) { + final state = context.watch(); + return DidvanScaffold( + appBarData: AppBarData( + title: 'نشان شده‌ها', + hasBack: true, + ), + children: [ + SearchField( + title: 'نشان شده‌ها', + onChanged: _onChanged, + focusNode: _focuseNode, + ), + const SizedBox(height: 16), + // AnimatedVisibility( + // duration: DesignConfig.lowAnimationDuration, + // isVisible: !state.searching, + // child: DidvanCard( + // child: Column( + // children: [ + // MenuItem( + // onTap: () => _onCategorySelected('radar'), + // title: 'تحلیل‌های رادار', + // icon: DidvanIcons.radar_regular, + // iconSize: 24, + // ), + // const DidvanDivider(), + // MenuItem( + // onTap: () => _onCategorySelected('news'), + // title: 'اخبار', + // icon: DidvanIcons.news_regular, + // iconSize: 24, + // ), + // const DidvanDivider(), + // MenuItem( + // onTap: () => _onCategorySelected('video'), + // title: 'ویدئو‌ها', + // icon: DidvanIcons.video_regular, + // iconSize: 24, + // ), + // const DidvanDivider(), + // MenuItem( + // onTap: () => _onCategorySelected('podcast'), + // title: 'پادکست‌ها', + // icon: DidvanIcons.podcast_regular, + // iconSize: 24, + // ), + // ], + // ), + // ), + // ), + // Align( + // alignment: Alignment.centerRight, + // child: AnimatedVisibility( + // duration: DesignConfig.lowAnimationDuration, + // isVisible: !state.searching, + // child: const ItemTitle(title: 'آخرین نشان نشده‌ها'), + // ), + // ), + ], + slivers: [ + SliverStateHandler( + state: state, + // centerEmptyState: state.searching, + builder: (context, state, index) => MultitypeItem( + item: state.bookmarks[index], + ), + placeholder: const _NewsOverviewPlaceholder(), + itemPadding: const EdgeInsets.only(bottom: 8), + emptyState: state.searching + ? EmptyResult(onNewSearch: _focuseNode.requestFocus) + : const EmptyList(), + enableEmptyState: state.bookmarks.isEmpty, + childCount: state.bookmarks.length, + onRetry: state.getBookmarks, + ), + ], + ); + } + + // void _onCategorySelected(String? type) { + // FocusScope.of(context).unfocus(); + // final state = context.read(); + // state.groupName = type; + // Navigator.of(context).pushNamed(Routes.filteredBookmarks, arguments: state); + // } + + void _onChanged(String value) { + final state = context.read(); + if (value.length < 4 && value.isNotEmpty || state.lastSearch == value) { + return; + } + _timer?.cancel(); + _timer = Timer(const Duration(seconds: 1), () { + state.search = value; + state.getBookmarks(); + }); + } +} + +class _NewsOverviewPlaceholder extends StatelessWidget { + const _NewsOverviewPlaceholder({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return DidvanCard( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ShimmerPlaceholder(height: 64, width: 64), + const SizedBox(width: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: const [ + ShimmerPlaceholder(height: 18, width: 200), + SizedBox(height: 8), + ShimmerPlaceholder(height: 18, width: 100), + ], + ), + ], + ), + const SizedBox(height: 12), + const ShimmerPlaceholder( + height: 16, + width: double.infinity, + ), + const SizedBox(height: 8), + const ShimmerPlaceholder( + height: 16, + width: double.infinity, + ), + const SizedBox(height: 8), + const ShimmerPlaceholder( + height: 16, + width: 100, + ), + const DidvanDivider(verticalPadding: 8), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: const [ + ShimmerPlaceholder(height: 12, width: 150), + ShimmerPlaceholder(height: 24, width: 24), + ], + ), + ], + ), + ); + } +} diff --git a/lib/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart b/lib/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart new file mode 100644 index 0000000..9b5fa6e --- /dev/null +++ b/lib/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart @@ -0,0 +1,138 @@ +import 'package:didvan/models/view/app_bar_data.dart'; +import 'package:didvan/pages/home/widgets/radar_overview.dart'; +import 'package:didvan/pages/home/settings/bookmarks/bookmark_state.dart'; +import 'package:didvan/widgets/didvan/card.dart'; +import 'package:didvan/widgets/didvan/divider.dart'; +import 'package:didvan/widgets/didvan/scaffold.dart'; +import 'package:didvan/widgets/shimmer_placeholder.dart'; +import 'package:didvan/widgets/state_handlers/empty_list.dart'; +import 'package:didvan/widgets/state_handlers/sliver_state_handler.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +class FilteredBookmarks extends StatefulWidget { + const FilteredBookmarks({Key? key}) : super(key: key); + + @override + _FilteredBookmarksState createState() => _FilteredBookmarksState(); +} + +class _FilteredBookmarksState extends State { + @override + void initState() { + Future.delayed(Duration.zero, context.read().getBookmarks); + super.initState(); + } + + String get _appBarTitle { + switch (context.read().groupName) { + case 'radar': + return 'تحلیل‌های رادار'; + case 'news': + return 'اخبار'; + case 'video': + return 'ویدئو‌ها'; + case 'podcast': + return 'پادکست‌ها'; + default: + return 'پادکست‌ها'; + } + } + + @override + Widget build(BuildContext context) { + return DidvanScaffold( + appBarData: AppBarData(title: _appBarTitle), + slivers: [ + Consumer( + builder: (context, state, child) => + SliverStateHandler( + state: state, + enableEmptyState: state.filterdBookmarks.isEmpty, + itemPadding: const EdgeInsets.only(bottom: 8), + placeholder: const _RadarOverviewPlaceholder(), + emptyState: const EmptyList(), + builder: (context, state, index) => RadarOverview( + radar: state.filterdBookmarks[index], + onMarkChanged: (value) {}, + onCommentsChanged: (count) => state.onCommentsChanged( + state.filterdBookmarks[index].id, + count, + ), + ), + childCount: state.filterdBookmarks.length, + onRetry: state.getBookmarks, + ), + ), + ], + ); + } +} + +class _RadarOverviewPlaceholder extends StatelessWidget { + const _RadarOverviewPlaceholder({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return DidvanCard( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ShimmerPlaceholder( + width: 200, + height: 16, + ), + const SizedBox(height: 8), + const AspectRatio(aspectRatio: 16 / 9, child: ShimmerPlaceholder()), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: const [ + ShimmerPlaceholder( + height: 12, + width: 70, + ), + ShimmerPlaceholder( + height: 12, + width: 70, + ), + ], + ), + const SizedBox(height: 8), + const ShimmerPlaceholder( + height: 16, + ), + const SizedBox(height: 8), + const ShimmerPlaceholder( + height: 16, + ), + const SizedBox(height: 8), + const ShimmerPlaceholder( + height: 16, + ), + const DidvanDivider(), + Row( + children: const [ + ShimmerPlaceholder( + height: 32, + width: 32, + ), + Spacer(), + ShimmerPlaceholder( + height: 32, + width: 32, + ), + SizedBox(width: 16), + ShimmerPlaceholder( + height: 32, + width: 32, + ), + ], + ), + ], + ), + ); + } +}