From 0a636e05b8d41c2c0b806b0b405b25f49cdb57f0 Mon Sep 17 00:00:00 2001 From: Username1548 Date: Tue, 8 Jul 2025 09:17:20 +0700 Subject: [PATCH] feat(comments): added actions bottom sheet with different actions for comments, added copy, reply and complain --- assets/icons/reply.svg | 3 + .../comments_cubit/comments_cubit.dart | 31 ++- .../comments_cubit/comments_state.dart | 0 .../comments_actions_bottom_sheet.dart | 141 +++++++++++++ .../repositories/comments_repository.dart | 23 +++ .../comments/services/comments_service.dart | 15 ++ lib/core/const.dart | 3 +- lib/core/enums/complained_content.dart | 8 +- lib/core/locator_service.dart | 8 +- .../presentation/pages/blog_post_screen.dart | 4 +- .../presentation/cubit/complaining_cubit.dart | 6 + .../repositories/complaining_repository.dart | 12 ++ .../services/complaining_service.dart | 7 + .../presentation/pages/about_diet_screen.dart | 4 +- .../presentation/widgets/comments_widget.dart | 191 +++++++++++------- .../presentation/pages/about_plan_screen.dart | 4 +- .../pages/about_recipe_screen.dart | 4 +- lib/generated/intl/messages_en.dart | 5 + lib/generated/l10n.dart | 20 ++ lib/l10n/intl_en.arb | 6 +- 20 files changed, 395 insertions(+), 100 deletions(-) create mode 100644 assets/icons/reply.svg rename lib/{features/feed/presentation/bloc => core/comments}/comments_cubit/comments_cubit.dart (75%) rename lib/{features/feed/presentation/bloc => core/comments}/comments_cubit/comments_state.dart (100%) create mode 100644 lib/core/comments/presentation/comments_actions_bottom_sheet.dart create mode 100644 lib/core/comments/repositories/comments_repository.dart create mode 100644 lib/core/comments/services/comments_service.dart diff --git a/assets/icons/reply.svg b/assets/icons/reply.svg new file mode 100644 index 00000000..b62c76ae --- /dev/null +++ b/assets/icons/reply.svg @@ -0,0 +1,3 @@ + + + diff --git a/lib/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart b/lib/core/comments/comments_cubit/comments_cubit.dart similarity index 75% rename from lib/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart rename to lib/core/comments/comments_cubit/comments_cubit.dart index 5bb62317..2bc21d14 100644 --- a/lib/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart +++ b/lib/core/comments/comments_cubit/comments_cubit.dart @@ -1,20 +1,25 @@ -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_state.dart'; +import 'dart:developer'; + +import 'package:eatvio_app/core/comments/comments_cubit/comments_state.dart'; +import 'package:eatvio_app/core/comments/repositories/comments_repository.dart'; import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart'; import 'package:eatvio_app/features/feed/repositories/feed_repository.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class CommentsCubit extends Cubit { final FeedRepository feedRepository; + final CommentsRepository commentsRepository; CommentsCubit({ required this.feedRepository, + required this.commentsRepository, }) : super(const CommentsState()); void setReplyId(int? replyId) { emit((state as CommentsStateLoaded).copyWith(replyId: replyId)); } - Future getComments(String id, CommentSourceType commentSourceType, [bool isFirstFetch = false]) async { + Future getComments(String id, CommentSourceType commentSourceType, [bool isFirstFetch = false]) async { if (isFirstFetch) emit(const CommentsState.loading()); try { switch (commentSourceType) { @@ -27,7 +32,7 @@ class CommentsCubit extends Cubit { case CommentSourceType.recipe: emit(CommentsState.loaded(comment: await feedRepository.getRecipesComments(id: id))); break; - case CommentSourceType.plan: + case CommentSourceType.plan: emit(CommentsState.loaded(comment: await feedRepository.getPlansComments(slug: id))); break; } @@ -78,4 +83,24 @@ class CommentsCubit extends Cubit { emit(CommentsState.error(errorMessage: e.toString())); } } + + Future deleteComment({required int id}) async { + try { + await commentsRepository.deleteComment(id: id); + return true; + } catch (e, st) { + log(e.toString(), stackTrace: st); + } + return false; + } + + Future updateComment({required int id, required String body}) async { + try { + await commentsRepository.updateComment(id: id, body: body); + return true; + } catch (e, st) { + log(e.toString(), stackTrace: st); + } + return false; + } } diff --git a/lib/features/feed/presentation/bloc/comments_cubit/comments_state.dart b/lib/core/comments/comments_cubit/comments_state.dart similarity index 100% rename from lib/features/feed/presentation/bloc/comments_cubit/comments_state.dart rename to lib/core/comments/comments_cubit/comments_state.dart diff --git a/lib/core/comments/presentation/comments_actions_bottom_sheet.dart b/lib/core/comments/presentation/comments_actions_bottom_sheet.dart new file mode 100644 index 00000000..2fc9498e --- /dev/null +++ b/lib/core/comments/presentation/comments_actions_bottom_sheet.dart @@ -0,0 +1,141 @@ +import 'package:eatvio_app/core/theme/custom_text_style.dart'; +import 'package:eatvio_app/core/theme/theme_helper.dart'; +import 'package:eatvio_app/core/widgets/bottom_sheet_handler_bar.dart'; +import 'package:eatvio_app/core/widgets/custom_divider.dart'; +import 'package:eatvio_app/generated/l10n.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; + +void showCommentsActionsBottomSheet( + BuildContext context, { + required void Function()? reply, + required void Function() copy, + required void Function() edit, + required void Function() delete, + required void Function() complain, + required bool isMyComment, +}) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) => Container( + margin: EdgeInsets.only(left: 8, right: 8, bottom: MediaQuery.of(context).padding.bottom), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + color: appTheme.whiteA700, + ), + child: CommentsActionsBottomSheet( + isMyComment: isMyComment, + reply: reply, + copy: copy, + edit: edit, + delete: delete, + complain: complain, + ), + )); +} + +class CommentsActionsBottomSheet extends StatelessWidget { + const CommentsActionsBottomSheet({ + super.key, + required this.isMyComment, + required this.reply, + required this.copy, + required this.edit, + required this.delete, + required this.complain, + }); + final bool isMyComment; + final void Function()? reply; + final void Function() copy; + final void Function() edit; + final void Function() delete; + final void Function() complain; + @override + Widget build(BuildContext context) { + final s = S.of(context); + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox( + height: 7, + ), + const BottomSheetHandlerBar(), + if (isMyComment) + _ActionWidget( + text: s.edit, + iconPath: 'assets/icons/edit_paint.svg', + onTap: edit, + ) + else if (reply != null) + _ActionWidget( + text: s.reply, + iconPath: 'assets/icons/reply.svg', + onTap: reply!, + ), + if (reply != null) const CustomDivider(), + _ActionWidget( + text: s.copy, + iconPath: 'assets/icons/copy2.svg', + onTap: copy, + ), + if (isMyComment) ...[ + if (reply != null) ...[ + const CustomDivider(), + _ActionWidget( + text: s.reply, + iconPath: 'assets/icons/reply.svg', + onTap: reply!, + ), + ], + const CustomDivider(), + _ActionWidget( + text: s.deleteComment, + iconPath: 'assets/icons/red_trash.svg', + onTap: delete, + ), + ] else ...[ + const CustomDivider(), + _ActionWidget( + text: s.complain, + iconPath: 'assets/icons/complain.svg', + onTap: complain, + ), + ] + ], + ), + ); + } +} + +class _ActionWidget extends StatelessWidget { + const _ActionWidget({required this.text, required this.iconPath, required this.onTap}); + final String text; + final String iconPath; + final void Function() onTap; + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () { + Navigator.pop(context); + onTap(); + }, + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 12), + child: Row( + children: [ + Text( + text, + style: TextStyles.textLMedium.copyWith(color: appTheme.black), + ), + const Spacer(), + SvgPicture.asset(iconPath) + ], + ), + ), + ); + } +} diff --git a/lib/core/comments/repositories/comments_repository.dart b/lib/core/comments/repositories/comments_repository.dart new file mode 100644 index 00000000..bc6e654b --- /dev/null +++ b/lib/core/comments/repositories/comments_repository.dart @@ -0,0 +1,23 @@ +import 'package:eatvio_app/core/comments/services/comments_service.dart'; + +class CommentsRepository { + final CommentsService service; + + CommentsRepository({required this.service}); + + Future deleteComment({required int id}) async { + try { + return service.deleteComment(id); + } catch (e) { + rethrow; + } + } + + Future updateComment({required int id, required String body}) async { + try { + return service.updateComment(id, body); + } catch (e) { + rethrow; + } + } +} diff --git a/lib/core/comments/services/comments_service.dart b/lib/core/comments/services/comments_service.dart new file mode 100644 index 00000000..d2db4218 --- /dev/null +++ b/lib/core/comments/services/comments_service.dart @@ -0,0 +1,15 @@ +import 'package:dio/dio.dart'; +import 'package:retrofit/retrofit.dart'; + +part 'comments_service.g.dart'; + +@RestApi() +abstract class CommentsService { + factory CommentsService(Dio dio, {String baseUrl}) = _CommentsService; + + @DELETE('/api/comments/{comment}') + Future deleteComment(@Path('id') int id); + + @PATCH('/api/comments/{comment}') + Future updateComment(@Path('id') int id, @Body() String body); +} diff --git a/lib/core/const.dart b/lib/core/const.dart index 618a9866..4f38a54e 100644 --- a/lib/core/const.dart +++ b/lib/core/const.dart @@ -1,4 +1,5 @@ -String baseUrl = 'https://eatvio.ru'; +// String baseUrl = 'https://eatvio.ru'; +String baseUrl = 'https://dev2.eatvio.com'; const List durationValues = [7, 14, 21]; diff --git a/lib/core/enums/complained_content.dart b/lib/core/enums/complained_content.dart index 66fe8ee1..4df54a33 100644 --- a/lib/core/enums/complained_content.dart +++ b/lib/core/enums/complained_content.dart @@ -1,7 +1 @@ -enum ComplainedContent { - diet, - plan, - recipe, - profile, - posts -} \ No newline at end of file +enum ComplainedContent { diet, plan, recipe, profile, posts, comment } diff --git a/lib/core/locator_service.dart b/lib/core/locator_service.dart index 9036809a..49c6c5dc 100644 --- a/lib/core/locator_service.dart +++ b/lib/core/locator_service.dart @@ -1,4 +1,6 @@ import 'package:dio/dio.dart'; +import 'package:eatvio_app/core/comments/repositories/comments_repository.dart'; +import 'package:eatvio_app/core/comments/services/comments_service.dart'; import 'package:eatvio_app/core/const.dart'; import 'package:eatvio_app/core/dio/phone_verify_error_interceptor.dart'; import 'package:eatvio_app/core/firebase_api.dart'; @@ -56,7 +58,7 @@ import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart'; import 'package:eatvio_app/features/diary/repositories/diary_repository.dart'; import 'package:eatvio_app/features/diary/services/diary_service.dart'; import 'package:eatvio_app/features/diets/presentation/cubit/about_diet_cubit.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart'; +import 'package:eatvio_app/core/comments/comments_cubit/comments_cubit.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/consultants_cubit/consultants_cubit.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/diets_cubit/diets_cubit.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart'; @@ -128,7 +130,7 @@ Future init() async { sl.registerFactory(() => ProfileCubit(profileRepository: sl(), chatRepository: sl(), consultantRepository: sl())); sl.registerFactory(() => profile_plans.PlansCubit(plansRepository: sl())); sl.registerFactory(() => DietsCubit(feedRepository: sl(), dietsRepository: sl())); - sl.registerFactory(() => CommentsCubit(feedRepository: sl())); + sl.registerFactory(() => CommentsCubit(feedRepository: sl(), commentsRepository: sl())); sl.registerFactory(() => PlansCubit(feedRepository: sl(), planRepository: sl())); sl.registerFactory(() => SettingsCubit(profileRepository: sl(), settingsRepository: sl(), consultantRepository: sl())); sl.registerFactory(() => RegisterConsultantCubit(consultantRepository: sl())); @@ -198,6 +200,7 @@ Future init() async { sl.registerFactory(() => MyRecipesRepository(myRecipesService: sl())); sl.registerFactory(() => ResetPasswordRepository(resetPasswordService: sl())); sl.registerLazySingleton(() => BlockedUsersRepository(blockedUserService: sl())); + sl.registerLazySingleton(() => CommentsRepository(service: sl())); // Services sl.registerLazySingleton(() => ChatService(sl())); @@ -230,6 +233,7 @@ Future init() async { sl.registerLazySingleton(() => FirebaseApi()); sl.registerLazySingleton(() => ResetPasswordService(sl())); sl.registerLazySingleton(() => BlockedUserService(sl())); + sl.registerLazySingleton(() => CommentsService(sl())); // External sl.registerLazySingleton( diff --git a/lib/features/blog_post/presentation/pages/blog_post_screen.dart b/lib/features/blog_post/presentation/pages/blog_post_screen.dart index aa4c82c2..25636a57 100644 --- a/lib/features/blog_post/presentation/pages/blog_post_screen.dart +++ b/lib/features/blog_post/presentation/pages/blog_post_screen.dart @@ -7,8 +7,8 @@ import 'package:eatvio_app/core/widgets/custom_popup.dart'; import 'package:eatvio_app/core/widgets/loader.dart'; import 'package:eatvio_app/features/blog_post/presentation/cubit/blog_post_cubit.dart'; import 'package:eatvio_app/features/blog_post/presentation/cubit/blog_post_state.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_state.dart'; +import 'package:eatvio_app/core/comments/comments_cubit/comments_cubit.dart'; +import 'package:eatvio_app/core/comments/comments_cubit/comments_state.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart'; import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart'; import 'package:eatvio_app/core/locator_service.dart'; diff --git a/lib/features/complaining/presentation/cubit/complaining_cubit.dart b/lib/features/complaining/presentation/cubit/complaining_cubit.dart index 0a2827f3..896fa6e9 100644 --- a/lib/features/complaining/presentation/cubit/complaining_cubit.dart +++ b/lib/features/complaining/presentation/cubit/complaining_cubit.dart @@ -72,6 +72,12 @@ class ComplainingCubit extends Cubit { emit(state.copyWith(wasSentSuccessfully: true)); return; } + case ComplainedContent.comment: + if (id != null) { + await repository.sendCommentComplain(id: id, category: category.getValue(), body: state.complainInfo); + emit(state.copyWith(wasSentSuccessfully: true)); + return; + } } } } catch (e, st) { diff --git a/lib/features/complaining/repositories/complaining_repository.dart b/lib/features/complaining/repositories/complaining_repository.dart index 1b1a5d14..32aab577 100644 --- a/lib/features/complaining/repositories/complaining_repository.dart +++ b/lib/features/complaining/repositories/complaining_repository.dart @@ -64,4 +64,16 @@ class ComplainingRepository { rethrow; } } + + Future sendCommentComplain({ + required int id, + required String category, + required ComplainModel body, + }) async { + try { + await service.sendCommentComplain(id: id, category: category, body: body); + } catch (e) { + rethrow; + } + } } diff --git a/lib/features/complaining/services/complaining_service.dart b/lib/features/complaining/services/complaining_service.dart index 242545ad..276ac750 100644 --- a/lib/features/complaining/services/complaining_service.dart +++ b/lib/features/complaining/services/complaining_service.dart @@ -42,5 +42,12 @@ abstract class ComplainingService { @Path() required String category, @Body() required ComplainModel body, }); + + @POST('/api/comments/{id}/complain/{category}') + Future sendCommentComplain({ + @Path() required int id, + @Path() required String category, + @Body() required ComplainModel body, + }); } diff --git a/lib/features/diets/presentation/pages/about_diet_screen.dart b/lib/features/diets/presentation/pages/about_diet_screen.dart index b38d1afd..e4dd4a75 100644 --- a/lib/features/diets/presentation/pages/about_diet_screen.dart +++ b/lib/features/diets/presentation/pages/about_diet_screen.dart @@ -21,8 +21,8 @@ import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart' import 'package:eatvio_app/core/widgets/main_background_bouble.dart'; import 'package:eatvio_app/features/diets/presentation/widgets/start_diet_bottom_sheet.dart'; import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_state.dart'; +import 'package:eatvio_app/core/comments/comments_cubit/comments_cubit.dart'; +import 'package:eatvio_app/core/comments/comments_cubit/comments_state.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart'; import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart'; import 'package:eatvio_app/generated/l10n.dart'; diff --git a/lib/features/feed/presentation/widgets/comments_widget.dart b/lib/features/feed/presentation/widgets/comments_widget.dart index 49f368cd..d3365b15 100644 --- a/lib/features/feed/presentation/widgets/comments_widget.dart +++ b/lib/features/feed/presentation/widgets/comments_widget.dart @@ -1,14 +1,19 @@ +import 'package:eatvio_app/core/comments/presentation/comments_actions_bottom_sheet.dart'; import 'package:eatvio_app/core/const.dart'; +import 'package:eatvio_app/core/enums/complained_content.dart'; import 'package:eatvio_app/core/locator_service.dart'; import 'package:eatvio_app/core/utils/date_time_utils.dart'; +import 'package:eatvio_app/core/utils/toasts.dart'; import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart'; import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_state.dart'; +import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart'; import 'package:eatvio_app/features/feed/models/comment_model.dart'; import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart'; +import 'package:eatvio_app/core/comments/comments_cubit/comments_cubit.dart'; import 'package:eatvio_app/generated/l10n.dart'; import 'package:eatvio_app/core/theme/theme_helper.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; @@ -53,98 +58,128 @@ class _CommentsWidgetState extends State { ); } - Container _comment(S s, Comment comment, [double radius = 18, bool isChild = false]) { - return Container( - width: MediaQuery.of(context).size.width, - decoration: BoxDecoration( - color: widget.replyId == comment.id ? appTheme.blueA400.withValues(alpha: 0.1) : Colors.white, - borderRadius: BorderRadius.circular(16), - ), - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 16), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - GestureDetector( - onTap: () { - GoRouter.of(context).pushNamed( - 'profileScreen', - extra: Author( - authorSlug: comment.authorSlug, - authorName: comment.authorName, - authorProfileIcon: comment.authorProfileIcon.contains('https') ? comment.authorProfileIcon : baseUrl + comment.authorProfileIcon, - authorIsMe: (sl().state as ProfileAvatarStateLoaded).profile.slug == comment.authorSlug ? true : false, - ), - ); - }, - child: CircleAvatar( - foregroundImage: NetworkImage( - comment.authorProfileIcon.contains('https') ? comment.authorProfileIcon : baseUrl + comment.authorProfileIcon, - ), - backgroundImage: const AssetImage('assets/images/no_avatar.png'), - radius: radius, + Widget _comment(S s, Comment comment, [double radius = 18, bool isChild = false]) { + final isMe = (sl().state as ProfileAvatarStateLoaded).profile.slug == comment.authorSlug; + return GestureDetector( + onTap: () { + showCommentsActionsBottomSheet( + context, + reply: !isChild + ? () { + context.read().setReplyId(comment.id); + } + : null, + copy: () { + Clipboard.setData(ClipboardData(text: comment.body)); + showInfoToast(s.link_was_copied); + }, + edit: () {}, + delete: () {}, + complain: () { + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (context) => ComplainingBottomSheet( + complainedContentType: ComplainedContent.comment, + id: comment.id, ), - ), - const SizedBox(width: 8), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - comment.authorName, - style: TextStyle( - height: 1, - color: appTheme.gray, - fontSize: 14, - fontWeight: FontWeight.w500, + ); + }, + isMyComment: isMe, + ); + }, + child: Container( + width: MediaQuery.of(context).size.width, + decoration: BoxDecoration( + color: widget.replyId == comment.id ? appTheme.blueA400.withValues(alpha: 0.1) : Colors.white, + borderRadius: BorderRadius.circular(16), + ), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: () { + GoRouter.of(context).pushNamed( + 'profileScreen', + extra: Author( + authorSlug: comment.authorSlug, + authorName: comment.authorName, + authorProfileIcon: comment.authorProfileIcon.contains('https') ? comment.authorProfileIcon : baseUrl + comment.authorProfileIcon, + authorIsMe: isMe, + ), + ); + }, + child: CircleAvatar( + foregroundImage: NetworkImage( + comment.authorProfileIcon.contains('https') ? comment.authorProfileIcon : baseUrl + comment.authorProfileIcon, ), + backgroundImage: const AssetImage('assets/images/no_avatar.png'), + radius: radius, ), - const SizedBox(height: 4), - SizedBox( - width: isChild ? MediaQuery.of(context).size.width * 0.72 : MediaQuery.of(context).size.width * 0.8, - child: Text( - comment.body, + ), + const SizedBox(width: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + comment.authorName, style: TextStyle( height: 1, - color: appTheme.black, - fontSize: 16, + color: appTheme.gray, + fontSize: 14, fontWeight: FontWeight.w500, ), ), - ), - const SizedBox(height: 4), - Row( - children: [ - Text( - comment.createdAt.format('dd MMMM', 'ru'), + const SizedBox(height: 4), + SizedBox( + width: isChild ? MediaQuery.of(context).size.width * 0.72 : MediaQuery.of(context).size.width * 0.8, + child: Text( + comment.body, style: TextStyle( height: 1, - color: appTheme.gray, - fontSize: 14, + color: appTheme.black, + fontSize: 16, fontWeight: FontWeight.w500, ), ), - const SizedBox(width: 16), - if (!isChild) - GestureDetector( - onTap: () { - context.read().setReplyId(comment.id); - }, - child: Text( - s.answer, - style: TextStyle( - height: 1, - color: appTheme.gray, - fontSize: 14, - fontWeight: FontWeight.w600, - ), + ), + const SizedBox(height: 4), + Row( + children: [ + Text( + comment.createdAt.format('dd MMMM', 'ru'), + style: TextStyle( + height: 1, + color: appTheme.gray, + fontSize: 14, + fontWeight: FontWeight.w500, ), ), - ], - ), - ], - ), - ], + const SizedBox(width: 16), + if (!isChild) + GestureDetector( + onTap: () { + context.read().setReplyId(comment.id); + }, + child: Text( + s.answer, + style: TextStyle( + height: 1, + color: appTheme.gray, + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + ], + ), + ], + ), ), ), ); diff --git a/lib/features/plans/presentation/pages/about_plan_screen.dart b/lib/features/plans/presentation/pages/about_plan_screen.dart index d2984b68..3903fc8d 100644 --- a/lib/features/plans/presentation/pages/about_plan_screen.dart +++ b/lib/features/plans/presentation/pages/about_plan_screen.dart @@ -15,8 +15,8 @@ import 'package:eatvio_app/features/diets/presentation/widgets/author_card.dart' import 'package:eatvio_app/features/diets/presentation/widgets/expandable_text.dart'; import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart'; import 'package:eatvio_app/core/widgets/main_background_bouble.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_state.dart'; +import 'package:eatvio_app/core/comments/comments_cubit/comments_cubit.dart'; +import 'package:eatvio_app/core/comments/comments_cubit/comments_state.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart'; import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart'; import 'package:eatvio_app/features/plans/presentation/cubit/about_plan_cubit.dart'; diff --git a/lib/features/recipe/presentation/pages/about_recipe_screen.dart b/lib/features/recipe/presentation/pages/about_recipe_screen.dart index 8c6a5e8b..f23ac880 100644 --- a/lib/features/recipe/presentation/pages/about_recipe_screen.dart +++ b/lib/features/recipe/presentation/pages/about_recipe_screen.dart @@ -16,8 +16,8 @@ import 'package:eatvio_app/features/diets/presentation/widgets/author_card.dart' import 'package:eatvio_app/features/diets/presentation/widgets/expandable_text.dart'; import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.dart'; import 'package:eatvio_app/core/widgets/main_background_bouble.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart'; -import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_state.dart'; +import 'package:eatvio_app/core/comments/comments_cubit/comments_cubit.dart'; +import 'package:eatvio_app/core/comments/comments_cubit/comments_state.dart'; import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart'; import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart'; import 'package:eatvio_app/features/recipe/presentation/cubit/about_recipe_cubit.dart'; diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index e318c962..73db6f27 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -200,6 +200,7 @@ class MessageLookup extends MessageLookupByLibrary { "continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"), "continue_": MessageLookupByLibrary.simpleMessage("Продолжить"), "copied": MessageLookupByLibrary.simpleMessage("cкопирован"), + "copy": MessageLookupByLibrary.simpleMessage("Скопировать"), "copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"), "copy_referral_link": MessageLookupByLibrary.simpleMessage( "Скопировать пригласительную ссылку", @@ -255,6 +256,9 @@ class MessageLookup extends MessageLookupByLibrary { ), "days": MessageLookupByLibrary.simpleMessage("дней"), "deception": MessageLookupByLibrary.simpleMessage("Обман"), + "deleteComment": MessageLookupByLibrary.simpleMessage( + "Удалить комментарий", + ), "deleted": MessageLookupByLibrary.simpleMessage("Удалена"), "diary": MessageLookupByLibrary.simpleMessage("Дневник"), "diet": MessageLookupByLibrary.simpleMessage("Диета"), @@ -619,6 +623,7 @@ class MessageLookup extends MessageLookupByLibrary { "removeFromActive": MessageLookupByLibrary.simpleMessage( "Снять с публикации", ), + "reply": MessageLookupByLibrary.simpleMessage("Ответить"), "save": MessageLookupByLibrary.simpleMessage("Сохранить"), "send": MessageLookupByLibrary.simpleMessage("Отправить"), "send_complain": MessageLookupByLibrary.simpleMessage("Отправить жалобу"), diff --git a/lib/generated/l10n.dart b/lib/generated/l10n.dart index 9f338062..5a4e420e 100644 --- a/lib/generated/l10n.dart +++ b/lib/generated/l10n.dart @@ -3394,6 +3394,26 @@ class S { args: [], ); } + + /// `Скопировать` + String get copy { + return Intl.message('Скопировать', name: 'copy', desc: '', args: []); + } + + /// `Ответить` + String get reply { + return Intl.message('Ответить', name: 'reply', desc: '', args: []); + } + + /// `Удалить комментарий` + String get deleteComment { + return Intl.message( + 'Удалить комментарий', + name: 'deleteComment', + desc: '', + args: [], + ); + } } class AppLocalizationDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 96ddc4be..2052d17b 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -402,6 +402,10 @@ "allowAcessToGaleryDescription": "Предоставление доступа позволит вам добавлять фото к записям", "allowAccessToCamera": "Разрешите доступ к камере", "allowAccessToCameraDescription": "Предоставление доступа позволит вам делать фотографии и добавлять к записям", - "allowAccess": "Разрешить доступ" + "allowAccess": "Разрешить доступ", + "copy": "Скопировать", + "reply": "Ответить", + "deleteComment": "Удалить комментарий" + }