forked from eatvio/eatvio_app
fix(feed): Issue-591
This commit is contained in:
@@ -18,4 +18,26 @@ class BlogPostCubit extends Cubit<BlogPostState> {
|
||||
emit(state.copyWith(isLoading: false));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> toggleLike() async {
|
||||
final current = state.blogPostModel;
|
||||
if (current == null) return;
|
||||
|
||||
// optimistic update
|
||||
final wasLiked = current.wasLikedByMe;
|
||||
final updated = current.copyWith(wasLikedByMe: !wasLiked, totalLikes: wasLiked ? current.totalLikes - 1 : current.totalLikes + 1);
|
||||
emit(state.copyWith(blogPostModel: updated));
|
||||
|
||||
try {
|
||||
if (wasLiked) {
|
||||
await feedRepository.unlikedBlogPost(id: current.id);
|
||||
} else {
|
||||
await feedRepository.likeBlogPost(id: current.id);
|
||||
}
|
||||
} catch (e, st) {
|
||||
// rollback on error
|
||||
log(e.toString(), stackTrace: st);
|
||||
emit(state.copyWith(blogPostModel: current));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,8 +32,6 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
final CommentsCubit commentsCubit = sl<CommentsCubit>();
|
||||
final textEditingController = TextEditingController();
|
||||
int? replyId;
|
||||
bool isLiked = false;
|
||||
int totalLikes = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -60,26 +58,30 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
builder: (BuildContext context, CommentsState state) {
|
||||
if (blogPostState.isLoading) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
leading: BackButton(
|
||||
onPressed: () {
|
||||
if (context.canPop()) {
|
||||
GoRouter.of(context).pop();
|
||||
return;
|
||||
}
|
||||
GoRouter.of(context).go('/feed-screen');
|
||||
},
|
||||
),
|
||||
appBar: AppBar(
|
||||
leading: BackButton(
|
||||
onPressed: () {
|
||||
if (context.canPop()) {
|
||||
GoRouter.of(context).pop();
|
||||
return;
|
||||
}
|
||||
GoRouter.of(context).go('/feed-screen');
|
||||
},
|
||||
),
|
||||
body: const Loader());
|
||||
),
|
||||
body: const Loader(),
|
||||
);
|
||||
}
|
||||
isLiked = blogPostState.blogPostModel?.wasLikedByMe ?? false;
|
||||
totalLikes = blogPostState.blogPostModel?.totalLikes ?? 0;
|
||||
final bool isLiked = blogPostState.blogPostModel?.wasLikedByMe ?? false;
|
||||
final int totalLikes = blogPostState.blogPostModel?.totalLikes ?? 0;
|
||||
return Scaffold(
|
||||
resizeToAvoidBottomInset: true,
|
||||
bottomSheet: Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 12) + (Platform.isIOS ? const EdgeInsets.only(bottom: 16) : EdgeInsets.zero),
|
||||
decoration: BoxDecoration(color: Colors.white, border: Border(top: BorderSide(color: Colors.black.withValues(alpha: 0.1)))),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border(top: BorderSide(color: Colors.black.withValues(alpha: 0.1))),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
@@ -114,24 +116,14 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
maxLines: 5,
|
||||
minLines: 1,
|
||||
keyboardType: TextInputType.multiline,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black,
|
||||
height: 1.2,
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: Colors.black, height: 1.2),
|
||||
decoration: InputDecoration(
|
||||
isDense: false,
|
||||
// убираем true, чтобы padding учитывался корректно
|
||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
|
||||
// вертикальный паддинг увеличен
|
||||
hintText: 'Комментарий',
|
||||
hintStyle: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.2,
|
||||
color: Color(0xFFAEAEB2),
|
||||
),
|
||||
hintStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w400, height: 1.2, color: Color(0xFFAEAEB2)),
|
||||
filled: true,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
@@ -196,7 +188,7 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
id: widget.id,
|
||||
feedBlogPostModel: blogPostState.blogPostModel,
|
||||
userSlug: blogPostState.blogPostModel?.author.authorSlug ?? '',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
],
|
||||
),
|
||||
@@ -215,9 +207,7 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 16,
|
||||
foregroundImage: NetworkImage(
|
||||
baseUrl + (blogPostState.blogPostModel?.author.authorProfileIcon ?? ''),
|
||||
),
|
||||
foregroundImage: NetworkImage(baseUrl + (blogPostState.blogPostModel?.author.authorProfileIcon ?? '')),
|
||||
backgroundImage: const AssetImage('assets/images/no_avatar.png'),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -242,30 +232,32 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
if (blogPostState.blogPostModel?.description.isNotEmpty ?? false)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Html(data: blogPostState.blogPostModel?.description.replaceAll('\n', '<br>'), style: {"*": Style(color: Colors.black87)}),
|
||||
child: Html(
|
||||
data: blogPostState.blogPostModel?.description.replaceAll('\n', '<br>'),
|
||||
style: {"*": Style(color: Colors.black87)},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
if (blogPostState.blogPostModel?.image.isNotEmpty ?? false)
|
||||
CachedNetworkImage(
|
||||
imageUrl: '$baseUrl/storage/${blogPostState.blogPostModel?.image ?? ''}',
|
||||
),
|
||||
CachedNetworkImage(imageUrl: '$baseUrl/storage/${blogPostState.blogPostModel?.image ?? ''}'),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
child: Row(
|
||||
children: [
|
||||
_iconButton(
|
||||
icon: Icons.favorite_border_rounded,
|
||||
icon: isLiked ? Icons.favorite_rounded : Icons.favorite_border_rounded,
|
||||
text: totalLikes.toString(),
|
||||
iconColor: isLiked ? Colors.red.withValues(alpha: 0.8) : null,
|
||||
backgroundColor: isLiked ? Colors.red.withValues(alpha: 0.1) : null,
|
||||
textColor: isLiked ? Colors.red.withValues(alpha: 0.8) : null,
|
||||
onTap: () async {
|
||||
setState(() {
|
||||
isLiked = !isLiked;
|
||||
isLiked ? totalLikes++ : totalLikes--;
|
||||
});
|
||||
isLiked ? await context.read<FeedCubit>().likePost(widget.id) : await context.read<FeedCubit>().unlikedPost(widget.id);
|
||||
sl<FeedCubit>().updateFeedBlogPostList(blogPostState.blogPostModel, isLiked);
|
||||
await context.read<BlogPostCubit>().toggleLike();
|
||||
// ignore: use_build_context_synchronously
|
||||
final updated = context.read<BlogPostCubit>().state.blogPostModel;
|
||||
if (updated != null) {
|
||||
// ignore: use_build_context_synchronously
|
||||
context.read<FeedCubit>().updateFeedBlogPostList(updated, updated.wasLikedByMe);
|
||||
}
|
||||
},
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -284,8 +276,10 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
const Spacer(),
|
||||
Icon(Icons.visibility_rounded, size: 16, color: appTheme.gray500),
|
||||
const SizedBox(width: 4),
|
||||
Text(blogPostState.blogPostModel?.totalViews.toString() ?? '',
|
||||
style: TextStyle(fontSize: 12, color: appTheme.gray500, fontWeight: FontWeight.w400)),
|
||||
Text(
|
||||
blogPostState.blogPostModel?.totalViews.toString() ?? '',
|
||||
style: TextStyle(fontSize: 12, color: appTheme.gray500, fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -332,7 +326,11 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
children: [
|
||||
Icon(icon, size: 20, color: iconColor ?? appTheme.gray600),
|
||||
if (text != null) const SizedBox(width: 8),
|
||||
if (text != null) Text(text, style: TextStyle(color: textColor ?? appTheme.gray600, fontWeight: FontWeight.w500)),
|
||||
if (text != null)
|
||||
Text(
|
||||
text,
|
||||
style: TextStyle(color: textColor ?? appTheme.gray600, fontWeight: FontWeight.w500),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
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/custom_divider.dart';
|
||||
@@ -66,7 +65,7 @@ class _ConsultationCardWidgetState extends State<ConsultationCardWidget> {
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
CircleAvatar(radius: 30, backgroundImage: NetworkImage(baseUrl + widget.consultationsModel.userProfilePhotoUrl)),
|
||||
CircleAvatar(radius: 30, backgroundImage: NetworkImage(widget.consultationsModel.userProfilePhotoUrl)),
|
||||
const SizedBox(width: 12),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
||||
@@ -15,13 +15,12 @@ class FeedCubit extends Cubit<FeedState> {
|
||||
FeedCubit({required this.feedRepository}) : super(const FeedState.loading());
|
||||
|
||||
void updateFeedBlogPostList(FeedBlogPostModel? feedBlogPostModel, bool wasLikedByMe) {
|
||||
if (feedBlogPostModel == null || isClosed) return;
|
||||
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,
|
||||
);
|
||||
if (feedBlogPostModel == null || isClosed || state is! FeedStateLoaded) return;
|
||||
final List<FeedBlogPostModel> feedBlogPostList = [...(state as FeedStateLoaded).feedBlogPostList];
|
||||
final int index = feedBlogPostList.indexWhere((e) => e.id == feedBlogPostModel.id);
|
||||
if (index == -1) return;
|
||||
final current = feedBlogPostList[index];
|
||||
feedBlogPostList[index] = current.copyWith(wasLikedByMe: wasLikedByMe, totalLikes: wasLikedByMe ? current.totalLikes + 1 : current.totalLikes - 1);
|
||||
if (!isClosed) {
|
||||
emit(FeedState.loaded(feedBlogPostList: feedBlogPostList, isLoading: isLoading));
|
||||
}
|
||||
@@ -81,5 +80,4 @@ class FeedCubit extends Cubit<FeedState> {
|
||||
Future<void> viewRecipe(String slug) async => await feedRepository.viewRecipe(slug);
|
||||
Future<void> viewDiet(int id) async => await feedRepository.viewDiet(id);
|
||||
Future<void> viewPlan(String slug) async => await feedRepository.viewPlan(slug);
|
||||
|
||||
}
|
||||
|
||||
@@ -36,7 +36,6 @@ class FeedScreen extends StatelessWidget {
|
||||
providers: [
|
||||
BlocProvider<RecipesCubit>(create: (context) => sl<RecipesCubit>()..loadRecipesList()),
|
||||
BlocProvider<FeedProfileCubit>(create: (context) => sl<FeedProfileCubit>()..getProfile()),
|
||||
BlocProvider<FeedCubit>(create: (context) => sl<FeedCubit>()..loadFeedBlogPostList()),
|
||||
BlocProvider<DietsCubit>(create: (context) => sl<DietsCubit>()..loadDiets()),
|
||||
if (!hidePlans) BlocProvider<PlansCubit>(create: (context) => sl<PlansCubit>()..loadPlans()),
|
||||
BlocProvider<ConsultantsCubit>(create: (context) => sl<ConsultantsCubit>()..getConsultants()),
|
||||
@@ -78,8 +77,6 @@ class _FeedScreenContentState extends State<FeedScreenContent> {
|
||||
if (consultantsScrollController.offset >= consultantsScrollController.position.maxScrollExtent && !consultantsScrollController.position.outOfRange) {}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
blogPostsScrollController.dispose();
|
||||
@@ -90,8 +87,6 @@ class _FeedScreenContentState extends State<FeedScreenContent> {
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
FlutterNativeSplash.remove();
|
||||
|
||||
@@ -21,10 +21,7 @@ import 'package:share_plus/share_plus.dart';
|
||||
class BlogPostWidget extends StatefulWidget {
|
||||
final int index;
|
||||
|
||||
const BlogPostWidget({
|
||||
super.key,
|
||||
required this.index,
|
||||
});
|
||||
const BlogPostWidget({super.key, required this.index});
|
||||
|
||||
@override
|
||||
State<BlogPostWidget> createState() => _BlogPostWidgetState();
|
||||
@@ -44,10 +41,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
totalLikes = state.feedBlogPostList[widget.index].totalLikes;
|
||||
return InkWell(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'blogPostScreen',
|
||||
extra: state.feedBlogPostList[widget.index].id,
|
||||
),
|
||||
onTap: () => GoRouter.of(context).pushNamed('blogPostScreen', extra: state.feedBlogPostList[widget.index].id),
|
||||
child: Material(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.white,
|
||||
@@ -95,21 +89,12 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
Text(
|
||||
state.feedBlogPostList[widget.index].author.authorName,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
height: 1,
|
||||
color: Colors.black87,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 16,
|
||||
),
|
||||
style: const TextStyle(height: 1, color: Colors.black87, fontWeight: FontWeight.w500, fontSize: 16),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'${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: const TextStyle(
|
||||
height: 1,
|
||||
color: Colors.black45,
|
||||
fontSize: 14,
|
||||
),
|
||||
style: const TextStyle(height: 1, color: Colors.black45, fontSize: 14),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -119,9 +104,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
!state.feedBlogPostList[widget.index].author.authorIsMe)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8),
|
||||
child: SubscribeButtonWidget(
|
||||
slug: state.feedBlogPostList[widget.index].author.authorSlug,
|
||||
),
|
||||
child: SubscribeButtonWidget(slug: state.feedBlogPostList[widget.index].author.authorSlug),
|
||||
),
|
||||
// Кнопка меню
|
||||
CustomPopup(
|
||||
@@ -141,11 +124,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Text(
|
||||
state.feedBlogPostList[widget.index].title,
|
||||
style: const TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.black87,
|
||||
),
|
||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Colors.black87),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -156,15 +135,12 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||
child: Html(
|
||||
data: (state.feedBlogPostList[widget.index].description.length > 200
|
||||
? state.feedBlogPostList[widget.index].description.substring(0, 200)
|
||||
: state.feedBlogPostList[widget.index].description).replaceAll('\n', '<br>'),
|
||||
style: {
|
||||
"*": Style(
|
||||
fontSize: FontSize(16),
|
||||
color: Colors.black87,
|
||||
),
|
||||
},
|
||||
data:
|
||||
(state.feedBlogPostList[widget.index].description.length > 200
|
||||
? state.feedBlogPostList[widget.index].description.substring(0, 200)
|
||||
: state.feedBlogPostList[widget.index].description)
|
||||
.replaceAll('\n', '<br>'),
|
||||
style: {"*": Style(fontSize: FontSize(16), color: Colors.black87)},
|
||||
),
|
||||
),
|
||||
if (state.feedBlogPostList[widget.index].description.length > 200)
|
||||
@@ -172,12 +148,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
padding: EdgeInsets.symmetric(horizontal: 12),
|
||||
child: Text(
|
||||
'Показать ещё',
|
||||
style: TextStyle(
|
||||
height: 1,
|
||||
color: Color(0xFF8B8B8B),
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
style: TextStyle(height: 1, color: Color(0xFF8B8B8B), fontSize: 14, fontWeight: FontWeight.w600),
|
||||
),
|
||||
),
|
||||
if (state.feedBlogPostList[widget.index].title.isNotEmpty || state.feedBlogPostList[widget.index].description.isNotEmpty)
|
||||
@@ -186,10 +157,7 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
onTap: () {
|
||||
context.pushTransparentRoute(
|
||||
rootNavigator: true,
|
||||
PhotoViewScreen(
|
||||
imageUrls: ['$baseUrl/storage/${state.feedBlogPostList[widget.index].image}'],
|
||||
index: 0,
|
||||
),
|
||||
PhotoViewScreen(imageUrls: ['$baseUrl/storage/${state.feedBlogPostList[widget.index].image}'], index: 0),
|
||||
);
|
||||
},
|
||||
child: Hero(
|
||||
@@ -218,11 +186,14 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
isLiked = !isLiked;
|
||||
isLiked ? totalLikes++ : totalLikes--;
|
||||
});
|
||||
isLiked
|
||||
? await context.read<FeedCubit>().likePost(state.feedBlogPostList[widget.index].id)
|
||||
: await context.read<FeedCubit>().unlikedPost(state.feedBlogPostList[widget.index].id);
|
||||
if (!context.mounted) return;
|
||||
await context.read<FeedCubit>().loadFeedBlogPostList();
|
||||
// Update feed list immediately by ID (no reload)
|
||||
context.read<FeedCubit>().updateFeedBlogPostList(state.feedBlogPostList[widget.index], isLiked);
|
||||
// Fire network call without introducing UI delay
|
||||
if (isLiked) {
|
||||
await context.read<FeedCubit>().likePost(state.feedBlogPostList[widget.index].id);
|
||||
} else {
|
||||
await context.read<FeedCubit>().unlikedPost(state.feedBlogPostList[widget.index].id);
|
||||
}
|
||||
},
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -231,16 +202,10 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
'assets/icons/comment.svg',
|
||||
height: 20,
|
||||
width: 20,
|
||||
colorFilter: ColorFilter.mode(
|
||||
appTheme.gray600,
|
||||
BlendMode.srcIn,
|
||||
),
|
||||
colorFilter: ColorFilter.mode(appTheme.gray600, BlendMode.srcIn),
|
||||
),
|
||||
text: state.feedBlogPostList[widget.index].totalComments.toString(),
|
||||
onTap: () => GoRouter.of(context).pushNamed(
|
||||
'blogPostScreen',
|
||||
extra: state.feedBlogPostList[widget.index].id,
|
||||
),
|
||||
onTap: () => GoRouter.of(context).pushNamed('blogPostScreen', extra: state.feedBlogPostList[widget.index].id),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
FeedIconButton(
|
||||
@@ -254,28 +219,18 @@ class _BlogPostWidgetState extends State<BlogPostWidget> {
|
||||
final box = context.findRenderObject() as RenderBox?;
|
||||
SharePlus.instance.share(
|
||||
ShareParams(
|
||||
uri: Uri.parse(
|
||||
'$baseUrl/ru/blog_post/${state.feedBlogPostList[widget.index].id}',
|
||||
),
|
||||
uri: Uri.parse('$baseUrl/ru/blog_post/${state.feedBlogPostList[widget.index].id}'),
|
||||
sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const Spacer(),
|
||||
Icon(
|
||||
Icons.visibility_rounded,
|
||||
size: 16,
|
||||
color: appTheme.gray500,
|
||||
),
|
||||
Icon(Icons.visibility_rounded, size: 16, color: appTheme.gray500),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
state.feedBlogPostList[widget.index].totalViews.toString(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color: appTheme.gray500,
|
||||
fontWeight: FontWeight.w400,
|
||||
),
|
||||
style: TextStyle(fontSize: 12, color: appTheme.gray500, fontWeight: FontWeight.w400),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -15,9 +15,6 @@ abstract class CardModel with _$CardModel {
|
||||
}
|
||||
|
||||
bool parseBool(dynamic json) {
|
||||
if (json == null) {
|
||||
throw Exception('parseBool: json is null');
|
||||
}
|
||||
if (json == 1 || json == true || json == '1') {
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user