feat(push_notifications): issue-660, fix: issue-908

This commit is contained in:
misha
2026-10-14 08:16:20 +03:00
parent 98c175df44
commit dcd343e765
29 changed files with 2281 additions and 608 deletions

View File

@@ -3,6 +3,7 @@ import 'package:eatvio_app/core/comments/presentation/comments_actions_bottom_sh
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/url_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';
@@ -54,13 +55,15 @@ class _CommentsWidgetState extends State<CommentsWidget> {
@override
void didUpdateWidget(CommentsWidget oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.highlightedCommentId != null && widget.highlightedCommentId != oldWidget.highlightedCommentId) {
if (widget.highlightedCommentId != null &&
widget.highlightedCommentId != oldWidget.highlightedCommentId) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollToHighlightedComment();
});
} else if (widget.comment != oldWidget.comment && widget.highlightedCommentId != null) {
// Comments might have just loaded
WidgetsBinding.instance.addPostFrameCallback((_) {
} else if (widget.comment != oldWidget.comment &&
widget.highlightedCommentId != null) {
// Comments might have just loaded
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollToHighlightedComment();
});
}
@@ -84,9 +87,22 @@ class _CommentsWidgetState extends State<CommentsWidget> {
children: [
for (int i = 0; i < widget.comment.data.length; i++) ...[
_comment(s, widget.comment.data[i]),
if (widget.comment.data[i].childrenComments.isNotEmpty) const SizedBox(height: 8),
for (int j = 0; j < widget.comment.data[i].childrenComments.length; j++)
Padding(padding: const EdgeInsets.only(left: 40), child: _comment(s, widget.comment.data[i].childrenComments[j], 16, true)),
if (widget.comment.data[i].childrenComments.isNotEmpty)
const SizedBox(height: 8),
for (
int j = 0;
j < widget.comment.data[i].childrenComments.length;
j++
)
Padding(
padding: const EdgeInsets.only(left: 40),
child: _comment(
s,
widget.comment.data[i].childrenComments[j],
16,
true,
),
),
const SizedBox(height: 8),
],
const SizedBox(height: 48),
@@ -94,9 +110,18 @@ class _CommentsWidgetState extends State<CommentsWidget> {
);
}
Widget _comment(S s, Comment comment, [double radius = 18, bool isChild = false]) {
Widget _comment(
S s,
Comment comment, [
double radius = 18,
bool isChild = false,
]) {
final key = commentKeys.putIfAbsent(comment.id, () => GlobalKey());
final isMe = (sl<ProfileAvatarCubit>().state as ProfileAvatarStateLoaded).profile.slug == comment.authorSlug;
final isMe =
(sl<ProfileAvatarCubit>().state as ProfileAvatarStateLoaded)
.profile
.slug ==
comment.authorSlug;
return GestureDetector(
key: key,
onTap: () {
@@ -113,7 +138,10 @@ class _CommentsWidgetState extends State<CommentsWidget> {
showInfoToast(s.text_was_copied);
},
edit: (String text) {
context.read<CommentsCubit>().updateComment(id: comment.id, body: text);
context.read<CommentsCubit>().updateComment(
id: comment.id,
body: text,
);
},
delete: () {
context.read<CommentsCubit>().deleteComment(id: comment.id);
@@ -122,7 +150,10 @@ class _CommentsWidgetState extends State<CommentsWidget> {
showModalBottomSheet(
context: context,
isScrollControlled: true,
builder: (context) => ComplainingBottomSheet(complainedContentType: ComplainedContent.comment, id: comment.id),
builder: (context) => ComplainingBottomSheet(
complainedContentType: ComplainedContent.comment,
id: comment.id,
),
);
},
isMyComment: isMe,
@@ -131,7 +162,11 @@ class _CommentsWidgetState extends State<CommentsWidget> {
child: Container(
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
color: (widget.replyId == comment.id || widget.highlightedCommentId == comment.id) ? appTheme.blueA400.withValues(alpha: 0.1) : Colors.white,
color:
(widget.replyId == comment.id ||
widget.highlightedCommentId == comment.id)
? appTheme.blueA400.withValues(alpha: 0.1)
: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Padding(
@@ -141,14 +176,20 @@ class _CommentsWidgetState extends State<CommentsWidget> {
children: [
GestureDetector(
onTap: () {
GoRouter.of(context).pushNamed(
'profileScreen',
extra: comment.authorSlug,
);
GoRouter.of(
context,
).pushNamed('profileScreen', extra: comment.authorSlug);
},
child: CircleAvatar(
foregroundImage: NetworkImage(comment.authorProfileIcon.contains('https') ? comment.authorProfileIcon : sl<AppConfig>().baseUrl + comment.authorProfileIcon),
backgroundImage: const AssetImage('assets/images/no_avatar.png'),
foregroundImage: NetworkImage(
joinBaseUrl(
sl<AppConfig>().baseUrl,
comment.authorProfileIcon,
),
),
backgroundImage: const AssetImage(
'assets/images/no_avatar.png',
),
radius: radius,
),
),
@@ -159,14 +200,26 @@ class _CommentsWidgetState extends State<CommentsWidget> {
children: [
Text(
comment.authorName,
style: TextStyle(height: 1, color: appTheme.gray, fontSize: 14, fontWeight: FontWeight.w500),
style: TextStyle(
height: 1,
color: appTheme.gray,
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
const SizedBox(height: 4),
SizedBox(
width: isChild ? MediaQuery.of(context).size.width * 0.72 : MediaQuery.of(context).size.width * 0.8,
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.black, fontSize: 16, fontWeight: FontWeight.w500),
style: TextStyle(
height: 1,
color: appTheme.black,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
const SizedBox(height: 4),
@@ -174,17 +227,29 @@ class _CommentsWidgetState extends State<CommentsWidget> {
children: [
Text(
comment.createdAt.format('dd MMMM', 'ru'),
style: TextStyle(height: 1, color: appTheme.gray, fontSize: 14, fontWeight: FontWeight.w500),
style: TextStyle(
height: 1,
color: appTheme.gray,
fontSize: 14,
fontWeight: FontWeight.w500,
),
),
const SizedBox(width: 16),
if (!isChild)
GestureDetector(
onTap: () {
context.read<CommentsCubit>().setReplyId(comment.id);
context.read<CommentsCubit>().setReplyId(
comment.id,
);
},
child: Text(
s.answer,
style: TextStyle(height: 1, color: appTheme.gray, fontSize: 14, fontWeight: FontWeight.w600),
style: TextStyle(
height: 1,
color: appTheme.gray,
fontSize: 14,
fontWeight: FontWeight.w600,
),
),
),
],