forked from eatvio/eatvio_app
feat(feed): edit and delete posts
This commit is contained in:
@@ -19,7 +19,6 @@ import 'package:eatvio_app/features/diets/presentation/pages/about_diet_screen.d
|
||||
import 'package:eatvio_app/features/feed/models/diets_pagination_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/feed/models/recipes_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/feed_cubit/feed_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/pages/feed_screen.dart';
|
||||
import 'package:eatvio_app/features/menu/presentation/pages/menu_screen.dart';
|
||||
import 'package:eatvio_app/features/notifications/presentation/pages/notifications_screen.dart';
|
||||
@@ -167,13 +166,15 @@ class AppRouter {
|
||||
path: '/blog-post-create-screen',
|
||||
name: 'blogPostCreateScreen',
|
||||
builder: (context, state) => BlogPostCreateScreen(
|
||||
feedCubit: state.extra != null ? state.extra as FeedCubit : null,
|
||||
feedBlogPostModel: state.extra != null ? state.extra as FeedBlogPostModel : null,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/blog-post-screen',
|
||||
name: 'blogPostScreen',
|
||||
builder: (context, state) => BlogPostScreen(blogPost: state.extra as FeedBlogPostModel),
|
||||
builder: (context, state) => BlogPostScreen(
|
||||
blogPost: state.extra as FeedBlogPostModel,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
path: '/chat-screen',
|
||||
@@ -273,7 +274,7 @@ class AppRouter {
|
||||
path: DietPreviewScreen.path,
|
||||
name: DietPreviewScreen.name,
|
||||
builder: (context, state) {
|
||||
final data = state.extra as Diet;
|
||||
final data = state.extra as Diet;
|
||||
return DietPreviewScreen(
|
||||
diet: data,
|
||||
);
|
||||
|
||||
@@ -60,11 +60,11 @@ Future<void> init() async {
|
||||
sl.registerLazySingleton<InitializationCubit>(() => InitializationCubit(chatRepository: sl()));
|
||||
sl.registerLazySingleton<NewMessagesCubit>(() => NewMessagesCubit());
|
||||
sl.registerLazySingleton<NotificationsCubit>(() => NotificationsCubit());
|
||||
sl.registerLazySingleton<FeedCubit>(() => FeedCubit(feedRepository: sl()));
|
||||
|
||||
// Cubit factories
|
||||
sl.registerFactory<RegistrationCubit>(() => RegistrationCubit(registrationRepository: sl()));
|
||||
sl.registerFactory<ChatRoomCubit>(() => ChatRoomCubit(chatRepository: sl(), initializationCubit: sl()));
|
||||
sl.registerFactory<FeedCubit>(() => FeedCubit(feedRepository: sl()));
|
||||
sl.registerFactory<RecipesCubit>(() => RecipesCubit(feedRepository: sl(), recipeRepository: sl()));
|
||||
sl.registerFactory<CalendarCubit>(() => CalendarCubit(calendarRepository: sl()));
|
||||
sl.registerFactory<ProfileCubit>(() => ProfileCubit(profileRepository: sl(), chatRepository: sl()));
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/utils/date_time_utils.dart';
|
||||
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/models/feed_blog_post_model.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_cubit.dart';
|
||||
import 'package:eatvio_app/features/feed/presentation/bloc/comments_cubit/comments_state.dart';
|
||||
@@ -19,7 +20,10 @@ import 'package:share_plus/share_plus.dart';
|
||||
class BlogPostScreen extends StatefulWidget {
|
||||
final FeedBlogPostModel blogPost;
|
||||
|
||||
BlogPostScreen({super.key, required this.blogPost});
|
||||
BlogPostScreen({
|
||||
super.key,
|
||||
required this.blogPost,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BlogPostScreen> createState() => _BlogPostScreenState();
|
||||
@@ -185,6 +189,40 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
),
|
||||
appBar: AppBar(
|
||||
title: Text(widget.blogPost.title),
|
||||
actions: [
|
||||
PopupMenuButton(
|
||||
onSelected: (value) {
|
||||
if (value == 'delete') {
|
||||
sl<BlogPostCreateCubit>().deleteBlogPost(widget.blogPost.id);
|
||||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
if (value == 'edit') {
|
||||
GoRouter.of(context).replaceNamed(
|
||||
'blogPostCreateScreen',
|
||||
extra: widget.blogPost,
|
||||
);
|
||||
}
|
||||
},
|
||||
itemBuilder: (context) => [
|
||||
if (widget.blogPost.author.authorIsMe)
|
||||
PopupMenuItem(
|
||||
value: 'edit',
|
||||
child: Text('Редактировать'),
|
||||
),
|
||||
if (widget.blogPost.author.authorIsMe)
|
||||
PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Text('Удалить'),
|
||||
),
|
||||
if (!widget.blogPost.author.authorIsMe)
|
||||
PopupMenuItem(
|
||||
value: 'report',
|
||||
child: Text('Пожаловаться'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: EdgeInsets.only(bottom: 80),
|
||||
@@ -318,8 +356,7 @@ class _BlogPostScreenState extends State<BlogPostScreen> {
|
||||
),
|
||||
),
|
||||
SizedBox(height: 16),
|
||||
if (state is CommentsStateLoading)
|
||||
const Loader(),
|
||||
if (state is CommentsStateLoading) const Loader(),
|
||||
if (state is CommentsStateLoaded)
|
||||
CommentsWidget(
|
||||
id: widget.blogPost.id.toString(),
|
||||
|
||||
@@ -25,4 +25,28 @@ class BlogPostCreateCubit extends Cubit<BlogPostCreateState> {
|
||||
);
|
||||
emit(BlogPostCreateState.loaded());
|
||||
}
|
||||
|
||||
updateBlogPost({
|
||||
required int id,
|
||||
String? title,
|
||||
String? videoUrl,
|
||||
String? description,
|
||||
XFile? image,
|
||||
String? oldImageUrl,
|
||||
}) async {
|
||||
emit(BlogPostCreateState.loading());
|
||||
await blogPostRepository.updateBlogPost(
|
||||
id,
|
||||
title,
|
||||
videoUrl,
|
||||
description,
|
||||
image,
|
||||
oldImageUrl,
|
||||
);
|
||||
emit(BlogPostCreateState.loaded());
|
||||
}
|
||||
|
||||
deleteBlogPost(int id) async {
|
||||
await blogPostRepository.deleteBlogPost(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,25 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:eatvio_app/core/theme/app_decoration.dart';
|
||||
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_cubit.dart';
|
||||
import 'package:eatvio_app/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_state.dart';
|
||||
import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/core/widgets/custom_text_form_field.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:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
|
||||
class BlogPostCreateScreen extends StatefulWidget {
|
||||
final FeedCubit? feedCubit;
|
||||
final FeedBlogPostModel? feedBlogPostModel;
|
||||
|
||||
const BlogPostCreateScreen({
|
||||
required this.feedCubit,
|
||||
this.feedBlogPostModel,
|
||||
}) : super();
|
||||
|
||||
@override
|
||||
@@ -44,6 +45,11 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
shrinkImage = visible;
|
||||
});
|
||||
});
|
||||
if (widget.feedBlogPostModel != null) {
|
||||
titleController.text = widget.feedBlogPostModel!.title;
|
||||
descriptionController.text = widget.feedBlogPostModel!.description;
|
||||
videoUrlController.text = widget.feedBlogPostModel!.videoUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -58,7 +64,8 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
child: BlocListener<BlogPostCreateCubit, BlogPostCreateState>(
|
||||
listener: (BuildContext context, BlogPostCreateState state) {
|
||||
if (state is BlogPostCreateStateLoaded) {
|
||||
GoRouter.of(context).pop();
|
||||
context.read<FeedCubit>().loadFeedBlogPostList();
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
},
|
||||
child: _buildBlogPostCreate(),
|
||||
@@ -141,13 +148,23 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
setState(() {
|
||||
isLoading = true;
|
||||
});
|
||||
await blogPostCubit.createBlogPost(
|
||||
title: titleController.text,
|
||||
description: descriptionController.text,
|
||||
videoUrl: videoUrlController.text,
|
||||
image: image,
|
||||
);
|
||||
widget.feedCubit?.loadFeedBlogPostList();
|
||||
if (widget.feedBlogPostModel != null) {
|
||||
await blogPostCubit.updateBlogPost(
|
||||
id: widget.feedBlogPostModel!.id,
|
||||
title: titleController.text,
|
||||
description: descriptionController.text,
|
||||
videoUrl: videoUrlController.text,
|
||||
image: image,
|
||||
oldImageUrl: widget.feedBlogPostModel!.image,
|
||||
);
|
||||
} else {
|
||||
await blogPostCubit.createBlogPost(
|
||||
title: titleController.text,
|
||||
description: descriptionController.text,
|
||||
videoUrl: videoUrlController.text,
|
||||
image: image,
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -175,9 +192,9 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
if (videoUrlController.text.isEmpty) SizedBox(height: 8),
|
||||
if (videoUrlController.text.isEmpty) _buildAddPhoto(),
|
||||
SizedBox(height: 16),
|
||||
if (image == null) Text('Ссылка на видео'),
|
||||
if (image == null) SizedBox(height: 8),
|
||||
if (image == null)
|
||||
if (image == null && widget.feedBlogPostModel?.image == null) Text('Ссылка на видео'),
|
||||
if (image == null && widget.feedBlogPostModel?.image == null) SizedBox(height: 8),
|
||||
if (image == null && widget.feedBlogPostModel?.image == null)
|
||||
CustomTextFormField(
|
||||
controller: videoUrlController,
|
||||
),
|
||||
@@ -195,7 +212,7 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
},
|
||||
child: Stack(
|
||||
children: [
|
||||
if (image == null)
|
||||
if (image == null && widget.feedBlogPostModel?.image == null)
|
||||
AnimatedContainer(
|
||||
height: shrinkImage ? 52 : 128,
|
||||
curve: Curves.easeIn,
|
||||
@@ -233,6 +250,16 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.feedBlogPostModel?.image != null && image == null)
|
||||
Container(
|
||||
width: shrinkImage ? 52 : MediaQuery.of(context).size.width - 32,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Image(
|
||||
image: NetworkImage(baseUrl + '/storage/' + widget.feedBlogPostModel!.image),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import 'dart:io';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:eatvio_app/core/const.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:eatvio_app/core/image_compressing/image_compress_utility.dart';
|
||||
import 'package:eatvio_app/features/blog_post_create/services/blog_post_service.dart';
|
||||
import 'package:flutter_image_compress/flutter_image_compress.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
class BlogPostRepository {
|
||||
final BlogPostService blogPostService;
|
||||
@@ -29,4 +32,58 @@ class BlogPostRepository {
|
||||
formData: formData,
|
||||
);
|
||||
}
|
||||
|
||||
Future<XFile?> downloadImage(String imageUrl) async {
|
||||
try {
|
||||
// Загрузка изображения
|
||||
final response = await http.get(Uri.parse(baseUrl + '/storage/' + imageUrl));
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
// Получение временной директории
|
||||
final directory = await getTemporaryDirectory();
|
||||
// Создание файла в временной директории
|
||||
final filePath = '${directory.path}/image.jpg'; // Вы можете изменить название файла
|
||||
final file = File(filePath);
|
||||
// Запись данных в файл
|
||||
await file.writeAsBytes(response.bodyBytes);
|
||||
|
||||
// Возвращаем объект XFile
|
||||
return XFile(file.path);
|
||||
} else {
|
||||
print('Ошибка загрузки изображения: ${response.statusCode}');
|
||||
return null;
|
||||
}
|
||||
} catch (e) {
|
||||
print('Произошла ошибка: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateBlogPost(
|
||||
int id,
|
||||
String? title,
|
||||
String? videoUrl,
|
||||
String? description,
|
||||
XFile? image,
|
||||
String? oldImageUrl,
|
||||
) async {
|
||||
FormData formData = FormData.fromMap({
|
||||
'title': title,
|
||||
'description': description,
|
||||
'state': 'active',
|
||||
'video_url': videoUrl,
|
||||
'image': image != null
|
||||
? await MultipartFile.fromFile((await ImageCompressUtility.compressFile(File(image.path))).path, filename: image.name)
|
||||
: oldImageUrl != null
|
||||
? await MultipartFile.fromFile((await downloadImage(oldImageUrl))?.path ?? '', filename: oldImageUrl.split('/').last)
|
||||
: null,
|
||||
});
|
||||
|
||||
return await blogPostService.updateBlogPost(
|
||||
id: id,
|
||||
formData: formData,
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> deleteBlogPost(int id) async => await blogPostService.deleteBlogPost(id: id);
|
||||
}
|
||||
|
||||
@@ -12,4 +12,16 @@ abstract class BlogPostService {
|
||||
Future<void> createBlogPost({
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@POST('/api/blogPosts/update/{id}')
|
||||
@MultiPart()
|
||||
Future<void> updateBlogPost({
|
||||
@Path('id') required int id,
|
||||
@Body() required FormData formData,
|
||||
});
|
||||
|
||||
@POST('/api/blogPosts/delete/{id}')
|
||||
Future<void> deleteBlogPost({
|
||||
@Path('id') required int id,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -47,6 +47,60 @@ class _BlogPostService implements BlogPostService {
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> updateBlogPost({
|
||||
required int id,
|
||||
required FormData formData,
|
||||
}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
final _data = formData;
|
||||
final _options = _setStreamType<void>(Options(
|
||||
method: 'POST',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
contentType: 'multipart/form-data',
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/blogPosts/update/${id}',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(
|
||||
baseUrl: _combineBaseUrls(
|
||||
_dio.options.baseUrl,
|
||||
baseUrl,
|
||||
)));
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteBlogPost({required int id}) async {
|
||||
final _extra = <String, dynamic>{};
|
||||
final queryParameters = <String, dynamic>{};
|
||||
final _headers = <String, dynamic>{};
|
||||
const Map<String, dynamic>? _data = null;
|
||||
final _options = _setStreamType<void>(Options(
|
||||
method: 'POST',
|
||||
headers: _headers,
|
||||
extra: _extra,
|
||||
)
|
||||
.compose(
|
||||
_dio.options,
|
||||
'/api/blogPosts/delete/${id}',
|
||||
queryParameters: queryParameters,
|
||||
data: _data,
|
||||
)
|
||||
.copyWith(
|
||||
baseUrl: _combineBaseUrls(
|
||||
_dio.options.baseUrl,
|
||||
baseUrl,
|
||||
)));
|
||||
await _dio.fetch<void>(_options);
|
||||
}
|
||||
|
||||
RequestOptions _setStreamType<T>(RequestOptions requestOptions) {
|
||||
if (T != dynamic &&
|
||||
!(requestOptions.responseType == ResponseType.bytes ||
|
||||
|
||||
@@ -14,6 +14,7 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
final ProfileRepository profileRepository;
|
||||
final GlossaryRepository glossaryRepository;
|
||||
static const _dietStateValues = ['active', 'personal', 'draft'];
|
||||
|
||||
CreateDietCubit({required this.profileRepository, required this.createDietRepository, required this.glossaryRepository}) : super(CreateDietState.initial());
|
||||
|
||||
void setDetails(String text) {
|
||||
@@ -236,7 +237,13 @@ class CreateDietCubit extends Cubit<CreateDietState> {
|
||||
),
|
||||
details: state.dietData.details ?? '',
|
||||
dailySchedule: state.dietData.dailySchedule ?? [],
|
||||
author: Author(authorSlug: authorProfile.slug, authorName: authorProfile.name, authorProfileIcon: authorProfile.profilePhotoUrl, authorIsMe: false),
|
||||
author: Author(
|
||||
authorSlug: authorProfile.slug,
|
||||
authorName: authorProfile.name,
|
||||
authorProfileIcon: authorProfile.profilePhotoUrl,
|
||||
authorIsMe: false,
|
||||
isEntitySubscribedByMe: false,
|
||||
),
|
||||
totalLikes: 0,
|
||||
totalViews: 0,
|
||||
totalComments: 0,
|
||||
|
||||
@@ -9,7 +9,7 @@ class FeedCubit extends Cubit<FeedState> {
|
||||
bool isLoading = false;
|
||||
String? _query;
|
||||
|
||||
FeedCubit({required this.feedRepository}) : super(const FeedState.loading());
|
||||
FeedCubit({required this.feedRepository,}) : super(const FeedState.loading());
|
||||
|
||||
loadFeedBlogPostList({
|
||||
String? query,
|
||||
|
||||
@@ -34,7 +34,7 @@ class FeedScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _FeedScreenState extends State<FeedScreen> {
|
||||
final FeedCubit feedCubit = sl<FeedCubit>()..loadFeedBlogPostList();
|
||||
late final FeedCubit feedCubit;
|
||||
final RecipesCubit recipesCubit = sl<RecipesCubit>()..loadRecipesList();
|
||||
final DietsCubit dietsCubit = sl<DietsCubit>()..loadDiets();
|
||||
final PlansCubit plansCubit = sl<PlansCubit>()..loadPlans();
|
||||
@@ -49,6 +49,8 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
feedCubit = context.read<FeedCubit>();
|
||||
feedCubit.loadFeedBlogPostList();
|
||||
blogPostsScrollController.addListener(_onScrollBlogPosts);
|
||||
recipesScrollController.addListener(_onScrollRecipes);
|
||||
dietsScrollController.addListener(_onScrollDiets);
|
||||
@@ -444,7 +446,7 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
GoRouter.of(context).pushNamed(CreatePlanScreen.name);
|
||||
break;
|
||||
default:
|
||||
GoRouter.of(context).pushNamed('blogPostCreateScreen', extra: feedCubit);
|
||||
GoRouter.of(context).pushNamed('blogPostCreateScreen');
|
||||
}
|
||||
},
|
||||
borderRadius: BorderRadius.circular(64),
|
||||
@@ -469,6 +471,7 @@ class _FeedScreenState extends State<FeedScreen> {
|
||||
width: MediaQuery.of(context).size.width - 84,
|
||||
child: TextFormField(
|
||||
controller: searchController,
|
||||
autofocus: false,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
),
|
||||
|
||||
@@ -18,7 +18,10 @@ import 'package:share_plus/share_plus.dart';
|
||||
class BlogPostWidget extends StatefulWidget {
|
||||
final FeedBlogPostModel feedBlogPostModel;
|
||||
|
||||
const BlogPostWidget({super.key, required this.feedBlogPostModel});
|
||||
const BlogPostWidget({
|
||||
super.key,
|
||||
required this.feedBlogPostModel,
|
||||
});
|
||||
|
||||
@override
|
||||
State<BlogPostWidget> createState() => _BlogPostWidgetState();
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:eatvio_app/core/locator_service.dart';
|
||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/new_messages_cubit/new_messages_cubit.dart';
|
||||
import 'package:eatvio_app/features/bottom_navigation_bar/presentation/bloc/notifications_cubit/notifications_cubit.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_bloc/flutter_bloc.dart';
|
||||
@@ -29,6 +30,7 @@ class MyApp extends StatelessWidget {
|
||||
BlocProvider<InitializationCubit>(create: (context) => sl<InitializationCubit>()),
|
||||
BlocProvider<NewMessagesCubit>(create: (context) => sl<NewMessagesCubit>()),
|
||||
BlocProvider<NotificationsCubit>(create: (context) => sl<NotificationsCubit>()),
|
||||
BlocProvider<FeedCubit>(create: (context) => sl<FeedCubit>()..loadFeedBlogPostList()),
|
||||
],
|
||||
child: Portal(
|
||||
child: KeyboardDismisser(
|
||||
|
||||
@@ -48,7 +48,7 @@ dependencies:
|
||||
file_picker: ^8.1.4
|
||||
audioplayers: ^6.1.0
|
||||
intl: ^0.19.0
|
||||
rive: ^0.13.18
|
||||
rive: ^0.13.19
|
||||
mask_text_input_formatter: ^2.9.0
|
||||
lottie: ^3.1.3
|
||||
flutter_portal: ^1.1.4
|
||||
@@ -58,6 +58,7 @@ dependencies:
|
||||
image: ^4.3.0
|
||||
flutter_native_splash: ^2.4.3
|
||||
dotted_border: ^2.1.0
|
||||
http: ^1.2.2
|
||||
|
||||
dev_dependencies:
|
||||
build_runner: ^2.4.13
|
||||
|
||||
Reference in New Issue
Block a user