24-02-1403 / Rhmn / changes: Customize category Create.
This commit is contained in:
parent
08d5564422
commit
48ccf55040
|
|
@ -33,6 +33,9 @@ class Assets {
|
|||
static String get stockStatCat =>
|
||||
'$_baseFeaturesPath/stock-$_themeSuffix.svg';
|
||||
|
||||
static String get note =>
|
||||
'$_baseFeaturesPath/note.svg';
|
||||
|
||||
static String get verticalLogoWithText =>
|
||||
'$_baseLogosPath/logo-vertical-$_themeSuffix.svg';
|
||||
static String get horizontalLogoWithText =>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
|
||||
|
||||
class FavoritesResponse {
|
||||
int? id;
|
||||
String? name;
|
||||
bool? selected;
|
||||
|
||||
FavoritesResponse({this.id, this.name, this.selected});
|
||||
|
||||
FavoritesResponse.fromJson(Map<String, dynamic> json) {
|
||||
id = json['id'];
|
||||
name = json['name'];
|
||||
selected = json['selected'];
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = new Map<String, dynamic>();
|
||||
data['id'] = this.id;
|
||||
data['name'] = this.name;
|
||||
data['selected'] = this.selected;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
class DayTime{
|
||||
String hour;
|
||||
String minute;
|
||||
Meridiem meridiem;
|
||||
|
||||
DayTime({this.hour = "1", this.minute = "0", this.meridiem = Meridiem.AM});
|
||||
}
|
||||
|
||||
enum SelectorType { meridiem, hour, minute }
|
||||
|
||||
enum Meridiem { AM, PM }
|
||||
|
|
@ -2,6 +2,8 @@ import 'package:didvan/views/authentication/authentication.dart';
|
|||
import 'package:didvan/views/authentication/authentication_state.dart';
|
||||
import 'package:didvan/views/comments/comments.dart';
|
||||
import 'package:didvan/views/comments/comments_state.dart';
|
||||
import 'package:didvan/views/customize_category/customize_category_state.dart';
|
||||
import 'package:didvan/views/customize_category/favorites_step.dart';
|
||||
import 'package:didvan/views/direct/direct.dart';
|
||||
import 'package:didvan/views/direct/direct_state.dart';
|
||||
import 'package:didvan/views/hashtag/hashtag.dart';
|
||||
|
|
@ -20,6 +22,7 @@ import 'package:didvan/views/news/news.dart';
|
|||
import 'package:didvan/views/news/news_details/news_details.dart';
|
||||
import 'package:didvan/views/news/news_details/news_details_state.dart';
|
||||
import 'package:didvan/views/news/news_state.dart';
|
||||
import 'package:didvan/views/notification_time/notification_time_state.dart';
|
||||
import 'package:didvan/views/podcasts/podcasts.dart';
|
||||
import 'package:didvan/views/profile/profile.dart';
|
||||
import 'package:didvan/views/radar/radar.dart';
|
||||
|
|
@ -47,6 +50,9 @@ import 'package:flutter/foundation.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../views/customize_category/notification_status_step.dart';
|
||||
import '../views/notification_time/notification_time.dart';
|
||||
|
||||
class RouteGenerator {
|
||||
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||
switch (settings.name) {
|
||||
|
|
@ -54,6 +60,28 @@ class RouteGenerator {
|
|||
return _createRoute(
|
||||
const Splash(),
|
||||
);
|
||||
case Routes.notificationTime:
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<NotificationTimeState>(
|
||||
create: (context) => NotificationTimeState(),
|
||||
child: NotificationTime(
|
||||
pageData: settings.arguments as Map<String, dynamic>,
|
||||
)),
|
||||
);
|
||||
|
||||
case Routes.favouritesStep:
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<CustomizeCategoryState>(
|
||||
create: (context) => CustomizeCategoryState(),
|
||||
child: FavoritesStep()),
|
||||
);
|
||||
|
||||
case Routes.notificationStatusStep:
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<CustomizeCategoryState>(
|
||||
create: (context) => CustomizeCategoryState(),
|
||||
child: NotificationStatusStep()),
|
||||
);
|
||||
case Routes.authenticaion:
|
||||
return _createRoute(
|
||||
ChangeNotifierProvider<AuthenticationState>(
|
||||
|
|
@ -263,7 +291,8 @@ class RouteGenerator {
|
|||
size: Size(
|
||||
deviceSize.height * 9 / 16,
|
||||
deviceSize.height,
|
||||
), textScaler: const TextScaler.linear(1.0),
|
||||
),
|
||||
textScaler: const TextScaler.linear(1.0),
|
||||
),
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
|
|
@ -273,7 +302,8 @@ class RouteGenerator {
|
|||
);
|
||||
}
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(textScaler: const TextScaler.linear(1.0)),
|
||||
data: MediaQuery.of(context)
|
||||
.copyWith(textScaler: const TextScaler.linear(1.0)),
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.surface,
|
||||
child: SafeArea(
|
||||
|
|
|
|||
|
|
@ -25,4 +25,7 @@ class Routes {
|
|||
static const String hashtag = '/hashtag';
|
||||
static const String statGeneral = '/general';
|
||||
static const String stock = '/stock';
|
||||
static const String favouritesStep = '/favourites-step';
|
||||
static const String notificationStatusStep = '/notification-status-step';
|
||||
static const String notificationTime = '/notification-time';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'package:didvan/services/storage/storage.dart';
|
||||
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
// ignore: depend_on_referenced_packages
|
||||
import 'package:http_parser/http_parser.dart' as parser;
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
|
@ -11,10 +13,12 @@ class RequestService {
|
|||
static late String token;
|
||||
int? statusCode;
|
||||
|
||||
dynamic data(String s){
|
||||
dynamic data(String s) {
|
||||
return _body?[s] ?? const {};
|
||||
}
|
||||
|
||||
Map<String, dynamic> get result => _body?['result'] ?? const {};
|
||||
|
||||
Map<String, dynamic> get errors => _body?['errors'] ?? const {};
|
||||
|
||||
String errorMessage =
|
||||
|
|
@ -39,7 +43,11 @@ class RequestService {
|
|||
}) {
|
||||
if (body != null) _requestBody = body;
|
||||
if (requestHeaders != null) _headers.addAll(requestHeaders);
|
||||
if (useAutherization) _headers.addAll({'Authorization': 'Bearer $token'});
|
||||
// if (useAutherization) _headers.addAll({'Authorization': 'Bearer $token'});
|
||||
_headers.addAll({
|
||||
'Authorization':
|
||||
'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6NCwicm9sZUlkIjo0LCJhcHBJZCI6MCwiaWF0IjoxNzEzOTM1NzkwfQ.i-SO9tLy0M9j-_C2Wh8tdp01vtYGlDZIBFPygglHQF0'
|
||||
});
|
||||
if (body != null) _requestBody = body;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -187,6 +187,9 @@ class RequestHelper {
|
|||
static String mark(int id, String type) => '$baseUrl/$type/$id/mark';
|
||||
static String tracking(int id, String type) => '$baseUrl/$type/$id/tracking';
|
||||
static String comments(int id, String type) => '$baseUrl/$type/$id/comments/v2';
|
||||
static String favourites() => '$baseUrl/user/favorites';
|
||||
static String notificationStatus() => '$baseUrl/user/notification/status';
|
||||
static String notificationTime() => '$baseUrl/user/notification/time';
|
||||
static String usersMentions(String search) => '$baseUrl/comment/user?search=$search';
|
||||
static String feedback(int id, int commentId, String type) =>
|
||||
'$baseUrl/$type/$id/comments/$commentId/feedback/v2';
|
||||
|
|
|
|||
|
|
@ -1,8 +1,41 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:persian_datetime_picker/persian_datetime_picker.dart';
|
||||
|
||||
import '../models/day_time.dart';
|
||||
|
||||
class DateTimeUtils {
|
||||
static DayTime handleDayTime(String dayTime) {
|
||||
DateFormat format = DateFormat("HH:mm");
|
||||
DateTime dateTime = format.parse(dayTime);
|
||||
int _selectedTimeHour = dateTime.hour;
|
||||
String _selectedTimeMinute = dateTime.minute.toString();
|
||||
Meridiem _selectedMeridiem = Meridiem.AM;
|
||||
|
||||
if (_selectedTimeHour > 12) {
|
||||
_selectedTimeHour -= 12;
|
||||
_selectedMeridiem = Meridiem.PM;
|
||||
} else if (_selectedTimeHour == 0) {
|
||||
_selectedTimeHour = 24;
|
||||
_selectedMeridiem = Meridiem.AM;
|
||||
}
|
||||
return DayTime(
|
||||
hour: _selectedTimeHour.toString(),
|
||||
minute: _selectedTimeMinute,
|
||||
meridiem: _selectedMeridiem);
|
||||
}
|
||||
|
||||
static String handleDayTimeReverse(DayTime dayTime) {
|
||||
String h = dayTime.hour;
|
||||
String m = dayTime.minute.padLeft(2, "0");
|
||||
if (dayTime.meridiem == Meridiem.PM) {
|
||||
h = (int.parse(h) + 12).toString().padLeft(2, "0");
|
||||
}
|
||||
|
||||
return "$h:$m";
|
||||
}
|
||||
|
||||
static TimeOfDay stringToTimeOfDay(String input) => TimeOfDay(
|
||||
hour: int.parse(input.split(':')[0]),
|
||||
minute: int.parse(input.split(':')[1]),
|
||||
|
|
@ -58,6 +91,38 @@ class DateTimeUtils {
|
|||
return result?.toDateTime().toString();
|
||||
}
|
||||
|
||||
static Future<String?> showCupertinoDatePicker({
|
||||
String? initialDate,
|
||||
String? startDate,
|
||||
String? endDate,
|
||||
}) async {
|
||||
final initDate = initialDate == null ? null : DateTime.parse(initialDate);
|
||||
final initialJalali = Jalali.fromDateTime(initDate ?? DateTime.now());
|
||||
|
||||
final firstDate = Jalali.fromDateTime(
|
||||
startDate == null ? DateTime(2021) : DateTime.parse(startDate),
|
||||
);
|
||||
|
||||
final lastDate = Jalali.fromDateTime(
|
||||
endDate == null ? DateTime.now() : DateTime.parse(endDate),
|
||||
);
|
||||
|
||||
final Jalali? result = await showPersianDatePicker(
|
||||
context: DesignConfig.context!,
|
||||
initialDate: initialJalali,
|
||||
firstDate: firstDate,
|
||||
lastDate: lastDate,
|
||||
builder: (context, child) => Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
textTheme: Theme.of(context).textTheme.copyWith(
|
||||
headlineMedium: Theme.of(context).textTheme.displaySmall)),
|
||||
child: child!,
|
||||
),
|
||||
);
|
||||
|
||||
return result?.toDateTime().toString();
|
||||
}
|
||||
|
||||
static String timeWithAmPm(String input) {
|
||||
final dateTime = utcToLocalTime(input);
|
||||
bool isAm = true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,121 @@
|
|||
import 'package:didvan/models/customize_categories/favorites_response.dart';
|
||||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
import '../../providers/core.dart';
|
||||
import '../../routes/routes.dart';
|
||||
import '../../services/network/request.dart';
|
||||
import '../../services/network/request_helper.dart';
|
||||
|
||||
class CustomizeCategoryState extends CoreProvier {
|
||||
CustomizeCategoryState() {
|
||||
appState = AppState.idle;
|
||||
}
|
||||
|
||||
List<int> selectedFavIds = [];
|
||||
List<int> selectedNotifIds = [];
|
||||
final List<FavoritesResponse> faves = [];
|
||||
final List<FavoritesResponse> notifs = [];
|
||||
|
||||
Future<void> getFavourites() async {
|
||||
appState = AppState.busy;
|
||||
|
||||
final service = RequestService(
|
||||
RequestHelper.favourites(),
|
||||
);
|
||||
await service.httpGet();
|
||||
if (service.isSuccess) {
|
||||
faves.clear();
|
||||
final favourites = service.data('types');
|
||||
for (var i = 0; i < favourites.length; i++) {
|
||||
faves.add(FavoritesResponse.fromJson(favourites[i]));
|
||||
}
|
||||
selectedFavIds.clear();
|
||||
faves.forEach((element) {
|
||||
if (element.selected!) {
|
||||
selectedFavIds.add(element.id!);
|
||||
}
|
||||
});
|
||||
|
||||
appState = AppState.idle;
|
||||
} else {
|
||||
appState = AppState.failed;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> getNotificationStatuses() async {
|
||||
appState = AppState.busy;
|
||||
|
||||
final service = RequestService(
|
||||
RequestHelper.notificationStatus(),
|
||||
);
|
||||
await service.httpGet();
|
||||
if (service.isSuccess) {
|
||||
final notificationsStatuses = service.data('types');
|
||||
for (var i = 0; i < notificationsStatuses.length; i++) {
|
||||
notifs.add(FavoritesResponse.fromJson(notificationsStatuses[i]));
|
||||
}
|
||||
selectedNotifIds.clear();
|
||||
notifs.forEach((element) {
|
||||
if (element.selected!) {
|
||||
selectedNotifIds.add(element.id!);
|
||||
}
|
||||
});
|
||||
appState = AppState.idle;
|
||||
} else {
|
||||
appState = AppState.failed;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> putFavourites(BuildContext context) async {
|
||||
// appState = AppState.busy;
|
||||
final favoritesRequest = {"favorites": selectedFavIds};
|
||||
final service = RequestService(
|
||||
RequestHelper.favourites(),
|
||||
body: favoritesRequest,
|
||||
);
|
||||
await service.put();
|
||||
if (service.isSuccess) {
|
||||
Navigator.of(context).pushNamed(
|
||||
Routes.notificationStatusStep,
|
||||
);
|
||||
appState = AppState.idle;
|
||||
return;
|
||||
}
|
||||
|
||||
appState = AppState.failed;
|
||||
}
|
||||
|
||||
Future<void> putNotificationsStatuses(BuildContext context) async {
|
||||
// appState = AppState.busy;
|
||||
final notificationsStatusesRequest = {"notification": selectedNotifIds};
|
||||
final service = RequestService(
|
||||
RequestHelper.notificationStatus(),
|
||||
body: notificationsStatusesRequest,
|
||||
);
|
||||
await service.put();
|
||||
if (service.isSuccess) {
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop();
|
||||
appState = AppState.idle;
|
||||
return;
|
||||
}
|
||||
|
||||
appState = AppState.failed;
|
||||
}
|
||||
|
||||
Future<void> changeSelected(int index, List<FavoritesResponse> list,List<int> selectedIds) async {
|
||||
list[index].selected = !list[index].selected!;
|
||||
selectedIds.clear();
|
||||
for (var ls in list) {
|
||||
if (ls.selected!) {
|
||||
selectedIds.add(ls.id!);
|
||||
}
|
||||
}
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/models/users_mention.dart';
|
||||
import 'package:didvan/models/view/app_bar_data.dart';
|
||||
import 'package:didvan/views/customize_category/customize_category_state.dart';
|
||||
import 'package:didvan/views/customize_category/widgets/customize_category_checkbox.dart';
|
||||
import 'package:didvan/views/widgets/didvan/checkbox.dart';
|
||||
import 'package:didvan/views/widgets/didvan/scaffold.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../config/design_config.dart';
|
||||
import '../../constants/assets.dart';
|
||||
import '../widgets/didvan/button.dart';
|
||||
import '../widgets/shimmer_placeholder.dart';
|
||||
import '../widgets/state_handlers/empty_state.dart';
|
||||
import '../widgets/state_handlers/sliver_state_handler.dart';
|
||||
import '../widgets/user_mention.dart';
|
||||
|
||||
class FavoritesStep extends StatefulWidget {
|
||||
const FavoritesStep({super.key});
|
||||
|
||||
@override
|
||||
State<FavoritesStep> createState() => _FavoritesStepState();
|
||||
}
|
||||
|
||||
class _FavoritesStepState extends State<FavoritesStep> {
|
||||
late CustomizeCategoryState state;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
state = context.read<CustomizeCategoryState>();
|
||||
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
() => state.getFavourites(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
state = context.read<CustomizeCategoryState>();
|
||||
|
||||
return Material(
|
||||
child: Stack(
|
||||
children: [
|
||||
DidvanScaffold(
|
||||
appBarData: AppBarData(
|
||||
hasBack: true,
|
||||
title: 'شخصیسازی برنامه',
|
||||
),
|
||||
physics: const BouncingScrollPhysics(),
|
||||
hidePlayer: true,
|
||||
padding: const EdgeInsets.all(16).copyWith(bottom: 92),
|
||||
showSliversFirst: false,
|
||||
slivers: [
|
||||
Consumer<CustomizeCategoryState>(
|
||||
builder: (context, state, child) =>
|
||||
SliverStateHandler<CustomizeCategoryState>(
|
||||
onRetry: state.getFavourites,
|
||||
state: state,
|
||||
itemPadding: const EdgeInsets.only(bottom: 16),
|
||||
childCount: state.faves.length,
|
||||
placeholder: ShimmerPlaceholder(
|
||||
height: 48,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
borderRadius: DesignConfig.mediumBorderRadius,
|
||||
),
|
||||
centerEmptyState: false,
|
||||
enableEmptyState: false,
|
||||
emptyState: EmptyState(
|
||||
asset: Assets.emptyChat,
|
||||
title: 'اولین نظر را بنویسید...',
|
||||
),
|
||||
builder: (context, state, index) => Center(
|
||||
child: Container(
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
width: 1,
|
||||
color: state.faves[index].selected!
|
||||
? Theme.of(context)
|
||||
.colorScheme
|
||||
.focusedBorder
|
||||
: Theme.of(context).colorScheme.cardBorder),
|
||||
color: state.faves[index].selected!
|
||||
? Theme.of(context).colorScheme.focused
|
||||
: Theme.of(context).colorScheme.cardBorder),
|
||||
child: CustomizeCategoryCheckbox(
|
||||
title: state.faves[index].name!,
|
||||
value: state.faves[index].selected,
|
||||
color: Theme.of(context).colorScheme.title,
|
||||
onChanged: (val) {
|
||||
state.changeSelected(index, state.faves,state.selectedFavIds);
|
||||
})),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
children: [
|
||||
DidvanText(
|
||||
"کاربر گرامی لطفا دستهبندیهای مورد علاقه خود را انتخاب کنید",
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
)
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
bottom: 40,
|
||||
left: 16,
|
||||
right: 16,
|
||||
child: DidvanButton(
|
||||
onPressed: state.appState == AppState.idle
|
||||
? () async {
|
||||
await state.putFavourites(context);
|
||||
}
|
||||
: null,
|
||||
title: 'تایید',
|
||||
style: ButtonStyleMode.primary,
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/models/users_mention.dart';
|
||||
import 'package:didvan/models/view/app_bar_data.dart';
|
||||
import 'package:didvan/views/customize_category/customize_category_state.dart';
|
||||
import 'package:didvan/views/customize_category/widgets/customize_category_checkbox.dart';
|
||||
import 'package:didvan/views/widgets/didvan/checkbox.dart';
|
||||
import 'package:didvan/views/widgets/didvan/scaffold.dart';
|
||||
import 'package:didvan/views/widgets/didvan/switch.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../config/design_config.dart';
|
||||
import '../../constants/assets.dart';
|
||||
import '../widgets/didvan/button.dart';
|
||||
import '../widgets/shimmer_placeholder.dart';
|
||||
import '../widgets/state_handlers/empty_state.dart';
|
||||
import '../widgets/state_handlers/sliver_state_handler.dart';
|
||||
import '../widgets/user_mention.dart';
|
||||
|
||||
class NotificationStatusStep extends StatefulWidget {
|
||||
const NotificationStatusStep({super.key});
|
||||
|
||||
@override
|
||||
State<NotificationStatusStep> createState() => _NotificationStatusStepState();
|
||||
}
|
||||
|
||||
class _NotificationStatusStepState extends State<NotificationStatusStep> {
|
||||
late CustomizeCategoryState state;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
state = context.read<CustomizeCategoryState>();
|
||||
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
() => state.getNotificationStatuses(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
state = context.watch<CustomizeCategoryState>();
|
||||
|
||||
return Material(
|
||||
child: Stack(
|
||||
children: [
|
||||
DidvanScaffold(
|
||||
appBarData: AppBarData(
|
||||
hasBack: true,
|
||||
title: 'شخصیسازی برنامه',
|
||||
),
|
||||
physics: const BouncingScrollPhysics(),
|
||||
hidePlayer: true,
|
||||
padding: const EdgeInsets.all(16),
|
||||
showSliversFirst: false,
|
||||
slivers: [
|
||||
Consumer<CustomizeCategoryState>(
|
||||
builder: (context, state, child) =>
|
||||
SliverStateHandler<CustomizeCategoryState>(
|
||||
onRetry: state.getNotificationStatuses,
|
||||
state: state,
|
||||
itemPadding: const EdgeInsets.only(bottom: 16),
|
||||
childCount: state.notifs.length,
|
||||
placeholder: ShimmerPlaceholder(
|
||||
height: 48,
|
||||
width: MediaQuery.sizeOf(context).width,
|
||||
borderRadius: DesignConfig.mediumBorderRadius,
|
||||
),
|
||||
centerEmptyState: false,
|
||||
enableEmptyState: false,
|
||||
emptyState: EmptyState(
|
||||
asset: Assets.emptyChat,
|
||||
title: 'اولین نظر را بنویسید...',
|
||||
),
|
||||
builder: (context, state, index) => Column(
|
||||
children: [
|
||||
Center(
|
||||
child: Column(
|
||||
children: [
|
||||
DidvanSwitch(
|
||||
value: state.notifs[index].selected!,
|
||||
title: state.notifs[index].name!,
|
||||
onChanged: (val) {
|
||||
state.changeSelected(index, state.notifs,state.selectedNotifIds);
|
||||
}),
|
||||
index != state.notifs.length - 1
|
||||
? Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
bottom: 16, top: 16),
|
||||
child: Divider(
|
||||
color:
|
||||
Theme.of(context).colorScheme.border,
|
||||
height: 1,
|
||||
),
|
||||
)
|
||||
: const SizedBox()
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: index == state.notifs.length - 1 ? 92 : 0,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
children: [
|
||||
DidvanText(
|
||||
"همیشه با اعلانات شخصیسازی شده خود بروز بمانید",
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
)
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
bottom: 40,
|
||||
left: 16,
|
||||
right: 16,
|
||||
child: DidvanButton(
|
||||
onPressed: state.appState == AppState.idle
|
||||
? () async {
|
||||
await state.putNotificationsStatuses(context);
|
||||
}
|
||||
: null,
|
||||
title: 'تایید',
|
||||
style: ButtonStyleMode.primary,
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/views/widgets/animated_visibility.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomizeCategoryCheckbox extends StatefulWidget {
|
||||
final String title;
|
||||
final bool? value;
|
||||
final double size;
|
||||
final Color? color;
|
||||
final void Function(bool value) onChanged;
|
||||
const CustomizeCategoryCheckbox({
|
||||
Key? key,
|
||||
required this.title,
|
||||
required this.value,
|
||||
required this.onChanged, this.size = 15, this.color,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<CustomizeCategoryCheckbox> createState() => _CustomizeCategoryCheckboxState();
|
||||
}
|
||||
|
||||
class _CustomizeCategoryCheckboxState extends State<CustomizeCategoryCheckbox> {
|
||||
bool _value = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
if (widget.value != null) {
|
||||
_value = widget.value!;
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color? _color = widget.color;
|
||||
_color ??= Theme.of(context).colorScheme.caption;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_value = !_value;
|
||||
});
|
||||
widget.onChanged(_value);
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Row(
|
||||
children: [
|
||||
Transform.scale(
|
||||
scale: widget.size ==15 ? 1 : 0.8,
|
||||
child: Container(
|
||||
width: 18,
|
||||
height: 18,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
border: Border.all(width: 1.0, color: _value? _color: Theme.of(context).colorScheme.caption),
|
||||
|
||||
),
|
||||
margin: EdgeInsets.all(8),
|
||||
child: AnimatedVisibility(
|
||||
isVisible: _value,
|
||||
duration: DesignConfig.mediumAnimationDuration,
|
||||
child: Center(child: Icon(Icons.check,size: 12,color: _value? _color: Theme.of(context).colorScheme.caption,))
|
||||
),
|
||||
),
|
||||
), DidvanText(widget.title,fontSize: widget.size,color: _value? _color: Theme.of(context).colorScheme.caption, ),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
import 'package:didvan/config/design_config.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/views/widgets/animated_visibility.dart';
|
||||
import 'package:didvan/views/widgets/didvan/switch.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomizeCategorySwitch extends StatefulWidget {
|
||||
final String title;
|
||||
final bool? value;
|
||||
final double size;
|
||||
final Color? color;
|
||||
final void Function(bool value) onChanged;
|
||||
|
||||
const CustomizeCategorySwitch({
|
||||
Key? key,
|
||||
required this.title,
|
||||
required this.value,
|
||||
required this.onChanged,
|
||||
this.size = 15,
|
||||
this.color,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<CustomizeCategorySwitch> createState() =>
|
||||
_CustomizeCategorySwitchState();
|
||||
}
|
||||
|
||||
class _CustomizeCategorySwitchState extends State<CustomizeCategorySwitch> {
|
||||
bool _value = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
if (widget.value != null) {
|
||||
_value = widget.value!;
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color? _color = widget.color;
|
||||
_color ??= Theme.of(context).colorScheme.caption;
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_value = !_value;
|
||||
});
|
||||
widget.onChanged(_value);
|
||||
},
|
||||
child: Container(
|
||||
color: Colors.transparent,
|
||||
child: Transform.scale(
|
||||
scale: widget.size == 15 ? 1 : 0.8,
|
||||
child: DidvanSwitch(
|
||||
value: _value, title: widget.title, onChanged: (val) {}),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,123 @@
|
|||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:didvan/models/day_time.dart';
|
||||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/models/users_mention.dart';
|
||||
import 'package:didvan/models/view/app_bar_data.dart';
|
||||
import 'package:didvan/views/customize_category/customize_category_state.dart';
|
||||
import 'package:didvan/views/notification_time/notification_time_state.dart';
|
||||
import 'package:didvan/views/notification_time/widgets/custom_cupertino_date_picker.dart';
|
||||
import 'package:didvan/views/customize_category/widgets/customize_category_checkbox.dart';
|
||||
import 'package:didvan/views/widgets/didvan/checkbox.dart';
|
||||
import 'package:didvan/views/widgets/didvan/scaffold.dart';
|
||||
import 'package:didvan/views/widgets/didvan/switch.dart';
|
||||
import 'package:didvan/views/widgets/didvan/text.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:persian_datetime_picker/persian_datetime_picker.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../constants/assets.dart';
|
||||
import '../widgets/date_picker_button.dart';
|
||||
import '../widgets/didvan/button.dart';
|
||||
import '../widgets/state_handlers/empty_state.dart';
|
||||
import '../widgets/state_handlers/sliver_state_handler.dart';
|
||||
import '../widgets/user_mention.dart';
|
||||
|
||||
class NotificationTime extends StatefulWidget {
|
||||
final Map<String, dynamic> pageData;
|
||||
|
||||
const NotificationTime({super.key, required this.pageData});
|
||||
|
||||
@override
|
||||
State<NotificationTime> createState() => _NotificationTimeState();
|
||||
}
|
||||
|
||||
class _NotificationTimeState extends State<NotificationTime> {
|
||||
late NotificationTimeState state;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
state = context.read<NotificationTimeState>();
|
||||
state.onTimeChanged = widget.pageData['onTimeChanged'];
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
() => state.getTime(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
state = context.watch<NotificationTimeState>();
|
||||
return Material(
|
||||
child: Stack(
|
||||
children: [
|
||||
DidvanScaffold(
|
||||
appBarData: AppBarData(
|
||||
hasBack: true,
|
||||
title: 'شخصیسازی برنامه',
|
||||
),
|
||||
physics: const BouncingScrollPhysics(),
|
||||
hidePlayer: true,
|
||||
padding: const EdgeInsets.all(16),
|
||||
showSliversFirst: false,
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
slivers: [],
|
||||
children: [
|
||||
Consumer<NotificationTimeState>(
|
||||
builder: (context, state, child) => Column(
|
||||
children: [
|
||||
DidvanText(
|
||||
"لطفا زمان دریافت اعلانات خود را مشخص کنید",
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
),
|
||||
state.appState == AppState.idle
|
||||
? Container(
|
||||
margin: EdgeInsets.all(24),
|
||||
height: 210,
|
||||
child: CustomCupertinoDatePicker(
|
||||
itemExtent: 64,
|
||||
selectedTime: state.selectedTime,
|
||||
selectedStyle: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.white),
|
||||
unselectedStyle:
|
||||
Theme.of(context).textTheme.titleSmall,
|
||||
disabledStyle: Theme.of(context)
|
||||
.textTheme
|
||||
.titleMedium!
|
||||
.copyWith(
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.disabledText),
|
||||
onSelectedItemChanged: (date) {
|
||||
state.selectedTime = date;
|
||||
}),
|
||||
)
|
||||
: SizedBox(),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
bottom: 40,
|
||||
left: 16,
|
||||
right: 16,
|
||||
child: DidvanButton(
|
||||
onPressed: () {
|
||||
state.putTime(context);
|
||||
},
|
||||
title: 'تایید',
|
||||
style: ButtonStyleMode.primary,
|
||||
))
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
import 'package:didvan/models/enums.dart';
|
||||
import 'package:didvan/providers/core.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../models/day_time.dart';
|
||||
import '../../routes/routes.dart';
|
||||
import '../../services/network/request.dart';
|
||||
import '../../services/network/request_helper.dart';
|
||||
import '../../utils/date_time.dart';
|
||||
import '../profile/general_settings/settings_state.dart';
|
||||
|
||||
class NotificationTimeState extends CoreProvier {
|
||||
late DayTime selectedTime;
|
||||
|
||||
late void Function( ) onTimeChanged;
|
||||
|
||||
Future<void> getTime() async {
|
||||
appState = AppState.busy;
|
||||
|
||||
final service = RequestService(
|
||||
RequestHelper.notificationTime(),
|
||||
);
|
||||
await service.httpGet();
|
||||
if (service.isSuccess) {
|
||||
final time = service.data('time');
|
||||
selectedTime = DateTimeUtils.handleDayTime(time);
|
||||
|
||||
appState = AppState.idle;
|
||||
} else {
|
||||
appState = AppState.failed;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
Future<void> putTime(BuildContext context) async {
|
||||
appState = AppState.busy;
|
||||
|
||||
final favoritesRequest = {
|
||||
"time": DateTimeUtils.handleDayTimeReverse(selectedTime)
|
||||
};
|
||||
final service = RequestService(
|
||||
RequestHelper.notificationTime(),
|
||||
body: favoritesRequest,
|
||||
);
|
||||
await service.put();
|
||||
if (service.isSuccess) {
|
||||
onTimeChanged();
|
||||
|
||||
// Navigator.of(context).pushNamed(
|
||||
// Routes.notificationStatusStep,
|
||||
// );
|
||||
appState = AppState.idle;
|
||||
return;
|
||||
}
|
||||
|
||||
appState = AppState.failed;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,341 @@
|
|||
import 'package:day_night_time_picker/lib/state/time.dart';
|
||||
import 'package:didvan/config/theme_data.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../../../models/day_time.dart';
|
||||
import '../../../utils/date_time.dart';
|
||||
|
||||
class CustomCupertinoDatePicker extends StatefulWidget {
|
||||
final double itemExtent;
|
||||
final void Function(DayTime)
|
||||
onSelectedItemChanged; // Text style of selected item
|
||||
final TextStyle? selectedStyle; // Text style of unselected item
|
||||
final TextStyle? unselectedStyle; // Text style of disabled item
|
||||
final TextStyle? disabledStyle; // Minimum selectable date
|
||||
final DayTime? selectedTime;
|
||||
|
||||
const CustomCupertinoDatePicker({
|
||||
Key? key,
|
||||
required this.itemExtent,
|
||||
required this.onSelectedItemChanged,
|
||||
this.selectedTime,
|
||||
this.selectedStyle,
|
||||
this.unselectedStyle,
|
||||
this.disabledStyle,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<CustomCupertinoDatePicker> createState() =>
|
||||
_CustomCupertinoDatePickerState();
|
||||
}
|
||||
|
||||
class _CustomCupertinoDatePickerState extends State<CustomCupertinoDatePicker> {
|
||||
late DayTime selectedTime = DateTimeUtils.handleDayTime(
|
||||
"${DateTime.now().hour.toString()}:${DateTime.now().minute.toString()}");
|
||||
|
||||
late int _selectedMeridiemIndex;
|
||||
late int _selectedHourIndex;
|
||||
late int _selectedMinuteIndex;
|
||||
|
||||
late final FixedExtentScrollController _meridiemScrollController;
|
||||
late final FixedExtentScrollController _hourScrollController;
|
||||
late final FixedExtentScrollController _minuteScrollController;
|
||||
|
||||
final _meridiem = [
|
||||
'قبل از ظهر',
|
||||
'بعد از ظهر',
|
||||
];
|
||||
|
||||
final _timeH = [];
|
||||
|
||||
final _timeM = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
|
||||
for (int i = 1; i < 12 + 1; i++) {
|
||||
String twoDigitNumber = i.toString().padLeft(2, '0');
|
||||
_timeH.add(twoDigitNumber);
|
||||
}
|
||||
for (int i = 1; i < 12 + 1; i++) {
|
||||
String twoDigitNumber = i.toString().padLeft(2, '0');
|
||||
_timeH.add(twoDigitNumber);
|
||||
}
|
||||
for (int i = 0; i < 59 + 1; i++) {
|
||||
String twoDigitNumber = i.toString().padLeft(2, '0');
|
||||
_timeM.add(twoDigitNumber);
|
||||
}
|
||||
_meridiemScrollController = FixedExtentScrollController();
|
||||
_hourScrollController = FixedExtentScrollController();
|
||||
_minuteScrollController = FixedExtentScrollController();
|
||||
if(widget.selectedTime !=null){
|
||||
selectedTime = widget.selectedTime!;
|
||||
|
||||
}
|
||||
_initDates();
|
||||
}
|
||||
|
||||
void _initDates() {
|
||||
_selectedMeridiemIndex = 0;
|
||||
|
||||
switch(selectedTime.meridiem){
|
||||
case Meridiem.AM:
|
||||
_selectedMeridiemIndex = 0;
|
||||
_selectedHourIndex = int.parse(selectedTime.hour)-1;
|
||||
|
||||
break;
|
||||
|
||||
case Meridiem.PM:
|
||||
_selectedMeridiemIndex = 1;
|
||||
_selectedHourIndex = (int.parse(selectedTime.hour)+12)-1;
|
||||
|
||||
break;
|
||||
}
|
||||
_selectedMinuteIndex = int.parse(selectedTime.minute);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_scrollList(_meridiemScrollController, _selectedMeridiemIndex);
|
||||
_scrollList(_hourScrollController, _selectedHourIndex);
|
||||
_scrollList(_minuteScrollController, _selectedMinuteIndex);
|
||||
});
|
||||
}
|
||||
|
||||
void _scrollList(FixedExtentScrollController controller, int index) {
|
||||
controller.animateToItem(
|
||||
index,
|
||||
curve: Curves.easeIn,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_meridiemScrollController.dispose();
|
||||
_hourScrollController.dispose();
|
||||
_minuteScrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onSelectedItemChanged(int index, SelectorType type) {
|
||||
switch (type) {
|
||||
case SelectorType.meridiem:
|
||||
|
||||
_selectedMeridiemIndex = index; // if month is changed to february &
|
||||
if (_selectedMeridiemIndex == 0) {
|
||||
if (_selectedHourIndex > 12 - 1) {
|
||||
_selectedHourIndex -= 12;
|
||||
_hourScrollController.jumpToItem(_selectedHourIndex);
|
||||
}
|
||||
} else {
|
||||
if (_selectedHourIndex < 12 - 1) {
|
||||
_selectedHourIndex += 12;
|
||||
_hourScrollController.jumpToItem(_selectedHourIndex);
|
||||
}
|
||||
}
|
||||
if(index == 0){
|
||||
selectedTime.meridiem = Meridiem.AM;
|
||||
}else{
|
||||
selectedTime.meridiem = Meridiem.PM;
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case SelectorType.hour:
|
||||
|
||||
_selectedHourIndex = index; // if month is changed to february &
|
||||
if (_selectedHourIndex > 12 - 1) {
|
||||
_selectedMeridiemIndex = 1;
|
||||
_meridiemScrollController.jumpToItem(_selectedMeridiemIndex);
|
||||
} else {
|
||||
_selectedMeridiemIndex = 0;
|
||||
_meridiemScrollController.jumpToItem(_selectedMeridiemIndex);
|
||||
}
|
||||
selectedTime.hour = _timeH[index];
|
||||
|
||||
break;
|
||||
|
||||
case SelectorType.minute:
|
||||
_selectedMinuteIndex = index;
|
||||
selectedTime.minute = _timeM[index];
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
setState(() {});
|
||||
widget.onSelectedItemChanged(selectedTime!);
|
||||
}
|
||||
|
||||
/// check if the given day, month or year index is disabled
|
||||
bool _isDisabled(int index, SelectorType type) {
|
||||
switch (type) {
|
||||
case SelectorType.meridiem:
|
||||
|
||||
break;
|
||||
|
||||
case SelectorType.hour:
|
||||
break;
|
||||
|
||||
case SelectorType.minute:
|
||||
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Color _shadow = Theme.of(context).colorScheme.background;
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: Center(
|
||||
child: Container(
|
||||
height: 64,
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
borderRadius: BorderRadius.circular(18)),
|
||||
child: const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 12),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
SizedBox(),
|
||||
VerticalDivider(
|
||||
color: Colors.white,
|
||||
),
|
||||
VerticalDivider(
|
||||
color: Colors.white,
|
||||
),
|
||||
SizedBox(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _meridiemSelector()),
|
||||
Expanded(child: _minuteSelector()),
|
||||
Expanded(child: _hourSelector()),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [
|
||||
_shadow.withOpacity(1),
|
||||
_shadow.withOpacity(0.9),
|
||||
_shadow.withOpacity(0.8),
|
||||
_shadow.withOpacity(0.6),
|
||||
_shadow.withOpacity(0.5),
|
||||
_shadow.withOpacity(0.4),
|
||||
])),
|
||||
)),
|
||||
Positioned(
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Container(
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.bottomCenter,
|
||||
end: Alignment.topCenter,
|
||||
colors: [
|
||||
_shadow.withOpacity(1),
|
||||
_shadow.withOpacity(0.9),
|
||||
_shadow.withOpacity(0.8),
|
||||
_shadow.withOpacity(0.6),
|
||||
_shadow.withOpacity(0.5),
|
||||
_shadow.withOpacity(0.4),
|
||||
])),
|
||||
)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _selector({
|
||||
required List<dynamic> values,
|
||||
required int selectedValueIndex,
|
||||
required bool Function(int) isDisabled,
|
||||
required void Function(int) onSelectedItemChanged,
|
||||
required FixedExtentScrollController scrollController,
|
||||
}) {
|
||||
return CupertinoPicker.builder(
|
||||
childCount: values.length,
|
||||
itemExtent: widget.itemExtent,
|
||||
scrollController: scrollController,
|
||||
squeeze: 1.45,
|
||||
useMagnifier: false,
|
||||
diameterRatio: 2.3,
|
||||
magnification: 1.0,
|
||||
offAxisFraction: 0.0,
|
||||
selectionOverlay: const SizedBox(),
|
||||
onSelectedItemChanged: onSelectedItemChanged,
|
||||
itemBuilder: (context, index) => Container(
|
||||
height: widget.itemExtent,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(),
|
||||
child: Text(
|
||||
'${values[index]}',
|
||||
style: index == selectedValueIndex
|
||||
? widget.selectedStyle
|
||||
: isDisabled(index)
|
||||
? widget.disabledStyle
|
||||
: widget.unselectedStyle,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _meridiemSelector() {
|
||||
return _selector(
|
||||
values: _meridiem,
|
||||
selectedValueIndex: _selectedMeridiemIndex,
|
||||
scrollController: _meridiemScrollController,
|
||||
isDisabled: (index) => _isDisabled(index, SelectorType.meridiem),
|
||||
onSelectedItemChanged: (v) => _onSelectedItemChanged(
|
||||
v,
|
||||
SelectorType.meridiem,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _hourSelector() {
|
||||
return _selector(
|
||||
values: _timeH,
|
||||
selectedValueIndex: _selectedHourIndex,
|
||||
scrollController: _hourScrollController,
|
||||
isDisabled: (index) => _isDisabled(index, SelectorType.hour),
|
||||
onSelectedItemChanged: (v) => _onSelectedItemChanged(
|
||||
v,
|
||||
SelectorType.hour,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _minuteSelector() {
|
||||
return _selector(
|
||||
values: _timeM,
|
||||
selectedValueIndex: _selectedMinuteIndex,
|
||||
scrollController: _minuteScrollController,
|
||||
isDisabled: (index) => _isDisabled(index, SelectorType.minute),
|
||||
onSelectedItemChanged: (v) => _onSelectedItemChanged(
|
||||
v,
|
||||
SelectorType.minute,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,8 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../../../routes/routes.dart';
|
||||
|
||||
class GeneralSettings extends StatefulWidget {
|
||||
const GeneralSettings({Key? key}) : super(key: key);
|
||||
|
||||
|
|
@ -41,6 +43,15 @@ class _GeneralSettingsState extends State<GeneralSettings> {
|
|||
int _intervalStart = 0;
|
||||
int _intervalEnd = 24;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
final state = context.read<GeneralSettingsState>();
|
||||
Future.delayed(
|
||||
Duration.zero,
|
||||
() => state.getTime(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Consumer<GeneralSettingsState>(
|
||||
|
|
@ -54,13 +65,39 @@ class _GeneralSettingsState extends State<GeneralSettings> {
|
|||
DidvanCard(
|
||||
child: MenuOption(
|
||||
title: 'زمان دریافت اعلان',
|
||||
onTap: () => _pickTimeRange(context),
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.notificationTime,
|
||||
arguments: {
|
||||
'onTimeChanged': () => Future.delayed(
|
||||
Duration.zero,
|
||||
() => state.getTime(),
|
||||
)
|
||||
},
|
||||
),
|
||||
icon: DidvanIcons.notification_regular,
|
||||
suffix: 'از${DateTimeUtils.normalizeTimeDuration(
|
||||
Duration(minutes: state.notificationTimeRange[0]),
|
||||
)} تا ${DateTimeUtils.normalizeTimeDuration(
|
||||
Duration(minutes: state.notificationTimeRange[1]),
|
||||
)}',
|
||||
suffix: state.time,
|
||||
// suffix: 'از${DateTimeUtils.normalizeTimeDuration(
|
||||
// Duration(minutes: state.notificationTimeRange[0]),
|
||||
// )} تا ${DateTimeUtils.normalizeTimeDuration(
|
||||
// Duration(minutes: state.notificationTimeRange[1]),
|
||||
// )}',
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
DidvanCard(
|
||||
child: MenuOption(
|
||||
title: 'شخصی سازی محتوا',
|
||||
onTap: () => Navigator.of(context).pushNamed(
|
||||
Routes.favouritesStep,
|
||||
),
|
||||
icon: DidvanIcons.notification_regular,
|
||||
// suffix: 'از${DateTimeUtils.normalizeTimeDuration(
|
||||
// Duration(minutes: state.notificationTimeRange[0]),
|
||||
// )} تا ${DateTimeUtils.normalizeTimeDuration(
|
||||
// Duration(minutes: state.notificationTimeRange[1]),
|
||||
// )}',
|
||||
),
|
||||
),
|
||||
const ItemTitle(
|
||||
|
|
|
|||
|
|
@ -13,6 +13,26 @@ class GeneralSettingsState extends CoreProvier {
|
|||
String _fontFamily = 'Dana-FA';
|
||||
double _fontSizeScale = 1;
|
||||
String _brightness = 'light';
|
||||
String time = "";
|
||||
|
||||
Future<void> getTime() async {
|
||||
appState = AppState.busy;
|
||||
|
||||
final service = RequestService(
|
||||
RequestHelper.notificationTime(),
|
||||
);
|
||||
await service.httpGet();
|
||||
if (service.isSuccess) {
|
||||
time = service.data('time');
|
||||
|
||||
appState = AppState.idle;
|
||||
} else {
|
||||
appState = AppState.failed;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
set notificationTimeRange(List<int> value) {
|
||||
_notificationTimeRange = value;
|
||||
|
|
|
|||
|
|
@ -69,3 +69,6 @@ class _DidvanCheckboxState extends State<DidvanCheckbox> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ dependencies:
|
|||
universal_html: ^2.0.8
|
||||
record: ^4.4.3
|
||||
record_web: ^0.5.0
|
||||
persian_datetime_picker: ^2.4.0
|
||||
persian_datetime_picker: ^2.6.0
|
||||
persian_number_utility: ^1.1.1
|
||||
bot_toast: ^4.0.1
|
||||
flutter_secure_storage: ^8.0.0
|
||||
|
|
|
|||
Loading…
Reference in New Issue