forked from eatvio/eatvio_app
Compare commits
8 Commits
notificati
...
comments
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9bbd149d03 | ||
|
|
6dc30f4c89 | ||
|
|
0a636e05b8 | ||
|
|
0886d1cd7b | ||
|
|
2759cc64c9 | ||
|
|
cfe6b50c28 | ||
|
|
61d1ad1f55 | ||
|
|
ebe28136af |
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:label="Eatvio"
|
android:label="Eatvio"
|
||||||
|
|||||||
3
assets/icons/reply.svg
Normal file
3
assets/icons/reply.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="19" height="14" viewBox="0 0 19 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3.56039 6.73215L7.06827 10.2925C7.22519 10.452 7.3026 10.6385 7.30049 10.8521C7.29855 11.0656 7.21569 11.2555 7.0519 11.4218C6.88812 11.577 6.70269 11.6573 6.49563 11.6629C6.28874 11.6682 6.1034 11.5879 5.93961 11.4218L1.19568 6.60653C1.0048 6.41278 0.909363 6.1868 0.909363 5.92858C0.909363 5.67037 1.0048 5.44439 1.19568 5.25064L5.93961 0.435368C6.08581 0.287154 6.26675 0.211261 6.48243 0.207689C6.69829 0.204297 6.88812 0.280189 7.0519 0.435368C7.21569 0.601618 7.29759 0.792601 7.29759 1.00831C7.29759 1.22385 7.21569 1.41474 7.0519 1.58099L3.56039 5.12501H13.4583C14.8441 5.12501 16.0261 5.62162 17.0045 6.61483C17.983 7.60787 18.4722 8.80769 18.4722 10.2143V13.1607C18.4722 13.3888 18.3964 13.5797 18.2448 13.7334C18.0933 13.8873 17.9052 13.9643 17.6806 13.9643C17.4559 13.9643 17.2678 13.8873 17.1164 13.7334C16.9647 13.5797 16.8889 13.3888 16.8889 13.1607V10.2143C16.8889 9.25269 16.5539 8.43197 15.884 7.75215C15.2143 7.07215 14.4057 6.73215 13.4583 6.73215H3.56039Z" fill="#2F80ED"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -121,7 +121,7 @@ class AppRouter {
|
|||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'forget-password-screen',
|
path: 'forget-password-screen',
|
||||||
name: 'forgetPasswordScreen',
|
name: 'forgetPasswordScreen',
|
||||||
builder: (context, state) => const ForgetPasswordScreen(),
|
builder: (context, state) => ForgetPasswordScreen(isAuth: state.extra as bool,),
|
||||||
),
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: 'scan-qr-code-screen',
|
path: 'scan-qr-code-screen',
|
||||||
|
|||||||
@@ -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/presentation/widgets/comments_widget.dart';
|
||||||
import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
|
import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
|
||||||
class CommentsCubit extends Cubit<CommentsState> {
|
class CommentsCubit extends Cubit<CommentsState> {
|
||||||
final FeedRepository feedRepository;
|
final FeedRepository feedRepository;
|
||||||
|
final CommentsRepository commentsRepository;
|
||||||
|
|
||||||
CommentsCubit({
|
CommentsCubit({
|
||||||
required this.feedRepository,
|
required this.feedRepository,
|
||||||
|
required this.commentsRepository,
|
||||||
}) : super(const CommentsState());
|
}) : super(const CommentsState());
|
||||||
|
|
||||||
void setReplyId(int? replyId) {
|
void setReplyId(int? replyId) {
|
||||||
emit((state as CommentsStateLoaded).copyWith(replyId: replyId));
|
emit((state as CommentsStateLoaded).copyWith(replyId: replyId));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getComments(String id, CommentSourceType commentSourceType, [bool isFirstFetch = false]) async {
|
Future<void> getComments(String id, CommentSourceType commentSourceType, [bool isFirstFetch = false]) async {
|
||||||
if (isFirstFetch) emit(const CommentsState.loading());
|
if (isFirstFetch) emit(const CommentsState.loading());
|
||||||
try {
|
try {
|
||||||
switch (commentSourceType) {
|
switch (commentSourceType) {
|
||||||
@@ -27,7 +32,7 @@ class CommentsCubit extends Cubit<CommentsState> {
|
|||||||
case CommentSourceType.recipe:
|
case CommentSourceType.recipe:
|
||||||
emit(CommentsState.loaded(comment: await feedRepository.getRecipesComments(id: id)));
|
emit(CommentsState.loaded(comment: await feedRepository.getRecipesComments(id: id)));
|
||||||
break;
|
break;
|
||||||
case CommentSourceType.plan:
|
case CommentSourceType.plan:
|
||||||
emit(CommentsState.loaded(comment: await feedRepository.getPlansComments(slug: id)));
|
emit(CommentsState.loaded(comment: await feedRepository.getPlansComments(slug: id)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -78,4 +83,34 @@ class CommentsCubit extends Cubit<CommentsState> {
|
|||||||
emit(CommentsState.error(errorMessage: e.toString()));
|
emit(CommentsState.error(errorMessage: e.toString()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> deleteComment({required int id}) async {
|
||||||
|
if (state is! CommentsStateLoaded) return false;
|
||||||
|
final commentModel = (state as CommentsStateLoaded).comment;
|
||||||
|
final updatedCommentModel = commentModel.copyWith(data: commentModel.data.where((comment) => comment.id != id).toList());
|
||||||
|
try {
|
||||||
|
await commentsRepository.deleteComment(id: id);
|
||||||
|
emit(CommentsState.loaded(comment: updatedCommentModel));
|
||||||
|
return true;
|
||||||
|
} catch (e, st) {
|
||||||
|
emit(CommentsState.loaded(comment: commentModel));
|
||||||
|
log(e.toString(), stackTrace: st);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> updateComment({required int id, required String body}) async {
|
||||||
|
final commentModel = (state as CommentsStateLoaded).comment;
|
||||||
|
final updatedCommentModel =
|
||||||
|
commentModel.copyWith(data: commentModel.data.map((comment) => comment.id == id ? comment.copyWith(body: body) : comment).toList());
|
||||||
|
try {
|
||||||
|
await commentsRepository.updateComment(id: id, body: body);
|
||||||
|
emit(CommentsState.loaded(comment: updatedCommentModel));
|
||||||
|
return true;
|
||||||
|
} catch (e, st) {
|
||||||
|
emit(CommentsState.loaded(comment: commentModel));
|
||||||
|
log(e.toString(), stackTrace: st);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -12,6 +12,7 @@ abstract class CommentsState with _$CommentsState {
|
|||||||
const factory CommentsState.loaded({
|
const factory CommentsState.loaded({
|
||||||
required CommentModel comment,
|
required CommentModel comment,
|
||||||
int? replyId,
|
int? replyId,
|
||||||
|
int? editedCommentId,
|
||||||
}) = CommentsStateLoaded;
|
}) = CommentsStateLoaded;
|
||||||
|
|
||||||
const factory CommentsState.error({
|
const factory CommentsState.error({
|
||||||
12
lib/core/comments/models/comment_update_model.dart
Normal file
12
lib/core/comments/models/comment_update_model.dart
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'comment_update_model.freezed.dart';
|
||||||
|
part 'comment_update_model.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
abstract class CommentUpdateModel with _$CommentUpdateModel {
|
||||||
|
|
||||||
|
factory CommentUpdateModel({required String body}) = _CommentUpdateModel;
|
||||||
|
|
||||||
|
factory CommentUpdateModel.fromJson(Map<String, dynamic> json) => _$CommentUpdateModelFromJson(json);
|
||||||
|
}
|
||||||
@@ -0,0 +1,203 @@
|
|||||||
|
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/core/widgets/custom_text_form_field.dart';
|
||||||
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
|
void showCommentsActionsBottomSheet(
|
||||||
|
BuildContext context, {
|
||||||
|
required void Function()? reply,
|
||||||
|
required void Function() copy,
|
||||||
|
required void Function(String text) edit,
|
||||||
|
required void Function() delete,
|
||||||
|
required void Function() complain,
|
||||||
|
required String commentText,
|
||||||
|
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,
|
||||||
|
commentText: commentText,
|
||||||
|
),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
class CommentsActionsBottomSheet extends StatefulWidget {
|
||||||
|
const CommentsActionsBottomSheet({
|
||||||
|
super.key,
|
||||||
|
required this.isMyComment,
|
||||||
|
required this.reply,
|
||||||
|
required this.copy,
|
||||||
|
required this.edit,
|
||||||
|
required this.delete,
|
||||||
|
required this.complain,
|
||||||
|
required this.commentText,
|
||||||
|
});
|
||||||
|
final bool isMyComment;
|
||||||
|
final void Function()? reply;
|
||||||
|
final void Function() copy;
|
||||||
|
final void Function(String text) edit;
|
||||||
|
final void Function() delete;
|
||||||
|
final void Function() complain;
|
||||||
|
final String commentText;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<CommentsActionsBottomSheet> createState() => _CommentsActionsBottomSheetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _CommentsActionsBottomSheetState extends State<CommentsActionsBottomSheet> {
|
||||||
|
bool isUserEditingComment = false;
|
||||||
|
final controller = TextEditingController();
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
controller.text = widget.commentText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final s = S.of(context);
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: isUserEditingComment
|
||||||
|
? Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Row(children: [
|
||||||
|
Expanded(
|
||||||
|
child: CustomTextFormField(
|
||||||
|
autofocus: true,
|
||||||
|
controller: controller,
|
||||||
|
onChanged: (value) => setState(() {}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
widget.edit(controller.text);
|
||||||
|
GoRouter.of(context).pop();
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: controller.text.length > 2 ? appTheme.blueA400 : appTheme.gray50,
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
),
|
||||||
|
height: 32,
|
||||||
|
width: 32,
|
||||||
|
child: Icon(
|
||||||
|
Icons.send_rounded,
|
||||||
|
size: 18,
|
||||||
|
color: controller.text.length > 2 ? appTheme.whiteA700 : appTheme.black,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
])
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 7,
|
||||||
|
),
|
||||||
|
const BottomSheetHandlerBar(),
|
||||||
|
if (widget.isMyComment)
|
||||||
|
_ActionWidget(
|
||||||
|
text: s.edit,
|
||||||
|
iconPath: 'assets/icons/edit_paint.svg',
|
||||||
|
needToPop: false,
|
||||||
|
onTap: () => setState(() {
|
||||||
|
isUserEditingComment = true;
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
else if (widget.reply != null)
|
||||||
|
_ActionWidget(
|
||||||
|
text: s.reply,
|
||||||
|
iconPath: 'assets/icons/reply.svg',
|
||||||
|
onTap: widget.reply!,
|
||||||
|
),
|
||||||
|
if (widget.reply != null) const CustomDivider(),
|
||||||
|
_ActionWidget(
|
||||||
|
text: s.copy,
|
||||||
|
iconPath: 'assets/icons/copy2.svg',
|
||||||
|
onTap: widget.copy,
|
||||||
|
),
|
||||||
|
if (widget.isMyComment) ...[
|
||||||
|
if (widget.reply != null) ...[
|
||||||
|
const CustomDivider(),
|
||||||
|
_ActionWidget(
|
||||||
|
text: s.reply,
|
||||||
|
iconPath: 'assets/icons/reply.svg',
|
||||||
|
onTap: widget.reply!,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
const CustomDivider(),
|
||||||
|
_ActionWidget(
|
||||||
|
text: s.deleteComment,
|
||||||
|
iconPath: 'assets/icons/red_trash.svg',
|
||||||
|
onTap: widget.delete,
|
||||||
|
),
|
||||||
|
] else ...[
|
||||||
|
const CustomDivider(),
|
||||||
|
_ActionWidget(
|
||||||
|
text: s.complain,
|
||||||
|
iconPath: 'assets/icons/complain.svg',
|
||||||
|
onTap: widget.complain,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ActionWidget extends StatelessWidget {
|
||||||
|
const _ActionWidget({required this.text, required this.iconPath, required this.onTap, this.needToPop = true});
|
||||||
|
final String text;
|
||||||
|
final String iconPath;
|
||||||
|
final void Function() onTap;
|
||||||
|
final bool needToPop;
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
if (needToPop) 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)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
24
lib/core/comments/repositories/comments_repository.dart
Normal file
24
lib/core/comments/repositories/comments_repository.dart
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import 'package:eatvio_app/core/comments/models/comment_update_model.dart';
|
||||||
|
import 'package:eatvio_app/core/comments/services/comments_service.dart';
|
||||||
|
|
||||||
|
class CommentsRepository {
|
||||||
|
final CommentsService service;
|
||||||
|
|
||||||
|
CommentsRepository({required this.service});
|
||||||
|
|
||||||
|
Future<void> deleteComment({required int id}) async {
|
||||||
|
try {
|
||||||
|
return service.deleteComment(id);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> updateComment({required int id, required String body}) async {
|
||||||
|
try {
|
||||||
|
return service.updateComment(id, CommentUpdateModel(body: body));
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
lib/core/comments/services/comments_service.dart
Normal file
16
lib/core/comments/services/comments_service.dart
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:eatvio_app/core/comments/models/comment_update_model.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/{id}')
|
||||||
|
Future<void> deleteComment(@Path('id') int id);
|
||||||
|
|
||||||
|
@PATCH('/api/comments/{id}')
|
||||||
|
Future<void> updateComment(@Path('id') int id, @Body() CommentUpdateModel body);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
String baseUrl = 'https://eatvio.ru';
|
String baseUrl = 'https://eatvio.ru';
|
||||||
|
// String baseUrl = 'https://dev2.eatvio.com';
|
||||||
|
|
||||||
const List<int> durationValues = [7, 14, 21];
|
const List<int> durationValues = [7, 14, 21];
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1 @@
|
|||||||
enum ComplainedContent {
|
enum ComplainedContent { diet, plan, recipe, profile, posts, comment }
|
||||||
diet,
|
|
||||||
plan,
|
|
||||||
recipe,
|
|
||||||
profile,
|
|
||||||
posts
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import 'package:dio/dio.dart';
|
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/const.dart';
|
||||||
import 'package:eatvio_app/core/dio/phone_verify_error_interceptor.dart';
|
import 'package:eatvio_app/core/dio/phone_verify_error_interceptor.dart';
|
||||||
import 'package:eatvio_app/core/firebase_api.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/repositories/diary_repository.dart';
|
||||||
import 'package:eatvio_app/features/diary/services/diary_service.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/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/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/diets_cubit/diets_cubit.dart';
|
||||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
||||||
@@ -128,7 +130,7 @@ Future<void> init() async {
|
|||||||
sl.registerFactory<ProfileCubit>(() => ProfileCubit(profileRepository: sl(), chatRepository: sl(), consultantRepository: sl()));
|
sl.registerFactory<ProfileCubit>(() => ProfileCubit(profileRepository: sl(), chatRepository: sl(), consultantRepository: sl()));
|
||||||
sl.registerFactory<profile_plans.PlansCubit>(() => profile_plans.PlansCubit(plansRepository: sl()));
|
sl.registerFactory<profile_plans.PlansCubit>(() => profile_plans.PlansCubit(plansRepository: sl()));
|
||||||
sl.registerFactory<DietsCubit>(() => DietsCubit(feedRepository: sl(), dietsRepository: sl()));
|
sl.registerFactory<DietsCubit>(() => DietsCubit(feedRepository: sl(), dietsRepository: sl()));
|
||||||
sl.registerFactory<CommentsCubit>(() => CommentsCubit(feedRepository: sl()));
|
sl.registerFactory<CommentsCubit>(() => CommentsCubit(feedRepository: sl(), commentsRepository: sl()));
|
||||||
sl.registerFactory<PlansCubit>(() => PlansCubit(feedRepository: sl(), planRepository: sl()));
|
sl.registerFactory<PlansCubit>(() => PlansCubit(feedRepository: sl(), planRepository: sl()));
|
||||||
sl.registerFactory<SettingsCubit>(() => SettingsCubit(profileRepository: sl(), settingsRepository: sl(), consultantRepository: sl()));
|
sl.registerFactory<SettingsCubit>(() => SettingsCubit(profileRepository: sl(), settingsRepository: sl(), consultantRepository: sl()));
|
||||||
sl.registerFactory<RegisterConsultantCubit>(() => RegisterConsultantCubit(consultantRepository: sl()));
|
sl.registerFactory<RegisterConsultantCubit>(() => RegisterConsultantCubit(consultantRepository: sl()));
|
||||||
@@ -198,6 +200,7 @@ Future<void> init() async {
|
|||||||
sl.registerFactory<MyRecipesRepository>(() => MyRecipesRepository(myRecipesService: sl()));
|
sl.registerFactory<MyRecipesRepository>(() => MyRecipesRepository(myRecipesService: sl()));
|
||||||
sl.registerFactory<ResetPasswordRepository>(() => ResetPasswordRepository(resetPasswordService: sl()));
|
sl.registerFactory<ResetPasswordRepository>(() => ResetPasswordRepository(resetPasswordService: sl()));
|
||||||
sl.registerLazySingleton<BlockedUsersRepository>(() => BlockedUsersRepository(blockedUserService: sl()));
|
sl.registerLazySingleton<BlockedUsersRepository>(() => BlockedUsersRepository(blockedUserService: sl()));
|
||||||
|
sl.registerLazySingleton<CommentsRepository>(() => CommentsRepository(service: sl()));
|
||||||
|
|
||||||
// Services
|
// Services
|
||||||
sl.registerLazySingleton<ChatService>(() => ChatService(sl()));
|
sl.registerLazySingleton<ChatService>(() => ChatService(sl()));
|
||||||
@@ -230,6 +233,7 @@ Future<void> init() async {
|
|||||||
sl.registerLazySingleton<FirebaseApi>(() => FirebaseApi());
|
sl.registerLazySingleton<FirebaseApi>(() => FirebaseApi());
|
||||||
sl.registerLazySingleton<ResetPasswordService>(() => ResetPasswordService(sl()));
|
sl.registerLazySingleton<ResetPasswordService>(() => ResetPasswordService(sl()));
|
||||||
sl.registerLazySingleton<BlockedUserService>(() => BlockedUserService(sl()));
|
sl.registerLazySingleton<BlockedUserService>(() => BlockedUserService(sl()));
|
||||||
|
sl.registerLazySingleton<CommentsService>(() => CommentsService(sl()));
|
||||||
|
|
||||||
// External
|
// External
|
||||||
sl.registerLazySingleton(
|
sl.registerLazySingleton(
|
||||||
|
|||||||
@@ -26,9 +26,13 @@ class SuccessPublishedRecipeBottomSheet extends StatelessWidget {
|
|||||||
s.recipe_publishing,
|
s.recipe_publishing,
|
||||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||||
),
|
),
|
||||||
Text(
|
Padding(
|
||||||
'"$title" ${s.successfully_published}',
|
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||||
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
child: Text(
|
||||||
|
'"$title" ${s.successfully_published}',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyles.headingXLSemibold.copyWith(color: appTheme.black),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(
|
const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ class _AuthScreenState extends State<AuthScreen> {
|
|||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Center(
|
Center(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
onTap: () => GoRouter.of(context).goNamed('forgetPasswordScreen'),
|
onTap: () => GoRouter.of(context).goNamed('forgetPasswordScreen', extra: false),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Забыли пароль?',
|
'Забыли пароль?',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
|||||||
@@ -9,7 +9,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
class ForgetPasswordScreen extends StatefulWidget {
|
class ForgetPasswordScreen extends StatefulWidget {
|
||||||
const ForgetPasswordScreen({super.key});
|
final bool isAuth;
|
||||||
|
const ForgetPasswordScreen({super.key, required this.isAuth});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ForgetPasswordScreen> createState() => _ForgetPasswordScreenState();
|
State<ForgetPasswordScreen> createState() => _ForgetPasswordScreenState();
|
||||||
@@ -29,7 +30,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
|||||||
builder: (BuildContext context, ResetPasswordState state) {
|
builder: (BuildContext context, ResetPasswordState state) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Смена пароля'),
|
title: widget.isAuth ? const Text('Смена пароля') : const Text('Восстановление пароля'),
|
||||||
centerTitle: false,
|
centerTitle: false,
|
||||||
),
|
),
|
||||||
body: state is ResetPasswordStateLoadingResetPassword || state is ResetPasswordStateLoadingSendEmailCode
|
body: state is ResetPasswordStateLoadingResetPassword || state is ResetPasswordStateLoadingSendEmailCode
|
||||||
@@ -42,9 +43,9 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (state is ResetPasswordStateCodeSendError || state is ResetPasswordStateEmpty) ...[
|
if (state is ResetPasswordStateCodeSendError || state is ResetPasswordStateEmpty) ...[
|
||||||
const Text(
|
Text(
|
||||||
'Забыли пароль? Укажите свой email,\nи мы пришлём код для сброса.',
|
'${widget.isAuth ? '' : 'Забыли пароль? '}Укажите свой email,\nи мы пришлём код для сброса.',
|
||||||
style: TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
@@ -156,7 +157,7 @@ class _ForgetPasswordScreenState extends State<ForgetPasswordScreen> {
|
|||||||
}
|
}
|
||||||
if (state is ResetPasswordStateResetPassowrdSuccess) {
|
if (state is ResetPasswordStateResetPassowrdSuccess) {
|
||||||
GoRouter.of(context).pop();
|
GoRouter.of(context).pop();
|
||||||
showSuccessToast('Пароль успешно сменён. Войдите в аккаунт');
|
showSuccessToast('Пароль успешно сменён. ${widget.isAuth ? '' : 'Войдите в аккаунт'}');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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/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_cubit.dart';
|
||||||
import 'package:eatvio_app/features/blog_post/presentation/cubit/blog_post_state.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/core/comments/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_state.dart';
|
||||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.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/feed/presentation/widgets/comments_widget.dart';
|
||||||
import 'package:eatvio_app/core/locator_service.dart';
|
import 'package:eatvio_app/core/locator_service.dart';
|
||||||
|
|||||||
@@ -72,6 +72,12 @@ class ComplainingCubit extends Cubit<ComplainingState> {
|
|||||||
emit(state.copyWith(wasSentSuccessfully: true));
|
emit(state.copyWith(wasSentSuccessfully: true));
|
||||||
return;
|
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) {
|
} catch (e, st) {
|
||||||
|
|||||||
@@ -64,4 +64,16 @@ class ComplainingRepository {
|
|||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> sendCommentComplain({
|
||||||
|
required int id,
|
||||||
|
required String category,
|
||||||
|
required ComplainModel body,
|
||||||
|
}) async {
|
||||||
|
try {
|
||||||
|
await service.sendCommentComplain(id: id, category: category, body: body);
|
||||||
|
} catch (e) {
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,5 +42,12 @@ abstract class ComplainingService {
|
|||||||
@Path() required String category,
|
@Path() required String category,
|
||||||
@Body() required ComplainModel body,
|
@Body() required ComplainModel body,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@POST('/api/comments/{id}/complain/{category}')
|
||||||
|
Future<void> sendCommentComplain({
|
||||||
|
@Path() required int id,
|
||||||
|
@Path() required String category,
|
||||||
|
@Body() required ComplainModel body,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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/core/widgets/main_background_bouble.dart';
|
||||||
import 'package:eatvio_app/features/diets/presentation/widgets/start_diet_bottom_sheet.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/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/features/feed/presentation/bloc/comments_cubit/comments_state.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/bloc/feed_cubit/feed_cubit.dart';
|
||||||
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
||||||
import 'package:eatvio_app/generated/l10n.dart';
|
import 'package:eatvio_app/generated/l10n.dart';
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ class ExpandableText extends StatefulWidget {
|
|||||||
final String text;
|
final String text;
|
||||||
final int maxLines;
|
final int maxLines;
|
||||||
|
|
||||||
const ExpandableText({super.key, required this.text, this.maxLines = 3});
|
const ExpandableText({
|
||||||
|
super.key,
|
||||||
|
required this.text,
|
||||||
|
this.maxLines = 5, // по умолчанию 5 строк
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<ExpandableText> createState() => _ExpandableTextState();
|
State<ExpandableText> createState() => _ExpandableTextState();
|
||||||
@@ -18,6 +22,29 @@ class ExpandableText extends StatefulWidget {
|
|||||||
|
|
||||||
class _ExpandableTextState extends State<ExpandableText> {
|
class _ExpandableTextState extends State<ExpandableText> {
|
||||||
bool isExpanded = false;
|
bool isExpanded = false;
|
||||||
|
bool showExpandButton = false;
|
||||||
|
|
||||||
|
final GlobalKey _textKey = GlobalKey();
|
||||||
|
|
||||||
|
@override
|
||||||
|
void didChangeDependencies() {
|
||||||
|
super.didChangeDependencies();
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) => _checkTextOverflow());
|
||||||
|
}
|
||||||
|
|
||||||
|
void _checkTextOverflow() {
|
||||||
|
final textRenderObject = _textKey.currentContext?.findRenderObject();
|
||||||
|
if (textRenderObject is RenderBox) {
|
||||||
|
final maxLinesHeight = widget.maxLines * TextStyles.textMMediumAuto.fontSize! * 1.2;
|
||||||
|
final actualHeight = textRenderObject.size.height;
|
||||||
|
|
||||||
|
if (actualHeight > maxLinesHeight && !showExpandButton) {
|
||||||
|
setState(() {
|
||||||
|
showExpandButton = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void toggleExpansion() {
|
void toggleExpansion() {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -33,52 +60,63 @@ class _ExpandableTextState extends State<ExpandableText> {
|
|||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
child: Stack(
|
child: AnimatedSize(
|
||||||
children: [
|
duration: const Duration(milliseconds: 200),
|
||||||
Text(
|
curve: Curves.easeInOut,
|
||||||
widget.text,
|
child: Stack(
|
||||||
style: TextStyles.textMMediumAuto.copyWith(color: appTheme.black),
|
children: [
|
||||||
// style: {
|
Text(
|
||||||
// "*": Style(
|
widget.text,
|
||||||
// margin: Margins.all(0),
|
key: _textKey,
|
||||||
// color: Colors.black87,
|
style: TextStyles.textMMediumAuto.copyWith(color: appTheme.black),
|
||||||
// maxLines: isExpanded ? null : widget.maxLines,
|
maxLines: isExpanded ? null : widget.maxLines,
|
||||||
// textOverflow: TextOverflow.clip,
|
overflow: TextOverflow.clip,
|
||||||
// ),
|
),
|
||||||
// },
|
if (!isExpanded && showExpandButton)
|
||||||
),
|
Positioned.fill(
|
||||||
if (!isExpanded)
|
child: Align(
|
||||||
Positioned.fill(
|
alignment: Alignment.bottomCenter,
|
||||||
child: Align(
|
child: Container(
|
||||||
alignment: Alignment.bottomCenter,
|
height: 35,
|
||||||
child: Container(
|
decoration: BoxDecoration(
|
||||||
height: 35,
|
gradient: LinearGradient(
|
||||||
decoration: BoxDecoration(
|
begin: Alignment.topCenter,
|
||||||
gradient: LinearGradient(
|
end: Alignment.bottomCenter,
|
||||||
begin: Alignment.topCenter,
|
colors: [
|
||||||
end: Alignment.bottomCenter,
|
Colors.white.withAlpha(0),
|
||||||
colors: [Colors.white.withValues(alpha: 0.0), Colors.white.withValues(alpha: 0.6), Colors.white],
|
Colors.white.withAlpha((255 * 0.6).toInt()),
|
||||||
|
Colors.white,
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
|
||||||
alignment: Alignment.bottomCenter,
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: toggleExpansion,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text(isExpanded ? s.hide : s.expand, style: TextStyles.textMMedium.copyWith(color: appTheme.blueA400)),
|
|
||||||
Transform.rotate(angle: isExpanded ? math.pi : 0, child: SvgPicture.asset('assets/icons/arrow_down.svg', width: 12, height: 12)),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (showExpandButton)
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: toggleExpansion,
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
isExpanded ? s.hide : s.expand,
|
||||||
|
style: TextStyles.textMMedium.copyWith(color: appTheme.blueA400),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 4),
|
||||||
|
Transform.rotate(
|
||||||
|
angle: isExpanded ? math.pi : 0,
|
||||||
|
child: SvgPicture.asset('assets/icons/arrow_down.svg', width: 12, height: 12),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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/const.dart';
|
||||||
|
import 'package:eatvio_app/core/enums/complained_content.dart';
|
||||||
import 'package:eatvio_app/core/locator_service.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/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_cubit.dart';
|
||||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_state.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/comment_model.dart';
|
||||||
import 'package:eatvio_app/features/feed/models/diets_pagination_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/generated/l10n.dart';
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
@@ -53,98 +58,133 @@ class _CommentsWidgetState extends State<CommentsWidget> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Container _comment(S s, Comment comment, [double radius = 18, bool isChild = false]) {
|
Widget _comment(S s, Comment comment, [double radius = 18, bool isChild = false]) {
|
||||||
return Container(
|
final isMe = (sl<ProfileAvatarCubit>().state as ProfileAvatarStateLoaded).profile.slug == comment.authorSlug;
|
||||||
width: MediaQuery.of(context).size.width,
|
return GestureDetector(
|
||||||
decoration: BoxDecoration(
|
onTap: () {
|
||||||
color: widget.replyId == comment.id ? appTheme.blueA400.withValues(alpha: 0.1) : Colors.white,
|
showCommentsActionsBottomSheet(
|
||||||
borderRadius: BorderRadius.circular(16),
|
context,
|
||||||
),
|
commentText: comment.body,
|
||||||
child: Padding(
|
reply: !isChild
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
? () {
|
||||||
child: Row(
|
context.read<CommentsCubit>().setReplyId(comment.id);
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
}
|
||||||
children: [
|
: null,
|
||||||
GestureDetector(
|
copy: () {
|
||||||
onTap: () {
|
Clipboard.setData(ClipboardData(text: comment.body));
|
||||||
GoRouter.of(context).pushNamed(
|
showInfoToast(s.link_was_copied);
|
||||||
'profileScreen',
|
},
|
||||||
extra: Author(
|
edit: (String text) {
|
||||||
authorSlug: comment.authorSlug,
|
context.read<CommentsCubit>().updateComment(id: comment.id, body: text);
|
||||||
authorName: comment.authorName,
|
},
|
||||||
authorProfileIcon: comment.authorProfileIcon.contains('https') ? comment.authorProfileIcon : baseUrl + comment.authorProfileIcon,
|
delete: () {
|
||||||
authorIsMe: (sl<ProfileAvatarCubit>().state as ProfileAvatarStateLoaded).profile.slug == comment.authorSlug ? true : false,
|
context.read<CommentsCubit>().deleteComment(id: comment.id);
|
||||||
),
|
},
|
||||||
);
|
complain: () {
|
||||||
},
|
showModalBottomSheet(
|
||||||
child: CircleAvatar(
|
context: context,
|
||||||
foregroundImage: NetworkImage(
|
isScrollControlled: true,
|
||||||
comment.authorProfileIcon.contains('https') ? comment.authorProfileIcon : baseUrl + comment.authorProfileIcon,
|
builder: (context) => ComplainingBottomSheet(
|
||||||
),
|
complainedContentType: ComplainedContent.comment,
|
||||||
backgroundImage: const AssetImage('assets/images/no_avatar.png'),
|
id: comment.id,
|
||||||
radius: radius,
|
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
const SizedBox(width: 8),
|
},
|
||||||
Column(
|
isMyComment: isMe,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
);
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
},
|
||||||
children: [
|
child: Container(
|
||||||
Text(
|
width: MediaQuery.of(context).size.width,
|
||||||
comment.authorName,
|
decoration: BoxDecoration(
|
||||||
style: TextStyle(
|
color: widget.replyId == comment.id ? appTheme.blueA400.withValues(alpha: 0.1) : Colors.white,
|
||||||
height: 1,
|
borderRadius: BorderRadius.circular(16),
|
||||||
color: appTheme.gray,
|
),
|
||||||
fontSize: 14,
|
child: Padding(
|
||||||
fontWeight: FontWeight.w500,
|
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(
|
const SizedBox(width: 8),
|
||||||
width: isChild ? MediaQuery.of(context).size.width * 0.72 : MediaQuery.of(context).size.width * 0.8,
|
Column(
|
||||||
child: Text(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
comment.body,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
comment.authorName,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
height: 1,
|
height: 1,
|
||||||
color: appTheme.black,
|
color: appTheme.gray,
|
||||||
fontSize: 16,
|
fontSize: 14,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 4),
|
||||||
const SizedBox(height: 4),
|
SizedBox(
|
||||||
Row(
|
width: isChild ? MediaQuery.of(context).size.width * 0.72 : MediaQuery.of(context).size.width * 0.8,
|
||||||
children: [
|
child: Text(
|
||||||
Text(
|
comment.body,
|
||||||
comment.createdAt.format('dd MMMM', 'ru'),
|
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
height: 1,
|
height: 1,
|
||||||
color: appTheme.gray,
|
color: appTheme.black,
|
||||||
fontSize: 14,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
),
|
||||||
if (!isChild)
|
const SizedBox(height: 4),
|
||||||
GestureDetector(
|
Row(
|
||||||
onTap: () {
|
children: [
|
||||||
context.read<CommentsCubit>().setReplyId(comment.id);
|
Text(
|
||||||
},
|
comment.createdAt.format('dd MMMM', 'ru'),
|
||||||
child: Text(
|
style: TextStyle(
|
||||||
s.answer,
|
height: 1,
|
||||||
style: TextStyle(
|
color: appTheme.gray,
|
||||||
height: 1,
|
fontSize: 14,
|
||||||
color: appTheme.gray,
|
fontWeight: FontWeight.w500,
|
||||||
fontSize: 14,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
const SizedBox(width: 16),
|
||||||
),
|
if (!isChild)
|
||||||
],
|
GestureDetector(
|
||||||
),
|
onTap: () {
|
||||||
],
|
context.read<CommentsCubit>().setReplyId(comment.id);
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
s.answer,
|
||||||
|
style: TextStyle(
|
||||||
|
height: 1,
|
||||||
|
color: appTheme.gray,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -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/expandable_text.dart';
|
||||||
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.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/core/widgets/main_background_bouble.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/comments_cubit/comments_state.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/bloc/feed_cubit/feed_cubit.dart';
|
||||||
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
||||||
import 'package:eatvio_app/features/plans/presentation/cubit/about_plan_cubit.dart';
|
import 'package:eatvio_app/features/plans/presentation/cubit/about_plan_cubit.dart';
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
|||||||
Scaffold _myProfileScreen(ProfileStateLoaded state) {
|
Scaffold _myProfileScreen(ProfileStateLoaded state) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.grey.shade200,
|
backgroundColor: Colors.grey.shade200,
|
||||||
appBar: AppBar(toolbarHeight: 0),
|
appBar: AppBar(),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|||||||
@@ -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/expandable_text.dart';
|
||||||
import 'package:eatvio_app/features/diets/presentation/widgets/info_bouble.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/core/widgets/main_background_bouble.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/comments_cubit/comments_state.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/bloc/feed_cubit/feed_cubit.dart';
|
||||||
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
import 'package:eatvio_app/features/feed/presentation/widgets/comments_widget.dart';
|
||||||
import 'package:eatvio_app/features/recipe/presentation/cubit/about_recipe_cubit.dart';
|
import 'package:eatvio_app/features/recipe/presentation/cubit/about_recipe_cubit.dart';
|
||||||
@@ -205,14 +205,14 @@ class _AboutRecipeScreenState extends State<AboutRecipeScreen> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
leading: BackButton(
|
leading: BackButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (context.canPop()) {
|
if (context.canPop()) {
|
||||||
GoRouter.of(context).pop();
|
GoRouter.of(context).pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GoRouter.of(context).go('/feed-screen');
|
GoRouter.of(context).go('/feed-screen');
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
recipeState.recipe.title ?? '',
|
recipeState.recipe.title ?? '',
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
@@ -356,6 +356,7 @@ class _AboutRecipeScreenState extends State<AboutRecipeScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
ExpandableText(text: recipeState.recipe.description),
|
ExpandableText(text: recipeState.recipe.description),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
Padding(
|
Padding(
|
||||||
@@ -400,14 +401,14 @@ class _AboutRecipeScreenState extends State<AboutRecipeScreen> {
|
|||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
leading: BackButton(
|
leading: BackButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (context.canPop()) {
|
if (context.canPop()) {
|
||||||
GoRouter.of(context).pop();
|
GoRouter.of(context).pop();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
GoRouter.of(context).go('/feed-screen');
|
GoRouter.of(context).go('/feed-screen');
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
'',
|
'',
|
||||||
maxLines: 2,
|
maxLines: 2,
|
||||||
|
|||||||
@@ -164,12 +164,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
|
|||||||
_divider(context),
|
_divider(context),
|
||||||
_tile(
|
_tile(
|
||||||
onTap: () => GoRouter.of(context).pushNamed(
|
onTap: () => GoRouter.of(context).pushNamed(
|
||||||
'changePasswordScreen',
|
'forgetPasswordScreen',
|
||||||
extra: SettingsEntity(
|
extra: true,
|
||||||
profileSettingsModel: state.profileSettings,
|
|
||||||
profileDetailsModel: state.profileDetails,
|
|
||||||
settingsCubit: settingsCubit,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
title: 'Сменить пароль',
|
title: 'Сменить пароль',
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -200,6 +200,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
"continueButton": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||||
"continue_": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
"continue_": MessageLookupByLibrary.simpleMessage("Продолжить"),
|
||||||
"copied": MessageLookupByLibrary.simpleMessage("cкопирован"),
|
"copied": MessageLookupByLibrary.simpleMessage("cкопирован"),
|
||||||
|
"copy": MessageLookupByLibrary.simpleMessage("Скопировать"),
|
||||||
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
"copy_link": MessageLookupByLibrary.simpleMessage("Скопировать ссылку"),
|
||||||
"copy_referral_link": MessageLookupByLibrary.simpleMessage(
|
"copy_referral_link": MessageLookupByLibrary.simpleMessage(
|
||||||
"Скопировать пригласительную ссылку",
|
"Скопировать пригласительную ссылку",
|
||||||
@@ -255,6 +256,9 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
),
|
),
|
||||||
"days": MessageLookupByLibrary.simpleMessage("дней"),
|
"days": MessageLookupByLibrary.simpleMessage("дней"),
|
||||||
"deception": MessageLookupByLibrary.simpleMessage("Обман"),
|
"deception": MessageLookupByLibrary.simpleMessage("Обман"),
|
||||||
|
"deleteComment": MessageLookupByLibrary.simpleMessage(
|
||||||
|
"Удалить комментарий",
|
||||||
|
),
|
||||||
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
|
"deleted": MessageLookupByLibrary.simpleMessage("Удалена"),
|
||||||
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
|
"diary": MessageLookupByLibrary.simpleMessage("Дневник"),
|
||||||
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
|
"diet": MessageLookupByLibrary.simpleMessage("Диета"),
|
||||||
@@ -619,6 +623,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"removeFromActive": MessageLookupByLibrary.simpleMessage(
|
"removeFromActive": MessageLookupByLibrary.simpleMessage(
|
||||||
"Снять с публикации",
|
"Снять с публикации",
|
||||||
),
|
),
|
||||||
|
"reply": MessageLookupByLibrary.simpleMessage("Ответить"),
|
||||||
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
|
"save": MessageLookupByLibrary.simpleMessage("Сохранить"),
|
||||||
"send": MessageLookupByLibrary.simpleMessage("Отправить"),
|
"send": MessageLookupByLibrary.simpleMessage("Отправить"),
|
||||||
"send_complain": MessageLookupByLibrary.simpleMessage("Отправить жалобу"),
|
"send_complain": MessageLookupByLibrary.simpleMessage("Отправить жалобу"),
|
||||||
|
|||||||
@@ -3394,6 +3394,26 @@ class S {
|
|||||||
args: [],
|
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<S> {
|
class AppLocalizationDelegate extends LocalizationsDelegate<S> {
|
||||||
|
|||||||
@@ -402,6 +402,10 @@
|
|||||||
"allowAcessToGaleryDescription": "Предоставление доступа позволит вам добавлять фото к записям",
|
"allowAcessToGaleryDescription": "Предоставление доступа позволит вам добавлять фото к записям",
|
||||||
"allowAccessToCamera": "Разрешите доступ к камере",
|
"allowAccessToCamera": "Разрешите доступ к камере",
|
||||||
"allowAccessToCameraDescription": "Предоставление доступа позволит вам делать фотографии и добавлять к записям",
|
"allowAccessToCameraDescription": "Предоставление доступа позволит вам делать фотографии и добавлять к записям",
|
||||||
"allowAccess": "Разрешить доступ"
|
"allowAccess": "Разрешить доступ",
|
||||||
|
"copy": "Скопировать",
|
||||||
|
"reply": "Ответить",
|
||||||
|
"deleteComment": "Удалить комментарий"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user