From b9d36190caff41764a2d724f605c2f89d3cfc4f8 Mon Sep 17 00:00:00 2001 From: mso7nueh Date: Fri, 15 Nov 2024 15:55:50 +0300 Subject: [PATCH 1/5] fix(feed): image constrains --- .../presentation/pages/blog_post_create_screen.dart | 13 ++++++++----- .../widgets/bottom_navigation_bar_widget.dart | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart b/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart index d76b7bd4..74a83a25 100644 --- a/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart +++ b/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart @@ -168,11 +168,14 @@ class _BlogPostCreateScreenState extends State { width: shrinkImage ? 52 : MediaQuery.of(context).size.width - 32, curve: Curves.easeIn, duration: Duration(milliseconds: 150), - child: ClipRRect( - borderRadius: BorderRadius.circular(16), - child: Image( - image: FileImage( - File(state.image!.path), + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context).size.width - 32, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: Image( + image: FileImage(File(state.image!.path)), ), ), ), diff --git a/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart b/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart index ce8a8bca..787fe3c4 100644 --- a/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart +++ b/lib/features/bottom_navigation_bar/presentation/widgets/bottom_navigation_bar_widget.dart @@ -63,7 +63,7 @@ class _BottomNavigationBarWidgetState extends State { return Scaffold( body: widget.child, bottomNavigationBar: SizedBox( - height: 58, + height: 80, child: BottomNavigationBar( type: BottomNavigationBarType.fixed, onTap: _onItemTapped, From 0d7d5a3a5a1f833d0fa349431642b3651cbc7964 Mon Sep 17 00:00:00 2001 From: mso7nueh Date: Fri, 15 Nov 2024 16:11:40 +0300 Subject: [PATCH 2/5] feat(feed): image from camera --- lib/app_router.dart | 2 +- .../pages/blog_post_create_screen.dart | 136 +++++++++++------- 2 files changed, 85 insertions(+), 53 deletions(-) diff --git a/lib/app_router.dart b/lib/app_router.dart index 91ab37fd..457c532c 100644 --- a/lib/app_router.dart +++ b/lib/app_router.dart @@ -159,7 +159,7 @@ class AppRouter { GoRoute( path: '/blog-post-create-screen', name: 'blogPostCreateScreen', - builder: (context, state) => BlogPostCreateScreen.builder(context), + builder: (context, state) => BlogPostCreateScreen(), ), GoRoute( path: '/blog-post-screen', diff --git a/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart b/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart index 74a83a25..d41a1967 100644 --- a/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart +++ b/lib/features/blog_post_create/presentation/pages/blog_post_create_screen.dart @@ -1,10 +1,10 @@ import 'dart:async'; import 'dart:io'; import 'package:eatvio_app/old/feed/blog_post_create_screen/bloc/blog_post_create_bloc.dart'; -import 'package:eatvio_app/old/feed/blog_post_create_screen/models/blog_post_create_model.dart'; import 'package:eatvio_app/theme/app_decoration.dart'; import 'package:eatvio_app/theme/theme_helper.dart'; import 'package:eatvio_app/widgets/custom_text_form_field.dart'; +import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; @@ -13,22 +13,13 @@ import 'package:image_picker/image_picker.dart'; class BlogPostCreateScreen extends StatefulWidget { const BlogPostCreateScreen({Key? key}) : super(key: key); - static Widget builder(BuildContext context) { - final blog_postID = ModalRoute.of(context)!.settings.arguments; - return BlocProvider( - create: (context) => BlogPostCreateBloc(BlogPostCreateState(blog_postModelObj: BlogPostCreateModel(blog_postID: blog_postID.toString()))) - ..add(BlogPostCreateInitialEvent()), - child: BlogPostCreateScreen(), - ); - } - @override State createState() => _BlogPostCreateScreenState(); } class _BlogPostCreateScreenState extends State { + final blogPostCreateBloc = BlogPostCreateBloc(BlogPostCreateState())..add(BlogPostCreateInitialEvent()); bool shrinkImage = false; - late StreamSubscription keyboardSubscription; @override @@ -49,24 +40,72 @@ class _BlogPostCreateScreenState extends State { } Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state is BlogPostCreateInitialState) { - // Это начальное состояние, данные ещё не загружены. - return Container( - color: Colors.white, - ); - } else if (state is BlogPostCreateLoadedState) { - // Данные загружены, можно строить экран. - return _buildBlogPostCreate(context, state); - } else if (state is BlogPostCreateErrorState) { - // Произошла ошибка при загрузке данных. - return Center(child: Text(state.errorMessage)); - } else { - // Другие состояния, если они есть. - return Container(); // Пустой контейнер для необработанных состояний. - } - }, + return BlocProvider( + create: (BuildContext context) => blogPostCreateBloc, + child: BlocBuilder( + builder: (context, state) { + if (state is BlogPostCreateInitialState) { + // Это начальное состояние, данные ещё не загружены. + return Container( + color: Colors.white, + ); + } else if (state is BlogPostCreateLoadedState) { + // Данные загружены, можно строить экран. + return _buildBlogPostCreate(context, state); + } else if (state is BlogPostCreateErrorState) { + // Произошла ошибка при загрузке данных. + return Center(child: Text(state.errorMessage)); + } else { + // Другие состояния, если они есть. + return Container(); // Пустой контейнер для необработанных состояний. + } + }, + ), + ); + } + + _showImagePicker() { + showCupertinoModalPopup( + context: context, + builder: (context) => CupertinoActionSheet( + actions: [ + CupertinoActionSheetAction( + onPressed: () async { + final picker = ImagePicker(); + XFile? image = await picker.pickImage(source: ImageSource.camera); + if (image != null) blogPostCreateBloc.add(UploadImages(image)); + Navigator.of(context).pop(); + }, + child: const Row( + children: const [ + Icon(Icons.photo_camera), + SizedBox(width: 8), + Text('Фото'), + ], + ), + ), + CupertinoActionSheetAction( + onPressed: () async { + final picker = ImagePicker(); + XFile? image = await picker.pickImage(source: ImageSource.gallery); + if (image != null) blogPostCreateBloc.add(UploadImages(image)); + Navigator.of(context).pop(); + }, + child: const Row( + children: const [ + Icon(Icons.photo), + SizedBox(width: 8), + Text('Галерея'), + ], + ), + ), + ], + cancelButton: CupertinoActionSheetAction( + onPressed: () => Navigator.of(context).pop(), + isDestructiveAction: true, + child: const Text('Отмена'), + ), + ), ); } @@ -164,18 +203,15 @@ class _BlogPostCreateScreenState extends State { ), ), if (state.image != null) - AnimatedContainer( + Container( width: shrinkImage ? 52 : MediaQuery.of(context).size.width - 32, - curve: Curves.easeIn, - duration: Duration(milliseconds: 150), - child: ConstrainedBox( - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context).size.width - 32, - ), - child: ClipRRect( - borderRadius: BorderRadius.circular(16), - child: Image( - image: FileImage(File(state.image!.path)), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: Image( + image: FileImage( + File( + state.image!.path, + ), ), ), ), @@ -184,6 +220,14 @@ class _BlogPostCreateScreenState extends State { ), ); } + + addImage(BuildContext context, bool isLoading) { + if (!isLoading) { + return () { + _showImagePicker(); + }; + } + } } _submitForm( @@ -194,15 +238,3 @@ _submitForm( ) async { context.read().add(CreateBlogPost()); } - -addImage(BuildContext context, bool isLoading) { - if (!isLoading) { - return () async { - final picker = ImagePicker(); - XFile? image = await picker.pickImage(source: ImageSource.gallery); - if (image != null) { - context.read().add(UploadImages(image)); - } - }; - } -} From ce7e620cb333716b190559d3071ffe96abcaeb29 Mon Sep 17 00:00:00 2001 From: mso7nueh Date: Fri, 15 Nov 2024 16:16:39 +0300 Subject: [PATCH 3/5] feat(other): add max length in textformfield --- .../settings/presentation/pages/other_info_screen.dart | 10 ++++++---- lib/widgets/custom_text_form_field.dart | 3 +++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/lib/features/settings/presentation/pages/other_info_screen.dart b/lib/features/settings/presentation/pages/other_info_screen.dart index b786a746..4cb62dc4 100644 --- a/lib/features/settings/presentation/pages/other_info_screen.dart +++ b/lib/features/settings/presentation/pages/other_info_screen.dart @@ -4,7 +4,6 @@ import 'package:eatvio_app/generated/l10n.dart'; import 'package:eatvio_app/theme/theme_helper.dart'; import 'package:eatvio_app/widgets/custom_text_form_field.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; class OtherInfoScreen extends StatefulWidget { @@ -60,6 +59,7 @@ class _OtherInfoScreenState extends State { autofocus: true, minLines: 2, maxLines: 8, + maxLength: 250, onChanged: (newValue) {}, ), SizedBox(height: 16), @@ -70,6 +70,7 @@ class _OtherInfoScreenState extends State { hintText: s.enter_information, autofocus: true, minLines: 2, + maxLength: 250, maxLines: 8, onChanged: (newValue) {}, ), @@ -82,6 +83,7 @@ class _OtherInfoScreenState extends State { "Я занимаюсь плаванием , почти каждый вечер прогулки на свежем воздухе, пару раз в месяц играю в волейбол. Стараюсь не сидеть на месте!", autofocus: true, maxLines: 8, + maxLength: 250, onChanged: (newValue) {}, ), SizedBox(height: 16), @@ -92,6 +94,7 @@ class _OtherInfoScreenState extends State { hintText: s.enter_information, maxLines: 7, minLines: 2, + maxLength: 250, onChanged: (newValue) {}, ), SizedBox(height: 16), @@ -102,6 +105,7 @@ class _OtherInfoScreenState extends State { hintText: s.enter_information, maxLines: 7, minLines: 2, + maxLength: 250, onChanged: (newValue) {}, ), SizedBox(height: 16), @@ -114,9 +118,7 @@ class _OtherInfoScreenState extends State { SizedBox(height: 4), CustomTextFormField( controller: additionalInfoController, - inputFormatters: [ - new LengthLimitingTextInputFormatter(250), - ], + maxLength: 250, hintText: "У меня крепкое здоровье, но последнее время часто утомляюсь, однако, это мне не мешает радоваться жизни", maxLines: 8, onChanged: (newValue) {}, diff --git a/lib/widgets/custom_text_form_field.dart b/lib/widgets/custom_text_form_field.dart index b493f9c9..6054079f 100644 --- a/lib/widgets/custom_text_form_field.dart +++ b/lib/widgets/custom_text_form_field.dart @@ -34,6 +34,7 @@ class CustomTextFormField extends StatelessWidget { this.onChanged, this.onEditingComplete, this.minLines = 1, + this.maxLength, super.key, }); @@ -67,6 +68,7 @@ class CustomTextFormField extends StatelessWidget { final Function()? onEditingComplete; final void Function(String?)? onSaved; final void Function(String)? onChanged; + final int? maxLength; @override Widget build(BuildContext context) { @@ -74,6 +76,7 @@ class CustomTextFormField extends StatelessWidget { alignment: alignment ?? Alignment.center, child: TextFormField( minLines: minLines, + maxLength: maxLength, onChanged: onChanged, controller: controller, focusNode: focusNode ?? null, From f836cb52c2f00ba5efa9db1c4f96a908dadb1f5f Mon Sep 17 00:00:00 2001 From: mso7nueh Date: Fri, 15 Nov 2024 16:22:49 +0300 Subject: [PATCH 4/5] feat(diary): cant fill future day --- .../presentation/pages/diary_screen.dart | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/lib/features/diary/presentation/pages/diary_screen.dart b/lib/features/diary/presentation/pages/diary_screen.dart index cfd571cf..747b084d 100644 --- a/lib/features/diary/presentation/pages/diary_screen.dart +++ b/lib/features/diary/presentation/pages/diary_screen.dart @@ -278,23 +278,25 @@ class _DiaryScreenState extends State { _mealButton(5), ], ), - const SizedBox(height: 12), - _divider(context), - const SizedBox(height: 12), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Время приема пищи', - style: TextStyle( - color: Color(0xFF323F4B), - fontSize: 16, - fontWeight: FontWeight.w500, + _selectedDay!.compareTo(today!) == 1 ? const SizedBox.shrink() : const SizedBox(height: 12), + _selectedDay!.compareTo(today!) == 1 ? const SizedBox.shrink() : _divider(context), + _selectedDay!.compareTo(today!) == 1 ? const SizedBox.shrink() : const SizedBox(height: 12), + _selectedDay!.compareTo(today!) == 1 + ? const SizedBox.shrink() + : Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Время приема пищи', + style: TextStyle( + color: Color(0xFF323F4B), + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + _timeOfMeal(time), + ], ), - ), - _timeOfMeal(time), - ], - ), const SizedBox(height: 12), _divider(context), const SizedBox(height: 12), @@ -303,21 +305,25 @@ class _DiaryScreenState extends State { _addProductButton(diaryDay), const SizedBox(height: 24), if (diaryDay.meals[currentSelectedMealNumber - 1].photos.isEmpty) - GestureDetector( - onTap: () => _showImagePicker(diaryDay), - child: SvgPicture.asset( - width: MediaQuery.of(context).size.width - 32, - 'assets/no_one_image_was_added.svg', - ), - ), + _selectedDay!.compareTo(today!) == 1 + ? const SizedBox.shrink() + : GestureDetector( + onTap: () => _showImagePicker(diaryDay), + child: SvgPicture.asset( + width: MediaQuery.of(context).size.width - 32, + 'assets/no_one_image_was_added.svg', + ), + ), if (diaryDay.meals[currentSelectedMealNumber - 1].photos.isNotEmpty) _photoGallery( diaryDay.meals[currentSelectedMealNumber - 1].photos, diaryDay, ), - SatietyRatingWidget( - currentSelectedSatietyRating: currentSelectedSatietyRating, - ), + _selectedDay!.compareTo(today!) == 1 + ? const SizedBox.shrink() + : SatietyRatingWidget( + currentSelectedSatietyRating: currentSelectedSatietyRating, + ), ], ), ), @@ -1057,6 +1063,7 @@ class _DiaryScreenState extends State { } _addProductButton(DiaryDayModel diaryDay) { + if (_selectedDay!.compareTo(today!) == 1) return const SizedBox.shrink(); return InkWell( onTap: () { setState(() { From ab975eb59b99ab18f9500c9a697465d8c853c765 Mon Sep 17 00:00:00 2001 From: mso7nueh Date: Fri, 15 Nov 2024 16:24:55 +0300 Subject: [PATCH 5/5] feat(diary): hide chart in future days --- lib/features/diary/presentation/pages/diary_screen.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/features/diary/presentation/pages/diary_screen.dart b/lib/features/diary/presentation/pages/diary_screen.dart index 747b084d..94d1eff5 100644 --- a/lib/features/diary/presentation/pages/diary_screen.dart +++ b/lib/features/diary/presentation/pages/diary_screen.dart @@ -130,7 +130,7 @@ class _DiaryScreenState extends State { state.diary, state.currentSelectedSatietyRating, ), - if (state is DiaryStateLoaded) _chart(state.nutrition), + if (state is DiaryStateLoaded && _selectedDay!.compareTo(today!) != 1) _chart(state.nutrition), if (state is DiaryStateLoaded && state.diary.closed == 0 && _selectedDay == today) Padding( padding: const EdgeInsets.only(top: 12),