forked from eatvio/eatvio_app
Merge pull request 'improvements: added loaders' (#766) from misha/eatvio_app:issue-580 into main
Reviewed-on: eatvio/eatvio_app#766
This commit is contained in:
@@ -411,7 +411,7 @@ class _AuthScreenState extends State<AuthScreen> {
|
|||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
label: state is AuthStateLoading
|
label: state is AuthStateLoading || _isLoading
|
||||||
? const CupertinoActivityIndicator()
|
? const CupertinoActivityIndicator()
|
||||||
: Text('Войти', style: theme.textTheme.titleSmall!.copyWith(color: Colors.white)),
|
: Text('Войти', style: theme.textTheme.titleSmall!.copyWith(color: Colors.white)),
|
||||||
),
|
),
|
||||||
@@ -426,8 +426,8 @@ class _AuthScreenState extends State<AuthScreen> {
|
|||||||
elevation: 0,
|
elevation: 0,
|
||||||
focusElevation: 0,
|
focusElevation: 0,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||||
backgroundColor: state is AuthStateLoading ? Colors.black.withAlpha(50) : appTheme.blueA400,
|
backgroundColor: state is AuthStateLoading || _isLoading ? Colors.black.withAlpha(50) : appTheme.blueA400,
|
||||||
onPressed: state is AuthStateLoading
|
onPressed: state is AuthStateLoading || _isLoading
|
||||||
? null
|
? null
|
||||||
: () async {
|
: () async {
|
||||||
await showDialog(
|
await showDialog(
|
||||||
@@ -487,7 +487,7 @@ class _AuthScreenState extends State<AuthScreen> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
label: state is AuthStateLoading
|
label: state is AuthStateLoading || _isLoading
|
||||||
? const CupertinoActivityIndicator()
|
? const CupertinoActivityIndicator()
|
||||||
: const Icon(Icons.qr_code_scanner_rounded, color: Colors.white),
|
: const Icon(Icons.qr_code_scanner_rounded, color: Colors.white),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:eatvio_app/core/app_config.dart';
|
|||||||
import 'package:eatvio_app/core/app_router.dart';
|
import 'package:eatvio_app/core/app_router.dart';
|
||||||
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
import 'package:eatvio_app/core/permission_handler/permission_handler.dart';
|
||||||
import 'package:eatvio_app/core/theme/app_decoration.dart';
|
import 'package:eatvio_app/core/theme/app_decoration.dart';
|
||||||
|
import 'package:eatvio_app/core/widgets/loader.dart';
|
||||||
import 'package:eatvio_app/core/widgets/show_error_dialog.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/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/features/blog_post_create/bloc/blog_post_create_cubit/blog_post_create_state.dart';
|
||||||
@@ -620,16 +621,16 @@ class _BlogPostCreateScreenState extends State<BlogPostCreateScreen> {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
child: Ink(
|
child: isLoading
|
||||||
width: MediaQuery.of(context).size.width - 32,
|
? const Center(child: Loader())
|
||||||
height: 52,
|
: Ink(
|
||||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(16), color: appTheme.blueA400),
|
width: MediaQuery.of(context).size.width - 32,
|
||||||
child: isLoading
|
height: 52,
|
||||||
? const Center(child: CircularProgressIndicator())
|
decoration: BoxDecoration(borderRadius: BorderRadius.circular(16), color: appTheme.blueA400),
|
||||||
: const Center(
|
child: const Center(
|
||||||
child: Text('Создать', style: TextStyle(color: Colors.white)),
|
child: Text('Создать', style: TextStyle(color: Colors.white)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ class _RecipeCreateScreenState extends State<RecipeCreateScreen> {
|
|||||||
late final CreateRecipeCubit createRecipeCubit;
|
late final CreateRecipeCubit createRecipeCubit;
|
||||||
final GlobalKey<MarkdownEditorState> _mdKey = GlobalKey<MarkdownEditorState>();
|
final GlobalKey<MarkdownEditorState> _mdKey = GlobalKey<MarkdownEditorState>();
|
||||||
bool _mdToolbarVisible = false;
|
bool _mdToolbarVisible = false;
|
||||||
|
bool _isRecipeBeingPublished = false;
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -58,9 +58,7 @@ class _RecipeCreateScreenState extends State<RecipeCreateScreen> {
|
|||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF0F2F5),
|
backgroundColor: const Color(0xFFF0F2F5),
|
||||||
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
|
||||||
floatingActionButton: _mdToolbarVisible && _mdKey.currentState != null
|
floatingActionButton: _mdToolbarVisible && _mdKey.currentState != null ? _mdKey.currentState!.buildToolbar(context) : null,
|
||||||
? _mdKey.currentState!.buildToolbar(context)
|
|
||||||
: null,
|
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: widget.recipe != null ? const Text('Редактирование рецепта') : const Text('Добавление рецепта'),
|
title: widget.recipe != null ? const Text('Редактирование рецепта') : const Text('Добавление рецепта'),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
@@ -83,44 +81,55 @@ class _RecipeCreateScreenState extends State<RecipeCreateScreen> {
|
|||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return Builder(
|
return Builder(
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
return InkWell(
|
return _isRecipeBeingPublished
|
||||||
key: AppKeys.recipeCreateScreenPublishButton,
|
? const Center(child: Loader())
|
||||||
onTap: () async {
|
: InkWell(
|
||||||
if (context.read<CreateRecipeCubit>().validateAll()) {
|
key: AppKeys.recipeCreateScreenPublishButton,
|
||||||
final isSuccess = await context.read<CreateRecipeCubit>().publishRecipe(
|
onTap: () async {
|
||||||
widget.recipe == null ? false : true,
|
setState(() {
|
||||||
widget.recipe?.slug,
|
_isRecipeBeingPublished = true;
|
||||||
|
});
|
||||||
|
if (context.read<CreateRecipeCubit>().validateAll()) {
|
||||||
|
final isSuccess = await context.read<CreateRecipeCubit>().publishRecipe(
|
||||||
|
widget.recipe == null ? false : true,
|
||||||
|
widget.recipe?.slug,
|
||||||
|
);
|
||||||
|
setState(() {
|
||||||
|
_isRecipeBeingPublished = false;
|
||||||
|
});
|
||||||
|
if (isSuccess) {
|
||||||
|
Future.delayed(const Duration(milliseconds: 500), () {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
context.pop();
|
||||||
|
showBottomSheetWithBlur(
|
||||||
|
userRootNavigator: true,
|
||||||
|
context: context,
|
||||||
|
child: SuccessPublishedRecipeBottomSheet(title: state.entity.title ?? 'Рецепт'),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (!context.mounted) return;
|
||||||
|
showErrorDialog(context, title: '${s.could_not_publish_recipe} ${state.entity.title}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setState(() {
|
||||||
|
_isRecipeBeingPublished = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
child: Ink(
|
||||||
|
width: MediaQuery.of(context).size.width - 32,
|
||||||
|
decoration: BoxDecoration(color: appTheme.blueA400, borderRadius: BorderRadius.circular(20)),
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
child: Text(
|
||||||
|
widget.recipe != null ? 'Обновить' : 'Опубликовать',
|
||||||
|
style: const TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w600),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
if (isSuccess) {
|
|
||||||
Future.delayed(const Duration(milliseconds: 500), () {
|
|
||||||
if (!context.mounted) return;
|
|
||||||
context.pop();
|
|
||||||
showBottomSheetWithBlur(
|
|
||||||
userRootNavigator: true,
|
|
||||||
context: context,
|
|
||||||
child: SuccessPublishedRecipeBottomSheet(title: state.entity.title ?? 'Рецепт'),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (!context.mounted) return;
|
|
||||||
showErrorDialog(context, title: '${s.could_not_publish_recipe} ${state.entity.title}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
|
||||||
child: Ink(
|
|
||||||
width: MediaQuery.of(context).size.width - 32,
|
|
||||||
decoration: BoxDecoration(color: appTheme.blueA400, borderRadius: BorderRadius.circular(20)),
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Text(
|
|
||||||
widget.recipe != null ? 'Обновить' : 'Опубликовать',
|
|
||||||
style: const TextStyle(fontSize: 16, color: Colors.white, fontWeight: FontWeight.w600),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -44,16 +44,24 @@ class UserDiaryScreen extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class DiaryScreenContent extends StatelessWidget {
|
class DiaryScreenContent extends StatefulWidget {
|
||||||
const DiaryScreenContent({super.key, this.diaryId, this.currentPlanDay});
|
const DiaryScreenContent({super.key, this.diaryId, this.currentPlanDay});
|
||||||
final int? diaryId;
|
final int? diaryId;
|
||||||
final int? currentPlanDay;
|
final int? currentPlanDay;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<DiaryScreenContent> createState() => _DiaryScreenContentState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DiaryScreenContentState extends State<DiaryScreenContent> {
|
||||||
|
bool _isDiaryFinishing = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final s = S.of(context);
|
final s = S.of(context);
|
||||||
return MultiBlocProvider(
|
return MultiBlocProvider(
|
||||||
providers: [
|
providers: [
|
||||||
BlocProvider<DiaryCubit>(create: (BuildContext context) => sl<DiaryCubit>()..fetchDiaryV2(needLoading: true, diaryId: diaryId)),
|
BlocProvider<DiaryCubit>(create: (BuildContext context) => sl<DiaryCubit>()..fetchDiaryV2(needLoading: true, diaryId: widget.diaryId)),
|
||||||
BlocProvider(create: (context) => sl<ConsultantCommentsCubit>()),
|
BlocProvider(create: (context) => sl<ConsultantCommentsCubit>()),
|
||||||
],
|
],
|
||||||
child: BlocBuilder<DiaryCubit, DiaryState>(
|
child: BlocBuilder<DiaryCubit, DiaryState>(
|
||||||
@@ -63,13 +71,13 @@ class DiaryScreenContent extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
if (state is DiaryStateError) {
|
if (state is DiaryStateError) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: DataErrorWidget(onReload: () => context.read<DiaryCubit>().fetchDiaryV2(needLoading: false, diaryId: diaryId)),
|
body: DataErrorWidget(onReload: () => context.read<DiaryCubit>().fetchDiaryV2(needLoading: false, diaryId: widget.diaryId)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: Colors.grey.shade200,
|
backgroundColor: Colors.grey.shade200,
|
||||||
appBar: diaryId == null
|
appBar: widget.diaryId == null
|
||||||
? AppBar(toolbarHeight: 0)
|
? AppBar(toolbarHeight: 0)
|
||||||
: AppBar(
|
: AppBar(
|
||||||
title: Text(
|
title: Text(
|
||||||
@@ -83,7 +91,7 @@ class DiaryScreenContent extends StatelessWidget {
|
|||||||
physics: const BouncingScrollPhysics(),
|
physics: const BouncingScrollPhysics(),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (diaryId == null) const CalendarWidget(),
|
if (widget.diaryId == null) const CalendarWidget(),
|
||||||
if (state is DiaryStateLoading) ...[const SizedBox(height: 60), const Loader()],
|
if (state is DiaryStateLoading) ...[const SizedBox(height: 60), const Loader()],
|
||||||
if (state is DiaryStateLoaded)
|
if (state is DiaryStateLoaded)
|
||||||
WakeupAndRetireWidget(
|
WakeupAndRetireWidget(
|
||||||
@@ -116,7 +124,23 @@ class DiaryScreenContent extends StatelessWidget {
|
|||||||
if (state is DiaryStateLoaded && !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented)
|
if (state is DiaryStateLoaded && !state.isConsultantView && !state.isDiaryFinished && !state.isDiaryCommented)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 12),
|
padding: const EdgeInsets.only(top: 12),
|
||||||
child: FinishDayButtonWidget(diaryDay: state.diary),
|
child: _isDiaryFinishing
|
||||||
|
? const Center(child: Loader())
|
||||||
|
: FinishDayButtonWidget(
|
||||||
|
onPressed: () async {
|
||||||
|
setState(() {
|
||||||
|
_isDiaryFinishing = true;
|
||||||
|
});
|
||||||
|
await context.read<DiaryCubit>().finishDiaryDay(
|
||||||
|
diaryId: state.diary.id,
|
||||||
|
wakeUp: state.diary.wakeup.toString(),
|
||||||
|
retire: state.diary.retire.toString(),
|
||||||
|
);
|
||||||
|
setState(() {
|
||||||
|
_isDiaryFinishing = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
if (state is DiaryStateLoaded && state.isConsultantView && !state.isDiaryCommented) ...[
|
if (state is DiaryStateLoaded && state.isConsultantView && !state.isDiaryCommented) ...[
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
import 'package:eatvio_app/features/diary/entities/diary_day_entity.dart';
|
|
||||||
import 'package:eatvio_app/features/diary/presentation/bloc/diary_cubit.dart';
|
|
||||||
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
import 'package:eatvio_app/core/theme/theme_helper.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
|
|
||||||
class FinishDayButtonWidget extends StatefulWidget {
|
class FinishDayButtonWidget extends StatefulWidget {
|
||||||
final DiaryDayEntity diaryDay;
|
final Future<void> Function() onPressed;
|
||||||
|
|
||||||
const FinishDayButtonWidget({super.key, required this.diaryDay});
|
const FinishDayButtonWidget({super.key, required this.onPressed});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<FinishDayButtonWidget> createState() => _FinishDayButtonWidgetState();
|
State<FinishDayButtonWidget> createState() => _FinishDayButtonWidgetState();
|
||||||
@@ -17,11 +14,7 @@ class _FinishDayButtonWidgetState extends State<FinishDayButtonWidget> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: () => context.read<DiaryCubit>().finishDiaryDay(
|
onTap: widget.onPressed,
|
||||||
diaryId: widget.diaryDay.id,
|
|
||||||
wakeUp: widget.diaryDay.wakeup.toString(),
|
|
||||||
retire: widget.diaryDay.retire.toString(),
|
|
||||||
),
|
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
child: Ink(
|
child: Ink(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import 'package:flutter_portal/flutter_portal.dart';
|
|||||||
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
|
import 'package:keyboard_dismisser/keyboard_dismisser.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
await AppInitializer.initialize(buildType: AppBuildType.prod);
|
await AppInitializer.initialize(buildType: AppBuildType.dev);
|
||||||
await AppInitializer.runAppWithSentry(() => runApp(const MyApp()));
|
await AppInitializer.runAppWithSentry(() => runApp(const MyApp()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user