forked from eatvio/eatvio_app
Merge pull request 'Контекстное меню (три точки)' (#403) from mso7nueh/eatvio_app:main into main
Reviewed-on: eatvio/eatvio_app#403
This commit is contained in:
175
lib/core/widgets/custom_popup.dart
Normal file
175
lib/core/widgets/custom_popup.dart
Normal file
@@ -0,0 +1,175 @@
|
||||
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/feed_cubit/feed_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);
|
||||
}
|
||||
});
|
||||
if (complainedContentType == ComplainedContent.plan || complainedContentType == ComplainedContent.diet) {
|
||||
addItem('assets/icons/remove_from_public.svg', 'Снять с публикации', () {});
|
||||
}
|
||||
addItem('assets/icons/red_trash.svg', 'Удалить', () async {
|
||||
if (complainedContentType == ComplainedContent.posts) {
|
||||
final result = await sl<BlogPostCreateCubit>().deleteBlogPost(id!);
|
||||
if (!context.mounted) return;
|
||||
if (!result) {
|
||||
showErrorDialog(context, title: S.current.could_not_delete_blog_post);
|
||||
return;
|
||||
}
|
||||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||||
}
|
||||
});
|
||||
} 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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user