D1APP-67 bookmarks
This commit is contained in:
parent
3b3cdd20d0
commit
afc9c7bafe
|
|
@ -1,62 +1,26 @@
|
|||
import 'package:didvan/models/category.dart';
|
||||
|
||||
class ItemOverview {
|
||||
class OverviewData {
|
||||
final int id;
|
||||
final String title;
|
||||
final String image;
|
||||
final String description;
|
||||
final int? timeToRead;
|
||||
final String? reference;
|
||||
final bool? forManagers;
|
||||
final String createdAt;
|
||||
final String? type;
|
||||
final List<Category>? categories;
|
||||
int? comments;
|
||||
|
||||
ItemOverview({
|
||||
const OverviewData({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.image,
|
||||
required this.description,
|
||||
required this.timeToRead,
|
||||
required this.reference,
|
||||
required this.forManagers,
|
||||
required this.createdAt,
|
||||
required this.type,
|
||||
required this.categories,
|
||||
required this.comments,
|
||||
});
|
||||
|
||||
factory ItemOverview.fromJson(Map<String, dynamic> json) => ItemOverview(
|
||||
factory OverviewData.fromJson(Map<String, dynamic> json) => OverviewData(
|
||||
id: json['id'],
|
||||
title: json['title'],
|
||||
image: json['image'],
|
||||
description: json['description'],
|
||||
timeToRead: json['timeToRead'],
|
||||
reference: json['reference'],
|
||||
forManagers: json['forManagers'],
|
||||
createdAt: json['createdAt'],
|
||||
type: json['type'],
|
||||
comments: json['comments'],
|
||||
categories: json['categories'] == null
|
||||
? null
|
||||
: List<Category>.from(
|
||||
json['categories'].map(
|
||||
(cat) => Category.fromJson(cat),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'title': title,
|
||||
'image': image,
|
||||
'description': description,
|
||||
'timeToRead': timeToRead,
|
||||
'reference': reference,
|
||||
'forManagers': forManagers,
|
||||
'createdAt': createdAt,
|
||||
'type': type,
|
||||
'categories': categories?.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,25 @@
|
|||
class NewsOverviewData {
|
||||
final int id;
|
||||
final String title;
|
||||
import 'package:didvan/models/item_overview.dart';
|
||||
|
||||
class NewsOverviewData extends OverviewData {
|
||||
final String reference;
|
||||
final String description;
|
||||
final String image;
|
||||
final String createdAt;
|
||||
bool marked;
|
||||
|
||||
NewsOverviewData({
|
||||
required this.id,
|
||||
required this.title,
|
||||
required this.reference,
|
||||
required this.description,
|
||||
required this.image,
|
||||
required this.createdAt,
|
||||
required this.marked,
|
||||
});
|
||||
required id,
|
||||
required createdAt,
|
||||
required description,
|
||||
required title,
|
||||
required image,
|
||||
}) : super(
|
||||
createdAt: createdAt,
|
||||
description: description,
|
||||
id: id,
|
||||
image: image,
|
||||
title: title,
|
||||
type: 'news',
|
||||
);
|
||||
|
||||
factory NewsOverviewData.fromJson(Map<String, dynamic> json) =>
|
||||
NewsOverviewData(
|
||||
|
|
@ -25,16 +29,6 @@ class NewsOverviewData {
|
|||
description: json['description'],
|
||||
image: json['image'],
|
||||
createdAt: json['createdAt'],
|
||||
marked: json['marked'],
|
||||
marked: json['marked'] ?? true,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'title': title,
|
||||
'reference': reference,
|
||||
'description': description,
|
||||
'image': image,
|
||||
'createdAt': createdAt,
|
||||
'marked': marked,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,29 +1,33 @@
|
|||
import 'package:didvan/models/item_overview.dart';
|
||||
|
||||
import 'category.dart';
|
||||
|
||||
class RadarOverviewData {
|
||||
final int id;
|
||||
final String image;
|
||||
final String title;
|
||||
final String description;
|
||||
final int timeToRead;
|
||||
final String createdAt;
|
||||
class RadarOverviewData extends OverviewData {
|
||||
final bool forManagers;
|
||||
bool marked;
|
||||
final List<Category> categories;
|
||||
final int timeToRead;
|
||||
int comments;
|
||||
bool marked;
|
||||
|
||||
RadarOverviewData({
|
||||
required this.id,
|
||||
required this.image,
|
||||
required this.title,
|
||||
required this.description,
|
||||
required this.timeToRead,
|
||||
required this.createdAt,
|
||||
required this.forManagers,
|
||||
required this.marked,
|
||||
required this.categories,
|
||||
required this.comments,
|
||||
});
|
||||
required this.timeToRead,
|
||||
required this.marked,
|
||||
required createdAt,
|
||||
required description,
|
||||
required id,
|
||||
required image,
|
||||
required title,
|
||||
}) : super(
|
||||
createdAt: createdAt,
|
||||
description: description,
|
||||
id: id,
|
||||
image: image,
|
||||
title: title,
|
||||
type: 'radar',
|
||||
);
|
||||
|
||||
factory RadarOverviewData.fromJson(Map<String, dynamic> json) =>
|
||||
RadarOverviewData(
|
||||
|
|
@ -42,17 +46,4 @@ class RadarOverviewData {
|
|||
),
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'id': id,
|
||||
'image': image,
|
||||
'title': title,
|
||||
'description': description,
|
||||
'timeToRead': timeToRead,
|
||||
'createdAt': createdAt,
|
||||
'forManagers': forManagers,
|
||||
'marked': marked,
|
||||
'comment': comments,
|
||||
'categories': categories.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ class ActionSheetData {
|
|||
final bool withoutButtonMode;
|
||||
final bool smallDismissButton;
|
||||
|
||||
ActionSheetData({
|
||||
const ActionSheetData({
|
||||
required this.content,
|
||||
required this.title,
|
||||
this.confrimTitle,
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@ import 'package:didvan/pages/home/widgets/date_picker_button.dart';
|
|||
import 'package:didvan/widgets/item_title.dart';
|
||||
import 'package:didvan/pages/home/widgets/search_field.dart';
|
||||
import 'package:didvan/pages/home/widgets/logo_app_bar.dart';
|
||||
import 'package:didvan/widgets/didvan/card.dart';
|
||||
import 'package:didvan/widgets/didvan/divider.dart';
|
||||
import 'package:didvan/widgets/shimmer_placeholder.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';
|
||||
|
|
@ -76,7 +73,7 @@ class _NewsState extends State<News> {
|
|||
),
|
||||
childCount: state.news.length,
|
||||
itemPadding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
|
||||
placeholder: const _NewsOverviewPlaceholder(),
|
||||
placeholder: NewsOverview.placeholder,
|
||||
),
|
||||
],
|
||||
);
|
||||
|
|
@ -141,56 +138,3 @@ class _NewsState extends State<News> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:didvan/models/requests/news.dart';
|
||||
import 'package:didvan/pages/home/news/news_details/news_details_state.dart';
|
||||
import 'package:didvan/widgets/didvan/page_view.dart';
|
||||
import 'package:didvan/pages/home/widgets/floating_navigation_bar.dart';
|
||||
|
|
@ -19,7 +20,7 @@ class _NewsDetailsState extends State<NewsDetails> {
|
|||
@override
|
||||
void initState() {
|
||||
final state = context.read<NewsDetailsState>();
|
||||
state.args = widget.pageData['args'];
|
||||
state.args = widget.pageData['args'] ?? const NewsRequestArgs(page: 0);
|
||||
Future.delayed(Duration.zero, () {
|
||||
state.getNewsDetails(widget.pageData['id']);
|
||||
});
|
||||
|
|
@ -49,6 +50,8 @@ class _NewsDetailsState extends State<NewsDetails> {
|
|||
left: 0,
|
||||
right: 0,
|
||||
child: FloatingNavigationBar(
|
||||
hasUnmarkConfirmation:
|
||||
widget.pageData['hasUnmarkConfirmation'],
|
||||
scrollController: _scrollController,
|
||||
comments: state.currentNews.comments,
|
||||
id: state.currentNews.id,
|
||||
|
|
|
|||
|
|
@ -29,11 +29,17 @@ class NewsDetailsState extends CoreProvier {
|
|||
_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']);
|
||||
}
|
||||
final newsItem = NewsDetailsData.fromJson(result['news']);
|
||||
NewsDetailsData? nextNews;
|
||||
if (result['nextNews'].isNotEmpty) {
|
||||
nextNews = NewsDetailsData.fromJson(result['nextNews']);
|
||||
|
|
|
|||
|
|
@ -18,12 +18,9 @@ import 'package:didvan/pages/home/widgets/search_field.dart';
|
|||
import 'package:didvan/pages/home/widgets/logo_app_bar.dart';
|
||||
import 'package:didvan/utils/action_sheet.dart';
|
||||
import 'package:didvan/pages/home/widgets/date_picker_button.dart';
|
||||
import 'package:didvan/widgets/didvan/card.dart';
|
||||
import 'package:didvan/widgets/didvan/checkbox.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/shimmer_placeholder.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';
|
||||
|
|
@ -129,7 +126,7 @@ class _RadarState extends State<Radar> {
|
|||
child:
|
||||
EmptyResult(onNewSearch: () => _focusNode.requestFocus()),
|
||||
),
|
||||
placeholder: const _RadarOverviewPlaceholder(),
|
||||
placeholder: RadarOverview.placeholder,
|
||||
builder: (context, state, index) {
|
||||
final radar = state.radars[index];
|
||||
return RadarOverview(
|
||||
|
|
@ -286,71 +283,3 @@ class _RadarState extends State<Radar> {
|
|||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ class _RadarDetailsState extends State<RadarDetails> {
|
|||
return Scaffold(
|
||||
body: Consumer<RadarDetailsState>(
|
||||
builder: (context, state, child) => StateHandler<RadarDetailsState>(
|
||||
onRetry: () => state.getRadarDetails(state.currentRadar.id),
|
||||
onRetry: () => state.getRadarDetails(widget.pageData['id']),
|
||||
state: state,
|
||||
builder: (context, state) => Stack(
|
||||
children: [
|
||||
|
|
@ -50,12 +50,15 @@ class _RadarDetailsState extends State<RadarDetails> {
|
|||
left: 0,
|
||||
right: 0,
|
||||
child: FloatingNavigationBar(
|
||||
hasUnmarkConfirmation:
|
||||
widget.pageData['hasUnmarkConfirmation'],
|
||||
comments: state.currentRadar.comments,
|
||||
id: state.currentRadar.id,
|
||||
isRadar: true,
|
||||
marked: state.currentRadar.marked,
|
||||
title: state.currentRadar.title,
|
||||
onMarkChanged: (value) => widget.pageData['onMarkChanged'](
|
||||
onMarkChanged: (value) =>
|
||||
widget.pageData['onMarkChanged']?.call(
|
||||
state.currentRadar.id,
|
||||
value,
|
||||
),
|
||||
|
|
@ -63,7 +66,7 @@ class _RadarDetailsState extends State<RadarDetails> {
|
|||
scrollController: _scrollController,
|
||||
onCommentsChanged: (count) {
|
||||
state.onCommentsChanged(count);
|
||||
widget.pageData['onCommentsChanged'](
|
||||
widget.pageData['onCommentsChanged']?.call(
|
||||
state.currentRadar.id,
|
||||
count,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,6 @@ class RadarDetailsState extends CoreProvier {
|
|||
_handleTracking(sendRequest: isForward != null);
|
||||
if (service.isSuccess) {
|
||||
final result = service.result;
|
||||
RadarDetailsData? prevRadar;
|
||||
final radar = RadarDetailsData.fromJson(result['radar']);
|
||||
if (args.page == 0) {
|
||||
radars.add(radar);
|
||||
|
|
@ -44,6 +43,7 @@ class RadarDetailsState extends CoreProvier {
|
|||
return;
|
||||
}
|
||||
|
||||
RadarDetailsData? prevRadar;
|
||||
if (result['prevRadar'].isNotEmpty) {
|
||||
prevRadar = RadarDetailsData.fromJson(result['prevRadar']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,15 @@
|
|||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/models/item_overview.dart';
|
||||
import 'package:didvan/providers/core_provider.dart';
|
||||
import 'package:didvan/providers/user_provider.dart';
|
||||
import 'package:didvan/services/network/request.dart';
|
||||
import 'package:didvan/services/network/request_helper.dart';
|
||||
|
||||
class BookmarksState extends CoreProvier {
|
||||
final List<ItemOverview> bookmarks = [];
|
||||
final List<dynamic> filterdBookmarks = [];
|
||||
final List<OverviewData> bookmarks = [];
|
||||
String search = '';
|
||||
String lastSearch = '';
|
||||
|
||||
String? groupName;
|
||||
|
||||
bool get searching => search != '';
|
||||
|
||||
Future<void> getBookmarks() async {
|
||||
|
|
@ -19,50 +17,34 @@ class BookmarksState extends CoreProvier {
|
|||
lastSearch = search;
|
||||
}
|
||||
appState = AppState.busy;
|
||||
final service = RequestService(RequestHelper.bookmarks(groupName));
|
||||
final service = RequestService(RequestHelper.bookmarks());
|
||||
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) {
|
||||
final marks = service.result['contents'];
|
||||
bookmarks.clear();
|
||||
for (var i = 0; i < marks.length; i++) {
|
||||
bookmarks.add(ItemOverview.fromJson(marks[i]));
|
||||
bookmarks.add(OverviewData.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) {
|
||||
void onMarkChanged(int id, bool value) {
|
||||
if (value) return;
|
||||
final type = bookmarks.firstWhere((element) => element.id == id).type;
|
||||
switch (type) {
|
||||
case 'radars':
|
||||
UserProvider.changeRadarMark(id, value);
|
||||
break;
|
||||
case 'news':
|
||||
UserProvider.changeNewsMark(id, value);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/models/view/app_bar_data.dart';
|
||||
import 'package:didvan/pages/home/settings/bookmarks/bookmark_state.dart';
|
||||
import 'package:didvan/pages/home/widgets/menu_item.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/widgets/animated_visibility.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/pages/home/widgets/multitype_item.dart';
|
||||
import 'package:didvan/pages/home/widgets/multitype_overview.dart';
|
||||
import 'package:didvan/pages/home/widgets/search_field.dart';
|
||||
import 'package:didvan/widgets/shimmer_placeholder.dart';
|
||||
import 'package:didvan/widgets/item_title.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';
|
||||
|
|
@ -48,60 +53,62 @@ class _BookmarksState extends State<Bookmarks> {
|
|||
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: 'آخرین نشان نشدهها'),
|
||||
// ),
|
||||
// ),
|
||||
AnimatedVisibility(
|
||||
duration: DesignConfig.lowAnimationDuration,
|
||||
isVisible: !state.searching,
|
||||
child: DidvanCard(
|
||||
child: Column(
|
||||
children: [
|
||||
MenuItem(
|
||||
onTap: () => _onCategorySelected('radars'),
|
||||
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('videos'),
|
||||
title: 'ویدئوها',
|
||||
icon: DidvanIcons.video_regular,
|
||||
iconSize: 24,
|
||||
),
|
||||
const DidvanDivider(),
|
||||
MenuItem(
|
||||
onTap: () => _onCategorySelected('podcasts'),
|
||||
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<BookmarksState>(
|
||||
state: state,
|
||||
// centerEmptyState: state.searching,
|
||||
builder: (context, state, index) => MultitypeItem(
|
||||
centerEmptyState: state.searching,
|
||||
builder: (context, state, index) => MultitypeOverview(
|
||||
item: state.bookmarks[index],
|
||||
onMarkChanged: state.onMarkChanged,
|
||||
hasUnmarkConfirmation: true,
|
||||
),
|
||||
placeholder: const _NewsOverviewPlaceholder(),
|
||||
placeholder: MultitypeOverview.placeholder,
|
||||
itemPadding: const EdgeInsets.only(bottom: 8),
|
||||
emptyState: state.searching
|
||||
? EmptyResult(onNewSearch: _focuseNode.requestFocus)
|
||||
|
|
@ -114,12 +121,11 @@ class _BookmarksState extends State<Bookmarks> {
|
|||
);
|
||||
}
|
||||
|
||||
// void _onCategorySelected(String? type) {
|
||||
// FocusScope.of(context).unfocus();
|
||||
// final state = context.read<BookmarksState>();
|
||||
// state.groupName = type;
|
||||
// Navigator.of(context).pushNamed(Routes.filteredBookmarks, arguments: state);
|
||||
// }
|
||||
void _onCategorySelected(String type) {
|
||||
if (type != 'radars' && type != 'news') return;
|
||||
FocusScope.of(context).unfocus();
|
||||
Navigator.of(context).pushNamed(Routes.filteredBookmarks, arguments: type);
|
||||
}
|
||||
|
||||
void _onChanged(String value) {
|
||||
final state = context.read<BookmarksState>();
|
||||
|
|
@ -133,56 +139,3 @@ class _BookmarksState extends State<Bookmarks> {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import 'package:didvan/models/news_overview.dart';
|
||||
import 'package:didvan/models/radar_overview.dart';
|
||||
import 'package:didvan/models/view/app_bar_data.dart';
|
||||
import 'package:didvan/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
|
||||
import 'package:didvan/pages/home/widgets/news_overview.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';
|
||||
|
|
@ -20,19 +20,22 @@ class FilteredBookmarks extends StatefulWidget {
|
|||
class _FilteredBookmarksState extends State<FilteredBookmarks> {
|
||||
@override
|
||||
void initState() {
|
||||
Future.delayed(Duration.zero, context.read<BookmarksState>().getBookmarks);
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
context.read<FilteredBookmarksState>().getBookmarks,
|
||||
);
|
||||
super.initState();
|
||||
}
|
||||
|
||||
String get _appBarTitle {
|
||||
switch (context.read<BookmarksState>().groupName) {
|
||||
case 'radar':
|
||||
switch (context.read<FilteredBookmarksState>().type) {
|
||||
case 'radars':
|
||||
return 'تحلیلهای رادار';
|
||||
case 'news':
|
||||
return 'اخبار';
|
||||
case 'video':
|
||||
case 'videos':
|
||||
return 'ویدئوها';
|
||||
case 'podcast':
|
||||
case 'podcasts':
|
||||
return 'پادکستها';
|
||||
default:
|
||||
return 'پادکستها';
|
||||
|
|
@ -44,93 +47,40 @@ class _FilteredBookmarksState extends State<FilteredBookmarks> {
|
|||
return DidvanScaffold(
|
||||
appBarData: AppBarData(title: _appBarTitle),
|
||||
slivers: [
|
||||
Consumer<BookmarksState>(
|
||||
Consumer<FilteredBookmarksState>(
|
||||
builder: (context, state, child) =>
|
||||
SliverStateHandler<BookmarksState>(
|
||||
SliverStateHandler<FilteredBookmarksState>(
|
||||
state: state,
|
||||
enableEmptyState: state.filterdBookmarks.isEmpty,
|
||||
enableEmptyState: state.bookmarks.isEmpty,
|
||||
itemPadding: const EdgeInsets.only(bottom: 8),
|
||||
placeholder: const _RadarOverviewPlaceholder(),
|
||||
placeholder: RadarOverview.placeholder,
|
||||
emptyState: const EmptyList(),
|
||||
builder: (context, state, index) => RadarOverview(
|
||||
radar: state.filterdBookmarks[index],
|
||||
onMarkChanged: (id, value) {},
|
||||
onCommentsChanged: (id, count) =>
|
||||
state.onCommentsChanged(id, count),
|
||||
),
|
||||
childCount: state.filterdBookmarks.length,
|
||||
onRetry: state.getBookmarks,
|
||||
builder: (context, state, index) {
|
||||
if (state.type == 'radars') {
|
||||
return RadarOverview(
|
||||
radar: state.bookmarks[index] as RadarOverviewData,
|
||||
onMarkChanged: _onBookmarkChanged,
|
||||
onCommentsChanged: state.onCommentsChanged,
|
||||
hasUnmarkConfirmation: true,
|
||||
);
|
||||
}
|
||||
return NewsOverview(
|
||||
news: state.bookmarks[index] as NewsOverviewData,
|
||||
onMarkChanged: _onBookmarkChanged,
|
||||
hasUnmarkConfirmation: true,
|
||||
);
|
||||
},
|
||||
childCount: state.bookmarks.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,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
Future<void> _onBookmarkChanged(int id, bool value) async {
|
||||
if (value) return;
|
||||
final state = context.read<FilteredBookmarksState>();
|
||||
state.onMarkChanged(id, false);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/models/item_overview.dart';
|
||||
import 'package:didvan/models/news_overview.dart';
|
||||
import 'package:didvan/models/radar_overview.dart';
|
||||
import 'package:didvan/providers/core_provider.dart';
|
||||
import 'package:didvan/providers/user_provider.dart';
|
||||
import 'package:didvan/services/network/request.dart';
|
||||
import 'package:didvan/services/network/request_helper.dart';
|
||||
|
||||
class FilteredBookmarksState extends CoreProvier {
|
||||
String search = '';
|
||||
String lastSearch = '';
|
||||
final List<OverviewData> bookmarks = [];
|
||||
final String type;
|
||||
|
||||
FilteredBookmarksState(this.type);
|
||||
|
||||
bool get searching => search != '';
|
||||
|
||||
Future<void> getBookmarks() async {
|
||||
if (search != '') {
|
||||
lastSearch = search;
|
||||
}
|
||||
appState = AppState.busy;
|
||||
final service = RequestService(
|
||||
RequestHelper.bookmarks(type: type == 'radars' ? 'radar' : type));
|
||||
await service.httpGet();
|
||||
|
||||
if (service.isSuccess) {
|
||||
final marks = service.result[type];
|
||||
bookmarks.clear();
|
||||
for (var i = 0; i < marks.length; i++) {
|
||||
if (type == 'radars') {
|
||||
bookmarks.add(RadarOverviewData.fromJson(marks[i]));
|
||||
}
|
||||
if (type == 'news') {
|
||||
bookmarks.add(NewsOverviewData.fromJson(marks[i]));
|
||||
}
|
||||
}
|
||||
appState = AppState.idle;
|
||||
return;
|
||||
}
|
||||
appState = AppState.failed;
|
||||
}
|
||||
|
||||
void onMarkChanged(int id, bool value) {
|
||||
switch (type) {
|
||||
case 'radars':
|
||||
UserProvider.changeRadarMark(id, value);
|
||||
break;
|
||||
case 'news':
|
||||
UserProvider.changeNewsMark(id, value);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
bookmarks.removeWhere((element) => element.id == id);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void onCommentsChanged(int id, int value) {
|
||||
(bookmarks.firstWhere((radar) => radar.id == id) as RadarOverviewData)
|
||||
.comments = value;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,16 +1,21 @@
|
|||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/models/view/action_sheet_data.dart';
|
||||
import 'package:didvan/utils/action_sheet.dart';
|
||||
import 'package:didvan/widgets/didvan/icon_button.dart';
|
||||
import 'package:didvan/widgets/didvan/text.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class BookmarkButton extends StatefulWidget {
|
||||
final bool value;
|
||||
final void Function(bool value) onMarkChanged;
|
||||
final bool bigGestureSize;
|
||||
final bool askForConfirmation;
|
||||
const BookmarkButton({
|
||||
Key? key,
|
||||
required this.value,
|
||||
this.bigGestureSize = false,
|
||||
required this.onMarkChanged,
|
||||
this.askForConfirmation = false,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -37,11 +42,27 @@ class _BookmarkButtonState extends State<BookmarkButton> {
|
|||
return DidvanIconButton(
|
||||
gestureSize: widget.bigGestureSize ? 32 : 24,
|
||||
icon: _value ? DidvanIcons.bookmark_solid : DidvanIcons.bookmark_regular,
|
||||
onPressed: () {
|
||||
onPressed: () async {
|
||||
bool confirm = false;
|
||||
if (widget.askForConfirmation) {
|
||||
await ActionSheetUtils.openDialog(
|
||||
data: ActionSheetData(
|
||||
content: const DidvanText(
|
||||
'آیا میخواهید این محتوا از نشان شدهها حذف شود؟',
|
||||
),
|
||||
titleIcon: DidvanIcons.bookmark_regular,
|
||||
titleColor: Theme.of(context).colorScheme.secondary,
|
||||
title: 'تایید عملیات',
|
||||
onConfirmed: () => confirm = true,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (!widget.askForConfirmation || confirm) {
|
||||
setState(() {
|
||||
_value = !_value;
|
||||
});
|
||||
widget.onMarkChanged(_value);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import 'package:flutter/material.dart';
|
|||
|
||||
class FloatingNavigationBar extends StatefulWidget {
|
||||
final ScrollController scrollController;
|
||||
final bool hasUnmarkConfirmation;
|
||||
final void Function(int count) onCommentsChanged;
|
||||
final bool isRadar;
|
||||
final bool marked;
|
||||
|
|
@ -36,6 +37,7 @@ class FloatingNavigationBar extends StatefulWidget {
|
|||
required this.id,
|
||||
required this.title,
|
||||
this.categories,
|
||||
this.hasUnmarkConfirmation = false,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -107,8 +109,14 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
|
|||
const Spacer(),
|
||||
if (widget.isRadar)
|
||||
BookmarkButton(
|
||||
askForConfirmation: widget.hasUnmarkConfirmation,
|
||||
value: widget.marked,
|
||||
onMarkChanged: widget.onMarkChanged,
|
||||
onMarkChanged: (value) {
|
||||
widget.onMarkChanged(value);
|
||||
if (widget.hasUnmarkConfirmation && !value) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
bigGestureSize: true,
|
||||
),
|
||||
SizedBox(
|
||||
|
|
@ -140,8 +148,14 @@ class _FloatingNavigationBarState extends State<FloatingNavigationBar> {
|
|||
if (!widget.isRadar) const SizedBox(width: 12),
|
||||
if (!widget.isRadar)
|
||||
BookmarkButton(
|
||||
askForConfirmation: widget.hasUnmarkConfirmation,
|
||||
value: widget.marked,
|
||||
onMarkChanged: widget.onMarkChanged,
|
||||
onMarkChanged: (value) {
|
||||
widget.onMarkChanged(value);
|
||||
if (widget.hasUnmarkConfirmation && !value) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
bigGestureSize: true,
|
||||
),
|
||||
if (widget.isRadar)
|
||||
|
|
|
|||
|
|
@ -1,19 +1,42 @@
|
|||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/constants/app_icons.dart';
|
||||
import 'package:didvan/models/item_overview.dart';
|
||||
import 'package:didvan/models/requests/news.dart';
|
||||
import 'package:didvan/models/requests/radar.dart';
|
||||
import 'package:didvan/routes/routes.dart';
|
||||
import 'package:didvan/widgets/didvan/card.dart';
|
||||
import 'package:didvan/widgets/didvan/text.dart';
|
||||
import 'package:didvan/widgets/shimmer_placeholder.dart';
|
||||
import 'package:didvan/widgets/skeleton_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:persian_number_utility/persian_number_utility.dart';
|
||||
|
||||
class MultitypeItem extends StatelessWidget {
|
||||
final ItemOverview item;
|
||||
const MultitypeItem({Key? key, required this.item}) : super(key: key);
|
||||
class MultitypeOverview extends StatelessWidget {
|
||||
final OverviewData item;
|
||||
final bool hasUnmarkConfirmation;
|
||||
final void Function(int id, bool value) onMarkChanged;
|
||||
|
||||
const MultitypeOverview({
|
||||
Key? key,
|
||||
required this.item,
|
||||
required this.onMarkChanged,
|
||||
this.hasUnmarkConfirmation = false,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return DidvanCard(
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
item.type == 'radar' ? Routes.radarDetails : Routes.newsDetails,
|
||||
arguments: {
|
||||
'onMarkChanged': onMarkChanged,
|
||||
'id': item.id,
|
||||
'args': item.type == 'radar'
|
||||
? const RadarRequestArgs(page: 0)
|
||||
: const NewsRequestArgs(page: 0),
|
||||
'hasUnmarkConfirmation': hasUnmarkConfirmation,
|
||||
},
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
|
|
@ -72,4 +95,27 @@ class MultitypeItem extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Widget get placeholder => DidvanCard(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const ShimmerPlaceholder(height: 80, width: 80),
|
||||
const SizedBox(width: 8),
|
||||
SizedBox(
|
||||
height: 80,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: const [
|
||||
ShimmerPlaceholder(height: 18, width: 200),
|
||||
SizedBox(height: 8),
|
||||
ShimmerPlaceholder(height: 18, width: 100),
|
||||
Spacer(),
|
||||
ShimmerPlaceholder(height: 14, width: 80),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import 'package:didvan/pages/home/widgets/bookmark_button.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/shimmer_placeholder.dart';
|
||||
import 'package:didvan/widgets/skeleton_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
@ -13,11 +14,13 @@ class NewsOverview extends StatelessWidget {
|
|||
final NewsOverviewData news;
|
||||
final NewsRequestArgs? newsRequestArgs;
|
||||
final void Function(int id, bool value) onMarkChanged;
|
||||
final bool hasUnmarkConfirmation;
|
||||
const NewsOverview({
|
||||
Key? key,
|
||||
required this.news,
|
||||
required this.onMarkChanged,
|
||||
this.newsRequestArgs,
|
||||
this.hasUnmarkConfirmation = false,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -29,6 +32,7 @@ class NewsOverview extends StatelessWidget {
|
|||
'onMarkChanged': onMarkChanged,
|
||||
'id': news.id,
|
||||
'args': newsRequestArgs,
|
||||
'hasUnmarkConfirmation': hasUnmarkConfirmation,
|
||||
},
|
||||
),
|
||||
child: Column(
|
||||
|
|
@ -77,6 +81,7 @@ class NewsOverview extends StatelessWidget {
|
|||
BookmarkButton(
|
||||
value: news.marked,
|
||||
onMarkChanged: (value) => onMarkChanged(news.id, value),
|
||||
askForConfirmation: hasUnmarkConfirmation,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
|
@ -84,4 +89,50 @@ class NewsOverview extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Widget get placeholder => 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),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import 'package:didvan/widgets/didvan/card.dart';
|
|||
import 'package:didvan/widgets/didvan/divider.dart';
|
||||
import 'package:didvan/widgets/didvan/icon_button.dart';
|
||||
import 'package:didvan/widgets/didvan/text.dart';
|
||||
import 'package:didvan/widgets/shimmer_placeholder.dart';
|
||||
import 'package:didvan/widgets/skeleton_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
|
@ -16,6 +17,7 @@ class RadarOverview extends StatelessWidget {
|
|||
final RadarOverviewData radar;
|
||||
final void Function(int id, int count) onCommentsChanged;
|
||||
final void Function(int id, bool value) onMarkChanged;
|
||||
final bool hasUnmarkConfirmation;
|
||||
final RadarRequestArgs? radarRequestArgs;
|
||||
const RadarOverview({
|
||||
Key? key,
|
||||
|
|
@ -23,6 +25,7 @@ class RadarOverview extends StatelessWidget {
|
|||
required this.onCommentsChanged,
|
||||
required this.onMarkChanged,
|
||||
this.radarRequestArgs,
|
||||
this.hasUnmarkConfirmation = false,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
|
@ -35,6 +38,7 @@ class RadarOverview extends StatelessWidget {
|
|||
'onCommentsChanged': onCommentsChanged,
|
||||
'id': radar.id,
|
||||
'args': radarRequestArgs,
|
||||
'hasUnmarkConfirmation': hasUnmarkConfirmation,
|
||||
},
|
||||
),
|
||||
child: Column(
|
||||
|
|
@ -101,6 +105,7 @@ class RadarOverview extends StatelessWidget {
|
|||
BookmarkButton(
|
||||
value: radar.marked,
|
||||
onMarkChanged: (value) => onMarkChanged(radar.id, value),
|
||||
askForConfirmation: hasUnmarkConfirmation,
|
||||
),
|
||||
const Spacer(),
|
||||
if (radar.comments != 0) DidvanText(radar.comments.toString()),
|
||||
|
|
@ -129,4 +134,63 @@ class RadarOverview extends StatelessWidget {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
static Widget get placeholder => 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,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import 'package:didvan/pages/home/settings/about_us/about_us.dart';
|
|||
import 'package:didvan/pages/home/settings/bookmarks/bookmarks.dart';
|
||||
import 'package:didvan/pages/home/settings/bookmarks/bookmark_state.dart';
|
||||
import 'package:didvan/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmark.dart';
|
||||
import 'package:didvan/pages/home/settings/bookmarks/filtered_bookmark/filtered_bookmarks_state.dart';
|
||||
import 'package:didvan/pages/home/settings/direct_list/direct_list.dart';
|
||||
import 'package:didvan/pages/home/settings/direct_list/direct_list_state.dart';
|
||||
import 'package:didvan/pages/home/settings/general_settings/settings.dart';
|
||||
|
|
@ -129,8 +130,10 @@ class RouteGenerator {
|
|||
);
|
||||
case Routes.filteredBookmarks:
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<BookmarksState>.value(
|
||||
value: settings.arguments as BookmarksState,
|
||||
ChangeNotifierProvider<FilteredBookmarksState>(
|
||||
create: (context) => FilteredBookmarksState(
|
||||
settings.arguments as String,
|
||||
),
|
||||
child: const FilteredBookmarks(),
|
||||
),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class RequestHelper {
|
|||
static const String updateUserProfile = _baseUserUrl + '/profile/photo';
|
||||
static const String checkUsername = _baseUserUrl + '/CheckUsername';
|
||||
static const String updateProfile = _baseUserUrl + '/profile/edit';
|
||||
static String bookmarks(String? type) =>
|
||||
static String bookmarks({String? type}) =>
|
||||
_baseUserUrl + '/marked/${type ?? ''}';
|
||||
|
||||
static const String directTypes = baseUrl + '/direct/types';
|
||||
|
|
|
|||
|
|
@ -156,6 +156,82 @@ class ActionSheetUtils {
|
|||
);
|
||||
}
|
||||
|
||||
static Future<void> openDialog({required ActionSheetData data}) async {
|
||||
await showDialog(
|
||||
context: context,
|
||||
builder: (context) => Dialog(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: DesignConfig.mediumBorderRadius,
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => Navigator.of(context).pop(),
|
||||
child: Icon(
|
||||
data.titleIcon,
|
||||
size: 20,
|
||||
color: data.titleColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 8,
|
||||
),
|
||||
Expanded(
|
||||
child: DidvanText(
|
||||
data.title,
|
||||
style: Theme.of(context).textTheme.headline3,
|
||||
color: data.titleColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
data.content,
|
||||
const SizedBox(
|
||||
height: 12,
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
if (data.hasDismissButton)
|
||||
Expanded(
|
||||
child: DidvanButton(
|
||||
onPressed: data.onDismissed ?? () => pop(),
|
||||
title: data.dismissTitle ?? 'بازگشت',
|
||||
style: ButtonStyleMode.flat,
|
||||
),
|
||||
),
|
||||
if (data.hasDismissButton)
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
),
|
||||
Expanded(
|
||||
child: DidvanButton(
|
||||
onPressed: () {
|
||||
pop();
|
||||
data.onConfirmed?.call();
|
||||
},
|
||||
title: data.confrimTitle ?? 'تایید',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static void pop() {
|
||||
DesignConfig.updateSystemUiOverlayStyle();
|
||||
Navigator.of(context).pop();
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class StateHandler<T extends CoreProvier> extends StatelessWidget {
|
|||
color: Theme.of(context).colorScheme.primary,
|
||||
);
|
||||
case AppState.failed:
|
||||
return EmptyConnection(onRetry: onRetry);
|
||||
return Center(child: EmptyConnection(onRetry: onRetry));
|
||||
default:
|
||||
return Container();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue