restucturing | reusablity

This commit is contained in:
MohammadTaha Basiri 2022-01-29 14:03:32 +03:30
parent 0553cc75ae
commit 711a4ad1d0
17 changed files with 166 additions and 349 deletions

View File

@ -1,4 +1,4 @@
class NewsOverview {
class NewsOverviewData {
final int id;
final String title;
final String reference;
@ -7,7 +7,7 @@ class NewsOverview {
final String createdAt;
bool marked;
NewsOverview({
NewsOverviewData({
required this.id,
required this.title,
required this.reference,
@ -17,7 +17,8 @@ class NewsOverview {
required this.marked,
});
factory NewsOverview.fromJson(Map<String, dynamic> json) => NewsOverview(
factory NewsOverviewData.fromJson(Map<String, dynamic> json) =>
NewsOverviewData(
id: json['id'],
title: json['title'],
reference: json['reference'],

View File

@ -1,6 +1,6 @@
import 'category.dart';
class RadarOverview {
class RadarOverviewData {
final int id;
final String image;
final String title;
@ -12,7 +12,7 @@ class RadarOverview {
final List<Category> categories;
int comments;
RadarOverview({
RadarOverviewData({
required this.id,
required this.image,
required this.title,
@ -25,7 +25,8 @@ class RadarOverview {
required this.comments,
});
factory RadarOverview.fromJson(Map<String, dynamic> json) => RadarOverview(
factory RadarOverviewData.fromJson(Map<String, dynamic> json) =>
RadarOverviewData(
id: json['id'],
image: json['image'],
title: json['title'],

View File

@ -4,7 +4,7 @@ import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/pages/home/news/news_state.dart';
import 'package:didvan/pages/home/news/widgets/news_item.dart';
import 'package:didvan/pages/home/widgets/news_overview.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/widgets/date_picker_button.dart';
import 'package:didvan/widgets/item_title.dart';
@ -56,16 +56,20 @@ class _NewsState extends State<News> {
SliverStateHandler<NewsState>(
onRetry: () => state.getNews(page: state.page),
state: state,
builder: (context, state, index) => NewsItem(
news: state.news[index],
),
builder: (context, state, index) {
final news = state.news[index];
return NewsOverview(
news: news,
onMarkChanged: (value) => state.onMarkChanged(news.id, value),
);
},
enableEmptyState: state.news.isEmpty,
emptyState: EmptyResult(
onNewSearch: () => _focusNode.requestFocus(),
),
childCount: state.news.length,
itemPadding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
placeholder: const _NewsItemPlaceholder(),
placeholder: const _NewsOverviewPlaceholder(),
),
],
);
@ -131,8 +135,8 @@ class _NewsState extends State<News> {
}
}
class _NewsItemPlaceholder extends StatelessWidget {
const _NewsItemPlaceholder({Key? key}) : super(key: key);
class _NewsOverviewPlaceholder extends StatelessWidget {
const _NewsOverviewPlaceholder({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {

View File

@ -49,8 +49,17 @@ class _NewsDetailsState extends State<NewsDetails> {
left: 0,
right: 0,
child: FloatingNavigationBar(
news: state.currentNews,
scrollController: _scrollController,
comments: state.currentNews.comments,
id: state.currentNews.id,
marked: state.currentNews.marked,
title: state.currentNews.title,
onCommentsChanged: state.onCommentsChanged,
onMarkChanged: (value) => widget.pageData['onMarkChanged'](
state.currentNews.id,
value,
),
isRadar: false,
),
),
],

View File

@ -66,8 +66,8 @@ class NewsDetailsState extends CoreProvier {
bool exists(NewsDetailsData? newsItem) =>
news.any((n) => newsItem != null && n != null && n.id == newsItem.id);
void onCommentAdded(int id) {
news.firstWhere((item) => item!.id == id)!.comments++;
void onCommentsChanged(int count) {
news.firstWhere((item) => item!.id == currentNews.id)!.comments = count;
notifyListeners();
}
}

View File

@ -1,8 +1,8 @@
import 'package:collection/collection.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/news_overview.dart';
import 'package:didvan/models/requests/news.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';
@ -13,8 +13,7 @@ class NewsState extends CoreProvier {
String? endDate;
int page = 1;
final List<MapEntry> _markQueue = [];
final List<NewsOverview> news = [];
final List<NewsOverviewData> news = [];
void init() {
search = '';
@ -58,7 +57,7 @@ class NewsState extends CoreProvier {
if (service.isSuccess) {
final newsList = service.result['news'];
for (var i = 0; i < newsList.length; i++) {
news.add(NewsOverview.fromJson(newsList[i]));
news.add(NewsOverviewData.fromJson(newsList[i]));
}
appState = AppState.idle;
return;
@ -66,36 +65,10 @@ class NewsState extends CoreProvier {
appState = AppState.failed;
}
Future<void> mark(int id) async {
news.firstWhere((element) => element.id == id).marked = true;
Future<void> onMarkChanged(int id, bool value) async {
news.firstWhere((element) => element.id == id).marked = value;
notifyListeners();
_markQueue.add(MapEntry(id, true));
Future.delayed(const Duration(milliseconds: 500), () async {
final MapEntry? lastChange =
_markQueue.lastWhereOrNull((item) => item.key == id);
if (lastChange == null) return;
if (lastChange.value) {
final service = RequestService(RequestHelper.markNews(id));
await service.post();
_markQueue.removeWhere((element) => element.key == id);
}
});
}
Future<void> unMark(int id) async {
news.firstWhere((element) => element.id == id).marked = false;
notifyListeners();
_markQueue.add(MapEntry(id, false));
Future.delayed(const Duration(milliseconds: 500), () async {
final MapEntry? lastChange =
_markQueue.lastWhereOrNull((item) => item.key == id);
if (lastChange == null) return;
if (!lastChange.value) {
final service = RequestService(RequestHelper.markNews(id));
await service.delete();
_markQueue.removeWhere((element) => element.key == id);
}
});
UserProvider.changeNewsMark(id, value);
}
bool get isFiltering => startDate != null || endDate != null;

View File

@ -9,7 +9,7 @@ import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/pages/home/radar/radar_state.dart';
import 'package:didvan/pages/home/radar/widgets/categories_gird.dart';
import 'package:didvan/pages/home/radar/widgets/categories_list.dart';
import 'package:didvan/pages/home/radar/widgets/radar_item.dart';
import 'package:didvan/pages/home/widgets/radar_overview.dart';
import 'package:didvan/widgets/animated_visibility.dart';
import 'package:didvan/widgets/search_field.dart';
import 'package:didvan/pages/home/widgets/logo_app_bar.dart';
@ -114,7 +114,7 @@ class _RadarState extends State<Radar> {
),
),
SliverStateHandler<RadarState>(
onRetry: () => state.getRadarOverviews(page: state.page),
onRetry: () => state.getRadarOverviewDatas(page: state.page),
state: state,
itemPadding: const EdgeInsets.only(
bottom: 20,
@ -122,12 +122,21 @@ class _RadarState extends State<Radar> {
right: 16,
),
enableEmptyState: state.radars.isEmpty,
emptyState:
emptyState: Padding(
padding: const EdgeInsets.only(bottom: 120),
child:
EmptyResult(onNewSearch: () => _focusNode.requestFocus()),
placeholder: const _RadarItemPlaceholder(),
builder: (context, state, index) => RadarItem(
radar: state.radars[index],
),
placeholder: const _RadarOverviewPlaceholder(),
builder: (context, state, index) {
final radar = state.radars[index];
return RadarOverview(
radar: radar,
onMarkChanged: (value) => state.changeMark(radar.id, value),
onCommentsChanged: (count) =>
state.onCommentsChanged(radar.id, count),
);
},
childCount: state.radars.length,
),
if (state.radars.length == 1)
@ -136,20 +145,9 @@ class _RadarState extends State<Radar> {
),
],
),
if (state.appState != AppState.failed)
CategoriesRow1(
isColapsed:
state.isColapsed || state.searching || state.filtering,
),
if (state.appState != AppState.failed)
CategoriesRow2(
isColapsed:
state.isColapsed || state.searching || state.filtering,
),
if (state.appState != AppState.failed)
CategoriesList(
isColapsed: state.isColapsed && !state.searching,
),
if (state.appState != AppState.failed) const CategoriesRow1(),
if (state.appState != AppState.failed) const CategoriesRow2(),
if (state.appState != AppState.failed) const CategoriesList(),
],
),
);
@ -163,7 +161,7 @@ class _RadarState extends State<Radar> {
_timer?.cancel();
_timer = Timer(const Duration(seconds: 1), () {
state.search = value;
state.getRadarOverviews(page: 1);
state.getRadarOverviewDatas(page: 1);
});
}
@ -208,7 +206,7 @@ class _RadarState extends State<Radar> {
dismissTitle: 'حذف فیلتر',
confrimTitle: 'نمایش نتایج',
onDismissed: () => state.resetFilters(false),
onConfirmed: () => state.getRadarOverviews(page: 1),
onConfirmed: () => state.getRadarOverviewDatas(page: 1),
content: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@ -276,8 +274,8 @@ class _RadarState extends State<Radar> {
}
}
class _RadarItemPlaceholder extends StatelessWidget {
const _RadarItemPlaceholder({
class _RadarOverviewPlaceholder extends StatelessWidget {
const _RadarOverviewPlaceholder({
Key? key,
}) : super(key: key);

View File

@ -50,7 +50,17 @@ class _RadarDetailsState extends State<RadarDetails> {
left: 0,
right: 0,
child: FloatingNavigationBar(
radar: state.currentRadar,
comments: state.currentRadar.comments,
id: state.currentRadar.id,
isRadar: true,
marked: state.currentRadar.marked,
title: state.currentRadar.title,
onMarkChanged: (value) => widget.pageData['onMarkChanged'](
state.currentRadar.id,
value,
),
onCommentsChanged: state.onCommentsChanged,
categories: state.currentRadar.categories,
scrollController: _scrollController,
),
),

View File

@ -15,7 +15,13 @@ class RadarDetailsState extends CoreProvier {
int _currentIndex = 0;
int get currentIndex => _currentIndex;
RadarDetailsData get currentRadar => radars[_currentIndex]!;
RadarDetailsData get currentRadar {
try {
return radars[_currentIndex]!;
} catch (e) {
return radars[_currentIndex + 1]!;
}
}
Future<void> getRadarDetails(int id, {bool? isForward}) async {
if (isForward == null) {
@ -74,8 +80,9 @@ class RadarDetailsState extends CoreProvier {
bool exists(RadarDetailsData? radar) =>
radars.any((r) => radar != null && r != null && r.id == radar.id);
void onCommentAdded(int id) {
radars.firstWhere((radar) => radar!.id == id)!.comments++;
void onCommentsChanged(int count) {
radars.firstWhere((radar) => radar!.id == currentRadar.id)!.comments =
count;
notifyListeners();
}
}

View File

@ -1,10 +1,10 @@
import 'package:collection/collection.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/models/view/radar_category.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';
@ -16,10 +16,9 @@ class RadarState extends CoreProvier {
int page = 1;
bool isScrolled = false;
bool shouldColapse = false;
final List<MapEntry> _markQueue = [];
final List<RadarCategory> selectedCats = [];
List<RadarCategory> categories = [];
final List<RadarOverview> radars = [];
final List<RadarOverviewData> radars = [];
bool get filtering =>
selectedCats.length > 1 || startDate != null || endDate != null;
@ -43,7 +42,7 @@ class RadarState extends CoreProvier {
}
}
Future<void> getRadarOverviews({
Future<void> getRadarOverviewDatas({
required int page,
}) async {
if (this.page == page) {
@ -66,7 +65,7 @@ class RadarState extends CoreProvier {
await service.httpGet();
if (service.isSuccess) {
for (var i = 0; i < service.result['radars'].length; i++) {
radars.add(RadarOverview.fromJson(service.result['radars'][i]));
radars.add(RadarOverviewData.fromJson(service.result['radars'][i]));
}
if (searching || filtering || isColapsed || isCategorySelected) {
shouldColapse = true;
@ -78,47 +77,21 @@ class RadarState extends CoreProvier {
appState = AppState.failed;
}
Future<void> mark(int id) async {
radars.firstWhere((element) => element.id == id).marked = true;
Future<void> changeMark(int id, bool value) async {
radars.firstWhere((element) => element.id == id).marked = value;
notifyListeners();
_markQueue.add(MapEntry(id, true));
Future.delayed(const Duration(milliseconds: 500), () async {
final MapEntry? lastChange =
_markQueue.lastWhereOrNull((item) => item.key == id);
if (lastChange == null) return;
if (lastChange.value) {
final service = RequestService(RequestHelper.markRadar(id));
await service.post();
_markQueue.removeWhere((element) => element.key == id);
}
});
UserProvider.changeRadarMark(id, value);
}
Future<void> unMark(int id) async {
radars.firstWhere((element) => element.id == id).marked = false;
notifyListeners();
_markQueue.add(MapEntry(id, false));
Future.delayed(const Duration(milliseconds: 500), () async {
final MapEntry? lastChange =
_markQueue.lastWhereOrNull((item) => item.key == id);
if (lastChange == null) return;
if (!lastChange.value) {
final service = RequestService(RequestHelper.markRadar(id));
await service.delete();
_markQueue.removeWhere((element) => element.key == id);
}
});
}
void onCommentAdded(int id) {
radars.firstWhere((radar) => radar.id == id).comments++;
void onCommentsChanged(int id, int count) {
radars.firstWhere((radar) => radar.id == id).comments = count;
notifyListeners();
}
void init() {
resetFilters(true);
Future.delayed(Duration.zero, () {
getRadarOverviews(page: 1);
getRadarOverviewDatas(page: 1);
});
categories = [
RadarCategory(

View File

@ -7,7 +7,7 @@ import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/app_bar_data.dart';
import 'package:didvan/pages/home/settings/general_settings/settings_state.dart';
import 'package:didvan/pages/home/settings/widgets/menu_item.dart';
import 'package:didvan/pages/home/widgets/menu_item.dart';
import 'package:didvan/providers/theme_provider.dart';
import 'package:didvan/utils/action_sheet.dart';
import 'package:didvan/widgets/didvan/card.dart';

View File

@ -1,14 +1,17 @@
import 'dart:async';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/models/view/app_bar_data.dart';
import 'package:didvan/pages/home/settings/profile/widgets/profile_photo.dart';
import 'package:didvan/pages/home/settings/widgets/menu_item.dart';
import 'package:didvan/pages/home/widgets/menu_item.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/widgets/animated_visibility.dart';
import 'package:didvan/widgets/didvan/button.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/didvan/text.dart';
import 'package:didvan/widgets/didvan/text_field.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
@ -26,6 +29,7 @@ class _ProfileState extends State<Profile> {
late String fullName;
String? username;
String? email;
bool _usernameIsAvailible = true;
final _formKey = GlobalKey<FormState>();
@ -54,6 +58,7 @@ class _ProfileState extends State<Profile> {
const SizedBox(height: 16),
DidvanCard(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DidvanTextField(
title: 'نام و نام‌ خانوادگی',
@ -76,12 +81,15 @@ class _ProfileState extends State<Profile> {
hintText: 'انتخاب نام کاربری (اختیاری)',
onChanged: _onUsernameChanged,
initialValue: state.user.username,
validator: (value) async {
final result = await state.checkUsername(value);
if (result == false) {
return 'نام کاربری در دسترس نمی‌باشد';
}
},
),
AnimatedVisibility(
duration: DesignConfig.lowAnimationDuration,
isVisible: !_usernameIsAvailible,
child: DidvanText(
'نام کاربری در دسترس نمی‌باشد',
style: Theme.of(context).textTheme.caption,
color: Theme.of(context).colorScheme.error,
),
),
const SizedBox(height: 16),
DidvanTextField(
@ -156,6 +164,7 @@ class _ProfileState extends State<Profile> {
}
void _onUsernameChanged(String value) {
_usernameIsAvailible = true;
_setButtonState();
username = value;
_timer?.cancel();
@ -163,7 +172,13 @@ class _ProfileState extends State<Profile> {
return;
}
_timer = Timer(const Duration(seconds: 1), () {
_formKey.currentState!.validate();
context.read<UserProvider>().checkUsername(value).then((value) {
if (value == false) {
setState(() {
_usernameIsAvailible = false;
});
}
});
});
}
}

View File

@ -1,5 +1,5 @@
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/pages/home/settings/widgets/menu_item.dart';
import 'package:didvan/pages/home/widgets/menu_item.dart';
import 'package:didvan/pages/home/widgets/logo_app_bar.dart';
import 'package:didvan/providers/theme_provider.dart';
import 'package:didvan/providers/user_provider.dart';
@ -11,6 +11,7 @@ import 'package:didvan/widgets/didvan/text.dart';
import 'package:didvan/widgets/item_title.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
class Settings extends StatelessWidget {
const Settings({Key? key}) : super(key: key);
@ -86,13 +87,15 @@ class Settings extends StatelessWidget {
MenuItem(
icon: DidvanIcons.didvan_solid,
title: 'معرفی دیدوان',
onTap: () => {},
onTap: () => Navigator.of(context).pushNamed(Routes.aboutUs),
),
const DidvanDivider(),
MenuItem(
icon: DidvanIcons.support_regular,
title: 'پیام به پشتیبانی',
onTap: () => {},
onTap: () {
launch('mailto:info@didvan.app');
},
),
const DidvanDivider(),
MenuItem(

View File

@ -1,190 +0,0 @@
import 'package:day_night_time_picker/lib/constants.dart';
import 'package:day_night_time_picker/lib/daynight_timepicker.dart';
import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/constants/assets.dart';
import 'package:didvan/models/view/action_sheet_data.dart';
import 'package:didvan/models/view/app_bar_data.dart';
import 'package:didvan/pages/home/settings/general_settings/settings_state.dart';
import 'package:didvan/pages/home/settings/widgets/menu_item.dart';
import 'package:didvan/providers/theme_provider.dart';
import 'package:didvan/utils/action_sheet.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/didvan/text.dart';
import 'package:didvan/widgets/item_title.dart';
import 'package:didvan/widgets/state_handler.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
class GeneralSettings extends StatelessWidget {
const GeneralSettings({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Consumer<GeneralSettingsState>(
builder: (context, state, child) => StateHandler<GeneralSettingsState>(
state: context.read<GeneralSettingsState>(),
builder: (context, state) => DidvanScaffold(
appBarData: AppBarData(hasBack: true, title: 'تنظیمات'),
children: [
DidvanCard(
child: MenuItem(
title: 'زمان دریافت اعلان',
onTap: () => _pickTimeRange(context),
icon: DidvanIcons.notification_regular,
suffix: state.notificationTimeRange[0],
),
),
const ItemTitle(
title: 'انتخاب قلم',
icon: DidvanIcons.font_solid,
),
DidvanCard(
child: Column(
children: [
MenuItem(
suffix: 'نیاز به پیاده‌سازی',
title: 'فونت برنامه',
onTap: () {},
),
const DidvanDivider(),
MenuItem(
suffix: 'نیاز به پیاده‌سازی',
title: 'اندازه متن',
onTap: () {},
),
],
),
),
const ItemTitle(
title: 'ظاهر برنامه',
icon: DidvanIcons.theme_solid,
),
DidvanCard(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_themeItem(context, state, 'light'),
_themeItem(context, state, 'dark'),
],
),
),
],
),
),
);
}
Future<void> _pickTimeRange(BuildContext context) async {
ActionSheetUtils.showBottomSheet(
data: ActionSheetData(
content: Row(
children: [
const SizedBox(width: 8),
Expanded(child: _timeFieldBuilder(context, 0)),
const SizedBox(width: 8),
const DidvanText('-'),
const SizedBox(width: 8),
Expanded(child: _timeFieldBuilder(context, 1)),
const SizedBox(width: 8),
],
),
title: 'زمان دریافت اعلان',
titleIcon: DidvanIcons.notification_regular,
),
);
}
Widget _timeFieldBuilder(BuildContext context, int index) {
final GeneralSettingsState state = context.read<GeneralSettingsState>();
return ChangeNotifierProvider.value(
value: state,
child: StatefulBuilder(
builder: (context, setState) => GestureDetector(
onTap: () async {
await _openTimePicker(context, index);
setState(() {});
},
child: Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.splash,
borderRadius: DesignConfig.mediumBorderRadius,
border: Border.all(
color: Theme.of(context).colorScheme.border,
),
),
child: DidvanText(state.notificationTimeRange[index]),
),
),
),
);
}
Future<void> _openTimePicker(BuildContext context, int index) async {
final GeneralSettingsState state = context.read<GeneralSettingsState>();
await Navigator.of(context).push(
showPicker(
okText: 'تایید',
cancelText: 'بازگشت',
accentColor: Theme.of(context).colorScheme.primary,
okStyle: Theme.of(context).textTheme.bodyText2!,
cancelStyle: Theme.of(context).textTheme.bodyText2!,
unselectedColor: Theme.of(context).colorScheme.text,
blurredBackground: true,
hourLabel: 'ساعت',
minuteLabel: 'دقیقه',
is24HrFormat: true,
iosStylePicker: true,
minuteInterval: MinuteInterval.FIFTEEN,
context: context,
value: const TimeOfDay(hour: 0, minute: 0),
themeData: Theme.of(context),
onChange: (time) {
state.notificationTimeRange = state.notificationTimeRange
..replaceRange(
index,
index + 1,
['${time.hour}:${time.minute}'],
);
},
),
);
}
Widget _themeItem(
BuildContext context, GeneralSettingsState state, String brightness) {
final bool isDarkTheme = brightness == 'dark';
return GestureDetector(
onTap: () {
state.brightness = brightness;
if (isDarkTheme && DesignConfig.isDark) {
return;
} else if (!isDarkTheme && !DesignConfig.isDark) {
return;
} else {
if (isDarkTheme) {
context.read<ThemeProvider>().themeMode = ThemeMode.dark;
} else {
context.read<ThemeProvider>().themeMode = ThemeMode.light;
}
DesignConfig.updateSystemUiOverlayStyle();
}
},
child: Column(
children: [
SvgPicture.asset(isDarkTheme ? Assets.darkTheme : Assets.lightTheme),
const SizedBox(height: 8),
DidvanText(
isDarkTheme ? 'تیره' : 'روشن',
),
],
),
);
}
}

View File

@ -4,21 +4,29 @@ import 'package:didvan/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class MenuItem extends StatelessWidget {
final String title;
final String? title;
final Widget? titleWidget;
final IconData? icon;
final double iconSize;
final String? suffix;
final VoidCallback onTap;
final Widget? trailing;
final Color? color;
const MenuItem({
MenuItem({
Key? key,
required this.title,
required this.onTap,
this.title,
this.icon,
this.suffix,
required this.onTap,
this.color,
this.trailing,
}) : super(key: key);
this.titleWidget,
this.iconSize = 18,
}) : super(key: key) {
if (title == null && titleWidget == null) {
throw Exception;
}
}
@override
Widget build(BuildContext context) {
@ -31,12 +39,14 @@ class MenuItem extends StatelessWidget {
if (icon != null)
Icon(
icon,
size: 18,
size: iconSize,
color: color ?? Theme.of(context).colorScheme.title,
),
if (icon != null) const SizedBox(width: 4),
if (titleWidget != null) titleWidget!,
if (titleWidget == null)
DidvanText(
title,
title!,
color: color ?? Theme.of(context).colorScheme.title,
),
const Spacer(),

View File

@ -11,9 +11,12 @@ import 'package:didvan/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class NewsItem extends StatelessWidget {
final NewsOverview news;
const NewsItem({Key? key, required this.news}) : super(key: key);
class NewsOverview extends StatelessWidget {
final NewsOverviewData news;
final void Function(bool value) onMarkChanged;
const NewsOverview(
{Key? key, required this.news, required this.onMarkChanged})
: super(key: key);
@override
Widget build(BuildContext context) {
@ -77,8 +80,8 @@ class NewsItem extends StatelessWidget {
),
BookmarkButton(
value: news.marked,
onMark: () => state.mark(news.id),
onUnmark: () => state.unMark(news.id),
onMarkChanged: onMarkChanged,
bigGestureSize: true,
),
],
),

View File

@ -2,7 +2,6 @@ import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/radar_overview.dart';
import 'package:didvan/models/requests/radar.dart';
import 'package:didvan/pages/home/radar/radar_state.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/utils/date_time.dart';
import 'package:didvan/widgets/bookmark_button.dart';
@ -12,28 +11,30 @@ import 'package:didvan/widgets/didvan/icon_button.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:didvan/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class RadarItem extends StatelessWidget {
final RadarOverview radar;
const RadarItem({Key? key, required this.radar}) : super(key: key);
class RadarOverview extends StatelessWidget {
final RadarOverviewData radar;
final void Function(int count) onCommentsChanged;
final void Function(bool value) onMarkChanged;
final RadarRequestArgs? radarRequestArgs;
const RadarOverview({
Key? key,
required this.radar,
required this.onCommentsChanged,
required this.onMarkChanged,
this.radarRequestArgs,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final state = context.read<RadarState>();
return DidvanCard(
onTap: () => Navigator.of(context).pushNamed(
Routes.radarDetails,
arguments: {
'state': state,
'onMarkChanged': onMarkChanged,
'onCommentsChanged': onCommentsChanged,
'id': radar.id,
'args': RadarRequestArgs(
page: state.page,
categories: state.selectedCats.map((e) => e.id).toList(),
endDate: state.endDate,
search: state.search,
startDate: state.startDate,
)
'args': radarRequestArgs,
},
),
child: Column(
@ -99,8 +100,7 @@ class RadarItem extends StatelessWidget {
children: [
BookmarkButton(
value: radar.marked,
onMark: () => state.mark(radar.id),
onUnmark: () => state.unMark(radar.id),
onMarkChanged: onMarkChanged,
),
const Spacer(),
if (radar.comments != 0) DidvanText(radar.comments.toString()),
@ -114,7 +114,7 @@ class RadarItem extends StatelessWidget {
'isRadar': true,
'title': radar.title,
'id': radar.id,
'onCommentAdded': () => state.onCommentAdded(radar.id)
'onCommentsChanged': onCommentsChanged
},
),
),