bnb last item changed

This commit is contained in:
MohammadTaha Basiri 2022-01-20 18:12:52 +03:30
parent 006c7982dd
commit 0df576e617
14 changed files with 459 additions and 99 deletions

View File

@ -1,40 +0,0 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:flutter/material.dart';
class ProfilePhoto extends StatelessWidget {
const ProfilePhoto({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {},
child: Center(
child: Stack(
children: [
Container(
height: 96,
width: 96,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).colorScheme.focused,
),
child: Icon(
DidvanIcons.profile_solid,
size: 60,
color: Theme.of(context).colorScheme.title,
),
),
const Positioned(
bottom: 4,
right: 4,
child: Icon(
DidvanIcons.camera_regular,
),
),
],
),
),
);
}
}

View File

@ -1,6 +1,6 @@
import 'package:didvan/models/view/app_bar_data.dart';
import 'package:didvan/pages/home/profile/direct_list/direct_list_state.dart';
import 'package:didvan/pages/home/profile/direct_list/widgets/chat_room_item.dart';
import 'package:didvan/pages/home/settings/direct_list/direct_list_state.dart';
import 'package:didvan/pages/home/settings/direct_list/widgets/chat_room_item.dart';
import 'package:didvan/widgets/didvan/badge.dart';
import 'package:didvan/widgets/didvan/divider.dart';
import 'package:didvan/widgets/didvan/scaffold.dart';

View File

@ -0,0 +1,74 @@
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/chat_room/chat_room.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/widgets/didvan/badge.dart';
import 'package:didvan/widgets/didvan/divider.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
class ChatRoomItem extends StatelessWidget {
final ChatRoom chatRoom;
const ChatRoomItem({Key? key, required this.chatRoom}) : super(key: key);
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => Navigator.of(context).pushNamed(
Routes.direct,
arguments: chatRoom.id,
),
child: Container(
color: Colors.transparent,
child: Column(
children: [
Row(
children: [
const Icon(
DidvanIcons.avatar_light,
size: 32,
),
const SizedBox(width: 12),
Expanded(
child: DidvanText(
chatRoom.type,
style: Theme.of(context).textTheme.bodyText1,
),
),
DidvanBadge(text: chatRoom.unread.toString()),
],
),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(width: 40),
const Icon(
DidvanIcons.check_double_light,
size: 16,
),
const SizedBox(width: 4),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DidvanText(
chatRoom.lastMessage.text ?? '',
maxLines: 1,
),
DidvanText(
chatRoom.updatedAt,
style: Theme.of(context).textTheme.caption,
color: Theme.of(context).colorScheme.caption,
)
],
),
),
],
),
const DidvanDivider(),
],
),
),
);
}
}

View File

