forked from eatvio/eatvio_app
231 lines
8.8 KiB
Dart
231 lines
8.8 KiB
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/theme/theme_helper.dart';
|
||
import 'package:eatvio_app/core/utils/toasts.dart';
|
||
import 'package:eatvio_app/core/widgets/show_error_dialog.dart';
|
||
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart';
|
||
import 'package:eatvio_app/features/complaining/presentation/complaining_bottom_sheet.dart';
|
||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.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/recipes_cubit/recipes_cubit.dart';
|
||
import 'package:eatvio_app/features/my_diets/presentation/cubit/my_diets_cubit.dart';
|
||
import 'package:eatvio_app/features/my_plans/presentation/cubit/my_plans_cubit.dart';
|
||
import 'package:eatvio_app/generated/l10n.dart';
|
||
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter_svg/flutter_svg.dart';
|
||
import 'package:go_router/go_router.dart';
|
||
import 'package:share_plus/share_plus.dart';
|
||
|
||
class CustomPopup extends StatelessWidget {
|
||
final bool isAuthor;
|
||
final ComplainedContent? complainedContentType;
|
||
final String path;
|
||
final String? slug;
|
||
final int? id;
|
||
final FeedBlogPostModel? feedBlogPostModel;
|
||
|
||
const CustomPopup({
|
||
super.key,
|
||
required this.isAuthor,
|
||
this.complainedContentType,
|
||
required this.path,
|
||
this.id,
|
||
this.slug,
|
||
this.feedBlogPostModel,
|
||
});
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
final s = S.of(context);
|
||
|
||
return GestureDetector(
|
||
onTap: () async {
|
||
final RenderBox button = context.findRenderObject() as RenderBox;
|
||
final RenderBox overlay = Overlay.of(context).context.findRenderObject() as RenderBox;
|
||
final Offset position = button.localToGlobal(Offset.zero, ancestor: overlay);
|
||
|
||
await showMenu(
|
||
context: context,
|
||
position: RelativeRect.fromLTRB(
|
||
position.dx,
|
||
position.dy + button.size.height,
|
||
position.dx + button.size.width,
|
||
position.dy,
|
||
),
|
||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||
color: Colors.white,
|
||
constraints: const BoxConstraints(minWidth: 260),
|
||
surfaceTintColor: Colors.transparent,
|
||
elevation: 2,
|
||
items: _buildMenuItems(s, context),
|
||
);
|
||
},
|
||
child: const Icon(
|
||
Icons.more_horiz_rounded,
|
||
),
|
||
);
|
||
}
|
||
|
||
List<PopupMenuEntry> _buildMenuItems(s, context) {
|
||
final entries = <PopupMenuEntry>[];
|
||
|
||
void addItem(String icon, String text, Function() onTap) {
|
||
entries.add(_buildCompactItem(icon: icon, text: text, onTap: onTap));
|
||
entries.add(_buildDivider());
|
||
}
|
||
|
||
if (isAuthor) {
|
||
addItem('assets/icons/copy2.svg', 'Скопировать ссылку', () {
|
||
Clipboard.setData(ClipboardData(text: '$baseUrl/ru/$path'));
|
||
showInfoToast(s.link_was_copied);
|
||
});
|
||
addItem('assets/icons/share2.svg', 'Поделиться', () {
|
||
final box = context.findRenderObject() as RenderBox?;
|
||
Share.shareUri(
|
||
Uri.parse(
|
||
'$baseUrl/ru/$path',
|
||
),
|
||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||
);
|
||
});
|
||
addItem('assets/icons/edit_paint.svg', 'Редактировать', () {
|
||
if (complainedContentType == ComplainedContent.posts) {
|
||
GoRouter.of(context).pushNamed('blogPostCreateScreen', extra: feedBlogPostModel);
|
||
} else {
|
||
showInfoToast('В разработке');
|
||
return;
|
||
}
|
||
});
|
||
if (complainedContentType == ComplainedContent.plan || complainedContentType == ComplainedContent.diet) {
|
||
addItem('assets/icons/remove_from_public.svg', 'Снять с публикации', () async {
|
||
if (complainedContentType == ComplainedContent.diet) {
|
||
final result = await sl<MyDietsCubit>().unpublishDiet(id!);
|
||
if (!context.mounted) return;
|
||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||
if (!result) {
|
||
showErrorDialog(context, title: S.current.could_not_delete_blog_post);
|
||
return;
|
||
}
|
||
showSuccessToast('Диета перенесена в архив, обновите ленту');
|
||
} else if (complainedContentType == ComplainedContent.plan) {
|
||
final result = await sl<MyPlansCubit>().unpublish(slug!);
|
||
if (!context.mounted) return;
|
||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||
if (!result) {
|
||
showErrorDialog(context, title: S.current.could_not_delete_blog_post);
|
||
return;
|
||
}
|
||
showSuccessToast('План перенесен в архив, обновите ленту');
|
||
}
|
||
});
|
||
}
|
||
addItem('assets/icons/red_trash.svg', 'Удалить', () async {
|
||
if (complainedContentType == ComplainedContent.posts) {
|
||
final result = await sl<BlogPostCreateCubit>().deleteBlogPost(id!);
|
||
if (!context.mounted) return;
|
||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||
if (!result) {
|
||
showErrorDialog(context, title: S.current.could_not_delete_blog_post);
|
||
return;
|
||
}
|
||
showSuccessToast('Пост удален, обновите ленту');
|
||
} else if (complainedContentType == ComplainedContent.recipe) {
|
||
final result = await sl<RecipesCubit>().deleteRecipe(slug!);
|
||
if (!context.mounted) return;
|
||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||
if (!result) {
|
||
showErrorDialog(context, title: S.current.could_not_delete_blog_post);
|
||
return;
|
||
}
|
||
showSuccessToast('Рецепт удален, обновите ленту');
|
||
} else if (complainedContentType == ComplainedContent.diet) {
|
||
final result = await sl<DietsCubit>().deleteDiet(id!);
|
||
if (!context.mounted) return;
|
||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||
if (!result) {
|
||
showErrorDialog(context, title: S.current.could_not_delete_blog_post);
|
||
return;
|
||
}
|
||
showSuccessToast('Диета удалена, обновите ленту');
|
||
} else if (complainedContentType == ComplainedContent.plan) {
|
||
final result = await sl<MyPlansCubit>().deletePlan(slug!);
|
||
if (!context.mounted) return;
|
||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||
if (!result) {
|
||
showErrorDialog(context, title: S.current.could_not_delete_blog_post);
|
||
return;
|
||
}
|
||
showSuccessToast('План удален, обновите ленту');
|
||
}
|
||
});
|
||
} else {
|
||
addItem('assets/icons/copy2.svg', 'Скопировать ссылку', () {
|
||
Clipboard.setData(ClipboardData(text: '$baseUrl/ru/$path'));
|
||
showInfoToast(s.link_was_copied);
|
||
});
|
||
addItem('assets/icons/share2.svg', 'Поделиться', () {
|
||
final box = context.findRenderObject() as RenderBox?;
|
||
Share.shareUri(
|
||
Uri.parse(
|
||
'$baseUrl/ru/$path',
|
||
),
|
||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||
);
|
||
});
|
||
addItem('assets/icons/complain.svg', 'Пожаловаться', () {
|
||
if (complainedContentType != null) {
|
||
showModalBottomSheet(
|
||
context: context,
|
||
isScrollControlled: true,
|
||
builder: (context) => ComplainingBottomSheet(
|
||
complainedContentType: complainedContentType!,
|
||
id: id,
|
||
slug: slug,
|
||
),
|
||
);
|
||
}
|
||
});
|
||
}
|
||
|
||
if (entries.isNotEmpty && entries.last is PopupMenuItem) {
|
||
entries.removeLast();
|
||
}
|
||
|
||
return entries;
|
||
}
|
||
|
||
PopupMenuItem _buildCompactItem({required String icon, required String text, required Function() onTap}) {
|
||
return PopupMenuItem(
|
||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
||
height: 36,
|
||
onTap: onTap,
|
||
child: SizedBox(
|
||
width: double.infinity,
|
||
child: Row(
|
||
children: [
|
||
Text(text, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
|
||
const Spacer(),
|
||
SvgPicture.asset(icon),
|
||
],
|
||
),
|
||
),
|
||
);
|
||
}
|
||
|
||
PopupMenuItem _buildDivider() {
|
||
return PopupMenuItem(
|
||
enabled: false,
|
||
height: 1,
|
||
padding: EdgeInsets.zero,
|
||
child: Container(
|
||
margin: const EdgeInsets.symmetric(horizontal: 12),
|
||
height: 1,
|
||
color: appTheme.dividerColor,
|
||
),
|
||
);
|
||
}
|
||
}
|