diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index a6d70a2a..acedcf72 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -3,7 +3,7 @@ name: Eatvio App Android Test on: [ pull_request ] env: - flutter_version: "3.24.5" + flutter_version: "3.27.0" java_version: "21.x" flutter_channel: "stable" diff --git a/.gitea/workflows/docker-run-tests.yml b/.gitea/workflows/docker-run-tests.yml index 99cc866e..52b8e53c 100644 --- a/.gitea/workflows/docker-run-tests.yml +++ b/.gitea/workflows/docker-run-tests.yml @@ -3,7 +3,7 @@ name: Eatvio App Android Test on custom docker on: [ pull_request ] env: - flutter_version: "3.24.5" + flutter_version: "3.27.0" java_version: "21.x" flutter_channel: "stable" my_local_cache_dir: "/opt/hostedtoolcache/" diff --git a/.gitea/workflows/test.yml b/.gitea/workflows/test.yml index bd6cf419..eac84bf6 100644 --- a/.gitea/workflows/test.yml +++ b/.gitea/workflows/test.yml @@ -3,7 +3,7 @@ name: Eatvio App Android Test on: [ pull_request ] env: - flutter_version: "3.24.5" + flutter_version: "3.27.0" java_version: "21.x" flutter_channel: "stable" my_local_cache_dir: "/opt/hostedtoolcache/" diff --git a/android/app/build.gradle b/android/app/build.gradle index 46a74368..ffffdd77 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -10,12 +10,12 @@ android { ndkVersion = "25.1.8937393" compileOptions { - sourceCompatibility = JavaVersion.VERSION_1_8 - targetCompatibility = JavaVersion.VERSION_1_8 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } kotlinOptions { - jvmTarget = JavaVersion.VERSION_1_8 + jvmTarget = 21 } defaultConfig { diff --git a/assets/icons/calories.svg b/assets/icons/calories.svg new file mode 100644 index 00000000..56188edf --- /dev/null +++ b/assets/icons/calories.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/assets/icons/clock.svg b/assets/icons/clock.svg new file mode 100644 index 00000000..f11f885b --- /dev/null +++ b/assets/icons/clock.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/steps.svg b/assets/icons/steps.svg new file mode 100644 index 00000000..45c8cb6a --- /dev/null +++ b/assets/icons/steps.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/features/feed/models/feed_blog_post_model.dart b/lib/features/feed/models/feed_blog_post_model.dart index f56c2998..d8a21194 100644 --- a/lib/features/feed/models/feed_blog_post_model.dart +++ b/lib/features/feed/models/feed_blog_post_model.dart @@ -18,7 +18,7 @@ class FeedBlogPostModel with _$FeedBlogPostModel { required String title, @JsonKey(name: "total_likes") required int totalLikes, @JsonKey(name: "total_views") required int totalViews, - @JsonKey(name: "total_comments") required int totalComments, + @JsonKey(name: "total_comments") int? totalComments, @JsonKey(name: "was_liked_by_me") required bool wasLikedByMe, }) = _FeedBlogPostModel; diff --git a/lib/features/feed/models/feed_blog_post_model.freezed.dart b/lib/features/feed/models/feed_blog_post_model.freezed.dart index 7814df66..ad757d23 100644 --- a/lib/features/feed/models/feed_blog_post_model.freezed.dart +++ b/lib/features/feed/models/feed_blog_post_model.freezed.dart @@ -37,7 +37,7 @@ mixin _$FeedBlogPostModel { @JsonKey(name: "total_views") int get totalViews => throw _privateConstructorUsedError; @JsonKey(name: "total_comments") - int get totalComments => throw _privateConstructorUsedError; + int? get totalComments => throw _privateConstructorUsedError; @JsonKey(name: "was_liked_by_me") bool get wasLikedByMe => throw _privateConstructorUsedError; @@ -69,7 +69,7 @@ abstract class $FeedBlogPostModelCopyWith<$Res> { String title, @JsonKey(name: "total_likes") int totalLikes, @JsonKey(name: "total_views") int totalViews, - @JsonKey(name: "total_comments") int totalComments, + @JsonKey(name: "total_comments") int? totalComments, @JsonKey(name: "was_liked_by_me") bool wasLikedByMe}); $AuthorCopyWith<$Res> get author; @@ -101,7 +101,7 @@ class _$FeedBlogPostModelCopyWithImpl<$Res, $Val extends FeedBlogPostModel> Object? title = null, Object? totalLikes = null, Object? totalViews = null, - Object? totalComments = null, + Object? totalComments = freezed, Object? wasLikedByMe = null, }) { return _then(_value.copyWith( @@ -149,10 +149,10 @@ class _$FeedBlogPostModelCopyWithImpl<$Res, $Val extends FeedBlogPostModel> ? _value.totalViews : totalViews // ignore: cast_nullable_to_non_nullable as int, - totalComments: null == totalComments + totalComments: freezed == totalComments ? _value.totalComments : totalComments // ignore: cast_nullable_to_non_nullable - as int, + as int?, wasLikedByMe: null == wasLikedByMe ? _value.wasLikedByMe : wasLikedByMe // ignore: cast_nullable_to_non_nullable @@ -191,7 +191,7 @@ abstract class _$$FeedBlogPostModelImplCopyWith<$Res> String title, @JsonKey(name: "total_likes") int totalLikes, @JsonKey(name: "total_views") int totalViews, - @JsonKey(name: "total_comments") int totalComments, + @JsonKey(name: "total_comments") int? totalComments, @JsonKey(name: "was_liked_by_me") bool wasLikedByMe}); @override @@ -222,7 +222,7 @@ class __$$FeedBlogPostModelImplCopyWithImpl<$Res> Object? title = null, Object? totalLikes = null, Object? totalViews = null, - Object? totalComments = null, + Object? totalComments = freezed, Object? wasLikedByMe = null, }) { return _then(_$FeedBlogPostModelImpl( @@ -270,10 +270,10 @@ class __$$FeedBlogPostModelImplCopyWithImpl<$Res> ? _value.totalViews : totalViews // ignore: cast_nullable_to_non_nullable as int, - totalComments: null == totalComments + totalComments: freezed == totalComments ? _value.totalComments : totalComments // ignore: cast_nullable_to_non_nullable - as int, + as int?, wasLikedByMe: null == wasLikedByMe ? _value.wasLikedByMe : wasLikedByMe // ignore: cast_nullable_to_non_nullable @@ -297,7 +297,7 @@ class _$FeedBlogPostModelImpl implements _FeedBlogPostModel { required this.title, @JsonKey(name: "total_likes") required this.totalLikes, @JsonKey(name: "total_views") required this.totalViews, - @JsonKey(name: "total_comments") required this.totalComments, + @JsonKey(name: "total_comments") this.totalComments, @JsonKey(name: "was_liked_by_me") required this.wasLikedByMe}); factory _$FeedBlogPostModelImpl.fromJson(Map json) => @@ -332,7 +332,7 @@ class _$FeedBlogPostModelImpl implements _FeedBlogPostModel { final int totalViews; @override @JsonKey(name: "total_comments") - final int totalComments; + final int? totalComments; @override @JsonKey(name: "was_liked_by_me") final bool wasLikedByMe; @@ -418,7 +418,7 @@ abstract class _FeedBlogPostModel implements FeedBlogPostModel { required final String title, @JsonKey(name: "total_likes") required final int totalLikes, @JsonKey(name: "total_views") required final int totalViews, - @JsonKey(name: "total_comments") required final int totalComments, + @JsonKey(name: "total_comments") final int? totalComments, @JsonKey(name: "was_liked_by_me") required final bool wasLikedByMe}) = _$FeedBlogPostModelImpl; @@ -454,7 +454,7 @@ abstract class _FeedBlogPostModel implements FeedBlogPostModel { int get totalViews; @override @JsonKey(name: "total_comments") - int get totalComments; + int? get totalComments; @override @JsonKey(name: "was_liked_by_me") bool get wasLikedByMe; diff --git a/lib/features/feed/models/feed_blog_post_model.g.dart b/lib/features/feed/models/feed_blog_post_model.g.dart index 50511fed..6abc8a23 100644 --- a/lib/features/feed/models/feed_blog_post_model.g.dart +++ b/lib/features/feed/models/feed_blog_post_model.g.dart @@ -20,7 +20,7 @@ _$FeedBlogPostModelImpl _$$FeedBlogPostModelImplFromJson( title: json['title'] as String, totalLikes: (json['total_likes'] as num).toInt(), totalViews: (json['total_views'] as num).toInt(), - totalComments: (json['total_comments'] as num).toInt(), + totalComments: (json['total_comments'] as num?)?.toInt(), wasLikedByMe: json['was_liked_by_me'] as bool, ); diff --git a/lib/features/feed/presentation/widgets/recipes_widget.dart b/lib/features/feed/presentation/widgets/recipes_widget.dart index 9e93074b..b1cf23aa 100644 --- a/lib/features/feed/presentation/widgets/recipes_widget.dart +++ b/lib/features/feed/presentation/widgets/recipes_widget.dart @@ -1,10 +1,15 @@ +// ignore_for_file: dead_code + import 'package:cached_network_image/cached_network_image.dart'; import 'package:eatvio_app/core/const.dart'; +import 'package:eatvio_app/core/widgets/feed_icon_button.dart'; import 'package:eatvio_app/features/feed/models/recipes_model.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:flutter/material.dart'; import 'package:flutter_html/flutter_html.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:go_router/go_router.dart'; +import 'package:share_plus/share_plus.dart'; class RecipesWidget extends StatefulWidget { final Recipes recipes; @@ -46,72 +51,14 @@ class _RecipesWidgetState extends State { child: Wrap( runSpacing: 8, children: [ - _iconButton(Icons.fastfood, '139.9 ккал'), + _iconButton('assets/icons/clock.svg', widget.recipes.cookingTime.toString() + ' минут'), SizedBox(width: 8), - _iconButton(Icons.timer_rounded, widget.recipes.cookingTime.toString() + ' минут'), + _iconButton('assets/icons/steps.svg', widget.recipes.steps.length.toString() + ' этапов'), SizedBox(width: 8), - _iconButton(Icons.fast_forward_rounded, widget.recipes.steps.length.toString() + ' этапов'), + _iconButton('assets/icons/calories.svg', '139.9 ккал'), ], ), ), - Positioned( - left: 8, - top: 8, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.8), - borderRadius: BorderRadius.circular(16), - ), - child: Row( - children: [ - Icon( - Icons.favorite_rounded, - size: 16, - color: Colors.black, - ), - SizedBox(width: 4), - Text( - '0', - style: TextStyle( - fontSize: 12, - color: Colors.black, - fontWeight: FontWeight.w400, - ), - ), - ], - ), - ), - ), - Positioned( - right: 8, - top: 8, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4), - decoration: BoxDecoration( - color: Colors.white.withOpacity(0.8), - borderRadius: BorderRadius.circular(16), - ), - child: Row( - children: [ - Icon( - Icons.visibility_rounded, - size: 16, - color: Colors.black, - ), - SizedBox(width: 4), - Text( - '0', - style: TextStyle( - fontSize: 12, - color: Colors.black, - fontWeight: FontWeight.w400, - ), - ), - ], - ), - ), - ), ], ), SizedBox(height: 12), @@ -150,27 +97,96 @@ class _RecipesWidgetState extends State { ), ), SizedBox(height: 12), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Row( + children: [ + FeedIconButton( + icon: true ? Icons.favorite_rounded : Icons.favorite_border_rounded, + text: widget.recipes.likesCount.toString(), + iconColor: true ? Colors.red.withOpacity(0.8) : null, + backgroundColor: true ? Colors.red.withOpacity(0.1) : null, + textColor: true ? Colors.red.withOpacity(0.8) : null, + onTap: () async { + // setState(() { + // isLiked = !isLiked; + // isLiked ? totalLikes++ : totalLikes--; + // }); + // isLiked + // ? await context.read().likePost(state.feedBlogPostList[widget.index].id) + // : await context.read().unlikedPost(state.feedBlogPostList[widget.index].id); + // await context.read().loadFeedBlogPostList(); + }, + ), + SizedBox(width: 8), + FeedIconButton( + svgIcon: SvgPicture.asset( + 'assets/icons/comment.svg', + height: 20, + width: 20, + colorFilter: ColorFilter.mode( + appTheme.gray600, + BlendMode.srcIn, + ), + ), + text: widget.recipes.commentsCount.toString(), + onTap: () => GoRouter.of(context).pushNamed( + 'aboutRecipesScreen', + extra: widget.recipes, + ), + ), + SizedBox(width: 8), + FeedIconButton( + svgIcon: SvgPicture.asset( + height: 20, + width: 20, + 'assets/icons/share.svg', + colorFilter: ColorFilter.mode(appTheme.gray600, BlendMode.srcIn), + ), + onTap: () => Share.shareUri( + Uri.parse( + baseUrl + '/ru/blog_post/' + widget.recipes.id.toString(), + ), + ), + ), + Spacer(), + Icon( + Icons.visibility_rounded, + size: 16, + color: appTheme.gray500, + ), + SizedBox(width: 4), + Text( + widget.recipes.viewsCount.toString(), + style: TextStyle( + fontSize: 12, + color: appTheme.gray500, + fontWeight: FontWeight.w400, + ), + ), + ], + ), + ), + SizedBox(height: 12), ], ), ), ); } - _iconButton(IconData icon, [String? text]) { + _iconButton(String iconPath, [String? text]) { return Container( padding: EdgeInsets.symmetric(horizontal: 12, vertical: 4), decoration: BoxDecoration( - color: Colors.white.withOpacity(0.8), + color: Colors.white.withValues(alpha: 0.8), borderRadius: BorderRadius.circular(16), ), height: 32, child: Row( mainAxisSize: MainAxisSize.min, children: [ - Icon( - icon, - size: 16, - color: Colors.black, + SvgPicture.asset( + iconPath, ), if (text != null) SizedBox(width: 8), if (text != null) diff --git a/pubspec.yaml b/pubspec.yaml index b9f4611f..341123b1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -45,7 +45,10 @@ dependencies: flutter_keyboard_visibility: ^6.0.0 share_plus: ^10.1.2 flutter_html: ^3.0.0-beta.2 - file_picker: ^8.1.4 + file_picker: + git: + url: https://github.com/abdelaziz-mahdy/flutter_file_picker + ref: fix-flutter-3.27-compile-error audioplayers: ^6.1.0 intl: ^0.19.0 rive: ^0.13.20