forked from eatvio/eatvio_app
fix: feed like sync
This commit is contained in:
4
android/.kotlin/errors/errors-1733227862976.log
Normal file
4
android/.kotlin/errors/errors-1733227862976.log
Normal file
@@ -0,0 +1,4 @@
|
||||
kotlin version: 2.0.21
|
||||
error message: The daemon has terminated unexpectedly on startup attempt #1 with error code: 0. The daemon process output:
|
||||
1. Kotlin compile daemon is ready
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:eatvio_app/core/initialization_cubit/initialization_cubit.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/token_storage.dart';
|
||||
import 'package:eatvio_app/features/auth/auth_screen/auth_screen.dart';
|
||||
import 'package:eatvio_app/features/blog_post/presentation/pages/blog_post_screen.dart';
|
||||
@@ -40,7 +41,6 @@ import 'package:eatvio_app/features/settings/presentation/pages/physical_form_sc
|
||||
import 'package:eatvio_app/features/settings/presentation/pages/pressure_screen.dart';
|
||||
import 'package:eatvio_app/features/settings/presentation/pages/settings_screen.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
class AppRouter {
|
||||
@@ -77,7 +77,7 @@ class AppRouter {
|
||||
path: '/my-profile-screen',
|
||||
name: 'myProfileScreen',
|
||||
redirect: (context, state) async {
|
||||
await context.read<InitializationCubit>().runInitialization();
|
||||
await sl<InitializationCubit>().runInitialization();
|
||||
return null;
|
||||
},
|
||||
pageBuilder: (context, state) => NoTransitionPage(child: ProfileScreen()),
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/token_storage.dart';
|
||||
import 'package:eatvio_app/core/utils/image_constant.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/profile_avatar_cubit/profile_avatar_cubit.dart';
|
||||
import 'package:eatvio_app/generated/l10n.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@@ -191,6 +193,7 @@ class _AuthScreenState extends State<AuthScreen> {
|
||||
final token = res['token'];
|
||||
await TokenStorage.saveTokenInStorage(token);
|
||||
GoRouter.of(context).go('/my-profile-screen');
|
||||
sl<ProfileAvatarCubit>().getMyProfile();
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
|
||||
@@ -304,7 +304,7 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
isLiked
|
||||
? await context.read<FeedCubit>().likePost(widget.blogPost.id)
|
||||
: await context.read<FeedCubit>().unlikedPost(widget.blogPost.id);
|
||||
await context.read<FeedCubit>().loadFeedBlogPostList();
|
||||
sl<FeedCubit>().updateFeedBlogPostList(widget.blogPost, isLiked);
|
||||
},
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_state.dart';
|
||||
import 'package:eatvio_app/features/feed/repositories/feed_repository.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -13,6 +14,21 @@ class FeedCubit extends Cubit<FeedState> {
|
||||
required this.feedRepository,
|
||||
}) : super(const FeedState.loading());
|
||||
|
||||
updateFeedBlogPostList(FeedBlogPostModel feedBlogPostModel, bool wasLikedByMe) {
|
||||
List<FeedBlogPostModel> feedBlogPostList = [...(state as FeedStateLoaded).feedBlogPostList];
|
||||
final int index = feedBlogPostList.indexOf(feedBlogPostModel);
|
||||
feedBlogPostList[index] = feedBlogPostModel.copyWith(
|
||||
wasLikedByMe: wasLikedByMe,
|
||||
totalLikes: wasLikedByMe == false ? feedBlogPostList[index].totalLikes - 1 : feedBlogPostList[index].totalLikes + 1,
|
||||
);
|
||||
emit(
|
||||
FeedState.loaded(
|
||||
feedBlogPostList: feedBlogPostList,
|
||||
isLoading: isLoading,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
loadFeedBlogPostList({
|
||||
String? query,
|
||||
}) async {
|
||||
|
||||
@@ -184,7 +184,7 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
if (index == state.feedBlogPostList.length) {
|
||||
return const Loader();
|
||||
}
|
||||
return BlogPostWidget(feedBlogPostModel: state.feedBlogPostList[index]);
|
||||
return BlogPostWidget(index: index);
|
||||
},
|
||||
separatorBuilder: (context, index) {
|
||||
return SizedBox(height: 8);
|
||||
|
||||
@@ -4,9 +4,9 @@ import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:eatvio_app/core/widgets/feed_icon_button.dart';
|
||||
import 'package:eatvio_app/features/chat/presentation/pages/photo_view_screen.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/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_state.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/widgets/subscribe_button_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@@ -16,11 +16,11 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:share_plus/share_plus.dart';
|
||||
|
||||
class BlogPostWidget extends StatefulWidget {
|
||||
final FeedBlogPostModel feedBlogPostModel;
|
||||
final int index;
|
||||
|
||||
const BlogPostWidget({
|
||||
super.key,
|
||||
required this.feedBlogPostModel,
|
||||
required this.index,
|
||||
});
|
||||
|
||||
@override
|
||||
@@ -31,20 +31,18 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
late bool isLiked;
|
||||
late int totalLikes;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
isLiked = widget.feedBlogPostModel.wasLikedByMe;
|
||||
totalLikes = widget.feedBlogPostModel.totalLikes;
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<FeedCubit, FeedState>(
|
||||
builder: (BuildContext context, FeedState state) {
|
||||
if (state is FeedStateLoaded) {
|
||||
isLiked = state.feedBlogPostList[widget.index].wasLikedByMe;
|
||||
totalLikes = state.feedBlogPostList[widget.index].totalLikes;
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'blogPostScreen',
|
||||
extra: widget.feedBlogPostModel,
|
||||
extra: state.feedBlogPostList[widget.index],
|
||||
),
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
@@ -64,7 +62,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
radius: 20,
|
||||
backgroundColor: Colors.black12,
|
||||
foregroundImage: NetworkImage(
|
||||
widget.feedBlogPostModel.author.authorProfileIcon,
|
||||
state.feedBlogPostList[widget.index].author.authorProfileIcon,
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
@@ -72,7 +70,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.feedBlogPostModel.author.authorName,
|
||||
state.feedBlogPostList[widget.index].author.authorName,
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: Colors.black87,
|
||||
@@ -81,7 +79,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'${calculateDifference(widget.feedBlogPostModel.createdAt)} в ${widget.feedBlogPostModel.createdAt.hour.toString().padLeft(2, '0')}:${widget.feedBlogPostModel.createdAt.minute.toString().padLeft(2, '0')}',
|
||||
'${calculateDifference(state.feedBlogPostList[widget.index].createdAt)} в ${state.feedBlogPostList[widget.index].createdAt.hour.toString().padLeft(2, '0')}:${state.feedBlogPostList[widget.index].createdAt.minute.toString().padLeft(2, '0')}',
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: Colors.black45,
|
||||
@@ -90,32 +88,33 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
],
|
||||
),
|
||||
const Spacer(),
|
||||
if (!widget.feedBlogPostModel.author.isEntitySubscribedByMe && !widget.feedBlogPostModel.author.authorIsMe)
|
||||
if (!state.feedBlogPostList[widget.index].author.isEntitySubscribedByMe && !state.feedBlogPostList[widget.index].author.authorIsMe)
|
||||
SubscribeButtonWidget(
|
||||
slug: widget.feedBlogPostModel.author.authorSlug,
|
||||
slug: state.feedBlogPostList[widget.index].author.authorSlug,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (widget.feedBlogPostModel.title.isNotEmpty || widget.feedBlogPostModel.description.isNotEmpty) SizedBox(height: 12),
|
||||
if (state.feedBlogPostList[widget.index].title.isNotEmpty || state.feedBlogPostList[widget.index].description.isNotEmpty)
|
||||
SizedBox(height: 12),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Text(
|
||||
widget.feedBlogPostModel.title,
|
||||
state.feedBlogPostList[widget.index].title,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.feedBlogPostModel.title.isNotEmpty && widget.feedBlogPostModel.description.isNotEmpty) SizedBox(height: 8),
|
||||
if (widget.feedBlogPostModel.description.isNotEmpty)
|
||||
if (state.feedBlogPostList[widget.index].title.isNotEmpty && state.feedBlogPostList[widget.index].description.isNotEmpty) SizedBox(height: 8),
|
||||
if (state.feedBlogPostList[widget.index].description.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Html(
|
||||
data: widget.feedBlogPostModel.description.length > 200
|
||||
? widget.feedBlogPostModel.description.substring(0, 200)
|
||||
: widget.feedBlogPostModel.description,
|
||||
data: state.feedBlogPostList[widget.index].description.length > 200
|
||||
? state.feedBlogPostList[widget.index].description.substring(0, 200)
|
||||
: state.feedBlogPostList[widget.index].description,
|
||||
style: {
|
||||
"*": Style(
|
||||
color: Colors.black87,
|
||||
@@ -123,7 +122,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
},
|
||||
),
|
||||
),
|
||||
if (widget.feedBlogPostModel.description.length > 200)
|
||||
if (state.feedBlogPostList[widget.index].description.length > 200)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Text(
|
||||
@@ -135,23 +134,23 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.feedBlogPostModel.title.isNotEmpty || widget.feedBlogPostModel.description.isNotEmpty) SizedBox(height: 8),
|
||||
if (state.feedBlogPostList[widget.index].title.isNotEmpty || state.feedBlogPostList[widget.index].description.isNotEmpty) SizedBox(height: 8),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
context.pushTransparentRoute(
|
||||
rootNavigator: true,
|
||||
PhotoViewScreen(
|
||||
imageUrls: [baseUrl + '/storage/' + widget.feedBlogPostModel.image],
|
||||
imageUrls: [baseUrl + '/storage/' + state.feedBlogPostList[widget.index].image],
|
||||
index: 0,
|
||||
),
|
||||
);
|
||||
},
|
||||
child: Hero(
|
||||
tag: baseUrl + '/storage/' + widget.feedBlogPostModel.image,
|
||||
tag: baseUrl + '/storage/' + state.feedBlogPostList[widget.index].image,
|
||||
child: CachedNetworkImage(
|
||||
fit: BoxFit.fitWidth,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
imageUrl: baseUrl + '/storage/' + widget.feedBlogPostModel.image,
|
||||
imageUrl: baseUrl + '/storage/' + state.feedBlogPostList[widget.index].image,
|
||||
errorWidget: (context, str, object) => SizedBox.shrink(),
|
||||
),
|
||||
),
|
||||
@@ -173,8 +172,8 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
isLiked ? totalLikes++ : totalLikes--;
|
||||
});
|
||||
isLiked
|
||||
? await context.read<FeedCubit>().likePost(widget.feedBlogPostModel.id)
|
||||
: await context.read<FeedCubit>().unlikedPost(widget.feedBlogPostModel.id);
|
||||
? await context.read<FeedCubit>().likePost(state.feedBlogPostList[widget.index].id)
|
||||
: await context.read<FeedCubit>().unlikedPost(state.feedBlogPostList[widget.index].id);
|
||||
await context.read<FeedCubit>().loadFeedBlogPostList();
|
||||
},
|
||||
),
|
||||
@@ -189,10 +188,10 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
),
|
||||
text: widget.feedBlogPostModel.totalComments.toString(),
|
||||
text: state.feedBlogPostList[widget.index].totalComments.toString(),
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'blogPostScreen',
|
||||
extra: widget.feedBlogPostModel,
|
||||
extra: state.feedBlogPostList[widget.index],
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8),
|
||||
@@ -205,7 +204,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
),
|
||||
onTap: () => Share.shareUri(
|
||||
Uri.parse(
|
||||
baseUrl + '/ru/blog_post/' + widget.feedBlogPostModel.id.toString(),
|
||||
baseUrl + '/ru/blog_post/' + state.feedBlogPostList[widget.index].id.toString(),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -217,7 +216,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
),
|
||||
SizedBox(width: 4),
|
||||
Text(
|
||||
widget.feedBlogPostModel.totalViews.toString(),
|
||||
state.feedBlogPostList[widget.index].totalViews.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: appTheme.gray500,
|
||||
@@ -233,4 +232,8 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,11 +122,11 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
),
|
||||
),
|
||||
_subscriptionsAndSubscribers(state),
|
||||
if (state.profile.badges.isNotEmpty) _badges(state),
|
||||
_socialLinks(state),
|
||||
_education(state),
|
||||
_diplomasAndCertificates(state),
|
||||
_activePlans(state),
|
||||
if (state.profile.badges.isNotEmpty) Padding(padding: EdgeInsets.only(bottom: 16), child: _badges(state)),
|
||||
if (state.profile.role == 'consultant') Padding(padding: EdgeInsets.only(bottom: 16), child: _socialLinks(state)),
|
||||
if (state.profile.role == 'consultant') Padding(padding: EdgeInsets.only(bottom: 16), child: _education(state)),
|
||||
if (state.profile.role == 'consultant') Padding(padding: EdgeInsets.only(bottom: 16), child: _diplomasAndCertificates(state)),
|
||||
if (state.profile.role == 'consultant') Padding(padding: EdgeInsets.only(bottom: 16), child: _activePlans(state)),
|
||||
_blogPosts(state),
|
||||
],
|
||||
),
|
||||
@@ -706,7 +706,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
itemBuilder: (context, index) => BlogPostWidget(
|
||||
feedBlogPostModel: state.blogPosts[index],
|
||||
index: index,
|
||||
),
|
||||
separatorBuilder: (context, index) => SizedBox(height: 8),
|
||||
itemCount: state.blogPosts.length,
|
||||
|
||||
@@ -28,7 +28,7 @@ class MyApp extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
return MultiBlocProvider(
|
||||
providers: [
|
||||
BlocProvider<InitializationCubit>(create: (context) => sl<InitializationCubit>()),
|
||||
BlocProvider<InitializationCubit>(create: (context) => sl<InitializationCubit>()..runInitialization()),
|
||||
BlocProvider<NewMessagesCubit>(create: (context) => sl<NewMessagesCubit>()),
|
||||
BlocProvider<NotificationsCubit>(create: (context) => sl<NotificationsCubit>()),
|
||||
BlocProvider<FeedCubit>(create: (context) => sl<FeedCubit>()..loadFeedBlogPostList()),
|
||||
|
||||
Reference in New Issue
Block a user