@ -6,8 +6,8 @@ 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/profile/settings/settings_state.dart';
import 'package:didvan/pages/home/profile/widgets/menu_item.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';
@ -20,14 +20,14 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:provider/provider.dart';
class Settings extends StatelessWidget {
const Settings({Key? key}) : super(key: key);
class GeneralSettings extends StatelessWidget {
const GeneralSettings({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Consumer<SettingsState>(
builder: (context, state, child) => StateHandler<SettingsState>(
state: context.read<SettingsState>(),
return Consumer<GeneralSettingsState>(
builder: (context, state, child) => StateHandler<GeneralSettingsState>(
state: context.read<GeneralSettingsState>(),
builder: (context, state) => DidvanScaffold(
appBarData: AppBarData(hasBack: true, title: 'تنظیمات'),
children: [
@ -100,7 +100,7 @@ class Settings extends StatelessWidget {
}
Widget _timeFieldBuilder(BuildContext context, int index) {
final SettingsState state = context.read<SettingsState>();
final GeneralSettingsState state = context.read<GeneralSettingsState>();
return ChangeNotifierProvider.value(
value: state,
child: StatefulBuilder(
@ -127,7 +127,7 @@ class Settings extends StatelessWidget {
}
Future<void> _openTimePicker(BuildContext context, int index) async {
final SettingsState state = context.read<SettingsState>();
final GeneralSettingsState state = context.read<GeneralSettingsState>();
await Navigator.of(context).push(
showPicker(
okText: 'تایید',
@ -158,7 +158,7 @@ class Settings extends StatelessWidget {
}
Widget _themeItem(
BuildContext context, SettingsState state, String brightness) {
BuildContext context, GeneralSettingsState state, String brightness) {
final bool isDarkTheme = brightness == 'dark';
return GestureDetector(
onTap: () {

View File

@ -2,12 +2,12 @@ import 'package:didvan/models/enums.dart';
import 'package:didvan/providers/core_provider.dart';
import 'package:didvan/services/storage/storage.dart';
class SettingsState extends CoreProvier {
SettingsState() {
class GeneralSettingsState extends CoreProvier {
GeneralSettingsState() {
getSettingsFromStorage();
}
List _notificationTimeRange = [];
List _notificationTimeRange = ['00:00', '23:59'];
String _fontFamily = 'Dana-FA';
double _fontSizeScale = 1;
String _brightness = 'light';
@ -15,9 +15,12 @@ class SettingsState extends CoreProvier {
set notificationTimeRange(List value) {
_notificationTimeRange = value;
StorageService.setValue(
key: 'notificationTimeRange',
value: value,
boxName: 'settings',
key: 'notificationTimeRangeStart',
value: value[0],
);
StorageService.setValue(
key: 'notificationTimeRangeStart',
value: value[1],
);
}
@ -28,7 +31,6 @@ class SettingsState extends CoreProvier {
StorageService.setValue(
key: 'fontFamily',
value: value,
boxName: 'settings',
);
notifyListeners();
}
@ -40,7 +42,6 @@ class SettingsState extends CoreProvier {
StorageService.setValue(
key: 'fontSizeScale',
value: value,
boxName: 'settings',
);
notifyListeners();
}
@ -52,7 +53,6 @@ class SettingsState extends CoreProvier {
StorageService.setValue(
key: 'brightness',
value: value,
boxName: 'settings',
);
notifyListeners();
}
@ -61,13 +61,14 @@ class SettingsState extends CoreProvier {
Future<void> getSettingsFromStorage() async {
appState = AppState.busy;
final Map settingsData = await StorageService.getBoxData(
boxName: 'settings',
);
_notificationTimeRange = settingsData['notificationTimeRange'];
_fontFamily = settingsData['fontFamily'];
_fontSizeScale = settingsData['fontSizeScale'];
_brightness = settingsData['brightness'];
_notificationTimeRange[0] =
await StorageService.getValue(key: 'notificationTimeRangeStart');
_notificationTimeRange[1] =
await StorageService.getValue(key: 'notificationTimeRangeEnd');
_fontFamily = await StorageService.getValue(key: 'fontFamily');
_brightness = await StorageService.getValue(key: 'brightness');
final scale = await StorageService.getValue(key: 'fontSizeScale');
_fontSizeScale = double.parse(scale);
appState = AppState.idle;
}
}

View File

@ -1,8 +1,8 @@
import 'dart:async';
import 'package:didvan/models/view/app_bar_data.dart';
import 'package:didvan/pages/home/profile/edit_profile/widgets/profile_photo.dart';
import 'package:didvan/pages/home/profile/widgets/menu_item.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/providers/user_provider.dart';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/widgets/didvan/button.dart';
@ -13,14 +13,14 @@ import 'package:didvan/widgets/didvan/text_field.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
class EditProfile extends StatefulWidget {
const EditProfile({Key? key}) : super(key: key);
class Profile extends StatefulWidget {
const Profile({Key? key}) : super(key: key);
@override
State<EditProfile> createState() => _EditProfileState();
State<Profile> createState() => _ProfileState();
}
class _EditProfileState extends State<EditProfile> {
class _ProfileState extends State<Profile> {
Timer? _timer;
late String fullName;

View File

@ -0,0 +1,128 @@
import 'dart:io';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/models/enums.dart';
import 'package:didvan/models/view/alert_data.dart';
import 'package:didvan/pages/home/settings/widgets/menu_item.dart';
import 'package:didvan/providers/user_provider.dart';
import 'package:didvan/services/media/media.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/text.dart';
import 'package:didvan/widgets/skeleton_image.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:provider/provider.dart';
class ProfilePhoto extends StatefulWidget {
const ProfilePhoto({Key? key}) : super(key: key);
@override
State<ProfilePhoto> createState() => _ProfilePhotoState();
}
class _ProfilePhotoState extends State<ProfilePhoto> {
File? profileImage;
@override
Widget build(BuildContext context) {
final userProvider = context.watch<UserProvider>();
return GestureDetector(
onTap: () => _openImagePickerSheet(),
child: Center(
child: Stack(
children: [
if (userProvider.user.photo == null)
Container(
height: 96,
width: 96,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Theme.of(context).colorScheme.focused,
),
child: Icon(
DidvanIcons.profile_solid,
size: 60,
color: Theme.of(context).colorScheme.title,
),
),
if (userProvider.user.photo != null)
SkeletonImage(
imageUrl: userProvider.user.photo!,
width: 96,
height: 96,
borderRadius: BorderRadius.circular(200),
),
Positioned(
bottom: 0,
right: 0,
child: Container(
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
border: Border.all(
color: Theme.of(context).colorScheme.cardBorder,
),
color: Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(100),
),
child: const Icon(
DidvanIcons.camera_regular,
),
),
),
],
),
),
);
}
Future<void> _openImagePickerSheet() async {
FocusScope.of(context).unfocus();
await showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => DidvanCard(
enableBorder: false,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const DidvanText('بارگذاری تصویر از:'),
const SizedBox(height: 16),
MenuItem(
title: 'دوربین',
onTap: () => _setProfilePhoto(ImageSource.camera),
icon: DidvanIcons.camera_regular,
),
const DidvanDivider(),
MenuItem(
title: 'گالری',
onTap: () => _setProfilePhoto(ImageSource.gallery),
icon: DidvanIcons.gallery_file_regular,
),
],
),
),
);
}
Future<void> _setProfilePhoto(ImageSource source) async {
ActionSheetUtils.pop();
final pickedFile = await MediaService.pickImage(source: source);
if (pickedFile != null) {
final state = context.read<UserProvider>();
final result = await state.setProfilePhoto(pickedFile);
ActionSheetUtils.showAlert(
AlertData(
message: result
? 'تصویر پروفایل بارگذاری شد.'
: 'بارگذاری تصویر موفقیت آمیز نبود.',
aLertType: result ? ALertType.success : ALertType.error,
),
);
}
}
}

View File

@ -1,18 +1,19 @@
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/pages/home/profile/widgets/menu_item.dart';
import 'package:didvan/pages/home/settings/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';
import 'package:didvan/routes/routes.dart';
import 'package:didvan/services/storage/storage.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/item_title.dart';
import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:provider/provider.dart';
class Profile extends StatelessWidget {
const Profile({Key? key}) : super(key: key);
class Settings extends StatelessWidget {
const Settings({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -41,14 +42,15 @@ class Profile extends StatelessWidget {
MenuItem(
title: 'ویرایش پروفایل',
icon: DidvanIcons.user_edit_regular,
onTap: () =>
Navigator.of(context).pushNamed(Routes.editProfile),
suffix: context.read<UserProvider>().user.fullName,
onTap: () => Navigator.of(context).pushNamed(Routes.profile),
),
const DidvanDivider(),
MenuItem(
title: 'تنظیمات',
icon: DidvanIcons.setting_regular,
onTap: () => Navigator.of(context).pushNamed(Routes.settings),
onTap: () =>
Navigator.of(context).pushNamed(Routes.generalSettings),
),
const DidvanDivider(),
MenuItem(
@ -62,8 +64,11 @@ class Profile extends StatelessWidget {
icon: DidvanIcons.sign_out_regular,
color: Theme.of(context).colorScheme.secondary,
onTap: () async {
await Hive.deleteBoxFromDisk('autherization');
Navigator.of(context).pushReplacementNamed(Routes.splash);
StorageService.delete(key: 'token');
Navigator.of(context).pushNamedAndRemoveUntil(
Routes.splash,
(_) => false,
);
},
),
],

View File

@ -0,0 +1,190 @@
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

@ -54,9 +54,9 @@ class DidvanBNB extends StatelessWidget {
),
_NavBarItem(
isSelected: currentTabIndex == 4,
title: 'پروفایل',
selectedIcon: DidvanIcons.profile_solid,
unselectedIcon: DidvanIcons.profile_light,
title: 'تنظیمات',
selectedIcon: DidvanIcons.setting_solid,
unselectedIcon: DidvanIcons.setting_light,
onTap: () => onTabChanged(4),
),
],

View File

@ -9,14 +9,14 @@ import 'package:didvan/pages/home/home_state.dart';
import 'package:didvan/pages/home/news/news_details/news_details.dart';
import 'package:didvan/pages/home/news/news_details/news_details_state.dart';
import 'package:didvan/pages/home/news/news_state.dart';
import 'package:didvan/pages/home/profile/direct_list/direct_list.dart';
import 'package:didvan/pages/home/profile/direct_list/direct_list_state.dart';
import 'package:didvan/pages/home/profile/edit_profile/edit_profile.dart';
import 'package:didvan/pages/home/profile/settings/settings.dart';
import 'package:didvan/pages/home/profile/settings/settings_state.dart';
import 'package:didvan/pages/home/radar/radar_details/radar_details.dart';
import 'package:didvan/pages/home/radar/radar_details/radar_details_state.dart';
import 'package:didvan/pages/home/radar/radar_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';
import 'package:didvan/pages/home/settings/general_settings/settings_state.dart';
import 'package:didvan/pages/home/settings/profile/edit_profile.dart';
import 'package:didvan/pages/splash/splash.dart';
import 'package:didvan/routes/routes.dart';
import 'package:flutter/material.dart';
@ -53,15 +53,15 @@ class RouteGenerator {
child: const Home(),
),
);
case Routes.editProfile:
case Routes.profile:
return _createRoute(
const EditProfile(),
const Profile(),
);
case Routes.settings:
case Routes.generalSettings:
return _createRoute(
ChangeNotifierProvider<SettingsState>(
create: (context) => SettingsState(),
child: const Settings(),
ChangeNotifierProvider<GeneralSettingsState>(
create: (context) => GeneralSettingsState(),
child: const GeneralSettings(),
),
);
case Routes.radarDetails:
@ -91,7 +91,9 @@ class RouteGenerator {
value: (settings.arguments as Map<String, dynamic>)['state'],
)
],
child: const NewsDetails(),
child: NewsDetails(
id: (settings.arguments as Map<String, dynamic>)['id'],
),
),
);
case Routes.directList:

View File

@ -3,8 +3,8 @@ class Routes {
static const String home = '/home';
static const String authenticaion = '/authentication';
static const String profile = '/profile';
static const String editProfile = '/edit-profile';
static const String settings = '/settings';
static const String generalSettings = '/general-settings';
static const String radarDetails = '/radar-details';
static const String newsDetails = '/news-details';
static const String directList = '/direct-list';